Fossil SCM
Update SQLite to the first release candidate for 3.6.21.
Commit
017d281f45656bb8919478ec6501e92dfc9637df
Parent
732d7c406e3f764…
2 files changed
+1133
-721
+10
-5
+1133
-721
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -643,11 +643,11 @@ | ||
| 643 | 643 | ** |
| 644 | 644 | ** Requirements: [H10011] [H10014] |
| 645 | 645 | */ |
| 646 | 646 | #define SQLITE_VERSION "3.6.21" |
| 647 | 647 | #define SQLITE_VERSION_NUMBER 3006021 |
| 648 | -#define SQLITE_SOURCE_ID "2009-11-25 21:05:09 5086bf8e838c824accda531afeb56a51dd40d795" | |
| 648 | +#define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" | |
| 649 | 649 | |
| 650 | 650 | /* |
| 651 | 651 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 652 | 652 | ** KEYWORDS: sqlite3_version |
| 653 | 653 | ** |
| @@ -1817,10 +1817,13 @@ | ||
| 1817 | 1817 | ** the return value of this interface. |
| 1818 | 1818 | ** |
| 1819 | 1819 | ** For the purposes of this routine, an [INSERT] is considered to |
| 1820 | 1820 | ** be successful even if it is subsequently rolled back. |
| 1821 | 1821 | ** |
| 1822 | +** This function is accessible to SQL statements via the | |
| 1823 | +** [last_insert_rowid() SQL function]. | |
| 1824 | +** | |
| 1822 | 1825 | ** Requirements: |
| 1823 | 1826 | ** [H12221] [H12223] |
| 1824 | 1827 | ** |
| 1825 | 1828 | ** If a separate thread performs a new [INSERT] on the same |
| 1826 | 1829 | ** database connection while the [sqlite3_last_insert_rowid()] |
| @@ -1874,12 +1877,12 @@ | ||
| 1874 | 1877 | ** changes in the most recently completed INSERT, UPDATE, or DELETE |
| 1875 | 1878 | ** statement within the body of the same trigger. |
| 1876 | 1879 | ** However, the number returned does not include changes |
| 1877 | 1880 | ** caused by subtriggers since those have their own context. |
| 1878 | 1881 | ** |
| 1879 | -** See also the [sqlite3_total_changes()] interface and the | |
| 1880 | -** [count_changes pragma]. | |
| 1882 | +** See also the [sqlite3_total_changes()] interface, the | |
| 1883 | +** [count_changes pragma], and the [changes() SQL function]. | |
| 1881 | 1884 | ** |
| 1882 | 1885 | ** Requirements: |
| 1883 | 1886 | ** [H12241] [H12243] |
| 1884 | 1887 | ** |
| 1885 | 1888 | ** If a separate thread makes changes on the same database connection |
| @@ -1902,12 +1905,12 @@ | ||
| 1902 | 1905 | ** are counted. |
| 1903 | 1906 | ** The changes are counted as soon as the statement that makes them is |
| 1904 | 1907 | ** completed (when the statement handle is passed to [sqlite3_reset()] or |
| 1905 | 1908 | ** [sqlite3_finalize()]). |
| 1906 | 1909 | ** |
| 1907 | -** See also the [sqlite3_changes()] interface and the | |
| 1908 | -** [count_changes pragma]. | |
| 1910 | +** See also the [sqlite3_changes()] interface, the | |
| 1911 | +** [count_changes pragma], and the [total_changes() SQL function]. | |
| 1909 | 1912 | ** |
| 1910 | 1913 | ** Requirements: |
| 1911 | 1914 | ** [H12261] [H12263] |
| 1912 | 1915 | ** |
| 1913 | 1916 | ** If a separate thread makes changes on the same database connection |
| @@ -4664,10 +4667,12 @@ | ||
| 4664 | 4667 | ** should free this memory by calling [sqlite3_free()]. |
| 4665 | 4668 | ** |
| 4666 | 4669 | ** {H12606} Extension loading must be enabled using |
| 4667 | 4670 | ** [sqlite3_enable_load_extension()] prior to calling this API, |
| 4668 | 4671 | ** otherwise an error will be returned. |
| 4672 | +** | |
| 4673 | +** See also the [load_extension() SQL function]. | |
| 4669 | 4674 | */ |
| 4670 | 4675 | SQLITE_API int sqlite3_load_extension( |
| 4671 | 4676 | sqlite3 *db, /* Load the extension into this database connection */ |
| 4672 | 4677 | const char *zFile, /* Name of the shared library containing extension */ |
| 4673 | 4678 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
| @@ -9662,19 +9667,20 @@ | ||
| 9662 | 9667 | ** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of |
| 9663 | 9668 | ** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable. |
| 9664 | 9669 | ** The Parse.pTriggerPrg list never contains two entries with the same |
| 9665 | 9670 | ** values for both pTrigger and orconf. |
| 9666 | 9671 | ** |
| 9667 | -** The TriggerPrg.oldmask variable is set to a mask of old.* columns | |
| 9672 | +** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns | |
| 9668 | 9673 | ** accessed (or set to 0 for triggers fired as a result of INSERT |
| 9669 | -** statements). | |
| 9674 | +** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to | |
| 9675 | +** a mask of new.* columns used by the program. | |
| 9670 | 9676 | */ |
| 9671 | 9677 | struct TriggerPrg { |
| 9672 | 9678 | Trigger *pTrigger; /* Trigger this program was coded from */ |
| 9673 | 9679 | int orconf; /* Default ON CONFLICT policy */ |
| 9674 | 9680 | SubProgram *pProgram; /* Program implementing pTrigger/orconf */ |
| 9675 | - u32 oldmask; /* Mask of old.* columns accessed */ | |
| 9681 | + u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ | |
| 9676 | 9682 | TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ |
| 9677 | 9683 | }; |
| 9678 | 9684 | |
| 9679 | 9685 | /* |
| 9680 | 9686 | ** An SQL parser context. A copy of this structure is passed through |
| @@ -9742,10 +9748,11 @@ | ||
| 9742 | 9748 | |
| 9743 | 9749 | /* Information used while coding trigger programs. */ |
| 9744 | 9750 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 9745 | 9751 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 9746 | 9752 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 9753 | + u32 newmask; /* Mask of new.* columns referenced */ | |
| 9747 | 9754 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 9748 | 9755 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 9749 | 9756 | u8 disableTriggers; /* True to disable triggers */ |
| 9750 | 9757 | |
| 9751 | 9758 | /* Above is constant between recursions. Below is reset before and after |
| @@ -10339,11 +10346,11 @@ | ||
| 10339 | 10346 | ExprList*,Select*,u8); |
| 10340 | 10347 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); |
| 10341 | 10348 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); |
| 10342 | 10349 | SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); |
| 10343 | 10350 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); |
| 10344 | -SQLITE_PRIVATE u32 sqlite3TriggerOldmask(Parse*,Trigger*,ExprList*,Table*,int); | |
| 10351 | +SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); | |
| 10345 | 10352 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) |
| 10346 | 10353 | #else |
| 10347 | 10354 | # define sqlite3TriggersExist(B,C,D,E,F) 0 |
| 10348 | 10355 | # define sqlite3DeleteTrigger(A,B) |
| 10349 | 10356 | # define sqlite3DropTriggerPtr(A,B) |
| @@ -10350,11 +10357,11 @@ | ||
| 10350 | 10357 | # define sqlite3UnlinkAndDeleteTrigger(A,B,C) |
| 10351 | 10358 | # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) |
| 10352 | 10359 | # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) |
| 10353 | 10360 | # define sqlite3TriggerList(X, Y) 0 |
| 10354 | 10361 | # define sqlite3ParseToplevel(p) p |
| 10355 | -# define sqlite3TriggerOldmask(A,B,C,D,E) 0 | |
| 10362 | +# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 | |
| 10356 | 10363 | #endif |
| 10357 | 10364 | |
| 10358 | 10365 | SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); |
| 10359 | 10366 | SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
| 10360 | 10367 | SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); |
| @@ -10564,10 +10571,11 @@ | ||
| 10564 | 10571 | SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); |
| 10565 | 10572 | SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); |
| 10566 | 10573 | SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); |
| 10567 | 10574 | SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); |
| 10568 | 10575 | SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); |
| 10576 | +SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); | |
| 10569 | 10577 | SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); |
| 10570 | 10578 | SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); |
| 10571 | 10579 | SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); |
| 10572 | 10580 | SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); |
| 10573 | 10581 | SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); |
| @@ -14914,10 +14922,43 @@ | ||
| 14914 | 14922 | assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 14915 | 14923 | DosCloseMutexSem( p->mutex ); |
| 14916 | 14924 | sqlite3_free( p ); |
| 14917 | 14925 | } |
| 14918 | 14926 | |
| 14927 | +#ifdef SQLITE_DEBUG | |
| 14928 | +/* | |
| 14929 | +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | |
| 14930 | +** intended for use inside assert() statements. | |
| 14931 | +*/ | |
| 14932 | +static int os2MutexHeld(sqlite3_mutex *p){ | |
| 14933 | + TID tid; | |
| 14934 | + PID pid; | |
| 14935 | + ULONG ulCount; | |
| 14936 | + PTIB ptib; | |
| 14937 | + if( p!=0 ) { | |
| 14938 | + DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); | |
| 14939 | + } else { | |
| 14940 | + DosGetInfoBlocks(&ptib, NULL); | |
| 14941 | + tid = ptib->tib_ptib2->tib2_ultid; | |
| 14942 | + } | |
| 14943 | + return p==0 || (p->nRef!=0 && p->owner==tid); | |
| 14944 | +} | |
| 14945 | +static int os2MutexNotheld(sqlite3_mutex *p){ | |
| 14946 | + TID tid; | |
| 14947 | + PID pid; | |
| 14948 | + ULONG ulCount; | |
| 14949 | + PTIB ptib; | |
| 14950 | + if( p!= 0 ) { | |
| 14951 | + DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); | |
| 14952 | + } else { | |
| 14953 | + DosGetInfoBlocks(&ptib, NULL); | |
| 14954 | + tid = ptib->tib_ptib2->tib2_ultid; | |
| 14955 | + } | |
| 14956 | + return p==0 || p->nRef==0 || p->owner!=tid; | |
| 14957 | +} | |
| 14958 | +#endif | |
| 14959 | + | |
| 14919 | 14960 | /* |
| 14920 | 14961 | ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt |
| 14921 | 14962 | ** to enter a mutex. If another thread is already within the mutex, |
| 14922 | 14963 | ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return |
| 14923 | 14964 | ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK |
| @@ -14974,43 +15015,10 @@ | ||
| 14974 | 15015 | p->nRef--; |
| 14975 | 15016 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 14976 | 15017 | DosReleaseMutexSem(p->mutex); |
| 14977 | 15018 | } |
| 14978 | 15019 | |
| 14979 | -#ifdef SQLITE_DEBUG | |
| 14980 | -/* | |
| 14981 | -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | |
| 14982 | -** intended for use inside assert() statements. | |
| 14983 | -*/ | |
| 14984 | -static int os2MutexHeld(sqlite3_mutex *p){ | |
| 14985 | - TID tid; | |
| 14986 | - PID pid; | |
| 14987 | - ULONG ulCount; | |
| 14988 | - PTIB ptib; | |
| 14989 | - if( p!=0 ) { | |
| 14990 | - DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); | |
| 14991 | - } else { | |
| 14992 | - DosGetInfoBlocks(&ptib, NULL); | |
| 14993 | - tid = ptib->tib_ptib2->tib2_ultid; | |
| 14994 | - } | |
| 14995 | - return p==0 || (p->nRef!=0 && p->owner==tid); | |
| 14996 | -} | |
| 14997 | -static int os2MutexNotheld(sqlite3_mutex *p){ | |
| 14998 | - TID tid; | |
| 14999 | - PID pid; | |
| 15000 | - ULONG ulCount; | |
| 15001 | - PTIB ptib; | |
| 15002 | - if( p!= 0 ) { | |
| 15003 | - DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); | |
| 15004 | - } else { | |
| 15005 | - DosGetInfoBlocks(&ptib, NULL); | |
| 15006 | - tid = ptib->tib_ptib2->tib2_ultid; | |
| 15007 | - } | |
| 15008 | - return p==0 || p->nRef==0 || p->owner!=tid; | |
| 15009 | -} | |
| 15010 | -#endif | |
| 15011 | - | |
| 15012 | 15020 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15013 | 15021 | static sqlite3_mutex_methods sMutex = { |
| 15014 | 15022 | os2MutexInit, |
| 15015 | 15023 | os2MutexEnd, |
| 15016 | 15024 | os2MutexAlloc, |
| @@ -22701,11 +22709,11 @@ | ||
| 22701 | 22709 | } |
| 22702 | 22710 | } |
| 22703 | 22711 | #endif |
| 22704 | 22712 | |
| 22705 | 22713 | unixLeaveMutex(); |
| 22706 | - OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); | |
| 22714 | + OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved); | |
| 22707 | 22715 | |
| 22708 | 22716 | *pResOut = reserved; |
| 22709 | 22717 | return rc; |
| 22710 | 22718 | } |
| 22711 | 22719 | |
| @@ -22834,20 +22842,20 @@ | ||
| 22834 | 22842 | struct flock lock; |
| 22835 | 22843 | int s = 0; |
| 22836 | 22844 | int tErrno; |
| 22837 | 22845 | |
| 22838 | 22846 | assert( pFile ); |
| 22839 | - OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, | |
| 22847 | + OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, | |
| 22840 | 22848 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22841 | 22849 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| 22842 | 22850 | |
| 22843 | 22851 | /* If there is already a lock of this type or more restrictive on the |
| 22844 | 22852 | ** unixFile, do nothing. Don't use the end_lock: exit path, as |
| 22845 | 22853 | ** unixEnterMutex() hasn't been called yet. |
| 22846 | 22854 | */ |
| 22847 | 22855 | if( pFile->locktype>=locktype ){ |
| 22848 | - OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, | |
| 22856 | + OSTRACE3("LOCK %d %s ok (already held) (unix)\n", pFile->h, | |
| 22849 | 22857 | locktypeName(locktype)); |
| 22850 | 22858 | return SQLITE_OK; |
| 22851 | 22859 | } |
| 22852 | 22860 | |
| 22853 | 22861 | /* Make sure the locking sequence is correct. |
| @@ -23013,11 +23021,11 @@ | ||
| 23013 | 23021 | pLock->locktype = PENDING_LOCK; |
| 23014 | 23022 | } |
| 23015 | 23023 | |
| 23016 | 23024 | end_lock: |
| 23017 | 23025 | unixLeaveMutex(); |
| 23018 | - OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), | |
| 23026 | + OSTRACE4("LOCK %d %s %s (unix)\n", pFile->h, locktypeName(locktype), | |
| 23019 | 23027 | rc==SQLITE_OK ? "ok" : "failed"); |
| 23020 | 23028 | return rc; |
| 23021 | 23029 | } |
| 23022 | 23030 | |
| 23023 | 23031 | /* |
| @@ -23077,11 +23085,11 @@ | ||
| 23077 | 23085 | int rc = SQLITE_OK; /* Return code from this interface */ |
| 23078 | 23086 | int h; /* The underlying file descriptor */ |
| 23079 | 23087 | int tErrno; /* Error code from system call errors */ |
| 23080 | 23088 | |
| 23081 | 23089 | assert( pFile ); |
| 23082 | - OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, | |
| 23090 | + OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype, | |
| 23083 | 23091 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| 23084 | 23092 | |
| 23085 | 23093 | assert( locktype<=SHARED_LOCK ); |
| 23086 | 23094 | if( pFile->locktype<=locktype ){ |
| 23087 | 23095 | return SQLITE_OK; |
| @@ -23358,11 +23366,11 @@ | ||
| 23358 | 23366 | }else{ |
| 23359 | 23367 | /* The lock is held if and only if the lockfile exists */ |
| 23360 | 23368 | const char *zLockFile = (const char*)pFile->lockingContext; |
| 23361 | 23369 | reserved = access(zLockFile, 0)==0; |
| 23362 | 23370 | } |
| 23363 | - OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); | |
| 23371 | + OSTRACE4("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved); | |
| 23364 | 23372 | *pResOut = reserved; |
| 23365 | 23373 | return rc; |
| 23366 | 23374 | } |
| 23367 | 23375 | |
| 23368 | 23376 | /* |
| @@ -23448,11 +23456,11 @@ | ||
| 23448 | 23456 | static int dotlockUnlock(sqlite3_file *id, int locktype) { |
| 23449 | 23457 | unixFile *pFile = (unixFile*)id; |
| 23450 | 23458 | char *zLockFile = (char *)pFile->lockingContext; |
| 23451 | 23459 | |
| 23452 | 23460 | assert( pFile ); |
| 23453 | - OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, | |
| 23461 | + OSTRACE5("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, locktype, | |
| 23454 | 23462 | pFile->locktype, getpid()); |
| 23455 | 23463 | assert( locktype<=SHARED_LOCK ); |
| 23456 | 23464 | |
| 23457 | 23465 | /* no-op if possible */ |
| 23458 | 23466 | if( pFile->locktype==locktype ){ |
| @@ -23562,11 +23570,11 @@ | ||
| 23562 | 23570 | pFile->lastErrno = tErrno; |
| 23563 | 23571 | rc = lrc; |
| 23564 | 23572 | } |
| 23565 | 23573 | } |
| 23566 | 23574 | } |
| 23567 | - OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); | |
| 23575 | + OSTRACE4("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved); | |
| 23568 | 23576 | |
| 23569 | 23577 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 23570 | 23578 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ |
| 23571 | 23579 | rc = SQLITE_OK; |
| 23572 | 23580 | reserved=1; |
| @@ -23629,11 +23637,11 @@ | ||
| 23629 | 23637 | } |
| 23630 | 23638 | } else { |
| 23631 | 23639 | /* got it, set the type and return ok */ |
| 23632 | 23640 | pFile->locktype = locktype; |
| 23633 | 23641 | } |
| 23634 | - OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), | |
| 23642 | + OSTRACE4("LOCK %d %s %s (flock)\n", pFile->h, locktypeName(locktype), | |
| 23635 | 23643 | rc==SQLITE_OK ? "ok" : "failed"); |
| 23636 | 23644 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 23637 | 23645 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ |
| 23638 | 23646 | rc = SQLITE_BUSY; |
| 23639 | 23647 | } |
| @@ -23651,11 +23659,11 @@ | ||
| 23651 | 23659 | */ |
| 23652 | 23660 | static int flockUnlock(sqlite3_file *id, int locktype) { |
| 23653 | 23661 | unixFile *pFile = (unixFile*)id; |
| 23654 | 23662 | |
| 23655 | 23663 | assert( pFile ); |
| 23656 | - OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, | |
| 23664 | + OSTRACE5("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, locktype, | |
| 23657 | 23665 | pFile->locktype, getpid()); |
| 23658 | 23666 | assert( locktype<=SHARED_LOCK ); |
| 23659 | 23667 | |
| 23660 | 23668 | /* no-op if possible */ |
| 23661 | 23669 | if( pFile->locktype==locktype ){ |
| @@ -23753,11 +23761,11 @@ | ||
| 23753 | 23761 | }else{ |
| 23754 | 23762 | /* we could have it if we want it */ |
| 23755 | 23763 | sem_post(pSem); |
| 23756 | 23764 | } |
| 23757 | 23765 | } |
| 23758 | - OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); | |
| 23766 | + OSTRACE4("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved); | |
| 23759 | 23767 | |
| 23760 | 23768 | *pResOut = reserved; |
| 23761 | 23769 | return rc; |
| 23762 | 23770 | } |
| 23763 | 23771 | |
| @@ -23828,11 +23836,11 @@ | ||
| 23828 | 23836 | unixFile *pFile = (unixFile*)id; |
| 23829 | 23837 | sem_t *pSem = pFile->pOpen->pSem; |
| 23830 | 23838 | |
| 23831 | 23839 | assert( pFile ); |
| 23832 | 23840 | assert( pSem ); |
| 23833 | - OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, | |
| 23841 | + OSTRACE5("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, locktype, | |
| 23834 | 23842 | pFile->locktype, getpid()); |
| 23835 | 23843 | assert( locktype<=SHARED_LOCK ); |
| 23836 | 23844 | |
| 23837 | 23845 | /* no-op if possible */ |
| 23838 | 23846 | if( pFile->locktype==locktype ){ |
| @@ -23998,11 +24006,11 @@ | ||
| 23998 | 24006 | if( IS_LOCK_ERROR(lrc) ){ |
| 23999 | 24007 | rc=lrc; |
| 24000 | 24008 | } |
| 24001 | 24009 | } |
| 24002 | 24010 | |
| 24003 | - OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); | |
| 24011 | + OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved); | |
| 24004 | 24012 | |
| 24005 | 24013 | *pResOut = reserved; |
| 24006 | 24014 | return rc; |
| 24007 | 24015 | } |
| 24008 | 24016 | |
| @@ -24034,19 +24042,19 @@ | ||
| 24034 | 24042 | int rc = SQLITE_OK; |
| 24035 | 24043 | unixFile *pFile = (unixFile*)id; |
| 24036 | 24044 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24037 | 24045 | |
| 24038 | 24046 | assert( pFile ); |
| 24039 | - OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, | |
| 24047 | + OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h, | |
| 24040 | 24048 | locktypeName(locktype), locktypeName(pFile->locktype), getpid()); |
| 24041 | 24049 | |
| 24042 | 24050 | /* If there is already a lock of this type or more restrictive on the |
| 24043 | 24051 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 24044 | 24052 | ** unixEnterMutex() hasn't been called yet. |
| 24045 | 24053 | */ |
| 24046 | 24054 | if( pFile->locktype>=locktype ){ |
| 24047 | - OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, | |
| 24055 | + OSTRACE3("LOCK %d %s ok (already held) (afp)\n", pFile->h, | |
| 24048 | 24056 | locktypeName(locktype)); |
| 24049 | 24057 | return SQLITE_OK; |
| 24050 | 24058 | } |
| 24051 | 24059 | |
| 24052 | 24060 | /* Make sure the locking sequence is correct |
| @@ -24161,11 +24169,11 @@ | ||
| 24161 | 24169 | pFile->locktype = PENDING_LOCK; |
| 24162 | 24170 | } |
| 24163 | 24171 | |
| 24164 | 24172 | afp_end_lock: |
| 24165 | 24173 | unixLeaveMutex(); |
| 24166 | - OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), | |
| 24174 | + OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype), | |
| 24167 | 24175 | rc==SQLITE_OK ? "ok" : "failed"); |
| 24168 | 24176 | return rc; |
| 24169 | 24177 | } |
| 24170 | 24178 | |
| 24171 | 24179 | /* |
| @@ -24179,11 +24187,11 @@ | ||
| 24179 | 24187 | int rc = SQLITE_OK; |
| 24180 | 24188 | unixFile *pFile = (unixFile*)id; |
| 24181 | 24189 | afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext; |
| 24182 | 24190 | |
| 24183 | 24191 | assert( pFile ); |
| 24184 | - OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, | |
| 24192 | + OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype, | |
| 24185 | 24193 | pFile->locktype, getpid()); |
| 24186 | 24194 | |
| 24187 | 24195 | assert( locktype<=SHARED_LOCK ); |
| 24188 | 24196 | if( pFile->locktype<=locktype ){ |
| 24189 | 24197 | return SQLITE_OK; |
| @@ -32430,10 +32438,11 @@ | ||
| 32430 | 32438 | pager_reset(pPager); |
| 32431 | 32439 | } |
| 32432 | 32440 | |
| 32433 | 32441 | pPager->changeCountDone = 0; |
| 32434 | 32442 | pPager->state = PAGER_UNLOCK; |
| 32443 | + pPager->dbModified = 0; | |
| 32435 | 32444 | } |
| 32436 | 32445 | } |
| 32437 | 32446 | |
| 32438 | 32447 | /* |
| 32439 | 32448 | ** This function should be called when an IOERR, CORRUPT or FULL error |
| @@ -33806,12 +33815,15 @@ | ||
| 33806 | 33815 | /* The OS lock values must be the same as the Pager lock values */ |
| 33807 | 33816 | assert( PAGER_SHARED==SHARED_LOCK ); |
| 33808 | 33817 | assert( PAGER_RESERVED==RESERVED_LOCK ); |
| 33809 | 33818 | assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); |
| 33810 | 33819 | |
| 33811 | - /* If the file is currently unlocked then the size must be unknown */ | |
| 33820 | + /* If the file is currently unlocked then the size must be unknown. It | |
| 33821 | + ** must not have been modified at this point. | |
| 33822 | + */ | |
| 33812 | 33823 | assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 ); |
| 33824 | + assert( pPager->state>=PAGER_SHARED || pPager->dbModified==0 ); | |
| 33813 | 33825 | |
| 33814 | 33826 | /* Check that this is either a no-op (because the requested lock is |
| 33815 | 33827 | ** already held, or one of the transistions that the busy-handler |
| 33816 | 33828 | ** may be invoked during, according to the comment above |
| 33817 | 33829 | ** sqlite3PagerSetBusyhandler(). |
| @@ -39966,15 +39978,12 @@ | ||
| 39966 | 39978 | unsigned char *data; |
| 39967 | 39979 | int rc; |
| 39968 | 39980 | int nPage; |
| 39969 | 39981 | |
| 39970 | 39982 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39971 | - /* The database size has already been measured and cached, so failure | |
| 39972 | - ** is impossible here. If the original size measurement failed, then | |
| 39973 | - ** processing aborts before entering this routine. */ | |
| 39974 | 39983 | rc = sqlite3PagerPagecount(pBt->pPager, &nPage); |
| 39975 | - if( NEVER(rc!=SQLITE_OK) || nPage>0 ){ | |
| 39984 | + if( rc!=SQLITE_OK || nPage>0 ){ | |
| 39976 | 39985 | return rc; |
| 39977 | 39986 | } |
| 39978 | 39987 | pP1 = pBt->pPage1; |
| 39979 | 39988 | assert( pP1!=0 ); |
| 39980 | 39989 | data = pP1->aData; |
| @@ -42918,12 +42927,17 @@ | ||
| 42918 | 42927 | if( *pRC ) return; |
| 42919 | 42928 | |
| 42920 | 42929 | assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); |
| 42921 | 42930 | assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); |
| 42922 | 42931 | assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); |
| 42923 | - assert( sz==cellSizePtr(pPage, pCell) ); | |
| 42924 | 42932 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 42933 | + /* The cell should normally be sized correctly. However, when moving a | |
| 42934 | + ** malformed cell from a leaf page to an interior page, if the cell size | |
| 42935 | + ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size | |
| 42936 | + ** might be less than 8 (leaf-size + pointer) on the interior node. Hence | |
| 42937 | + ** the term after the || in the following assert(). */ | |
| 42938 | + assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) ); | |
| 42925 | 42939 | if( pPage->nOverflow || sz+2>pPage->nFree ){ |
| 42926 | 42940 | if( pTemp ){ |
| 42927 | 42941 | memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); |
| 42928 | 42942 | pCell = pTemp; |
| 42929 | 42943 | } |
| @@ -51381,26 +51395,28 @@ | ||
| 51381 | 51395 | /* |
| 51382 | 51396 | ** Given a wildcard parameter name, return the index of the variable |
| 51383 | 51397 | ** with that name. If there is no variable with the given name, |
| 51384 | 51398 | ** return 0. |
| 51385 | 51399 | */ |
| 51386 | -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ | |
| 51387 | - Vdbe *p = (Vdbe*)pStmt; | |
| 51400 | +SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ | |
| 51388 | 51401 | int i; |
| 51389 | 51402 | if( p==0 ){ |
| 51390 | 51403 | return 0; |
| 51391 | 51404 | } |
| 51392 | 51405 | createVarMap(p); |
| 51393 | 51406 | if( zName ){ |
| 51394 | 51407 | for(i=0; i<p->nVar; i++){ |
| 51395 | 51408 | const char *z = p->azVar[i]; |
| 51396 | - if( z && strcmp(z,zName)==0 ){ | |
| 51409 | + if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){ | |
| 51397 | 51410 | return i+1; |
| 51398 | 51411 | } |
| 51399 | 51412 | } |
| 51400 | 51413 | } |
| 51401 | 51414 | return 0; |
| 51415 | +} | |
| 51416 | +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ | |
| 51417 | + return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); | |
| 51402 | 51418 | } |
| 51403 | 51419 | |
| 51404 | 51420 | /* |
| 51405 | 51421 | ** Transfer all bindings from the first statement over to the second. |
| 51406 | 51422 | */ |
| @@ -51509,29 +51525,33 @@ | ||
| 51509 | 51525 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
| 51510 | 51526 | ** bytes in this text up to but excluding the first character in |
| 51511 | 51527 | ** a host parameter. If the text contains no host parameters, return |
| 51512 | 51528 | ** the total number of bytes in the text. |
| 51513 | 51529 | */ |
| 51514 | -static int findNextHostParameter(const char *zSql){ | |
| 51530 | +static int findNextHostParameter(const char *zSql, int *pnToken){ | |
| 51515 | 51531 | int tokenType; |
| 51516 | 51532 | int nTotal = 0; |
| 51517 | 51533 | int n; |
| 51518 | 51534 | |
| 51535 | + *pnToken = 0; | |
| 51519 | 51536 | while( zSql[0] ){ |
| 51520 | 51537 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 51521 | 51538 | assert( n>0 && tokenType!=TK_ILLEGAL ); |
| 51522 | - if( tokenType==TK_VARIABLE ) break; | |
| 51539 | + if( tokenType==TK_VARIABLE ){ | |
| 51540 | + *pnToken = n; | |
| 51541 | + break; | |
| 51542 | + } | |
| 51523 | 51543 | nTotal += n; |
| 51524 | 51544 | zSql += n; |
| 51525 | 51545 | } |
| 51526 | 51546 | return nTotal; |
| 51527 | 51547 | } |
| 51528 | 51548 | |
| 51529 | 51549 | /* |
| 51530 | -** Return a pointer to a string in memory obtained form sqlite3Malloc() which | |
| 51550 | +** Return a pointer to a string in memory obtained form sqlite3DbMalloc() which | |
| 51531 | 51551 | ** holds a copy of zRawSql but with host parameters expanded to their |
| 51532 | -** current values. | |
| 51552 | +** current bindings. | |
| 51533 | 51553 | ** |
| 51534 | 51554 | ** The calling function is responsible for making sure the memory returned |
| 51535 | 51555 | ** is eventually freed. |
| 51536 | 51556 | ** |
| 51537 | 51557 | ** ALGORITHM: Scan the input string looking for host parameters in any of |
| @@ -51545,60 +51565,46 @@ | ||
| 51545 | 51565 | SQLITE_PRIVATE char *sqlite3VdbeExpandSql( |
| 51546 | 51566 | Vdbe *p, /* The prepared statement being evaluated */ |
| 51547 | 51567 | const char *zRawSql /* Raw text of the SQL statement */ |
| 51548 | 51568 | ){ |
| 51549 | 51569 | sqlite3 *db; /* The database connection */ |
| 51550 | - int idx; /* Index of a host parameter */ | |
| 51570 | + int idx = 0; /* Index of a host parameter */ | |
| 51551 | 51571 | int nextIndex = 1; /* Index of next ? host parameter */ |
| 51552 | 51572 | int n; /* Length of a token prefix */ |
| 51573 | + int nToken; /* Length of the parameter token */ | |
| 51553 | 51574 | int i; /* Loop counter */ |
| 51554 | - int dummy; /* For holding a unused return value */ | |
| 51555 | 51575 | Mem *pVar; /* Value of a host parameter */ |
| 51556 | - VdbeOp *pOp; /* For looping over opcodes */ | |
| 51557 | 51576 | StrAccum out; /* Accumulate the output here */ |
| 51558 | 51577 | char zBase[100]; /* Initial working space */ |
| 51559 | 51578 | |
| 51560 | 51579 | db = p->db; |
| 51561 | 51580 | sqlite3StrAccumInit(&out, zBase, sizeof(zBase), |
| 51562 | 51581 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 51563 | 51582 | out.db = db; |
| 51564 | 51583 | while( zRawSql[0] ){ |
| 51565 | - n = findNextHostParameter(zRawSql); | |
| 51584 | + n = findNextHostParameter(zRawSql, &nToken); | |
| 51566 | 51585 | assert( n>0 ); |
| 51567 | 51586 | sqlite3StrAccumAppend(&out, zRawSql, n); |
| 51568 | 51587 | zRawSql += n; |
| 51569 | - if( zRawSql[0]==0 ) break; | |
| 51588 | + assert( zRawSql[0] || nToken==0 ); | |
| 51589 | + if( nToken==0 ) break; | |
| 51570 | 51590 | if( zRawSql[0]=='?' ){ |
| 51571 | - zRawSql++; | |
| 51572 | - if( sqlite3Isdigit(zRawSql[0]) ){ | |
| 51573 | - idx = 0; | |
| 51574 | - while( sqlite3Isdigit(zRawSql[0]) ){ | |
| 51575 | - idx = idx*10 + zRawSql[0] - '0'; | |
| 51576 | - zRawSql++; | |
| 51577 | - } | |
| 51591 | + if( nToken>1 ){ | |
| 51592 | + assert( sqlite3Isdigit(zRawSql[1]) ); | |
| 51593 | + sqlite3GetInt32(&zRawSql[1], &idx); | |
| 51578 | 51594 | }else{ |
| 51579 | 51595 | idx = nextIndex; |
| 51580 | 51596 | } |
| 51581 | 51597 | }else{ |
| 51582 | 51598 | assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); |
| 51583 | 51599 | testcase( zRawSql[0]==':' ); |
| 51584 | 51600 | testcase( zRawSql[0]=='$' ); |
| 51585 | 51601 | testcase( zRawSql[0]=='@' ); |
| 51586 | - n = sqlite3GetToken((u8*)zRawSql, &dummy); | |
| 51587 | - idx = 0; | |
| 51588 | - for(i=0, pOp=p->aOp; ALWAYS(i<p->nOp); i++, pOp++){ | |
| 51589 | - if( pOp->opcode!=OP_Variable ) continue; | |
| 51590 | - if( pOp->p3>1 ) continue; | |
| 51591 | - if( pOp->p4.z==0 ) continue; | |
| 51592 | - if( memcmp(pOp->p4.z, zRawSql, n)==0 && pOp->p4.z[n]==0 ){ | |
| 51593 | - idx = pOp->p1; | |
| 51594 | - break; | |
| 51595 | - } | |
| 51596 | - } | |
| 51602 | + idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); | |
| 51597 | 51603 | assert( idx>0 ); |
| 51598 | - zRawSql += n; | |
| 51599 | 51604 | } |
| 51605 | + zRawSql += nToken; | |
| 51600 | 51606 | nextIndex = idx + 1; |
| 51601 | 51607 | assert( idx>0 && idx<=p->nVar ); |
| 51602 | 51608 | pVar = &p->aVar[idx-1]; |
| 51603 | 51609 | if( pVar->flags & MEM_Null ){ |
| 51604 | 51610 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| @@ -51606,15 +51612,16 @@ | ||
| 51606 | 51612 | sqlite3XPrintf(&out, "%lld", pVar->u.i); |
| 51607 | 51613 | }else if( pVar->flags & MEM_Real ){ |
| 51608 | 51614 | sqlite3XPrintf(&out, "%!.15g", pVar->r); |
| 51609 | 51615 | }else if( pVar->flags & MEM_Str ){ |
| 51610 | 51616 | #ifndef SQLITE_OMIT_UTF16 |
| 51611 | - if( ENC(db)!=SQLITE_UTF8 ){ | |
| 51617 | + u8 enc = ENC(db); | |
| 51618 | + if( enc!=SQLITE_UTF8 ){ | |
| 51612 | 51619 | Mem utf8; |
| 51613 | 51620 | memset(&utf8, 0, sizeof(utf8)); |
| 51614 | 51621 | utf8.db = db; |
| 51615 | - sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, ENC(db), SQLITE_STATIC); | |
| 51622 | + sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); | |
| 51616 | 51623 | sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); |
| 51617 | 51624 | sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z); |
| 51618 | 51625 | sqlite3VdbeMemRelease(&utf8); |
| 51619 | 51626 | }else |
| 51620 | 51627 | #endif |
| @@ -52272,11 +52279,11 @@ | ||
| 52272 | 52279 | int rc = SQLITE_OK; /* Value to return */ |
| 52273 | 52280 | sqlite3 *db = p->db; /* The database */ |
| 52274 | 52281 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| 52275 | 52282 | u8 encoding = ENC(db); /* The database encoding */ |
| 52276 | 52283 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 52277 | - u8 checkProgress; /* True if progress callbacks are enabled */ | |
| 52284 | + int checkProgress; /* True if progress callbacks are enabled */ | |
| 52278 | 52285 | int nProgressOps = 0; /* Opcodes executed since progress callback. */ |
| 52279 | 52286 | #endif |
| 52280 | 52287 | Mem *aMem = p->aMem; /* Copy of p->aMem */ |
| 52281 | 52288 | Mem *pIn1 = 0; /* 1st input operand */ |
| 52282 | 52289 | Mem *pIn2 = 0; /* 2nd input operand */ |
| @@ -55461,11 +55468,11 @@ | ||
| 55461 | 55468 | ** u.az.r.flags = UNPACKED_INCRKEY; |
| 55462 | 55469 | ** }else{ |
| 55463 | 55470 | ** u.az.r.flags = 0; |
| 55464 | 55471 | ** } |
| 55465 | 55472 | */ |
| 55466 | - u.az.r.flags = UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt)); | |
| 55473 | + u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt))); | |
| 55467 | 55474 | assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY ); |
| 55468 | 55475 | assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY ); |
| 55469 | 55476 | assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 ); |
| 55470 | 55477 | assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 ); |
| 55471 | 55478 | |
| @@ -55594,11 +55601,11 @@ | ||
| 55594 | 55601 | if( ALWAYS(u.bb.pC->pCursor!=0) ){ |
| 55595 | 55602 | |
| 55596 | 55603 | assert( u.bb.pC->isTable==0 ); |
| 55597 | 55604 | if( pOp->p4.i>0 ){ |
| 55598 | 55605 | u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo; |
| 55599 | - u.bb.r.nField = pOp->p4.i; | |
| 55606 | + u.bb.r.nField = (u16)pOp->p4.i; | |
| 55600 | 55607 | u.bb.r.aMem = pIn3; |
| 55601 | 55608 | u.bb.r.flags = UNPACKED_PREFIX_MATCH; |
| 55602 | 55609 | u.bb.pIdxKey = &u.bb.r; |
| 55603 | 55610 | }else{ |
| 55604 | 55611 | assert( pIn3->flags & MEM_Blob ); |
| @@ -59309,10 +59316,14 @@ | ||
| 59309 | 59316 | pExpr->affinity = SQLITE_AFF_INTEGER; |
| 59310 | 59317 | }else if( pExpr->iTable==0 ){ |
| 59311 | 59318 | testcase( iCol==31 ); |
| 59312 | 59319 | testcase( iCol==32 ); |
| 59313 | 59320 | pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); |
| 59321 | + }else{ | |
| 59322 | + testcase( iCol==31 ); | |
| 59323 | + testcase( iCol==32 ); | |
| 59324 | + pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); | |
| 59314 | 59325 | } |
| 59315 | 59326 | pExpr->iColumn = (i16)iCol; |
| 59316 | 59327 | pExpr->pTab = pTab; |
| 59317 | 59328 | isTrigger = 1; |
| 59318 | 59329 | } |
| @@ -70890,11 +70901,13 @@ | ||
| 70890 | 70901 | u32 mask; /* Mask of OLD.* columns in use */ |
| 70891 | 70902 | int iCol; /* Iterator used while populating OLD.* */ |
| 70892 | 70903 | |
| 70893 | 70904 | /* TODO: Could use temporary registers here. Also could attempt to |
| 70894 | 70905 | ** avoid copying the contents of the rowid register. */ |
| 70895 | - mask = sqlite3TriggerOldmask(pParse, pTrigger, 0, pTab, onconf); | |
| 70906 | + mask = sqlite3TriggerColmask( | |
| 70907 | + pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf | |
| 70908 | + ); | |
| 70896 | 70909 | mask |= sqlite3FkOldmask(pParse, pTab); |
| 70897 | 70910 | iOld = pParse->nMem+1; |
| 70898 | 70911 | pParse->nMem += (1 + pTab->nCol); |
| 70899 | 70912 | |
| 70900 | 70913 | /* Populate the OLD.* pseudo-table register array. These values will be |
| @@ -84240,11 +84253,12 @@ | ||
| 84240 | 84253 | pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); |
| 84241 | 84254 | if( !pProgram ) return 0; |
| 84242 | 84255 | pProgram->nRef = 1; |
| 84243 | 84256 | pPrg->pTrigger = pTrigger; |
| 84244 | 84257 | pPrg->orconf = orconf; |
| 84245 | - pPrg->oldmask = 0xffffffff; | |
| 84258 | + pPrg->aColmask[0] = 0xffffffff; | |
| 84259 | + pPrg->aColmask[1] = 0xffffffff; | |
| 84246 | 84260 | |
| 84247 | 84261 | /* Allocate and populate a new Parse context to use for coding the |
| 84248 | 84262 | ** trigger sub-program. */ |
| 84249 | 84263 | pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); |
| 84250 | 84264 | if( !pSubParse ) return 0; |
| @@ -84301,11 +84315,12 @@ | ||
| 84301 | 84315 | pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); |
| 84302 | 84316 | } |
| 84303 | 84317 | pProgram->nMem = pSubParse->nMem; |
| 84304 | 84318 | pProgram->nCsr = pSubParse->nTab; |
| 84305 | 84319 | pProgram->token = (void *)pTrigger; |
| 84306 | - pPrg->oldmask = pSubParse->oldmask; | |
| 84320 | + pPrg->aColmask[0] = pSubParse->oldmask; | |
| 84321 | + pPrg->aColmask[1] = pSubParse->newmask; | |
| 84307 | 84322 | sqlite3VdbeDelete(v); |
| 84308 | 84323 | } |
| 84309 | 84324 | |
| 84310 | 84325 | assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); |
| 84311 | 84326 | assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); |
| @@ -84461,45 +84476,56 @@ | ||
| 84461 | 84476 | } |
| 84462 | 84477 | } |
| 84463 | 84478 | } |
| 84464 | 84479 | |
| 84465 | 84480 | /* |
| 84466 | -** Triggers fired by UPDATE or DELETE statements may access values stored | |
| 84467 | -** in the old.* pseudo-table. This function returns a 32-bit bitmask | |
| 84468 | -** indicating which columns of the old.* table actually are used by | |
| 84469 | -** triggers. This information may be used by the caller to avoid having | |
| 84470 | -** to load the entire old.* record into memory when executing an UPDATE | |
| 84471 | -** or DELETE command. | |
| 84481 | +** Triggers may access values stored in the old.* or new.* pseudo-table. | |
| 84482 | +** This function returns a 32-bit bitmask indicating which columns of the | |
| 84483 | +** old.* or new.* tables actually are used by triggers. This information | |
| 84484 | +** may be used by the caller, for example, to avoid having to load the entire | |
| 84485 | +** old.* record into memory when executing an UPDATE or DELETE command. | |
| 84472 | 84486 | ** |
| 84473 | 84487 | ** Bit 0 of the returned mask is set if the left-most column of the |
| 84474 | -** table may be accessed using an old.<col> reference. Bit 1 is set if | |
| 84488 | +** table may be accessed using an [old|new].<col> reference. Bit 1 is set if | |
| 84475 | 84489 | ** the second leftmost column value is required, and so on. If there |
| 84476 | 84490 | ** are more than 32 columns in the table, and at least one of the columns |
| 84477 | 84491 | ** with an index greater than 32 may be accessed, 0xffffffff is returned. |
| 84478 | 84492 | ** |
| 84479 | -** It is not possible to determine if the old.rowid column is accessed | |
| 84480 | -** by triggers. The caller must always assume that it is. | |
| 84493 | +** It is not possible to determine if the old.rowid or new.rowid column is | |
| 84494 | +** accessed by triggers. The caller must always assume that it is. | |
| 84481 | 84495 | ** |
| 84482 | -** There is no equivalent function for new.* references. | |
| 84496 | +** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned | |
| 84497 | +** applies to the old.* table. If 1, the new.* table. | |
| 84498 | +** | |
| 84499 | +** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE | |
| 84500 | +** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only | |
| 84501 | +** included in the returned mask if the TRIGGER_BEFORE bit is set in the | |
| 84502 | +** tr_tm parameter. Similarly, values accessed by AFTER triggers are only | |
| 84503 | +** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. | |
| 84483 | 84504 | */ |
| 84484 | -SQLITE_PRIVATE u32 sqlite3TriggerOldmask( | |
| 84505 | +SQLITE_PRIVATE u32 sqlite3TriggerColmask( | |
| 84485 | 84506 | Parse *pParse, /* Parse context */ |
| 84486 | 84507 | Trigger *pTrigger, /* List of triggers on table pTab */ |
| 84487 | 84508 | ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ |
| 84509 | + int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ | |
| 84510 | + int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ | |
| 84488 | 84511 | Table *pTab, /* The table to code triggers from */ |
| 84489 | 84512 | int orconf /* Default ON CONFLICT policy for trigger steps */ |
| 84490 | 84513 | ){ |
| 84491 | 84514 | const int op = pChanges ? TK_UPDATE : TK_DELETE; |
| 84492 | 84515 | u32 mask = 0; |
| 84493 | 84516 | Trigger *p; |
| 84494 | 84517 | |
| 84518 | + assert( isNew==1 || isNew==0 ); | |
| 84495 | 84519 | for(p=pTrigger; p; p=p->pNext){ |
| 84496 | - if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){ | |
| 84520 | + if( p->op==op && (tr_tm&p->tr_tm) | |
| 84521 | + && checkColumnOverlap(p->pColumns,pChanges) | |
| 84522 | + ){ | |
| 84497 | 84523 | TriggerPrg *pPrg; |
| 84498 | 84524 | pPrg = getRowTrigger(pParse, p, pTab, orconf); |
| 84499 | 84525 | if( pPrg ){ |
| 84500 | - mask |= pPrg->oldmask; | |
| 84526 | + mask |= pPrg->aColmask[isNew]; | |
| 84501 | 84527 | } |
| 84502 | 84528 | } |
| 84503 | 84529 | } |
| 84504 | 84530 | |
| 84505 | 84531 | return mask; |
| @@ -84619,18 +84645,19 @@ | ||
| 84619 | 84645 | Expr *pRowidExpr = 0; /* Expression defining the new record number */ |
| 84620 | 84646 | int openAll = 0; /* True if all indices need to be opened */ |
| 84621 | 84647 | AuthContext sContext; /* The authorization context */ |
| 84622 | 84648 | NameContext sNC; /* The name-context to resolve expressions in */ |
| 84623 | 84649 | int iDb; /* Database containing the table being updated */ |
| 84624 | - int j1; /* Addresses of jump instructions */ | |
| 84625 | 84650 | int okOnePass; /* True for one-pass algorithm without the FIFO */ |
| 84626 | 84651 | int hasFK; /* True if foreign key processing is required */ |
| 84627 | 84652 | |
| 84628 | 84653 | #ifndef SQLITE_OMIT_TRIGGER |
| 84629 | - int isView; /* Trying to update a view */ | |
| 84630 | - Trigger *pTrigger; /* List of triggers on pTab, if required */ | |
| 84654 | + int isView; /* True when updating a view (INSTEAD OF trigger) */ | |
| 84655 | + Trigger *pTrigger; /* List of triggers on pTab, if required */ | |
| 84656 | + int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ | |
| 84631 | 84657 | #endif |
| 84658 | + int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ | |
| 84632 | 84659 | |
| 84633 | 84660 | /* Register Allocations */ |
| 84634 | 84661 | int regRowCount = 0; /* A count of rows changed */ |
| 84635 | 84662 | int regOldRowid; /* The old rowid */ |
| 84636 | 84663 | int regNewRowid; /* The new rowid */ |
| @@ -84654,25 +84681,27 @@ | ||
| 84654 | 84681 | |
| 84655 | 84682 | /* Figure out if we have any triggers and if the table being |
| 84656 | 84683 | ** updated is a view. |
| 84657 | 84684 | */ |
| 84658 | 84685 | #ifndef SQLITE_OMIT_TRIGGER |
| 84659 | - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, 0); | |
| 84686 | + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); | |
| 84660 | 84687 | isView = pTab->pSelect!=0; |
| 84688 | + assert( pTrigger || tmask==0 ); | |
| 84661 | 84689 | #else |
| 84662 | 84690 | # define pTrigger 0 |
| 84663 | 84691 | # define isView 0 |
| 84692 | +# define tmask 0 | |
| 84664 | 84693 | #endif |
| 84665 | 84694 | #ifdef SQLITE_OMIT_VIEW |
| 84666 | 84695 | # undef isView |
| 84667 | 84696 | # define isView 0 |
| 84668 | 84697 | #endif |
| 84669 | 84698 | |
| 84670 | 84699 | if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
| 84671 | 84700 | goto update_cleanup; |
| 84672 | 84701 | } |
| 84673 | - if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ | |
| 84702 | + if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ | |
| 84674 | 84703 | goto update_cleanup; |
| 84675 | 84704 | } |
| 84676 | 84705 | aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); |
| 84677 | 84706 | if( aXRef==0 ) goto update_cleanup; |
| 84678 | 84707 | for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; |
| @@ -84896,11 +84925,13 @@ | ||
| 84896 | 84925 | |
| 84897 | 84926 | /* If there are triggers on this table, populate an array of registers |
| 84898 | 84927 | ** with the required old.* column data. */ |
| 84899 | 84928 | if( hasFK || pTrigger ){ |
| 84900 | 84929 | u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); |
| 84901 | - oldmask |= sqlite3TriggerOldmask(pParse, pTrigger, pChanges, pTab, onError); | |
| 84930 | + oldmask |= sqlite3TriggerColmask(pParse, | |
| 84931 | + pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError | |
| 84932 | + ); | |
| 84902 | 84933 | for(i=0; i<pTab->nCol; i++){ |
| 84903 | 84934 | if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){ |
| 84904 | 84935 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i); |
| 84905 | 84936 | sqlite3ColumnDefault(v, pTab, i, regOld+i); |
| 84906 | 84937 | }else{ |
| @@ -84913,42 +84944,76 @@ | ||
| 84913 | 84944 | } |
| 84914 | 84945 | |
| 84915 | 84946 | /* Populate the array of registers beginning at regNew with the new |
| 84916 | 84947 | ** row data. This array is used to check constaints, create the new |
| 84917 | 84948 | ** table and index records, and as the values for any new.* references |
| 84918 | - ** made by triggers. */ | |
| 84949 | + ** made by triggers. | |
| 84950 | + ** | |
| 84951 | + ** If there are one or more BEFORE triggers, then do not populate the | |
| 84952 | + ** registers associated with columns that are (a) not modified by | |
| 84953 | + ** this UPDATE statement and (b) not accessed by new.* references. The | |
| 84954 | + ** values for registers not modified by the UPDATE must be reloaded from | |
| 84955 | + ** the database after the BEFORE triggers are fired anyway (as the trigger | |
| 84956 | + ** may have modified them). So not loading those that are not going to | |
| 84957 | + ** be used eliminates some redundant opcodes. | |
| 84958 | + */ | |
| 84959 | + newmask = sqlite3TriggerColmask( | |
| 84960 | + pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError | |
| 84961 | + ); | |
| 84919 | 84962 | for(i=0; i<pTab->nCol; i++){ |
| 84920 | 84963 | if( i==pTab->iPKey ){ |
| 84921 | 84964 | sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
| 84922 | 84965 | }else{ |
| 84923 | 84966 | j = aXRef[i]; |
| 84924 | - if( j<0 ){ | |
| 84967 | + if( j>=0 ){ | |
| 84968 | + sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); | |
| 84969 | + }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){ | |
| 84970 | + /* This branch loads the value of a column that will not be changed | |
| 84971 | + ** into a register. This is done if there are no BEFORE triggers, or | |
| 84972 | + ** if there are one or more BEFORE triggers that use this value via | |
| 84973 | + ** a new.* reference in a trigger program. | |
| 84974 | + */ | |
| 84975 | + testcase( i==31 ); | |
| 84976 | + testcase( i==32 ); | |
| 84925 | 84977 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); |
| 84926 | 84978 | sqlite3ColumnDefault(v, pTab, i, regNew+i); |
| 84927 | - }else{ | |
| 84928 | - sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); | |
| 84929 | 84979 | } |
| 84930 | 84980 | } |
| 84931 | 84981 | } |
| 84932 | 84982 | |
| 84933 | 84983 | /* Fire any BEFORE UPDATE triggers. This happens before constraints are |
| 84934 | - ** verified. One could argue that this is wrong. */ | |
| 84935 | - if( pTrigger ){ | |
| 84984 | + ** verified. One could argue that this is wrong. | |
| 84985 | + */ | |
| 84986 | + if( tmask&TRIGGER_BEFORE ){ | |
| 84936 | 84987 | sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); |
| 84937 | 84988 | sqlite3TableAffinityStr(v, pTab); |
| 84938 | 84989 | sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, |
| 84939 | 84990 | TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); |
| 84940 | 84991 | |
| 84941 | 84992 | /* The row-trigger may have deleted the row being updated. In this |
| 84942 | 84993 | ** case, jump to the next row. No updates or AFTER triggers are |
| 84943 | 84994 | ** required. This behaviour - what happens when the row being updated |
| 84944 | 84995 | ** is deleted or renamed by a BEFORE trigger - is left undefined in the |
| 84945 | - ** documentation. */ | |
| 84996 | + ** documentation. | |
| 84997 | + */ | |
| 84946 | 84998 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); |
| 84999 | + | |
| 85000 | + /* If it did not delete it, the row-trigger may still have modified | |
| 85001 | + ** some of the columns of the row being updated. Load the values for | |
| 85002 | + ** all columns not modified by the update statement into their | |
| 85003 | + ** registers in case this has happened. | |
| 85004 | + */ | |
| 85005 | + for(i=0; i<pTab->nCol; i++){ | |
| 85006 | + if( aXRef[i]<0 && i!=pTab->iPKey ){ | |
| 85007 | + sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); | |
| 85008 | + sqlite3ColumnDefault(v, pTab, i, regNew+i); | |
| 85009 | + } | |
| 85010 | + } | |
| 84947 | 85011 | } |
| 84948 | 85012 | |
| 84949 | 85013 | if( !isView ){ |
| 85014 | + int j1; /* Address of jump instruction */ | |
| 84950 | 85015 | |
| 84951 | 85016 | /* Do constraint checks. */ |
| 84952 | 85017 | sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, |
| 84953 | 85018 | aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0); |
| 84954 | 85019 | |
| @@ -90583,11 +90648,11 @@ | ||
| 90583 | 90648 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 90584 | 90649 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 90585 | 90650 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 90586 | 90651 | sqlite3 *db = pParse->db; |
| 90587 | 90652 | if( db->mallocFailed==0 && pY->op==TK_NULL ){ |
| 90588 | - pA->op = op; | |
| 90653 | + pA->op = (u8)op; | |
| 90589 | 90654 | sqlite3ExprDelete(db, pA->pRight); |
| 90590 | 90655 | pA->pRight = 0; |
| 90591 | 90656 | } |
| 90592 | 90657 | } |
| 90593 | 90658 | |
| @@ -97946,11 +98011,558 @@ | ||
| 97946 | 98011 | |
| 97947 | 98012 | #if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) |
| 97948 | 98013 | # define SQLITE_CORE 1 |
| 97949 | 98014 | #endif |
| 97950 | 98015 | |
| 97951 | -#include "fts3Int.h" | |
| 98016 | +/************** Include fts3Int.h in the middle of fts3.c ********************/ | |
| 98017 | +/************** Begin file fts3Int.h *****************************************/ | |
| 98018 | +/* | |
| 98019 | +** 2009 Nov 12 | |
| 98020 | +** | |
| 98021 | +** The author disclaims copyright to this source code. In place of | |
| 98022 | +** a legal notice, here is a blessing: | |
| 98023 | +** | |
| 98024 | +** May you do good and not evil. | |
| 98025 | +** May you find forgiveness for yourself and forgive others. | |
| 98026 | +** May you share freely, never taking more than you give. | |
| 98027 | +** | |
| 98028 | +****************************************************************************** | |
| 98029 | +** | |
| 98030 | +*/ | |
| 98031 | + | |
| 98032 | +#ifndef _FTSINT_H | |
| 98033 | +#define _FTSINT_H | |
| 98034 | + | |
| 98035 | +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) | |
| 98036 | +# define NDEBUG 1 | |
| 98037 | +#endif | |
| 98038 | + | |
| 98039 | +/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ | |
| 98040 | +/************** Begin file fts3_tokenizer.h **********************************/ | |
| 98041 | +/* | |
| 98042 | +** 2006 July 10 | |
| 98043 | +** | |
| 98044 | +** The author disclaims copyright to this source code. | |
| 98045 | +** | |
| 98046 | +************************************************************************* | |
| 98047 | +** Defines the interface to tokenizers used by fulltext-search. There | |
| 98048 | +** are three basic components: | |
| 98049 | +** | |
| 98050 | +** sqlite3_tokenizer_module is a singleton defining the tokenizer | |
| 98051 | +** interface functions. This is essentially the class structure for | |
| 98052 | +** tokenizers. | |
| 98053 | +** | |
| 98054 | +** sqlite3_tokenizer is used to define a particular tokenizer, perhaps | |
| 98055 | +** including customization information defined at creation time. | |
| 98056 | +** | |
| 98057 | +** sqlite3_tokenizer_cursor is generated by a tokenizer to generate | |
| 98058 | +** tokens from a particular input. | |
| 98059 | +*/ | |
| 98060 | +#ifndef _FTS3_TOKENIZER_H_ | |
| 98061 | +#define _FTS3_TOKENIZER_H_ | |
| 98062 | + | |
| 98063 | +/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. | |
| 98064 | +** If tokenizers are to be allowed to call sqlite3_*() functions, then | |
| 98065 | +** we will need a way to register the API consistently. | |
| 98066 | +*/ | |
| 98067 | + | |
| 98068 | +/* | |
| 98069 | +** Structures used by the tokenizer interface. When a new tokenizer | |
| 98070 | +** implementation is registered, the caller provides a pointer to | |
| 98071 | +** an sqlite3_tokenizer_module containing pointers to the callback | |
| 98072 | +** functions that make up an implementation. | |
| 98073 | +** | |
| 98074 | +** When an fts3 table is created, it passes any arguments passed to | |
| 98075 | +** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the | |
| 98076 | +** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer | |
| 98077 | +** implementation. The xCreate() function in turn returns an | |
| 98078 | +** sqlite3_tokenizer structure representing the specific tokenizer to | |
| 98079 | +** be used for the fts3 table (customized by the tokenizer clause arguments). | |
| 98080 | +** | |
| 98081 | +** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() | |
| 98082 | +** method is called. It returns an sqlite3_tokenizer_cursor object | |
| 98083 | +** that may be used to tokenize a specific input buffer based on | |
| 98084 | +** the tokenization rules supplied by a specific sqlite3_tokenizer | |
| 98085 | +** object. | |
| 98086 | +*/ | |
| 98087 | +typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; | |
| 98088 | +typedef struct sqlite3_tokenizer sqlite3_tokenizer; | |
| 98089 | +typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; | |
| 98090 | + | |
| 98091 | +struct sqlite3_tokenizer_module { | |
| 98092 | + | |
| 98093 | + /* | |
| 98094 | + ** Structure version. Should always be set to 0. | |
| 98095 | + */ | |
| 98096 | + int iVersion; | |
| 98097 | + | |
| 98098 | + /* | |
| 98099 | + ** Create a new tokenizer. The values in the argv[] array are the | |
| 98100 | + ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL | |
| 98101 | + ** TABLE statement that created the fts3 table. For example, if | |
| 98102 | + ** the following SQL is executed: | |
| 98103 | + ** | |
| 98104 | + ** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2) | |
| 98105 | + ** | |
| 98106 | + ** then argc is set to 2, and the argv[] array contains pointers | |
| 98107 | + ** to the strings "arg1" and "arg2". | |
| 98108 | + ** | |
| 98109 | + ** This method should return either SQLITE_OK (0), or an SQLite error | |
| 98110 | + ** code. If SQLITE_OK is returned, then *ppTokenizer should be set | |
| 98111 | + ** to point at the newly created tokenizer structure. The generic | |
| 98112 | + ** sqlite3_tokenizer.pModule variable should not be initialised by | |
| 98113 | + ** this callback. The caller will do so. | |
| 98114 | + */ | |
| 98115 | + int (*xCreate)( | |
| 98116 | + int argc, /* Size of argv array */ | |
| 98117 | + const char *const*argv, /* Tokenizer argument strings */ | |
| 98118 | + sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ | |
| 98119 | + ); | |
| 98120 | + | |
| 98121 | + /* | |
| 98122 | + ** Destroy an existing tokenizer. The fts3 module calls this method | |
| 98123 | + ** exactly once for each successful call to xCreate(). | |
| 98124 | + */ | |
| 98125 | + int (*xDestroy)(sqlite3_tokenizer *pTokenizer); | |
| 98126 | + | |
| 98127 | + /* | |
| 98128 | + ** Create a tokenizer cursor to tokenize an input buffer. The caller | |
| 98129 | + ** is responsible for ensuring that the input buffer remains valid | |
| 98130 | + ** until the cursor is closed (using the xClose() method). | |
| 98131 | + */ | |
| 98132 | + int (*xOpen)( | |
| 98133 | + sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ | |
| 98134 | + const char *pInput, int nBytes, /* Input buffer */ | |
| 98135 | + sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ | |
| 98136 | + ); | |
| 98137 | + | |
| 98138 | + /* | |
| 98139 | + ** Destroy an existing tokenizer cursor. The fts3 module calls this | |
| 98140 | + ** method exactly once for each successful call to xOpen(). | |
| 98141 | + */ | |
| 98142 | + int (*xClose)(sqlite3_tokenizer_cursor *pCursor); | |
| 98143 | + | |
| 98144 | + /* | |
| 98145 | + ** Retrieve the next token from the tokenizer cursor pCursor. This | |
| 98146 | + ** method should either return SQLITE_OK and set the values of the | |
| 98147 | + ** "OUT" variables identified below, or SQLITE_DONE to indicate that | |
| 98148 | + ** the end of the buffer has been reached, or an SQLite error code. | |
| 98149 | + ** | |
| 98150 | + ** *ppToken should be set to point at a buffer containing the | |
| 98151 | + ** normalized version of the token (i.e. after any case-folding and/or | |
| 98152 | + ** stemming has been performed). *pnBytes should be set to the length | |
| 98153 | + ** of this buffer in bytes. The input text that generated the token is | |
| 98154 | + ** identified by the byte offsets returned in *piStartOffset and | |
| 98155 | + ** *piEndOffset. *piStartOffset should be set to the index of the first | |
| 98156 | + ** byte of the token in the input buffer. *piEndOffset should be set | |
| 98157 | + ** to the index of the first byte just past the end of the token in | |
| 98158 | + ** the input buffer. | |
| 98159 | + ** | |
| 98160 | + ** The buffer *ppToken is set to point at is managed by the tokenizer | |
| 98161 | + ** implementation. It is only required to be valid until the next call | |
| 98162 | + ** to xNext() or xClose(). | |
| 98163 | + */ | |
| 98164 | + /* TODO(shess) current implementation requires pInput to be | |
| 98165 | + ** nul-terminated. This should either be fixed, or pInput/nBytes | |
| 98166 | + ** should be converted to zInput. | |
| 98167 | + */ | |
| 98168 | + int (*xNext)( | |
| 98169 | + sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ | |
| 98170 | + const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ | |
| 98171 | + int *piStartOffset, /* OUT: Byte offset of token in input buffer */ | |
| 98172 | + int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ | |
| 98173 | + int *piPosition /* OUT: Number of tokens returned before this one */ | |
| 98174 | + ); | |
| 98175 | +}; | |
| 98176 | + | |
| 98177 | +struct sqlite3_tokenizer { | |
| 98178 | + const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ | |
| 98179 | + /* Tokenizer implementations will typically add additional fields */ | |
| 98180 | +}; | |
| 98181 | + | |
| 98182 | +struct sqlite3_tokenizer_cursor { | |
| 98183 | + sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ | |
| 98184 | + /* Tokenizer implementations will typically add additional fields */ | |
| 98185 | +}; | |
| 98186 | + | |
| 98187 | +#endif /* _FTS3_TOKENIZER_H_ */ | |
| 98188 | + | |
| 98189 | +/************** End of fts3_tokenizer.h **************************************/ | |
| 98190 | +/************** Continuing where we left off in fts3Int.h ********************/ | |
| 98191 | +/************** Include fts3_hash.h in the middle of fts3Int.h ***************/ | |
| 98192 | +/************** Begin file fts3_hash.h ***************************************/ | |
| 98193 | +/* | |
| 98194 | +** 2001 September 22 | |
| 98195 | +** | |
| 98196 | +** The author disclaims copyright to this source code. In place of | |
| 98197 | +** a legal notice, here is a blessing: | |
| 98198 | +** | |
| 98199 | +** May you do good and not evil. | |
| 98200 | +** May you find forgiveness for yourself and forgive others. | |
| 98201 | +** May you share freely, never taking more than you give. | |
| 98202 | +** | |
| 98203 | +************************************************************************* | |
| 98204 | +** This is the header file for the generic hash-table implemenation | |
| 98205 | +** used in SQLite. We've modified it slightly to serve as a standalone | |
| 98206 | +** hash table implementation for the full-text indexing module. | |
| 98207 | +** | |
| 98208 | +*/ | |
| 98209 | +#ifndef _FTS3_HASH_H_ | |
| 98210 | +#define _FTS3_HASH_H_ | |
| 98211 | + | |
| 98212 | +/* Forward declarations of structures. */ | |
| 98213 | +typedef struct Fts3Hash Fts3Hash; | |
| 98214 | +typedef struct Fts3HashElem Fts3HashElem; | |
| 98215 | + | |
| 98216 | +/* A complete hash table is an instance of the following structure. | |
| 98217 | +** The internals of this structure are intended to be opaque -- client | |
| 98218 | +** code should not attempt to access or modify the fields of this structure | |
| 98219 | +** directly. Change this structure only by using the routines below. | |
| 98220 | +** However, many of the "procedures" and "functions" for modifying and | |
| 98221 | +** accessing this structure are really macros, so we can't really make | |
| 98222 | +** this structure opaque. | |
| 98223 | +*/ | |
| 98224 | +struct Fts3Hash { | |
| 98225 | + char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ | |
| 98226 | + char copyKey; /* True if copy of key made on insert */ | |
| 98227 | + int count; /* Number of entries in this table */ | |
| 98228 | + Fts3HashElem *first; /* The first element of the array */ | |
| 98229 | + int htsize; /* Number of buckets in the hash table */ | |
| 98230 | + struct _fts3ht { /* the hash table */ | |
| 98231 | + int count; /* Number of entries with this hash */ | |
| 98232 | + Fts3HashElem *chain; /* Pointer to first entry with this hash */ | |
| 98233 | + } *ht; | |
| 98234 | +}; | |
| 98235 | + | |
| 98236 | +/* Each element in the hash table is an instance of the following | |
| 98237 | +** structure. All elements are stored on a single doubly-linked list. | |
| 98238 | +** | |
| 98239 | +** Again, this structure is intended to be opaque, but it can't really | |
| 98240 | +** be opaque because it is used by macros. | |
| 98241 | +*/ | |
| 98242 | +struct Fts3HashElem { | |
| 98243 | + Fts3HashElem *next, *prev; /* Next and previous elements in the table */ | |
| 98244 | + void *data; /* Data associated with this element */ | |
| 98245 | + void *pKey; int nKey; /* Key associated with this element */ | |
| 98246 | +}; | |
| 98247 | + | |
| 98248 | +/* | |
| 98249 | +** There are 2 different modes of operation for a hash table: | |
| 98250 | +** | |
| 98251 | +** FTS3_HASH_STRING pKey points to a string that is nKey bytes long | |
| 98252 | +** (including the null-terminator, if any). Case | |
| 98253 | +** is respected in comparisons. | |
| 98254 | +** | |
| 98255 | +** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. | |
| 98256 | +** memcmp() is used to compare keys. | |
| 98257 | +** | |
| 98258 | +** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. | |
| 98259 | +*/ | |
| 98260 | +#define FTS3_HASH_STRING 1 | |
| 98261 | +#define FTS3_HASH_BINARY 2 | |
| 98262 | + | |
| 98263 | +/* | |
| 98264 | +** Access routines. To delete, insert a NULL pointer. | |
| 98265 | +*/ | |
| 98266 | +SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey); | |
| 98267 | +SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); | |
| 98268 | +SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); | |
| 98269 | +SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*); | |
| 98270 | + | |
| 98271 | +/* | |
| 98272 | +** Shorthand for the functions above | |
| 98273 | +*/ | |
| 98274 | +#define fts3HashInit sqlite3Fts3HashInit | |
| 98275 | +#define fts3HashInsert sqlite3Fts3HashInsert | |
| 98276 | +#define fts3HashFind sqlite3Fts3HashFind | |
| 98277 | +#define fts3HashClear sqlite3Fts3HashClear | |
| 98278 | + | |
| 98279 | +/* | |
| 98280 | +** Macros for looping over all elements of a hash table. The idiom is | |
| 98281 | +** like this: | |
| 98282 | +** | |
| 98283 | +** Fts3Hash h; | |
| 98284 | +** Fts3HashElem *p; | |
| 98285 | +** ... | |
| 98286 | +** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ | |
| 98287 | +** SomeStructure *pData = fts3HashData(p); | |
| 98288 | +** // do something with pData | |
| 98289 | +** } | |
| 98290 | +*/ | |
| 98291 | +#define fts3HashFirst(H) ((H)->first) | |
| 98292 | +#define fts3HashNext(E) ((E)->next) | |
| 98293 | +#define fts3HashData(E) ((E)->data) | |
| 98294 | +#define fts3HashKey(E) ((E)->pKey) | |
| 98295 | +#define fts3HashKeysize(E) ((E)->nKey) | |
| 98296 | + | |
| 98297 | +/* | |
| 98298 | +** Number of entries in a hash table | |
| 98299 | +*/ | |
| 98300 | +#define fts3HashCount(H) ((H)->count) | |
| 98301 | + | |
| 98302 | +#endif /* _FTS3_HASH_H_ */ | |
| 98303 | + | |
| 98304 | +/************** End of fts3_hash.h *******************************************/ | |
| 98305 | +/************** Continuing where we left off in fts3Int.h ********************/ | |
| 98306 | + | |
| 98307 | +/* | |
| 98308 | +** This constant controls how often segments are merged. Once there are | |
| 98309 | +** FTS3_MERGE_COUNT segments of level N, they are merged into a single | |
| 98310 | +** segment of level N+1. | |
| 98311 | +*/ | |
| 98312 | +#define FTS3_MERGE_COUNT 16 | |
| 98313 | + | |
| 98314 | +/* | |
| 98315 | +** This is the maximum amount of data (in bytes) to store in the | |
| 98316 | +** Fts3Table.pendingTerms hash table. Normally, the hash table is | |
| 98317 | +** populated as documents are inserted/updated/deleted in a transaction | |
| 98318 | +** and used to create a new segment when the transaction is committed. | |
| 98319 | +** However if this limit is reached midway through a transaction, a new | |
| 98320 | +** segment is created and the hash table cleared immediately. | |
| 98321 | +*/ | |
| 98322 | +#define FTS3_MAX_PENDING_DATA (1*1024*1024) | |
| 98323 | + | |
| 98324 | +/* | |
| 98325 | +** Macro to return the number of elements in an array. SQLite has a | |
| 98326 | +** similar macro called ArraySize(). Use a different name to avoid | |
| 98327 | +** a collision when building an amalgamation with built-in FTS3. | |
| 98328 | +*/ | |
| 98329 | +#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0]))) | |
| 98330 | + | |
| 98331 | +/* | |
| 98332 | +** Maximum length of a varint encoded integer. The varint format is different | |
| 98333 | +** from that used by SQLite, so the maximum length is 10, not 9. | |
| 98334 | +*/ | |
| 98335 | +#define FTS3_VARINT_MAX 10 | |
| 98336 | + | |
| 98337 | +/* | |
| 98338 | +** This section provides definitions to allow the | |
| 98339 | +** FTS3 extension to be compiled outside of the | |
| 98340 | +** amalgamation. | |
| 98341 | +*/ | |
| 98342 | +#ifndef SQLITE_AMALGAMATION | |
| 98343 | +/* | |
| 98344 | +** Macros indicating that conditional expressions are always true or | |
| 98345 | +** false. | |
| 98346 | +*/ | |
| 98347 | +# define ALWAYS(x) (x) | |
| 98348 | +# define NEVER(X) (x) | |
| 98349 | +/* | |
| 98350 | +** Internal types used by SQLite. | |
| 98351 | +*/ | |
| 98352 | +typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ | |
| 98353 | +typedef short int i16; /* 2-byte (or larger) signed integer */ | |
| 98354 | +/* | |
| 98355 | +** Macro used to suppress compiler warnings for unused parameters. | |
| 98356 | +*/ | |
| 98357 | +#define UNUSED_PARAMETER(x) (void)(x) | |
| 98358 | +#endif | |
| 98359 | + | |
| 98360 | +typedef struct Fts3Table Fts3Table; | |
| 98361 | +typedef struct Fts3Cursor Fts3Cursor; | |
| 98362 | +typedef struct Fts3Expr Fts3Expr; | |
| 98363 | +typedef struct Fts3Phrase Fts3Phrase; | |
| 98364 | +typedef struct Fts3SegReader Fts3SegReader; | |
| 98365 | +typedef struct Fts3SegFilter Fts3SegFilter; | |
| 98366 | + | |
| 98367 | +/* | |
| 98368 | +** A connection to a fulltext index is an instance of the following | |
| 98369 | +** structure. The xCreate and xConnect methods create an instance | |
| 98370 | +** of this structure and xDestroy and xDisconnect free that instance. | |
| 98371 | +** All other methods receive a pointer to the structure as one of their | |
| 98372 | +** arguments. | |
| 98373 | +*/ | |
| 98374 | +struct Fts3Table { | |
| 98375 | + sqlite3_vtab base; /* Base class used by SQLite core */ | |
| 98376 | + sqlite3 *db; /* The database connection */ | |
| 98377 | + const char *zDb; /* logical database name */ | |
| 98378 | + const char *zName; /* virtual table name */ | |
| 98379 | + int nColumn; /* number of named columns in virtual table */ | |
| 98380 | + char **azColumn; /* column names. malloced */ | |
| 98381 | + sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ | |
| 98382 | + | |
| 98383 | + /* Precompiled statements used by the implementation. Each of these | |
| 98384 | + ** statements is run and reset within a single virtual table API call. | |
| 98385 | + */ | |
| 98386 | + sqlite3_stmt *aStmt[18]; | |
| 98387 | + | |
| 98388 | + /* Pointer to string containing the SQL: | |
| 98389 | + ** | |
| 98390 | + ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? | |
| 98391 | + ** ORDER BY blockid" | |
| 98392 | + */ | |
| 98393 | + char *zSelectLeaves; | |
| 98394 | + int nLeavesStmt; /* Valid statements in aLeavesStmt */ | |
| 98395 | + int nLeavesTotal; /* Total number of prepared leaves stmts */ | |
| 98396 | + int nLeavesAlloc; /* Allocated size of aLeavesStmt */ | |
| 98397 | + sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ | |
| 98398 | + | |
| 98399 | + int nNodeSize; /* Soft limit for node size */ | |
| 98400 | + | |
| 98401 | + /* The following hash table is used to buffer pending index updates during | |
| 98402 | + ** transactions. Variable nPendingData estimates the memory size of the | |
| 98403 | + ** pending data, including hash table overhead, but not malloc overhead. | |
| 98404 | + ** When nPendingData exceeds FTS3_MAX_PENDING_DATA, the buffer is flushed | |
| 98405 | + ** automatically. Variable iPrevDocid is the docid of the most recently | |
| 98406 | + ** inserted record. | |
| 98407 | + */ | |
| 98408 | + int nPendingData; | |
| 98409 | + sqlite_int64 iPrevDocid; | |
| 98410 | + Fts3Hash pendingTerms; | |
| 98411 | +}; | |
| 98412 | + | |
| 98413 | +/* | |
| 98414 | +** When the core wants to read from the virtual table, it creates a | |
| 98415 | +** virtual table cursor (an instance of the following structure) using | |
| 98416 | +** the xOpen method. Cursors are destroyed using the xClose method. | |
| 98417 | +*/ | |
| 98418 | +struct Fts3Cursor { | |
| 98419 | + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ | |
| 98420 | + i16 eSearch; /* Search strategy (see below) */ | |
| 98421 | + u8 isEof; /* True if at End Of Results */ | |
| 98422 | + u8 isRequireSeek; /* True if must seek pStmt to %_content row */ | |
| 98423 | + sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ | |
| 98424 | + Fts3Expr *pExpr; /* Parsed MATCH query string */ | |
| 98425 | + sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ | |
| 98426 | + char *pNextId; /* Pointer into the body of aDoclist */ | |
| 98427 | + char *aDoclist; /* List of docids for full-text queries */ | |
| 98428 | + int nDoclist; /* Size of buffer at aDoclist */ | |
| 98429 | +}; | |
| 98430 | + | |
| 98431 | +/* | |
| 98432 | +** The Fts3Cursor.eSearch member is always set to one of the following. | |
| 98433 | +** Actualy, Fts3Cursor.eSearch can be greater than or equal to | |
| 98434 | +** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index | |
| 98435 | +** of the column to be searched. For example, in | |
| 98436 | +** | |
| 98437 | +** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d); | |
| 98438 | +** SELECT docid FROM ex1 WHERE b MATCH 'one two three'; | |
| 98439 | +** | |
| 98440 | +** Because the LHS of the MATCH operator is 2nd column "b", | |
| 98441 | +** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a, | |
| 98442 | +** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" | |
| 98443 | +** indicating that all columns should be searched, | |
| 98444 | +** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. | |
| 98445 | +*/ | |
| 98446 | +#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ | |
| 98447 | +#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ | |
| 98448 | +#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ | |
| 98449 | + | |
| 98450 | +/* | |
| 98451 | +** A "phrase" is a sequence of one or more tokens that must match in | |
| 98452 | +** sequence. A single token is the base case and the most common case. | |
| 98453 | +** For a sequence of tokens contained in "...", nToken will be the number | |
| 98454 | +** of tokens in the string. | |
| 98455 | +*/ | |
| 98456 | +struct Fts3Phrase { | |
| 98457 | + int nToken; /* Number of tokens in the phrase */ | |
| 98458 | + int iColumn; /* Index of column this phrase must match */ | |
| 98459 | + int isNot; /* Phrase prefixed by unary not (-) operator */ | |
| 98460 | + struct PhraseToken { | |
| 98461 | + char *z; /* Text of the token */ | |
| 98462 | + int n; /* Number of bytes in buffer pointed to by z */ | |
| 98463 | + int isPrefix; /* True if token ends in with a "*" character */ | |
| 98464 | + } aToken[1]; /* One entry for each token in the phrase */ | |
| 98465 | +}; | |
| 98466 | + | |
| 98467 | +/* | |
| 98468 | +** A tree of these objects forms the RHS of a MATCH operator. | |
| 98469 | +*/ | |
| 98470 | +struct Fts3Expr { | |
| 98471 | + int eType; /* One of the FTSQUERY_XXX values defined below */ | |
| 98472 | + int nNear; /* Valid if eType==FTSQUERY_NEAR */ | |
| 98473 | + Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */ | |
| 98474 | + Fts3Expr *pLeft; /* Left operand */ | |
| 98475 | + Fts3Expr *pRight; /* Right operand */ | |
| 98476 | + Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */ | |
| 98477 | +}; | |
| 98478 | + | |
| 98479 | +/* | |
| 98480 | +** Candidate values for Fts3Query.eType. Note that the order of the first | |
| 98481 | +** four values is in order of precedence when parsing expressions. For | |
| 98482 | +** example, the following: | |
| 98483 | +** | |
| 98484 | +** "a OR b AND c NOT d NEAR e" | |
| 98485 | +** | |
| 98486 | +** is equivalent to: | |
| 98487 | +** | |
| 98488 | +** "a OR (b AND (c NOT (d NEAR e)))" | |
| 98489 | +*/ | |
| 98490 | +#define FTSQUERY_NEAR 1 | |
| 98491 | +#define FTSQUERY_NOT 2 | |
| 98492 | +#define FTSQUERY_AND 3 | |
| 98493 | +#define FTSQUERY_OR 4 | |
| 98494 | +#define FTSQUERY_PHRASE 5 | |
| 98495 | + | |
| 98496 | + | |
| 98497 | +/* fts3_init.c */ | |
| 98498 | +SQLITE_PRIVATE int sqlite3Fts3DeleteVtab(int, sqlite3_vtab *); | |
| 98499 | +SQLITE_PRIVATE int sqlite3Fts3InitVtab(int, sqlite3*, void*, int, const char*const*, | |
| 98500 | + sqlite3_vtab **, char **); | |
| 98501 | + | |
| 98502 | +/* fts3_write.c */ | |
| 98503 | +SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); | |
| 98504 | +SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); | |
| 98505 | +SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); | |
| 98506 | +SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); | |
| 98507 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64, | |
| 98508 | + sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); | |
| 98509 | +SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); | |
| 98510 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( | |
| 98511 | + Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, | |
| 98512 | + int (*)(Fts3Table *, void *, char *, int, char *, int), void * | |
| 98513 | +); | |
| 98514 | +SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); | |
| 98515 | +SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); | |
| 98516 | + | |
| 98517 | +/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ | |
| 98518 | +#define FTS3_SEGMENT_REQUIRE_POS 0x00000001 | |
| 98519 | +#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 | |
| 98520 | +#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 | |
| 98521 | +#define FTS3_SEGMENT_PREFIX 0x00000008 | |
| 98522 | + | |
| 98523 | +/* Type passed as 4th argument to SegmentReaderIterate() */ | |
| 98524 | +struct Fts3SegFilter { | |
| 98525 | + const char *zTerm; | |
| 98526 | + int nTerm; | |
| 98527 | + int iCol; | |
| 98528 | + int flags; | |
| 98529 | +}; | |
| 98530 | + | |
| 98531 | +/* fts3.c */ | |
| 98532 | +SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); | |
| 98533 | +SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); | |
| 98534 | +SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); | |
| 98535 | +SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); | |
| 98536 | +SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); | |
| 98537 | + | |
| 98538 | +/* fts3_tokenizer.c */ | |
| 98539 | +SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); | |
| 98540 | +SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); | |
| 98541 | +SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, | |
| 98542 | + const char *, sqlite3_tokenizer **, const char **, char ** | |
| 98543 | +); | |
| 98544 | + | |
| 98545 | +/* fts3_snippet.c */ | |
| 98546 | +SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); | |
| 98547 | +SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*, | |
| 98548 | + const char *, const char *, const char * | |
| 98549 | +); | |
| 98550 | + | |
| 98551 | +/* fts3_expr.c */ | |
| 98552 | +SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, | |
| 98553 | + char **, int, int, const char *, int, Fts3Expr ** | |
| 98554 | +); | |
| 98555 | +SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); | |
| 98556 | +#ifdef SQLITE_TEST | |
| 98557 | +SQLITE_PRIVATE void sqlite3Fts3ExprInitTestInterface(sqlite3 *db); | |
| 98558 | +#endif | |
| 98559 | + | |
| 98560 | +#endif /* _FTSINT_H */ | |
| 98561 | + | |
| 98562 | +/************** End of fts3Int.h *********************************************/ | |
| 98563 | +/************** Continuing where we left off in fts3.c ***********************/ | |
| 97952 | 98564 | |
| 97953 | 98565 | |
| 97954 | 98566 | #ifndef SQLITE_CORE |
| 97955 | 98567 | SQLITE_EXTENSION_INIT1 |
| 97956 | 98568 | #endif |
| @@ -98108,11 +98720,11 @@ | ||
| 98108 | 98720 | default: return; |
| 98109 | 98721 | } |
| 98110 | 98722 | for(i=1, j=0; z[i]; i++){ |
| 98111 | 98723 | if( z[i]==quote ){ |
| 98112 | 98724 | if( z[i+1]==quote ){ |
| 98113 | - z[j++] = quote; | |
| 98725 | + z[j++] = (char)quote; | |
| 98114 | 98726 | i++; |
| 98115 | 98727 | }else{ |
| 98116 | 98728 | z[j++] = 0; |
| 98117 | 98729 | break; |
| 98118 | 98730 | } |
| @@ -98134,22 +98746,10 @@ | ||
| 98134 | 98746 | }else{ |
| 98135 | 98747 | fts3GetDeltaVarint(pp, pVal); |
| 98136 | 98748 | } |
| 98137 | 98749 | } |
| 98138 | 98750 | |
| 98139 | - | |
| 98140 | -/* | |
| 98141 | -** The Fts3Cursor.eType member is always set to one of the following. | |
| 98142 | -*/ | |
| 98143 | -#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ | |
| 98144 | -#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ | |
| 98145 | -#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ | |
| 98146 | - | |
| 98147 | -static Fts3Table *cursor_vtab(Fts3Cursor *c){ | |
| 98148 | - return (Fts3Table *) c->base.pVtab; | |
| 98149 | -} | |
| 98150 | - | |
| 98151 | 98751 | /* |
| 98152 | 98752 | ** The xDisconnect() virtual table method. |
| 98153 | 98753 | */ |
| 98154 | 98754 | static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ |
| 98155 | 98755 | Fts3Table *p = (Fts3Table *)pVtab; |
| @@ -98295,11 +98895,11 @@ | ||
| 98295 | 98895 | ** The argv[] array contains the following: |
| 98296 | 98896 | ** |
| 98297 | 98897 | ** argv[0] -> module name |
| 98298 | 98898 | ** argv[1] -> database name |
| 98299 | 98899 | ** argv[2] -> table name |
| 98300 | -** argv[...] -> "column name" fields... | |
| 98900 | +** argv[...] -> "column name" and other module argument fields. | |
| 98301 | 98901 | */ |
| 98302 | 98902 | int fts3InitVtab( |
| 98303 | 98903 | int isCreate, /* True for xCreate, false for xConnect */ |
| 98304 | 98904 | sqlite3 *db, /* The SQLite database connection */ |
| 98305 | 98905 | void *pAux, /* Hash table containing tokenizers */ |
| @@ -98307,34 +98907,42 @@ | ||
| 98307 | 98907 | const char * const *argv, /* xCreate/xConnect argument array */ |
| 98308 | 98908 | sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ |
| 98309 | 98909 | char **pzErr /* Write any error message here */ |
| 98310 | 98910 | ){ |
| 98311 | 98911 | Fts3Hash *pHash = (Fts3Hash *)pAux; |
| 98312 | - Fts3Table *p; /* Pointer to allocated vtab */ | |
| 98912 | + Fts3Table *p; /* Pointer to allocated vtab */ | |
| 98313 | 98913 | int rc; /* Return code */ |
| 98314 | - int i; | |
| 98315 | - int nByte; | |
| 98914 | + int i; /* Iterator variable */ | |
| 98915 | + int nByte; /* Size of allocation used for *p */ | |
| 98316 | 98916 | int iCol; |
| 98317 | 98917 | int nString = 0; |
| 98318 | 98918 | int nCol = 0; |
| 98319 | 98919 | char *zCsr; |
| 98320 | 98920 | int nDb; |
| 98321 | 98921 | int nName; |
| 98322 | 98922 | |
| 98323 | - const char *zTokenizer = 0; | |
| 98324 | - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this table */ | |
| 98923 | +#ifdef SQLITE_TEST | |
| 98924 | + char *zTestParam = 0; | |
| 98925 | + if( strncmp(argv[argc-1], "test:", 5)==0 ){ | |
| 98926 | + zTestParam = argv[argc-1]; | |
| 98927 | + argc--; | |
| 98928 | + } | |
| 98929 | +#endif | |
| 98325 | 98930 | |
| 98326 | - nDb = strlen(argv[1]) + 1; | |
| 98327 | - nName = strlen(argv[2]) + 1; | |
| 98931 | + const char *zTokenizer = 0; /* Name of tokenizer to use */ | |
| 98932 | + sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ | |
| 98933 | + | |
| 98934 | + nDb = (int)strlen(argv[1]) + 1; | |
| 98935 | + nName = (int)strlen(argv[2]) + 1; | |
| 98328 | 98936 | for(i=3; i<argc; i++){ |
| 98329 | 98937 | char const *z = argv[i]; |
| 98330 | 98938 | rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr); |
| 98331 | 98939 | if( rc!=SQLITE_OK ){ |
| 98332 | 98940 | return rc; |
| 98333 | 98941 | } |
| 98334 | 98942 | if( z!=zTokenizer ){ |
| 98335 | - nString += strlen(z) + 1; | |
| 98943 | + nString += (int)(strlen(z) + 1); | |
| 98336 | 98944 | } |
| 98337 | 98945 | } |
| 98338 | 98946 | nCol = argc - 3 - (zTokenizer!=0); |
| 98339 | 98947 | if( zTokenizer==0 ){ |
| 98340 | 98948 | rc = sqlite3Fts3InitTokenizer(pHash, 0, &pTokenizer, 0, pzErr); |
| @@ -98341,10 +98949,14 @@ | ||
| 98341 | 98949 | if( rc!=SQLITE_OK ){ |
| 98342 | 98950 | return rc; |
| 98343 | 98951 | } |
| 98344 | 98952 | assert( pTokenizer ); |
| 98345 | 98953 | } |
| 98954 | + | |
| 98955 | + if( nCol==0 ){ | |
| 98956 | + nCol = 1; | |
| 98957 | + } | |
| 98346 | 98958 | |
| 98347 | 98959 | /* Allocate and populate the Fts3Table structure. */ |
| 98348 | 98960 | nByte = sizeof(Fts3Table) + /* Fts3Table */ |
| 98349 | 98961 | nCol * sizeof(char *) + /* azColumn */ |
| 98350 | 98962 | nName + /* zName */ |
| @@ -98360,10 +98972,11 @@ | ||
| 98360 | 98972 | p->db = db; |
| 98361 | 98973 | p->nColumn = nCol; |
| 98362 | 98974 | p->nPendingData = 0; |
| 98363 | 98975 | p->azColumn = (char **)&p[1]; |
| 98364 | 98976 | p->pTokenizer = pTokenizer; |
| 98977 | + p->nNodeSize = 1000; | |
| 98365 | 98978 | zCsr = (char *)&p->azColumn[nCol]; |
| 98366 | 98979 | |
| 98367 | 98980 | fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1); |
| 98368 | 98981 | |
| 98369 | 98982 | /* Fill in the zName and zDb fields of the vtab structure. */ |
| @@ -98387,10 +99000,14 @@ | ||
| 98387 | 99000 | p->azColumn[iCol++] = zCsr; |
| 98388 | 99001 | zCsr += n+1; |
| 98389 | 99002 | assert( zCsr <= &((char *)p)[nByte] ); |
| 98390 | 99003 | } |
| 98391 | 99004 | } |
| 99005 | + if( iCol==0 ){ | |
| 99006 | + assert( nCol==1 ); | |
| 99007 | + p->azColumn[0] = "content"; | |
| 99008 | + } | |
| 98392 | 99009 | |
| 98393 | 99010 | /* If this is an xCreate call, create the underlying tables in the |
| 98394 | 99011 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 98395 | 99012 | */ |
| 98396 | 99013 | if( isCreate ){ |
| @@ -98399,16 +99016,25 @@ | ||
| 98399 | 99016 | } |
| 98400 | 99017 | |
| 98401 | 99018 | rc = fts3DeclareVtab(p); |
| 98402 | 99019 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 98403 | 99020 | |
| 99021 | +#ifdef SQLITE_TEST | |
| 99022 | + if( zTestParam ){ | |
| 99023 | + p->nNodeSize = atoi(&zTestParam[5]); | |
| 99024 | + } | |
| 99025 | +#endif | |
| 98404 | 99026 | *ppVTab = &p->base; |
| 98405 | 99027 | |
| 98406 | 99028 | fts3_init_out: |
| 99029 | + assert( p || (pTokenizer && rc!=SQLITE_OK) ); | |
| 98407 | 99030 | if( rc!=SQLITE_OK ){ |
| 98408 | - if( p ) fts3DisconnectMethod((sqlite3_vtab *)p); | |
| 98409 | - else if( pTokenizer ) pTokenizer->pModule->xDestroy(pTokenizer); | |
| 99031 | + if( p ){ | |
| 99032 | + fts3DisconnectMethod((sqlite3_vtab *)p); | |
| 99033 | + }else{ | |
| 99034 | + pTokenizer->pModule->xDestroy(pTokenizer); | |
| 99035 | + } | |
| 98410 | 99036 | } |
| 98411 | 99037 | return rc; |
| 98412 | 99038 | } |
| 98413 | 99039 | |
| 98414 | 99040 | /* |
| @@ -98497,10 +99123,12 @@ | ||
| 98497 | 99123 | /* |
| 98498 | 99124 | ** Implementation of xOpen method. |
| 98499 | 99125 | */ |
| 98500 | 99126 | static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ |
| 98501 | 99127 | sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ |
| 99128 | + | |
| 99129 | + UNUSED_PARAMETER(pVTab); | |
| 98502 | 99130 | |
| 98503 | 99131 | /* Allocate a buffer large enough for an Fts3Cursor structure. If the |
| 98504 | 99132 | ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, |
| 98505 | 99133 | ** if the allocation fails, return SQLITE_NOMEM. |
| 98506 | 99134 | */ |
| @@ -98664,16 +99292,20 @@ | ||
| 98664 | 99292 | } |
| 98665 | 99293 | sqlite3_free(zBuffer); |
| 98666 | 99294 | return rc; |
| 98667 | 99295 | } |
| 98668 | 99296 | |
| 99297 | +/* | |
| 99298 | +** This function is used to create delta-encoded serialized lists of FTS3 | |
| 99299 | +** varints. Each call to this function appends a single varint to a list. | |
| 99300 | +*/ | |
| 98669 | 99301 | static void fts3PutDeltaVarint( |
| 98670 | - char **pp, | |
| 98671 | - sqlite3_int64 *piPrev, | |
| 98672 | - sqlite3_int64 iVal | |
| 99302 | + char **pp, /* IN/OUT: Output pointer */ | |
| 99303 | + sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ | |
| 99304 | + sqlite3_int64 iVal /* Write this value to the list */ | |
| 98673 | 99305 | ){ |
| 98674 | - assert( iVal-*piPrev > 0 ); | |
| 99306 | + assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); | |
| 98675 | 99307 | *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); |
| 98676 | 99308 | *piPrev = iVal; |
| 98677 | 99309 | } |
| 98678 | 99310 | |
| 98679 | 99311 | static void fts3PoslistCopy(char **pp, char **ppPoslist){ |
| @@ -98680,11 +99312,11 @@ | ||
| 98680 | 99312 | char *pEnd = *ppPoslist; |
| 98681 | 99313 | char c = 0; |
| 98682 | 99314 | while( *pEnd | c ) c = *pEnd++ & 0x80; |
| 98683 | 99315 | pEnd++; |
| 98684 | 99316 | if( pp ){ |
| 98685 | - int n = pEnd - *ppPoslist; | |
| 99317 | + int n = (int)(pEnd - *ppPoslist); | |
| 98686 | 99318 | char *p = *pp; |
| 98687 | 99319 | memcpy(p, *ppPoslist, n); |
| 98688 | 99320 | p += n; |
| 98689 | 99321 | *pp = p; |
| 98690 | 99322 | } |
| @@ -98694,11 +99326,11 @@ | ||
| 98694 | 99326 | static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ |
| 98695 | 99327 | char *pEnd = *ppPoslist; |
| 98696 | 99328 | char c = 0; |
| 98697 | 99329 | while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; |
| 98698 | 99330 | if( pp ){ |
| 98699 | - int n = pEnd - *ppPoslist; | |
| 99331 | + int n = (int)(pEnd - *ppPoslist); | |
| 98700 | 99332 | char *p = *pp; |
| 98701 | 99333 | memcpy(p, *ppPoslist, n); |
| 98702 | 99334 | p += n; |
| 98703 | 99335 | *pp = p; |
| 98704 | 99336 | } |
| @@ -99081,11 +99713,11 @@ | ||
| 99081 | 99713 | |
| 99082 | 99714 | default: |
| 99083 | 99715 | assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); |
| 99084 | 99716 | } |
| 99085 | 99717 | |
| 99086 | - *pnBuffer = (p-aBuffer); | |
| 99718 | + *pnBuffer = (int)(p-aBuffer); | |
| 99087 | 99719 | return SQLITE_OK; |
| 99088 | 99720 | } |
| 99089 | 99721 | |
| 99090 | 99722 | /* |
| 99091 | 99723 | ** A pointer to an instance of this structure is used as the context |
| @@ -99113,10 +99745,14 @@ | ||
| 99113 | 99745 | ){ |
| 99114 | 99746 | TermSelect *pTS = (TermSelect *)pContext; |
| 99115 | 99747 | int nNew = pTS->nOutput + nDoclist; |
| 99116 | 99748 | char *aNew = sqlite3_malloc(nNew); |
| 99117 | 99749 | |
| 99750 | + UNUSED_PARAMETER(p); | |
| 99751 | + UNUSED_PARAMETER(zTerm); | |
| 99752 | + UNUSED_PARAMETER(nTerm); | |
| 99753 | + | |
| 99118 | 99754 | if( !aNew ){ |
| 99119 | 99755 | return SQLITE_NOMEM; |
| 99120 | 99756 | } |
| 99121 | 99757 | |
| 99122 | 99758 | if( pTS->nOutput==0 ){ |
| @@ -99194,25 +99830,38 @@ | ||
| 99194 | 99830 | ** leaf). Do not bother inspecting any data in this case, just |
| 99195 | 99831 | ** create a Fts3SegReader to scan the single leaf. |
| 99196 | 99832 | */ |
| 99197 | 99833 | rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew); |
| 99198 | 99834 | }else{ |
| 99199 | - sqlite3_int64 i1; | |
| 99835 | + int rc2; /* Return value of sqlite3Fts3ReadBlock() */ | |
| 99836 | + sqlite3_int64 i1; /* Blockid of leaf that may contain zTerm */ | |
| 99200 | 99837 | rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1); |
| 99201 | 99838 | if( rc==SQLITE_OK ){ |
| 99202 | 99839 | sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2); |
| 99203 | 99840 | rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew); |
| 99204 | 99841 | } |
| 99842 | + | |
| 99843 | + /* The following call to ReadBlock() serves to reset the SQL statement | |
| 99844 | + ** used to retrieve blocks of data from the %_segments table. If it is | |
| 99845 | + ** not reset here, then it may remain classified as an active statement | |
| 99846 | + ** by SQLite, which may lead to "DROP TABLE" or "DETACH" commands | |
| 99847 | + ** failing. | |
| 99848 | + */ | |
| 99849 | + rc2 = sqlite3Fts3ReadBlock(p, 0, 0, 0); | |
| 99850 | + if( rc==SQLITE_OK ){ | |
| 99851 | + rc = rc2; | |
| 99852 | + } | |
| 99205 | 99853 | } |
| 99206 | 99854 | iAge++; |
| 99207 | 99855 | |
| 99208 | 99856 | /* If a new Fts3SegReader was allocated, add it to the apSegment array. */ |
| 99209 | - assert( (rc==SQLITE_OK)==(pNew!=0) ); | |
| 99857 | + assert( pNew!=0 || rc!=SQLITE_OK ); | |
| 99210 | 99858 | if( pNew ){ |
| 99211 | 99859 | if( nSegment==nAlloc ){ |
| 99860 | + Fts3SegReader **pArray; | |
| 99212 | 99861 | nAlloc += 16; |
| 99213 | - Fts3SegReader **pArray = (Fts3SegReader **)sqlite3_realloc( | |
| 99862 | + pArray = (Fts3SegReader **)sqlite3_realloc( | |
| 99214 | 99863 | apSegment, nAlloc*sizeof(Fts3SegReader *) |
| 99215 | 99864 | ); |
| 99216 | 99865 | if( !pArray ){ |
| 99217 | 99866 | sqlite3Fts3SegReaderFree(p, pNew); |
| 99218 | 99867 | rc = SQLITE_NOMEM; |
| @@ -99348,10 +99997,13 @@ | ||
| 99348 | 99997 | int nRight; |
| 99349 | 99998 | |
| 99350 | 99999 | if( SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pRight, &aRight, &nRight)) |
| 99351 | 100000 | && SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pLeft, &aLeft, &nLeft)) |
| 99352 | 100001 | ){ |
| 100002 | + assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR | |
| 100003 | + || pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT | |
| 100004 | + ); | |
| 99353 | 100005 | switch( pExpr->eType ){ |
| 99354 | 100006 | case FTSQUERY_NEAR: { |
| 99355 | 100007 | Fts3Expr *pLeft; |
| 99356 | 100008 | Fts3Expr *pRight; |
| 99357 | 100009 | int mergetype = MERGE_NEAR; |
| @@ -99398,12 +100050,11 @@ | ||
| 99398 | 100050 | *paOut = aBuffer; |
| 99399 | 100051 | sqlite3_free(aLeft); |
| 99400 | 100052 | break; |
| 99401 | 100053 | } |
| 99402 | 100054 | |
| 99403 | - case FTSQUERY_AND: | |
| 99404 | - case FTSQUERY_NOT: { | |
| 100055 | + default: { | |
| 99405 | 100056 | assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND ); |
| 99406 | 100057 | fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut, |
| 99407 | 100058 | aLeft, nLeft, aRight, nRight |
| 99408 | 100059 | ); |
| 99409 | 100060 | *paOut = aLeft; |
| @@ -99452,10 +100103,13 @@ | ||
| 99452 | 100103 | }; |
| 99453 | 100104 | int rc; /* Return code */ |
| 99454 | 100105 | char *zSql; /* SQL statement used to access %_content */ |
| 99455 | 100106 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 99456 | 100107 | Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
| 100108 | + | |
| 100109 | + UNUSED_PARAMETER(idxStr); | |
| 100110 | + UNUSED_PARAMETER(nVal); | |
| 99457 | 100111 | |
| 99458 | 100112 | assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
| 99459 | 100113 | assert( nVal==0 || nVal==1 ); |
| 99460 | 100114 | assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); |
| 99461 | 100115 | |
| @@ -99475,18 +100129,21 @@ | ||
| 99475 | 100129 | }else{ |
| 99476 | 100130 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
| 99477 | 100131 | sqlite3_free(zSql); |
| 99478 | 100132 | } |
| 99479 | 100133 | if( rc!=SQLITE_OK ) return rc; |
| 99480 | - pCsr->eType = idxNum; | |
| 100134 | + pCsr->eSearch = (i16)idxNum; | |
| 99481 | 100135 | |
| 99482 | 100136 | if( idxNum==FTS3_DOCID_SEARCH ){ |
| 99483 | 100137 | rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); |
| 99484 | 100138 | }else if( idxNum!=FTS3_FULLSCAN_SEARCH ){ |
| 99485 | 100139 | int iCol = idxNum-FTS3_FULLTEXT_SEARCH; |
| 99486 | 100140 | const char *zQuery = (const char *)sqlite3_value_text(apVal[0]); |
| 99487 | 100141 | |
| 100142 | + if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ | |
| 100143 | + return SQLITE_NOMEM; | |
| 100144 | + } | |
| 99488 | 100145 | rc = sqlite3Fts3PendingTermsFlush(p); |
| 99489 | 100146 | if( rc!=SQLITE_OK ) return rc; |
| 99490 | 100147 | |
| 99491 | 100148 | rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn, |
| 99492 | 100149 | iCol, zQuery, -1, &pCsr->pExpr |
| @@ -99508,42 +100165,10 @@ | ||
| 99508 | 100165 | */ |
| 99509 | 100166 | static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ |
| 99510 | 100167 | return ((Fts3Cursor *)pCursor)->isEof; |
| 99511 | 100168 | } |
| 99512 | 100169 | |
| 99513 | -/* | |
| 99514 | -** This is the xColumn method of the virtual table. The SQLite | |
| 99515 | -** core calls this method during a query when it needs the value | |
| 99516 | -** of a column from the virtual table. This method needs to use | |
| 99517 | -** one of the sqlite3_result_*() routines to store the requested | |
| 99518 | -** value back in the pContext. | |
| 99519 | -*/ | |
| 99520 | -static int fts3ColumnMethod(sqlite3_vtab_cursor *pCursor, | |
| 99521 | - sqlite3_context *pContext, int idxCol){ | |
| 99522 | - Fts3Cursor *c = (Fts3Cursor *) pCursor; | |
| 99523 | - Fts3Table *v = cursor_vtab(c); | |
| 99524 | - int rc = fts3CursorSeek(c); | |
| 99525 | - if( rc!=SQLITE_OK ){ | |
| 99526 | - return rc; | |
| 99527 | - } | |
| 99528 | - | |
| 99529 | - if( idxCol<v->nColumn ){ | |
| 99530 | - sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); | |
| 99531 | - sqlite3_result_value(pContext, pVal); | |
| 99532 | - }else if( idxCol==v->nColumn ){ | |
| 99533 | - /* The extra column whose name is the same as the table. | |
| 99534 | - ** Return a blob which is a pointer to the cursor | |
| 99535 | - */ | |
| 99536 | - sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); | |
| 99537 | - }else if( idxCol==v->nColumn+1 ){ | |
| 99538 | - /* The docid column, which is an alias for rowid. */ | |
| 99539 | - sqlite3_value *pVal = sqlite3_column_value(c->pStmt, 0); | |
| 99540 | - sqlite3_result_value(pContext, pVal); | |
| 99541 | - } | |
| 99542 | - return SQLITE_OK; | |
| 99543 | -} | |
| 99544 | - | |
| 99545 | 100170 | /* |
| 99546 | 100171 | ** This is the xRowid method. The SQLite core calls this routine to |
| 99547 | 100172 | ** retrieve the rowid for the current row of the result set. fts3 |
| 99548 | 100173 | ** exposes %_content.docid as the rowid for the virtual table. The |
| 99549 | 100174 | ** rowid should be written to *pRowid. |
| @@ -99555,10 +100180,47 @@ | ||
| 99555 | 100180 | }else{ |
| 99556 | 100181 | *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); |
| 99557 | 100182 | } |
| 99558 | 100183 | return SQLITE_OK; |
| 99559 | 100184 | } |
| 100185 | + | |
| 100186 | +/* | |
| 100187 | +** This is the xColumn method, called by SQLite to request a value from | |
| 100188 | +** the row that the supplied cursor currently points to. | |
| 100189 | +*/ | |
| 100190 | +static int fts3ColumnMethod( | |
| 100191 | + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ | |
| 100192 | + sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ | |
| 100193 | + int iCol /* Index of column to read value from */ | |
| 100194 | +){ | |
| 100195 | + int rc; /* Return Code */ | |
| 100196 | + Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; | |
| 100197 | + Fts3Table *p = (Fts3Table *)pCursor->pVtab; | |
| 100198 | + | |
| 100199 | + /* The column value supplied by SQLite must be in range. */ | |
| 100200 | + assert( iCol>=0 && iCol<=p->nColumn+1 ); | |
| 100201 | + | |
| 100202 | + rc = fts3CursorSeek(pCsr); | |
| 100203 | + if( rc==SQLITE_OK ){ | |
| 100204 | + if( iCol==p->nColumn+1 ){ | |
| 100205 | + /* This call is a request for the "docid" column. Since "docid" is an | |
| 100206 | + ** alias for "rowid", use the xRowid() method to obtain the value. | |
| 100207 | + */ | |
| 100208 | + sqlite3_int64 iRowid; | |
| 100209 | + rc = fts3RowidMethod(pCursor, &iRowid); | |
| 100210 | + sqlite3_result_int64(pContext, iRowid); | |
| 100211 | + }else if( iCol==p->nColumn ){ | |
| 100212 | + /* The extra column whose name is the same as the table. | |
| 100213 | + ** Return a blob which is a pointer to the cursor. | |
| 100214 | + */ | |
| 100215 | + sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); | |
| 100216 | + }else{ | |
| 100217 | + sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1)); | |
| 100218 | + } | |
| 100219 | + } | |
| 100220 | + return rc; | |
| 100221 | +} | |
| 99560 | 100222 | |
| 99561 | 100223 | /* |
| 99562 | 100224 | ** This function is the implementation of the xUpdate callback used by |
| 99563 | 100225 | ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be |
| 99564 | 100226 | ** inserted, updated or deleted. |
| @@ -99582,10 +100244,11 @@ | ||
| 99582 | 100244 | |
| 99583 | 100245 | /* |
| 99584 | 100246 | ** Implementation of xBegin() method. This is a no-op. |
| 99585 | 100247 | */ |
| 99586 | 100248 | static int fts3BeginMethod(sqlite3_vtab *pVtab){ |
| 100249 | + UNUSED_PARAMETER(pVtab); | |
| 99587 | 100250 | assert( ((Fts3Table *)pVtab)->nPendingData==0 ); |
| 99588 | 100251 | return SQLITE_OK; |
| 99589 | 100252 | } |
| 99590 | 100253 | |
| 99591 | 100254 | /* |
| @@ -99592,10 +100255,11 @@ | ||
| 99592 | 100255 | ** Implementation of xCommit() method. This is a no-op. The contents of |
| 99593 | 100256 | ** the pending-terms hash-table have already been flushed into the database |
| 99594 | 100257 | ** by fts3SyncMethod(). |
| 99595 | 100258 | */ |
| 99596 | 100259 | static int fts3CommitMethod(sqlite3_vtab *pVtab){ |
| 100260 | + UNUSED_PARAMETER(pVtab); | |
| 99597 | 100261 | assert( ((Fts3Table *)pVtab)->nPendingData==0 ); |
| 99598 | 100262 | return SQLITE_OK; |
| 99599 | 100263 | } |
| 99600 | 100264 | |
| 99601 | 100265 | /* |
| @@ -99670,10 +100334,12 @@ | ||
| 99670 | 100334 | int nVal, /* Size of argument array */ |
| 99671 | 100335 | sqlite3_value **apVal /* Array of arguments */ |
| 99672 | 100336 | ){ |
| 99673 | 100337 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 99674 | 100338 | |
| 100339 | + UNUSED_PARAMETER(nVal); | |
| 100340 | + | |
| 99675 | 100341 | assert( nVal==1 ); |
| 99676 | 100342 | if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return; |
| 99677 | 100343 | assert( pCsr ); |
| 99678 | 100344 | sqlite3Fts3Offsets(pContext, pCsr); |
| 99679 | 100345 | } |
| @@ -99693,10 +100359,12 @@ | ||
| 99693 | 100359 | sqlite3_value **apVal /* Array of arguments */ |
| 99694 | 100360 | ){ |
| 99695 | 100361 | int rc; /* Return code */ |
| 99696 | 100362 | Fts3Table *p; /* Virtual table handle */ |
| 99697 | 100363 | Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */ |
| 100364 | + | |
| 100365 | + UNUSED_PARAMETER(nVal); | |
| 99698 | 100366 | |
| 99699 | 100367 | assert( nVal==1 ); |
| 99700 | 100368 | if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return; |
| 99701 | 100369 | p = (Fts3Table *)pCursor->base.pVtab; |
| 99702 | 100370 | assert( p ); |
| @@ -99734,10 +100402,15 @@ | ||
| 99734 | 100402 | { "snippet", fts3SnippetFunc }, |
| 99735 | 100403 | { "offsets", fts3OffsetsFunc }, |
| 99736 | 100404 | { "optimize", fts3OptimizeFunc }, |
| 99737 | 100405 | }; |
| 99738 | 100406 | int i; /* Iterator variable */ |
| 100407 | + | |
| 100408 | + UNUSED_PARAMETER(pVtab); | |
| 100409 | + UNUSED_PARAMETER(nArg); | |
| 100410 | + UNUSED_PARAMETER(ppArg); | |
| 100411 | + | |
| 99739 | 100412 | for(i=0; i<SizeofArray(aOverload); i++){ |
| 99740 | 100413 | if( strcmp(zName, aOverload[i].zName)==0 ){ |
| 99741 | 100414 | *pxFunc = aOverload[i].xFunc; |
| 99742 | 100415 | return 1; |
| 99743 | 100416 | } |
| @@ -100150,11 +100823,11 @@ | ||
| 100150 | 100823 | pCursor = 0; |
| 100151 | 100824 | } |
| 100152 | 100825 | |
| 100153 | 100826 | if( rc==SQLITE_DONE ){ |
| 100154 | 100827 | int jj; |
| 100155 | - char *zNew; | |
| 100828 | + char *zNew = NULL; | |
| 100156 | 100829 | int nNew = 0; |
| 100157 | 100830 | int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase); |
| 100158 | 100831 | nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(struct PhraseToken); |
| 100159 | 100832 | p = fts3ReallocOrFree(p, nByte + nTemp); |
| 100160 | 100833 | if( !p ){ |
| @@ -100209,11 +100882,11 @@ | ||
| 100209 | 100882 | const char *z, int n, /* Input string */ |
| 100210 | 100883 | Fts3Expr **ppExpr, /* OUT: expression */ |
| 100211 | 100884 | int *pnConsumed /* OUT: Number of bytes consumed */ |
| 100212 | 100885 | ){ |
| 100213 | 100886 | static const struct Fts3Keyword { |
| 100214 | - char z[4]; /* Keyword text */ | |
| 100887 | + char *z; /* Keyword text */ | |
| 100215 | 100888 | unsigned char n; /* Length of the keyword */ |
| 100216 | 100889 | unsigned char parenOnly; /* Only valid in paren mode */ |
| 100217 | 100890 | unsigned char eType; /* Keyword code */ |
| 100218 | 100891 | } aKeyword[] = { |
| 100219 | 100892 | { "OR" , 2, 0, FTSQUERY_OR }, |
| @@ -100279,11 +100952,11 @@ | ||
| 100279 | 100952 | } |
| 100280 | 100953 | memset(pRet, 0, sizeof(Fts3Expr)); |
| 100281 | 100954 | pRet->eType = pKey->eType; |
| 100282 | 100955 | pRet->nNear = nNear; |
| 100283 | 100956 | *ppExpr = pRet; |
| 100284 | - *pnConsumed = (zInput - z) + nKey; | |
| 100957 | + *pnConsumed = (int)((zInput - z) + nKey); | |
| 100285 | 100958 | return SQLITE_OK; |
| 100286 | 100959 | } |
| 100287 | 100960 | |
| 100288 | 100961 | /* Turns out that wasn't a keyword after all. This happens if the |
| 100289 | 100962 | ** user has supplied a token such as "ORacle". Continue. |
| @@ -100299,18 +100972,18 @@ | ||
| 100299 | 100972 | pParse->nNest++; |
| 100300 | 100973 | rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); |
| 100301 | 100974 | if( rc==SQLITE_OK && !*ppExpr ){ |
| 100302 | 100975 | rc = SQLITE_DONE; |
| 100303 | 100976 | } |
| 100304 | - *pnConsumed = (zInput - z) + 1 + nConsumed; | |
| 100977 | + *pnConsumed = (int)((zInput - z) + 1 + nConsumed); | |
| 100305 | 100978 | return rc; |
| 100306 | 100979 | } |
| 100307 | 100980 | |
| 100308 | 100981 | /* Check for a close bracket. */ |
| 100309 | 100982 | if( *zInput==')' ){ |
| 100310 | 100983 | pParse->nNest--; |
| 100311 | - *pnConsumed = (zInput - z) + 1; | |
| 100984 | + *pnConsumed = (int)((zInput - z) + 1); | |
| 100312 | 100985 | return SQLITE_DONE; |
| 100313 | 100986 | } |
| 100314 | 100987 | } |
| 100315 | 100988 | |
| 100316 | 100989 | /* See if we are dealing with a quoted phrase. If this is the case, then |
| @@ -100318,11 +100991,11 @@ | ||
| 100318 | 100991 | ** for processing. This is easy to do, as fts3 has no syntax for escaping |
| 100319 | 100992 | ** a quote character embedded in a string. |
| 100320 | 100993 | */ |
| 100321 | 100994 | if( *zInput=='"' ){ |
| 100322 | 100995 | for(ii=1; ii<nInput && zInput[ii]!='"'; ii++); |
| 100323 | - *pnConsumed = (zInput - z) + ii + 1; | |
| 100996 | + *pnConsumed = (int)((zInput - z) + ii + 1); | |
| 100324 | 100997 | if( ii==nInput ){ |
| 100325 | 100998 | return SQLITE_ERROR; |
| 100326 | 100999 | } |
| 100327 | 101000 | return getNextString(pParse, &zInput[1], ii-1, ppExpr); |
| 100328 | 101001 | } |
| @@ -100341,16 +101014,16 @@ | ||
| 100341 | 101014 | */ |
| 100342 | 101015 | iCol = pParse->iDefaultCol; |
| 100343 | 101016 | iColLen = 0; |
| 100344 | 101017 | for(ii=0; ii<pParse->nCol; ii++){ |
| 100345 | 101018 | const char *zStr = pParse->azCol[ii]; |
| 100346 | - int nStr = strlen(zStr); | |
| 101019 | + int nStr = (int)strlen(zStr); | |
| 100347 | 101020 | if( nInput>nStr && zInput[nStr]==':' |
| 100348 | 101021 | && sqlite3_strnicmp(zStr, zInput, nStr)==0 |
| 100349 | 101022 | ){ |
| 100350 | 101023 | iCol = ii; |
| 100351 | - iColLen = ((zInput - z) + nStr + 1); | |
| 101024 | + iColLen = (int)((zInput - z) + nStr + 1); | |
| 100352 | 101025 | break; |
| 100353 | 101026 | } |
| 100354 | 101027 | } |
| 100355 | 101028 | rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed); |
| 100356 | 101029 | *pnConsumed += iColLen; |
| @@ -100612,11 +101285,11 @@ | ||
| 100612 | 101285 | if( z==0 ){ |
| 100613 | 101286 | *ppExpr = 0; |
| 100614 | 101287 | return SQLITE_OK; |
| 100615 | 101288 | } |
| 100616 | 101289 | if( n<0 ){ |
| 100617 | - n = strlen(z); | |
| 101290 | + n = (int)strlen(z); | |
| 100618 | 101291 | } |
| 100619 | 101292 | rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); |
| 100620 | 101293 | |
| 100621 | 101294 | /* Check for mismatched parenthesis */ |
| 100622 | 101295 | if( rc==SQLITE_OK && sParse.nNest ){ |
| @@ -100666,11 +101339,11 @@ | ||
| 100666 | 101339 | } |
| 100667 | 101340 | |
| 100668 | 101341 | sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 100669 | 101342 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 100670 | 101343 | if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 100671 | - memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); | |
| 101344 | + memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); | |
| 100672 | 101345 | } |
| 100673 | 101346 | } |
| 100674 | 101347 | |
| 100675 | 101348 | return sqlite3_finalize(pStmt); |
| 100676 | 101349 | } |
| @@ -100849,125 +101522,10 @@ | ||
| 100849 | 101522 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 100850 | 101523 | */ |
| 100851 | 101524 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 100852 | 101525 | |
| 100853 | 101526 | |
| 100854 | -/************** Include fts3_hash.h in the middle of fts3_hash.c *************/ | |
| 100855 | -/************** Begin file fts3_hash.h ***************************************/ | |
| 100856 | -/* | |
| 100857 | -** 2001 September 22 | |
| 100858 | -** | |
| 100859 | -** The author disclaims copyright to this source code. In place of | |
| 100860 | -** a legal notice, here is a blessing: | |
| 100861 | -** | |
| 100862 | -** May you do good and not evil. | |
| 100863 | -** May you find forgiveness for yourself and forgive others. | |
| 100864 | -** May you share freely, never taking more than you give. | |
| 100865 | -** | |
| 100866 | -************************************************************************* | |
| 100867 | -** This is the header file for the generic hash-table implemenation | |
| 100868 | -** used in SQLite. We've modified it slightly to serve as a standalone | |
| 100869 | -** hash table implementation for the full-text indexing module. | |
| 100870 | -** | |
| 100871 | -*/ | |
| 100872 | -#ifndef _FTS3_HASH_H_ | |
| 100873 | -#define _FTS3_HASH_H_ | |
| 100874 | - | |
| 100875 | -/* Forward declarations of structures. */ | |
| 100876 | -typedef struct Fts3Hash Fts3Hash; | |
| 100877 | -typedef struct Fts3HashElem Fts3HashElem; | |
| 100878 | - | |
| 100879 | -/* A complete hash table is an instance of the following structure. | |
| 100880 | -** The internals of this structure are intended to be opaque -- client | |
| 100881 | -** code should not attempt to access or modify the fields of this structure | |
| 100882 | -** directly. Change this structure only by using the routines below. | |
| 100883 | -** However, many of the "procedures" and "functions" for modifying and | |
| 100884 | -** accessing this structure are really macros, so we can't really make | |
| 100885 | -** this structure opaque. | |
| 100886 | -*/ | |
| 100887 | -struct Fts3Hash { | |
| 100888 | - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ | |
| 100889 | - char copyKey; /* True if copy of key made on insert */ | |
| 100890 | - int count; /* Number of entries in this table */ | |
| 100891 | - Fts3HashElem *first; /* The first element of the array */ | |
| 100892 | - int htsize; /* Number of buckets in the hash table */ | |
| 100893 | - struct _fts3ht { /* the hash table */ | |
| 100894 | - int count; /* Number of entries with this hash */ | |
| 100895 | - Fts3HashElem *chain; /* Pointer to first entry with this hash */ | |
| 100896 | - } *ht; | |
| 100897 | -}; | |
| 100898 | - | |
| 100899 | -/* Each element in the hash table is an instance of the following | |
| 100900 | -** structure. All elements are stored on a single doubly-linked list. | |
| 100901 | -** | |
| 100902 | -** Again, this structure is intended to be opaque, but it can't really | |
| 100903 | -** be opaque because it is used by macros. | |
| 100904 | -*/ | |
| 100905 | -struct Fts3HashElem { | |
| 100906 | - Fts3HashElem *next, *prev; /* Next and previous elements in the table */ | |
| 100907 | - void *data; /* Data associated with this element */ | |
| 100908 | - void *pKey; int nKey; /* Key associated with this element */ | |
| 100909 | -}; | |
| 100910 | - | |
| 100911 | -/* | |
| 100912 | -** There are 2 different modes of operation for a hash table: | |
| 100913 | -** | |
| 100914 | -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long | |
| 100915 | -** (including the null-terminator, if any). Case | |
| 100916 | -** is respected in comparisons. | |
| 100917 | -** | |
| 100918 | -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. | |
| 100919 | -** memcmp() is used to compare keys. | |
| 100920 | -** | |
| 100921 | -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. | |
| 100922 | -*/ | |
| 100923 | -#define FTS3_HASH_STRING 1 | |
| 100924 | -#define FTS3_HASH_BINARY 2 | |
| 100925 | - | |
| 100926 | -/* | |
| 100927 | -** Access routines. To delete, insert a NULL pointer. | |
| 100928 | -*/ | |
| 100929 | -SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash*, int keytype, int copyKey); | |
| 100930 | -SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); | |
| 100931 | -SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); | |
| 100932 | -SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*); | |
| 100933 | - | |
| 100934 | -/* | |
| 100935 | -** Shorthand for the functions above | |
| 100936 | -*/ | |
| 100937 | -#define fts3HashInit sqlite3Fts3HashInit | |
| 100938 | -#define fts3HashInsert sqlite3Fts3HashInsert | |
| 100939 | -#define fts3HashFind sqlite3Fts3HashFind | |
| 100940 | -#define fts3HashClear sqlite3Fts3HashClear | |
| 100941 | - | |
| 100942 | -/* | |
| 100943 | -** Macros for looping over all elements of a hash table. The idiom is | |
| 100944 | -** like this: | |
| 100945 | -** | |
| 100946 | -** Fts3Hash h; | |
| 100947 | -** Fts3HashElem *p; | |
| 100948 | -** ... | |
| 100949 | -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ | |
| 100950 | -** SomeStructure *pData = fts3HashData(p); | |
| 100951 | -** // do something with pData | |
| 100952 | -** } | |
| 100953 | -*/ | |
| 100954 | -#define fts3HashFirst(H) ((H)->first) | |
| 100955 | -#define fts3HashNext(E) ((E)->next) | |
| 100956 | -#define fts3HashData(E) ((E)->data) | |
| 100957 | -#define fts3HashKey(E) ((E)->pKey) | |
| 100958 | -#define fts3HashKeysize(E) ((E)->nKey) | |
| 100959 | - | |
| 100960 | -/* | |
| 100961 | -** Number of entries in a hash table | |
| 100962 | -*/ | |
| 100963 | -#define fts3HashCount(H) ((H)->count) | |
| 100964 | - | |
| 100965 | -#endif /* _FTS3_HASH_H_ */ | |
| 100966 | - | |
| 100967 | -/************** End of fts3_hash.h *******************************************/ | |
| 100968 | -/************** Continuing where we left off in fts3_hash.c ******************/ | |
| 100969 | 101527 | |
| 100970 | 101528 | /* |
| 100971 | 101529 | ** Malloc and Free functions |
| 100972 | 101530 | */ |
| 100973 | 101531 | static void *fts3HashMalloc(int n){ |
| @@ -100989,11 +101547,11 @@ | ||
| 100989 | 101547 | ** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass |
| 100990 | 101548 | ** determines what kind of key the hash table will use. "copyKey" is |
| 100991 | 101549 | ** true if the hash table should make its own private copy of keys and |
| 100992 | 101550 | ** false if it should just use the supplied pointer. |
| 100993 | 101551 | */ |
| 100994 | -SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, int keyClass, int copyKey){ | |
| 101552 | +SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){ | |
| 100995 | 101553 | assert( pNew!=0 ); |
| 100996 | 101554 | assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); |
| 100997 | 101555 | pNew->keyClass = keyClass; |
| 100998 | 101556 | pNew->copyKey = copyKey; |
| 100999 | 101557 | pNew->first = 0; |
| @@ -101123,28 +101681,31 @@ | ||
| 101123 | 101681 | |
| 101124 | 101682 | |
| 101125 | 101683 | /* Resize the hash table so that it cantains "new_size" buckets. |
| 101126 | 101684 | ** "new_size" must be a power of 2. The hash table might fail |
| 101127 | 101685 | ** to resize if sqliteMalloc() fails. |
| 101686 | +** | |
| 101687 | +** Return non-zero if a memory allocation error occurs. | |
| 101128 | 101688 | */ |
| 101129 | -static void fts3Rehash(Fts3Hash *pH, int new_size){ | |
| 101689 | +static int fts3Rehash(Fts3Hash *pH, int new_size){ | |
| 101130 | 101690 | struct _fts3ht *new_ht; /* The new hash table */ |
| 101131 | 101691 | Fts3HashElem *elem, *next_elem; /* For looping over existing elements */ |
| 101132 | 101692 | int (*xHash)(const void*,int); /* The hash function */ |
| 101133 | 101693 | |
| 101134 | 101694 | assert( (new_size & (new_size-1))==0 ); |
| 101135 | 101695 | new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); |
| 101136 | - if( new_ht==0 ) return; | |
| 101696 | + if( new_ht==0 ) return 1; | |
| 101137 | 101697 | fts3HashFree(pH->ht); |
| 101138 | 101698 | pH->ht = new_ht; |
| 101139 | 101699 | pH->htsize = new_size; |
| 101140 | 101700 | xHash = ftsHashFunction(pH->keyClass); |
| 101141 | 101701 | for(elem=pH->first, pH->first=0; elem; elem = next_elem){ |
| 101142 | 101702 | int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); |
| 101143 | 101703 | next_elem = elem->next; |
| 101144 | 101704 | fts3HashInsertElement(pH, &new_ht[h], elem); |
| 101145 | 101705 | } |
| 101706 | + return 0; | |
| 101146 | 101707 | } |
| 101147 | 101708 | |
| 101148 | 101709 | /* This function (for internal use only) locates an element in an |
| 101149 | 101710 | ** hash table that matches the given key. The hash for this key has |
| 101150 | 101711 | ** already been computed and is passed as the 4th parameter. |
| @@ -101271,17 +101832,17 @@ | ||
| 101271 | 101832 | elem->data = data; |
| 101272 | 101833 | } |
| 101273 | 101834 | return old_data; |
| 101274 | 101835 | } |
| 101275 | 101836 | if( data==0 ) return 0; |
| 101276 | - if( pH->htsize==0 ){ | |
| 101277 | - fts3Rehash(pH,8); | |
| 101278 | - if( pH->htsize==0 ){ | |
| 101279 | - pH->count = 0; | |
| 101280 | - return data; | |
| 101281 | - } | |
| 101837 | + if( (pH->htsize==0 && fts3Rehash(pH,8)) | |
| 101838 | + || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2)) | |
| 101839 | + ){ | |
| 101840 | + pH->count = 0; | |
| 101841 | + return data; | |
| 101282 | 101842 | } |
| 101843 | + assert( pH->htsize>0 ); | |
| 101283 | 101844 | new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) ); |
| 101284 | 101845 | if( new_elem==0 ) return data; |
| 101285 | 101846 | if( pH->copyKey && pKey!=0 ){ |
| 101286 | 101847 | new_elem->pKey = fts3HashMalloc( nKey ); |
| 101287 | 101848 | if( new_elem->pKey==0 ){ |
| @@ -101292,13 +101853,10 @@ | ||
| 101292 | 101853 | }else{ |
| 101293 | 101854 | new_elem->pKey = (void*)pKey; |
| 101294 | 101855 | } |
| 101295 | 101856 | new_elem->nKey = nKey; |
| 101296 | 101857 | pH->count++; |
| 101297 | - if( pH->count > pH->htsize ){ | |
| 101298 | - fts3Rehash(pH,pH->htsize*2); | |
| 101299 | - } | |
| 101300 | 101858 | assert( pH->htsize>0 ); |
| 101301 | 101859 | assert( (pH->htsize & (pH->htsize-1))==0 ); |
| 101302 | 101860 | h = hraw & (pH->htsize-1); |
| 101303 | 101861 | fts3HashInsertElement(pH, &pH->ht[h], new_elem); |
| 101304 | 101862 | new_elem->data = data; |
| @@ -101335,162 +101893,10 @@ | ||
| 101335 | 101893 | */ |
| 101336 | 101894 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 101337 | 101895 | |
| 101338 | 101896 | |
| 101339 | 101897 | |
| 101340 | -/************** Include fts3_tokenizer.h in the middle of fts3_porter.c ******/ | |
| 101341 | -/************** Begin file fts3_tokenizer.h **********************************/ | |
| 101342 | -/* | |
| 101343 | -** 2006 July 10 | |
| 101344 | -** | |
| 101345 | -** The author disclaims copyright to this source code. | |
| 101346 | -** | |
| 101347 | -************************************************************************* | |
| 101348 | -** Defines the interface to tokenizers used by fulltext-search. There | |
| 101349 | -** are three basic components: | |
| 101350 | -** | |
| 101351 | -** sqlite3_tokenizer_module is a singleton defining the tokenizer | |
| 101352 | -** interface functions. This is essentially the class structure for | |
| 101353 | -** tokenizers. | |
| 101354 | -** | |
| 101355 | -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps | |
| 101356 | -** including customization information defined at creation time. | |
| 101357 | -** | |
| 101358 | -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate | |
| 101359 | -** tokens from a particular input. | |
| 101360 | -*/ | |
| 101361 | -#ifndef _FTS3_TOKENIZER_H_ | |
| 101362 | -#define _FTS3_TOKENIZER_H_ | |
| 101363 | - | |
| 101364 | -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. | |
| 101365 | -** If tokenizers are to be allowed to call sqlite3_*() functions, then | |
| 101366 | -** we will need a way to register the API consistently. | |
| 101367 | -*/ | |
| 101368 | - | |
| 101369 | -/* | |
| 101370 | -** Structures used by the tokenizer interface. When a new tokenizer | |
| 101371 | -** implementation is registered, the caller provides a pointer to | |
| 101372 | -** an sqlite3_tokenizer_module containing pointers to the callback | |
| 101373 | -** functions that make up an implementation. | |
| 101374 | -** | |
| 101375 | -** When an fts3 table is created, it passes any arguments passed to | |
| 101376 | -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the | |
| 101377 | -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer | |
| 101378 | -** implementation. The xCreate() function in turn returns an | |
| 101379 | -** sqlite3_tokenizer structure representing the specific tokenizer to | |
| 101380 | -** be used for the fts3 table (customized by the tokenizer clause arguments). | |
| 101381 | -** | |
| 101382 | -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() | |
| 101383 | -** method is called. It returns an sqlite3_tokenizer_cursor object | |
| 101384 | -** that may be used to tokenize a specific input buffer based on | |
| 101385 | -** the tokenization rules supplied by a specific sqlite3_tokenizer | |
| 101386 | -** object. | |
| 101387 | -*/ | |
| 101388 | -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; | |
| 101389 | -typedef struct sqlite3_tokenizer sqlite3_tokenizer; | |
| 101390 | -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; | |
| 101391 | - | |
| 101392 | -struct sqlite3_tokenizer_module { | |
| 101393 | - | |
| 101394 | - /* | |
| 101395 | - ** Structure version. Should always be set to 0. | |
| 101396 | - */ | |
| 101397 | - int iVersion; | |
| 101398 | - | |
| 101399 | - /* | |
| 101400 | - ** Create a new tokenizer. The values in the argv[] array are the | |
| 101401 | - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL | |
| 101402 | - ** TABLE statement that created the fts3 table. For example, if | |
| 101403 | - ** the following SQL is executed: | |
| 101404 | - ** | |
| 101405 | - ** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2) | |
| 101406 | - ** | |
| 101407 | - ** then argc is set to 2, and the argv[] array contains pointers | |
| 101408 | - ** to the strings "arg1" and "arg2". | |
| 101409 | - ** | |
| 101410 | - ** This method should return either SQLITE_OK (0), or an SQLite error | |
| 101411 | - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set | |
| 101412 | - ** to point at the newly created tokenizer structure. The generic | |
| 101413 | - ** sqlite3_tokenizer.pModule variable should not be initialised by | |
| 101414 | - ** this callback. The caller will do so. | |
| 101415 | - */ | |
| 101416 | - int (*xCreate)( | |
| 101417 | - int argc, /* Size of argv array */ | |
| 101418 | - const char *const*argv, /* Tokenizer argument strings */ | |
| 101419 | - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ | |
| 101420 | - ); | |
| 101421 | - | |
| 101422 | - /* | |
| 101423 | - ** Destroy an existing tokenizer. The fts3 module calls this method | |
| 101424 | - ** exactly once for each successful call to xCreate(). | |
| 101425 | - */ | |
| 101426 | - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); | |
| 101427 | - | |
| 101428 | - /* | |
| 101429 | - ** Create a tokenizer cursor to tokenize an input buffer. The caller | |
| 101430 | - ** is responsible for ensuring that the input buffer remains valid | |
| 101431 | - ** until the cursor is closed (using the xClose() method). | |
| 101432 | - */ | |
| 101433 | - int (*xOpen)( | |
| 101434 | - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ | |
| 101435 | - const char *pInput, int nBytes, /* Input buffer */ | |
| 101436 | - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ | |
| 101437 | - ); | |
| 101438 | - | |
| 101439 | - /* | |
| 101440 | - ** Destroy an existing tokenizer cursor. The fts3 module calls this | |
| 101441 | - ** method exactly once for each successful call to xOpen(). | |
| 101442 | - */ | |
| 101443 | - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); | |
| 101444 | - | |
| 101445 | - /* | |
| 101446 | - ** Retrieve the next token from the tokenizer cursor pCursor. This | |
| 101447 | - ** method should either return SQLITE_OK and set the values of the | |
| 101448 | - ** "OUT" variables identified below, or SQLITE_DONE to indicate that | |
| 101449 | - ** the end of the buffer has been reached, or an SQLite error code. | |
| 101450 | - ** | |
| 101451 | - ** *ppToken should be set to point at a buffer containing the | |
| 101452 | - ** normalized version of the token (i.e. after any case-folding and/or | |
| 101453 | - ** stemming has been performed). *pnBytes should be set to the length | |
| 101454 | - ** of this buffer in bytes. The input text that generated the token is | |
| 101455 | - ** identified by the byte offsets returned in *piStartOffset and | |
| 101456 | - ** *piEndOffset. *piStartOffset should be set to the index of the first | |
| 101457 | - ** byte of the token in the input buffer. *piEndOffset should be set | |
| 101458 | - ** to the index of the first byte just past the end of the token in | |
| 101459 | - ** the input buffer. | |
| 101460 | - ** | |
| 101461 | - ** The buffer *ppToken is set to point at is managed by the tokenizer | |
| 101462 | - ** implementation. It is only required to be valid until the next call | |
| 101463 | - ** to xNext() or xClose(). | |
| 101464 | - */ | |
| 101465 | - /* TODO(shess) current implementation requires pInput to be | |
| 101466 | - ** nul-terminated. This should either be fixed, or pInput/nBytes | |
| 101467 | - ** should be converted to zInput. | |
| 101468 | - */ | |
| 101469 | - int (*xNext)( | |
| 101470 | - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ | |
| 101471 | - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ | |
| 101472 | - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ | |
| 101473 | - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ | |
| 101474 | - int *piPosition /* OUT: Number of tokens returned before this one */ | |
| 101475 | - ); | |
| 101476 | -}; | |
| 101477 | - | |
| 101478 | -struct sqlite3_tokenizer { | |
| 101479 | - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ | |
| 101480 | - /* Tokenizer implementations will typically add additional fields */ | |
| 101481 | -}; | |
| 101482 | - | |
| 101483 | -struct sqlite3_tokenizer_cursor { | |
| 101484 | - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ | |
| 101485 | - /* Tokenizer implementations will typically add additional fields */ | |
| 101486 | -}; | |
| 101487 | - | |
| 101488 | -#endif /* _FTS3_TOKENIZER_H_ */ | |
| 101489 | - | |
| 101490 | -/************** End of fts3_tokenizer.h **************************************/ | |
| 101491 | -/************** Continuing where we left off in fts3_porter.c ****************/ | |
| 101492 | 101898 | |
| 101493 | 101899 | /* |
| 101494 | 101900 | ** Class derived from sqlite3_tokenizer |
| 101495 | 101901 | */ |
| 101496 | 101902 | typedef struct porter_tokenizer { |
| @@ -101508,23 +101914,23 @@ | ||
| 101508 | 101914 | int iToken; /* index of next token to be returned */ |
| 101509 | 101915 | char *zToken; /* storage for current token */ |
| 101510 | 101916 | int nAllocated; /* space allocated to zToken buffer */ |
| 101511 | 101917 | } porter_tokenizer_cursor; |
| 101512 | 101918 | |
| 101513 | - | |
| 101514 | -/* Forward declaration */ | |
| 101515 | -static const sqlite3_tokenizer_module porterTokenizerModule; | |
| 101516 | - | |
| 101517 | 101919 | |
| 101518 | 101920 | /* |
| 101519 | 101921 | ** Create a new tokenizer instance. |
| 101520 | 101922 | */ |
| 101521 | 101923 | static int porterCreate( |
| 101522 | 101924 | int argc, const char * const *argv, |
| 101523 | 101925 | sqlite3_tokenizer **ppTokenizer |
| 101524 | 101926 | ){ |
| 101525 | 101927 | porter_tokenizer *t; |
| 101928 | + | |
| 101929 | + UNUSED_PARAMETER(argc); | |
| 101930 | + UNUSED_PARAMETER(argv); | |
| 101931 | + | |
| 101526 | 101932 | t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); |
| 101527 | 101933 | if( t==NULL ) return SQLITE_NOMEM; |
| 101528 | 101934 | memset(t, 0, sizeof(*t)); |
| 101529 | 101935 | *ppTokenizer = &t->base; |
| 101530 | 101936 | return SQLITE_OK; |
| @@ -101548,10 +101954,12 @@ | ||
| 101548 | 101954 | sqlite3_tokenizer *pTokenizer, /* The tokenizer */ |
| 101549 | 101955 | const char *zInput, int nInput, /* String to be tokenized */ |
| 101550 | 101956 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ |
| 101551 | 101957 | ){ |
| 101552 | 101958 | porter_tokenizer_cursor *c; |
| 101959 | + | |
| 101960 | + UNUSED_PARAMETER(pTokenizer); | |
| 101553 | 101961 | |
| 101554 | 101962 | c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); |
| 101555 | 101963 | if( c==NULL ) return SQLITE_NOMEM; |
| 101556 | 101964 | |
| 101557 | 101965 | c->zInput = zInput; |
| @@ -101689,11 +102097,11 @@ | ||
| 101689 | 102097 | ** |
| 101690 | 102098 | ** The text is reversed here. So we are really looking at |
| 101691 | 102099 | ** the first two characters of z[]. |
| 101692 | 102100 | */ |
| 101693 | 102101 | static int doubleConsonant(const char *z){ |
| 101694 | - return isConsonant(z) && z[0]==z[1] && isConsonant(z+1); | |
| 102102 | + return isConsonant(z) && z[0]==z[1]; | |
| 101695 | 102103 | } |
| 101696 | 102104 | |
| 101697 | 102105 | /* |
| 101698 | 102106 | ** Return TRUE if the word ends with three letters which |
| 101699 | 102107 | ** are consonant-vowel-consonent and where the final consonant |
| @@ -101702,14 +102110,14 @@ | ||
| 101702 | 102110 | ** The word is reversed here. So we are really checking the |
| 101703 | 102111 | ** first three letters and the first one cannot be in [wxy]. |
| 101704 | 102112 | */ |
| 101705 | 102113 | static int star_oh(const char *z){ |
| 101706 | 102114 | return |
| 101707 | - z[0]!=0 && isConsonant(z) && | |
| 102115 | + isConsonant(z) && | |
| 101708 | 102116 | z[0]!='w' && z[0]!='x' && z[0]!='y' && |
| 101709 | - z[1]!=0 && isVowel(z+1) && | |
| 101710 | - z[2]!=0 && isConsonant(z+2); | |
| 102117 | + isVowel(z+1) && | |
| 102118 | + isConsonant(z+2); | |
| 101711 | 102119 | } |
| 101712 | 102120 | |
| 101713 | 102121 | /* |
| 101714 | 102122 | ** If the word ends with zFrom and xCond() is true for the stem |
| 101715 | 102123 | ** of the word that preceeds the zFrom ending, then change the |
| @@ -101749,11 +102157,11 @@ | ||
| 101749 | 102157 | */ |
| 101750 | 102158 | static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 101751 | 102159 | int i, mx, j; |
| 101752 | 102160 | int hasDigit = 0; |
| 101753 | 102161 | for(i=0; i<nIn; i++){ |
| 101754 | - int c = zIn[i]; | |
| 102162 | + char c = zIn[i]; | |
| 101755 | 102163 | if( c>='A' && c<='Z' ){ |
| 101756 | 102164 | zOut[i] = c - 'A' + 'a'; |
| 101757 | 102165 | }else{ |
| 101758 | 102166 | if( c>='0' && c<='9' ) hasDigit = 1; |
| 101759 | 102167 | zOut[i] = c; |
| @@ -101793,21 +102201,21 @@ | ||
| 101793 | 102201 | ** |
| 101794 | 102202 | ** Stemming never increases the length of the word. So there is |
| 101795 | 102203 | ** no chance of overflowing the zOut buffer. |
| 101796 | 102204 | */ |
| 101797 | 102205 | static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 101798 | - int i, j, c; | |
| 102206 | + int i, j; | |
| 101799 | 102207 | char zReverse[28]; |
| 101800 | 102208 | char *z, *z2; |
| 101801 | 102209 | if( nIn<3 || nIn>=sizeof(zReverse)-7 ){ |
| 101802 | 102210 | /* The word is too big or too small for the porter stemmer. |
| 101803 | 102211 | ** Fallback to the copy stemmer */ |
| 101804 | 102212 | copy_stemmer(zIn, nIn, zOut, pnOut); |
| 101805 | 102213 | return; |
| 101806 | 102214 | } |
| 101807 | 102215 | for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){ |
| 101808 | - c = zIn[i]; | |
| 102216 | + char c = zIn[i]; | |
| 101809 | 102217 | if( c>='A' && c<='Z' ){ |
| 101810 | 102218 | zReverse[j] = c + 'a' - 'A'; |
| 101811 | 102219 | }else if( c>='a' && c<='z' ){ |
| 101812 | 102220 | zReverse[j] = c; |
| 101813 | 102221 | }else{ |
| @@ -102002,11 +102410,11 @@ | ||
| 102002 | 102410 | } |
| 102003 | 102411 | |
| 102004 | 102412 | /* z[] is now the stemmed word in reverse order. Flip it back |
| 102005 | 102413 | ** around into forward order and return. |
| 102006 | 102414 | */ |
| 102007 | - *pnOut = i = strlen(z); | |
| 102415 | + *pnOut = i = (int)strlen(z); | |
| 102008 | 102416 | zOut[i] = 0; |
| 102009 | 102417 | while( *z ){ |
| 102010 | 102418 | zOut[--i] = *(z++); |
| 102011 | 102419 | } |
| 102012 | 102420 | } |
| @@ -102240,11 +102648,11 @@ | ||
| 102240 | 102648 | z1++; |
| 102241 | 102649 | } |
| 102242 | 102650 | } |
| 102243 | 102651 | } |
| 102244 | 102652 | |
| 102245 | - *pn = (z2-z1); | |
| 102653 | + *pn = (int)(z2-z1); | |
| 102246 | 102654 | return z1; |
| 102247 | 102655 | } |
| 102248 | 102656 | |
| 102249 | 102657 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( |
| 102250 | 102658 | Fts3Hash *pHash, /* Tokenizer hash table */ |
| @@ -102278,24 +102686,24 @@ | ||
| 102278 | 102686 | |
| 102279 | 102687 | z = (char *)sqlite3Fts3NextToken(zCopy, &n); |
| 102280 | 102688 | z[n] = '\0'; |
| 102281 | 102689 | sqlite3Fts3Dequote(z); |
| 102282 | 102690 | |
| 102283 | - m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, strlen(z)+1); | |
| 102691 | + m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, (int)strlen(z)+1); | |
| 102284 | 102692 | if( !m ){ |
| 102285 | 102693 | *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); |
| 102286 | 102694 | rc = SQLITE_ERROR; |
| 102287 | 102695 | }else{ |
| 102288 | 102696 | char const **aArg = 0; |
| 102289 | 102697 | int iArg = 0; |
| 102290 | 102698 | z = &z[n+1]; |
| 102291 | - while( z<zEnd && (z = (char *)sqlite3Fts3NextToken(z, &n)) ){ | |
| 102699 | + while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){ | |
| 102292 | 102700 | int nNew = sizeof(char *)*(iArg+1); |
| 102293 | - char const **aNew = (const char **)sqlite3_realloc(aArg, nNew); | |
| 102701 | + char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew); | |
| 102294 | 102702 | if( !aNew ){ |
| 102295 | 102703 | sqlite3_free(zCopy); |
| 102296 | - sqlite3_free(aArg); | |
| 102704 | + sqlite3_free((void *)aArg); | |
| 102297 | 102705 | return SQLITE_NOMEM; |
| 102298 | 102706 | } |
| 102299 | 102707 | aArg = aNew; |
| 102300 | 102708 | aArg[iArg++] = z; |
| 102301 | 102709 | z[n] = '\0'; |
| @@ -102303,15 +102711,15 @@ | ||
| 102303 | 102711 | z = &z[n+1]; |
| 102304 | 102712 | } |
| 102305 | 102713 | rc = m->xCreate(iArg, aArg, ppTok); |
| 102306 | 102714 | assert( rc!=SQLITE_OK || *ppTok ); |
| 102307 | 102715 | if( rc!=SQLITE_OK ){ |
| 102308 | - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); | |
| 102716 | + *pzErr = sqlite3_mprintf("unknown tokenizer"); | |
| 102309 | 102717 | }else{ |
| 102310 | 102718 | (*ppTok)->pModule = m; |
| 102311 | 102719 | } |
| 102312 | - sqlite3_free(aArg); | |
| 102720 | + sqlite3_free((void *)aArg); | |
| 102313 | 102721 | } |
| 102314 | 102722 | |
| 102315 | 102723 | sqlite3_free(zCopy); |
| 102316 | 102724 | return rc; |
| 102317 | 102725 | } |
| @@ -102473,11 +102881,11 @@ | ||
| 102473 | 102881 | } |
| 102474 | 102882 | |
| 102475 | 102883 | sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 102476 | 102884 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 102477 | 102885 | if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 102478 | - memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); | |
| 102886 | + memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); | |
| 102479 | 102887 | } |
| 102480 | 102888 | } |
| 102481 | 102889 | |
| 102482 | 102890 | return sqlite3_finalize(pStmt); |
| 102483 | 102891 | } |
| @@ -102509,10 +102917,13 @@ | ||
| 102509 | 102917 | ){ |
| 102510 | 102918 | int rc; |
| 102511 | 102919 | const sqlite3_tokenizer_module *p1; |
| 102512 | 102920 | const sqlite3_tokenizer_module *p2; |
| 102513 | 102921 | sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); |
| 102922 | + | |
| 102923 | + UNUSED_PARAMETER(argc); | |
| 102924 | + UNUSED_PARAMETER(argv); | |
| 102514 | 102925 | |
| 102515 | 102926 | /* Test the query function */ |
| 102516 | 102927 | sqlite3Fts3SimpleTokenizerModule(&p1); |
| 102517 | 102928 | rc = queryTokenizer(db, "simple", &p2); |
| 102518 | 102929 | assert( rc==SQLITE_OK ); |
| @@ -102569,17 +102980,17 @@ | ||
| 102569 | 102980 | if( !zTest || !zTest2 ){ |
| 102570 | 102981 | rc = SQLITE_NOMEM; |
| 102571 | 102982 | } |
| 102572 | 102983 | #endif |
| 102573 | 102984 | |
| 102574 | - if( rc!=SQLITE_OK | |
| 102575 | - || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) | |
| 102576 | - || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) | |
| 102985 | + if( SQLITE_OK!=rc | |
| 102986 | + || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) | |
| 102987 | + || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) | |
| 102577 | 102988 | #ifdef SQLITE_TEST |
| 102578 | - || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) | |
| 102579 | - || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) | |
| 102580 | - || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) | |
| 102989 | + || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) | |
| 102990 | + || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) | |
| 102991 | + || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) | |
| 102581 | 102992 | #endif |
| 102582 | 102993 | ); |
| 102583 | 102994 | |
| 102584 | 102995 | sqlite3_free(zTest); |
| 102585 | 102996 | sqlite3_free(zTest2); |
| @@ -102633,13 +103044,10 @@ | ||
| 102633 | 103044 | char *pToken; /* storage for current token */ |
| 102634 | 103045 | int nTokenAllocated; /* space allocated to zToken buffer */ |
| 102635 | 103046 | } simple_tokenizer_cursor; |
| 102636 | 103047 | |
| 102637 | 103048 | |
| 102638 | -/* Forward declaration */ | |
| 102639 | -static const sqlite3_tokenizer_module simpleTokenizerModule; | |
| 102640 | - | |
| 102641 | 103049 | static int simpleDelim(simple_tokenizer *t, unsigned char c){ |
| 102642 | 103050 | return c<0x80 && t->delim[c]; |
| 102643 | 103051 | } |
| 102644 | 103052 | |
| 102645 | 103053 | /* |
| @@ -102659,11 +103067,11 @@ | ||
| 102659 | 103067 | ** else we need to reindex. One solution would be a meta-table to |
| 102660 | 103068 | ** track such information in the database, then we'd only want this |
| 102661 | 103069 | ** information on the initial create. |
| 102662 | 103070 | */ |
| 102663 | 103071 | if( argc>1 ){ |
| 102664 | - int i, n = strlen(argv[1]); | |
| 103072 | + int i, n = (int)strlen(argv[1]); | |
| 102665 | 103073 | for(i=0; i<n; i++){ |
| 102666 | 103074 | unsigned char ch = argv[1][i]; |
| 102667 | 103075 | /* We explicitly don't support UTF-8 delimiters for now. */ |
| 102668 | 103076 | if( ch>=0x80 ){ |
| 102669 | 103077 | sqlite3_free(t); |
| @@ -102673,11 +103081,11 @@ | ||
| 102673 | 103081 | } |
| 102674 | 103082 | } else { |
| 102675 | 103083 | /* Mark non-alphanumeric ASCII characters as delimiters */ |
| 102676 | 103084 | int i; |
| 102677 | 103085 | for(i=1; i<0x80; i++){ |
| 102678 | - t->delim[i] = !isalnum(i); | |
| 103086 | + t->delim[i] = !isalnum(i) ? -1 : 0; | |
| 102679 | 103087 | } |
| 102680 | 103088 | } |
| 102681 | 103089 | |
| 102682 | 103090 | *ppTokenizer = &t->base; |
| 102683 | 103091 | return SQLITE_OK; |
| @@ -102701,10 +103109,12 @@ | ||
| 102701 | 103109 | sqlite3_tokenizer *pTokenizer, /* The tokenizer */ |
| 102702 | 103110 | const char *pInput, int nBytes, /* String to be tokenized */ |
| 102703 | 103111 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ |
| 102704 | 103112 | ){ |
| 102705 | 103113 | simple_tokenizer_cursor *c; |
| 103114 | + | |
| 103115 | + UNUSED_PARAMETER(pTokenizer); | |
| 102706 | 103116 | |
| 102707 | 103117 | c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); |
| 102708 | 103118 | if( c==NULL ) return SQLITE_NOMEM; |
| 102709 | 103119 | |
| 102710 | 103120 | c->pInput = pInput; |
| @@ -102775,11 +103185,11 @@ | ||
| 102775 | 103185 | for(i=0; i<n; i++){ |
| 102776 | 103186 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 102777 | 103187 | ** case-insensitivity. |
| 102778 | 103188 | */ |
| 102779 | 103189 | unsigned char ch = p[iStartOffset+i]; |
| 102780 | - c->pToken[i] = ch<0x80 ? tolower(ch) : ch; | |
| 103190 | + c->pToken[i] = (char)(ch<0x80 ? tolower(ch) : ch); | |
| 102781 | 103191 | } |
| 102782 | 103192 | *ppToken = c->pToken; |
| 102783 | 103193 | *pnBytes = n; |
| 102784 | 103194 | *piStartOffset = iStartOffset; |
| 102785 | 103195 | *piEndOffset = c->iOffset; |
| @@ -102837,13 +103247,10 @@ | ||
| 102837 | 103247 | */ |
| 102838 | 103248 | |
| 102839 | 103249 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 102840 | 103250 | |
| 102841 | 103251 | |
| 102842 | -#define INTERIOR_MAX 2048 /* Soft limit for segment node size */ | |
| 102843 | -#define LEAF_MAX 2048 /* Soft limit for segment leaf size */ | |
| 102844 | - | |
| 102845 | 103252 | typedef struct PendingList PendingList; |
| 102846 | 103253 | typedef struct SegmentNode SegmentNode; |
| 102847 | 103254 | typedef struct SegmentWriter SegmentWriter; |
| 102848 | 103255 | |
| 102849 | 103256 | /* |
| @@ -103092,20 +103499,22 @@ | ||
| 103092 | 103499 | sqlite3_stmt *pStmt; |
| 103093 | 103500 | int rc = fts3SqlStmt(p, SQL_GET_BLOCK, &pStmt, 0); |
| 103094 | 103501 | if( rc!=SQLITE_OK ) return rc; |
| 103095 | 103502 | sqlite3_reset(pStmt); |
| 103096 | 103503 | |
| 103097 | - sqlite3_bind_int64(pStmt, 1, iBlock); | |
| 103098 | - rc = sqlite3_step(pStmt); | |
| 103099 | - if( rc!=SQLITE_ROW ){ | |
| 103100 | - return SQLITE_CORRUPT; | |
| 103101 | - } | |
| 103102 | - | |
| 103103 | - *pnBlock = sqlite3_column_bytes(pStmt, 0); | |
| 103104 | - *pzBlock = (char *)sqlite3_column_blob(pStmt, 0); | |
| 103105 | - if( !*pzBlock ){ | |
| 103106 | - return SQLITE_NOMEM; | |
| 103504 | + if( pzBlock ){ | |
| 103505 | + sqlite3_bind_int64(pStmt, 1, iBlock); | |
| 103506 | + rc = sqlite3_step(pStmt); | |
| 103507 | + if( rc!=SQLITE_ROW ){ | |
| 103508 | + return SQLITE_CORRUPT; | |
| 103509 | + } | |
| 103510 | + | |
| 103511 | + *pnBlock = sqlite3_column_bytes(pStmt, 0); | |
| 103512 | + *pzBlock = (char *)sqlite3_column_blob(pStmt, 0); | |
| 103513 | + if( !*pzBlock ){ | |
| 103514 | + return SQLITE_NOMEM; | |
| 103515 | + } | |
| 103107 | 103516 | } |
| 103108 | 103517 | return SQLITE_OK; |
| 103109 | 103518 | } |
| 103110 | 103519 | |
| 103111 | 103520 | /* |
| @@ -103222,11 +103631,13 @@ | ||
| 103222 | 103631 | p->iLastPos = 0; |
| 103223 | 103632 | } |
| 103224 | 103633 | if( iCol>=0 ){ |
| 103225 | 103634 | assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) ); |
| 103226 | 103635 | rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos); |
| 103227 | - p->iLastPos = iPos; | |
| 103636 | + if( rc==SQLITE_OK ){ | |
| 103637 | + p->iLastPos = iPos; | |
| 103638 | + } | |
| 103228 | 103639 | } |
| 103229 | 103640 | |
| 103230 | 103641 | pendinglistappend_out: |
| 103231 | 103642 | *pRc = rc; |
| 103232 | 103643 | if( p!=*pp ){ |
| @@ -103371,11 +103782,10 @@ | ||
| 103371 | 103782 | Fts3Table *p, /* Full-text table */ |
| 103372 | 103783 | sqlite3_value **apVal, /* Array of values to insert */ |
| 103373 | 103784 | sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ |
| 103374 | 103785 | ){ |
| 103375 | 103786 | int rc; /* Return code */ |
| 103376 | - int i; /* Iterator variable */ | |
| 103377 | 103787 | sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */ |
| 103378 | 103788 | |
| 103379 | 103789 | /* Locate the statement handle used to insert data into the %_content |
| 103380 | 103790 | ** table. The SQL for this statement is: |
| 103381 | 103791 | ** |
| @@ -103394,14 +103804,20 @@ | ||
| 103394 | 103804 | ** Which is a problem, since "rowid" and "docid" are aliases for the |
| 103395 | 103805 | ** same value. For example: |
| 103396 | 103806 | ** |
| 103397 | 103807 | ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2); |
| 103398 | 103808 | ** |
| 103399 | - ** In FTS3, if a non-NULL docid value is specified, it is the value | |
| 103400 | - ** inserted. Otherwise, the rowid value is used. | |
| 103809 | + ** In FTS3, this is an error. It is an error to specify non-NULL values | |
| 103810 | + ** for both docid and some other rowid alias. | |
| 103401 | 103811 | */ |
| 103402 | 103812 | if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){ |
| 103813 | + if( SQLITE_NULL==sqlite3_value_type(apVal[0]) | |
| 103814 | + && SQLITE_NULL!=sqlite3_value_type(apVal[1]) | |
| 103815 | + ){ | |
| 103816 | + /* A rowid/docid conflict. */ | |
| 103817 | + return SQLITE_ERROR; | |
| 103818 | + } | |
| 103403 | 103819 | rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); |
| 103404 | 103820 | if( rc!=SQLITE_OK ) return rc; |
| 103405 | 103821 | } |
| 103406 | 103822 | |
| 103407 | 103823 | /* Execute the statement to insert the record. Set *piDocid to the |
| @@ -103457,13 +103873,15 @@ | ||
| 103457 | 103873 | sqlite3_reset(pSelect); |
| 103458 | 103874 | return rc; |
| 103459 | 103875 | } |
| 103460 | 103876 | } |
| 103461 | 103877 | } |
| 103878 | + rc = sqlite3_reset(pSelect); | |
| 103879 | + }else{ | |
| 103880 | + sqlite3_reset(pSelect); | |
| 103462 | 103881 | } |
| 103463 | - | |
| 103464 | - return sqlite3_reset(pSelect); | |
| 103882 | + return rc; | |
| 103465 | 103883 | } |
| 103466 | 103884 | |
| 103467 | 103885 | /* |
| 103468 | 103886 | ** Forward declaration to account for the circular dependency between |
| 103469 | 103887 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| @@ -103486,18 +103904,18 @@ | ||
| 103486 | 103904 | ** returned. Otherwise, an SQLite error code is returned. |
| 103487 | 103905 | */ |
| 103488 | 103906 | static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){ |
| 103489 | 103907 | int rc; /* Return Code */ |
| 103490 | 103908 | sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ |
| 103491 | - int iNext; /* Result of query pNextIdx */ | |
| 103909 | + int iNext = 0; /* Result of query pNextIdx */ | |
| 103492 | 103910 | |
| 103493 | 103911 | /* Set variable iNext to the next available segdir index at level iLevel. */ |
| 103494 | 103912 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); |
| 103495 | 103913 | if( rc==SQLITE_OK ){ |
| 103496 | 103914 | sqlite3_bind_int(pNextIdx, 1, iLevel); |
| 103497 | 103915 | if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ |
| 103498 | - iNext = sqlite3_column_int64(pNextIdx, 0); | |
| 103916 | + iNext = sqlite3_column_int(pNextIdx, 0); | |
| 103499 | 103917 | } |
| 103500 | 103918 | rc = sqlite3_reset(pNextIdx); |
| 103501 | 103919 | } |
| 103502 | 103920 | |
| 103503 | 103921 | if( rc==SQLITE_OK ){ |
| @@ -103611,11 +104029,11 @@ | ||
| 103611 | 104029 | /* If required, populate the output variables with a pointer to and the |
| 103612 | 104030 | ** size of the previous offset-list. |
| 103613 | 104031 | */ |
| 103614 | 104032 | if( ppOffsetList ){ |
| 103615 | 104033 | *ppOffsetList = pReader->pOffsetList; |
| 103616 | - *pnOffsetList = p - pReader->pOffsetList - 1; | |
| 104034 | + *pnOffsetList = (int)(p - pReader->pOffsetList - 1); | |
| 103617 | 104035 | } |
| 103618 | 104036 | |
| 103619 | 104037 | /* If there are no more entries in the doclist, set pOffsetList to |
| 103620 | 104038 | ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and |
| 103621 | 104039 | ** Fts3SegReader.pOffsetList to point to the next offset list before |
| @@ -103683,12 +104101,10 @@ | ||
| 103683 | 104101 | /* The entire segment is stored in the root node. */ |
| 103684 | 104102 | pReader->aNode = (char *)&pReader[1]; |
| 103685 | 104103 | pReader->nNode = nRoot; |
| 103686 | 104104 | memcpy(pReader->aNode, zRoot, nRoot); |
| 103687 | 104105 | }else{ |
| 103688 | - sqlite3_stmt *pStmt; | |
| 103689 | - | |
| 103690 | 104106 | /* If the text of the SQL statement to iterate through a contiguous |
| 103691 | 104107 | ** set of entries in the %_segments table has not yet been composed, |
| 103692 | 104108 | ** compose it now. |
| 103693 | 104109 | */ |
| 103694 | 104110 | if( !p->zSelectLeaves ){ |
| @@ -103966,10 +104382,11 @@ | ||
| 103966 | 104382 | int nPrev, /* Size of buffer zPrev in bytes */ |
| 103967 | 104383 | const char *zNext, /* Buffer containing next term */ |
| 103968 | 104384 | int nNext /* Size of buffer zNext in bytes */ |
| 103969 | 104385 | ){ |
| 103970 | 104386 | int n; |
| 104387 | + UNUSED_PARAMETER(nNext); | |
| 103971 | 104388 | for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++); |
| 103972 | 104389 | return n; |
| 103973 | 104390 | } |
| 103974 | 104391 | |
| 103975 | 104392 | /* |
| @@ -103998,17 +104415,17 @@ | ||
| 103998 | 104415 | |
| 103999 | 104416 | nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); |
| 104000 | 104417 | nSuffix = nTerm-nPrefix; |
| 104001 | 104418 | |
| 104002 | 104419 | nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; |
| 104003 | - if( nReq<=INTERIOR_MAX || !pTree->zTerm ){ | |
| 104420 | + if( nReq<=p->nNodeSize || !pTree->zTerm ){ | |
| 104004 | 104421 | |
| 104005 | - if( nReq>INTERIOR_MAX ){ | |
| 104422 | + if( nReq>p->nNodeSize ){ | |
| 104006 | 104423 | /* An unusual case: this is the first term to be added to the node |
| 104007 | - ** and the static node buffer (INTERIOR_MAX bytes) is not large | |
| 104424 | + ** and the static node buffer (p->nNodeSize bytes) is not large | |
| 104008 | 104425 | ** enough. Use a separately malloced buffer instead This wastes |
| 104009 | - ** INTERIOR_MAX bytes, but since this scenario only comes about when | |
| 104426 | + ** p->nNodeSize bytes, but since this scenario only comes about when | |
| 104010 | 104427 | ** the database contain two terms that share a prefix of almost 2KB, |
| 104011 | 104428 | ** this is not expected to be a serious problem. |
| 104012 | 104429 | */ |
| 104013 | 104430 | assert( pTree->aData==(char *)&pTree[1] ); |
| 104014 | 104431 | pTree->aData = (char *)sqlite3_malloc(nReq); |
| @@ -104053,11 +104470,11 @@ | ||
| 104053 | 104470 | ** |
| 104054 | 104471 | ** Otherwise, the term is not added to the new node, it is left empty for |
| 104055 | 104472 | ** now. Instead, the term is inserted into the parent of pTree. If pTree |
| 104056 | 104473 | ** has no parent, one is created here. |
| 104057 | 104474 | */ |
| 104058 | - pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + INTERIOR_MAX); | |
| 104475 | + pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); | |
| 104059 | 104476 | if( !pNew ){ |
| 104060 | 104477 | return SQLITE_NOMEM; |
| 104061 | 104478 | } |
| 104062 | 104479 | memset(pNew, 0, sizeof(SegmentNode)); |
| 104063 | 104480 | pNew->nData = 1 + FTS3_VARINT_MAX; |
| @@ -104206,13 +104623,13 @@ | ||
| 104206 | 104623 | if( !pWriter ) return SQLITE_NOMEM; |
| 104207 | 104624 | memset(pWriter, 0, sizeof(SegmentWriter)); |
| 104208 | 104625 | *ppWriter = pWriter; |
| 104209 | 104626 | |
| 104210 | 104627 | /* Allocate a buffer in which to accumulate data */ |
| 104211 | - pWriter->aData = (char *)sqlite3_malloc(LEAF_MAX); | |
| 104628 | + pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize); | |
| 104212 | 104629 | if( !pWriter->aData ) return SQLITE_NOMEM; |
| 104213 | - pWriter->nSize = LEAF_MAX; | |
| 104630 | + pWriter->nSize = p->nNodeSize; | |
| 104214 | 104631 | |
| 104215 | 104632 | /* Find the next free blockid in the %_segments table */ |
| 104216 | 104633 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); |
| 104217 | 104634 | if( rc!=SQLITE_OK ) return rc; |
| 104218 | 104635 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| @@ -104232,11 +104649,11 @@ | ||
| 104232 | 104649 | sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ |
| 104233 | 104650 | nSuffix + /* Term suffix */ |
| 104234 | 104651 | sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ |
| 104235 | 104652 | nDoclist; /* Doclist data */ |
| 104236 | 104653 | |
| 104237 | - if( nData>0 && nData+nReq>LEAF_MAX ){ | |
| 104654 | + if( nData>0 && nData+nReq>p->nNodeSize ){ | |
| 104238 | 104655 | int rc; |
| 104239 | 104656 | |
| 104240 | 104657 | /* The current leaf node is full. Write it out to the database. */ |
| 104241 | 104658 | rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); |
| 104242 | 104659 | if( rc!=SQLITE_OK ) return rc; |
| @@ -104326,14 +104743,14 @@ | ||
| 104326 | 104743 | int iLevel, /* Value for 'level' column of %_segdir */ |
| 104327 | 104744 | int iIdx /* Value for 'idx' column of %_segdir */ |
| 104328 | 104745 | ){ |
| 104329 | 104746 | int rc; /* Return code */ |
| 104330 | 104747 | if( pWriter->pTree ){ |
| 104331 | - sqlite3_int64 iLast; /* Largest block id written to database */ | |
| 104748 | + sqlite3_int64 iLast = 0; /* Largest block id written to database */ | |
| 104332 | 104749 | sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ |
| 104333 | - char *zRoot; /* Pointer to buffer containing root node */ | |
| 104334 | - int nRoot; /* Size of buffer zRoot */ | |
| 104750 | + char *zRoot = NULL; /* Pointer to buffer containing root node */ | |
| 104751 | + int nRoot = 0; /* Size of buffer zRoot */ | |
| 104335 | 104752 | |
| 104336 | 104753 | iLastLeaf = pWriter->iFree; |
| 104337 | 104754 | rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); |
| 104338 | 104755 | if( rc==SQLITE_OK ){ |
| 104339 | 104756 | rc = fts3NodeWrite(p, pWriter->pTree, 1, |
| @@ -104502,15 +104919,15 @@ | ||
| 104502 | 104919 | while( 1 ){ |
| 104503 | 104920 | char c = 0; |
| 104504 | 104921 | while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80; |
| 104505 | 104922 | |
| 104506 | 104923 | if( iCol==iCurrent ){ |
| 104507 | - nList = (p - pList); | |
| 104924 | + nList = (int)(p - pList); | |
| 104508 | 104925 | break; |
| 104509 | 104926 | } |
| 104510 | 104927 | |
| 104511 | - nList -= (p - pList); | |
| 104928 | + nList -= (int)(p - pList); | |
| 104512 | 104929 | pList = p; |
| 104513 | 104930 | if( nList==0 ){ |
| 104514 | 104931 | break; |
| 104515 | 104932 | } |
| 104516 | 104933 | p = &pList[1]; |
| @@ -104577,10 +104994,15 @@ | ||
| 104577 | 104994 | |
| 104578 | 104995 | int isIgnoreEmpty = (pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); |
| 104579 | 104996 | int isRequirePos = (pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); |
| 104580 | 104997 | int isColFilter = (pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); |
| 104581 | 104998 | int isPrefix = (pFilter->flags & FTS3_SEGMENT_PREFIX); |
| 104999 | + | |
| 105000 | + /* If there are zero segments, this function is a no-op. This scenario | |
| 105001 | + ** comes about only when reading from an empty database. | |
| 105002 | + */ | |
| 105003 | + if( nSegment==0 ) goto finished; | |
| 104582 | 105004 | |
| 104583 | 105005 | /* If the Fts3SegFilter defines a specific term (or term prefix) to search |
| 104584 | 105006 | ** for, then advance each segment iterator until it points to a term of |
| 104585 | 105007 | ** equal or greater value than the specified term. This prevents many |
| 104586 | 105008 | ** unnecessary merge/sort operations for the case where single segment |
| @@ -104906,11 +105328,11 @@ | ||
| 104906 | 105328 | sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ |
| 104907 | 105329 | ){ |
| 104908 | 105330 | Fts3Table *p = (Fts3Table *)pVtab; |
| 104909 | 105331 | int rc = SQLITE_OK; /* Return Code */ |
| 104910 | 105332 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 104911 | - sqlite3_int64 iRemove; /* Rowid removed by UPDATE or DELETE */ | |
| 105333 | + sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */ | |
| 104912 | 105334 | |
| 104913 | 105335 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 104914 | 105336 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 104915 | 105337 | int isEmpty; |
| 104916 | 105338 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| @@ -104953,13 +105375,22 @@ | ||
| 104953 | 105375 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| 104954 | 105376 | ** merge all segments in the database (including the new segment, if |
| 104955 | 105377 | ** there was any data to flush) into a single segment. |
| 104956 | 105378 | */ |
| 104957 | 105379 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ |
| 104958 | - int rc = sqlite3Fts3PendingTermsFlush(p); | |
| 105380 | + int rc; | |
| 105381 | + rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); | |
| 104959 | 105382 | if( rc==SQLITE_OK ){ |
| 104960 | - rc = fts3SegmentMerge(p, -1); | |
| 105383 | + rc = sqlite3Fts3PendingTermsFlush(p); | |
| 105384 | + if( rc==SQLITE_OK ){ | |
| 105385 | + rc = fts3SegmentMerge(p, -1); | |
| 105386 | + } | |
| 105387 | + if( rc==SQLITE_OK ){ | |
| 105388 | + rc = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); | |
| 105389 | + }else{ | |
| 105390 | + sqlite3_exec(p->db, "ROLLBACK TO fts3 ; RELEASE fts3", 0, 0, 0); | |
| 105391 | + } | |
| 104961 | 105392 | } |
| 104962 | 105393 | return rc; |
| 104963 | 105394 | } |
| 104964 | 105395 | |
| 104965 | 105396 | #endif |
| @@ -104991,14 +105422,14 @@ | ||
| 104991 | 105422 | struct Snippet { |
| 104992 | 105423 | int nMatch; /* Total number of matches */ |
| 104993 | 105424 | int nAlloc; /* Space allocated for aMatch[] */ |
| 104994 | 105425 | struct snippetMatch { /* One entry for each matching term */ |
| 104995 | 105426 | char snStatus; /* Status flag for use while constructing snippets */ |
| 105427 | + short int nByte; /* Number of bytes in the term */ | |
| 104996 | 105428 | short int iCol; /* The column that contains the match */ |
| 104997 | 105429 | short int iTerm; /* The index in Query.pTerms[] of the matching term */ |
| 104998 | 105430 | int iToken; /* The index of the matching document token */ |
| 104999 | - short int nByte; /* Number of bytes in the term */ | |
| 105000 | 105431 | int iStart; /* The offset to the first character of the term */ |
| 105001 | 105432 | } *aMatch; /* Points to space obtained from malloc */ |
| 105002 | 105433 | char *zOffset; /* Text rendering of aMatch[] */ |
| 105003 | 105434 | int nOffset; /* strlen(zOffset) */ |
| 105004 | 105435 | char *zSnippet; /* Snippet text */ |
| @@ -105008,171 +105439,125 @@ | ||
| 105008 | 105439 | |
| 105009 | 105440 | /* It is not safe to call isspace(), tolower(), or isalnum() on |
| 105010 | 105441 | ** hi-bit-set characters. This is the same solution used in the |
| 105011 | 105442 | ** tokenizer. |
| 105012 | 105443 | */ |
| 105013 | -/* TODO(shess) The snippet-generation code should be using the | |
| 105014 | -** tokenizer-generated tokens rather than doing its own local | |
| 105015 | -** tokenization. | |
| 105016 | -*/ | |
| 105017 | -/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ | |
| 105018 | -static int safe_isspace(char c){ | |
| 105444 | +static int fts3snippetIsspace(char c){ | |
| 105019 | 105445 | return (c&0x80)==0 ? isspace(c) : 0; |
| 105020 | 105446 | } |
| 105021 | -static int safe_isalnum(char c){ | |
| 105022 | - return (c&0x80)==0 ? isalnum(c) : 0; | |
| 105023 | -} | |
| 105024 | - | |
| 105025 | -/*******************************************************************/ | |
| 105026 | -/* DataBuffer is used to collect data into a buffer in piecemeal | |
| 105027 | -** fashion. It implements the usual distinction between amount of | |
| 105028 | -** data currently stored (nData) and buffer capacity (nCapacity). | |
| 105029 | -** | |
| 105030 | -** dataBufferInit - create a buffer with given initial capacity. | |
| 105031 | -** dataBufferReset - forget buffer's data, retaining capacity. | |
| 105032 | -** dataBufferSwap - swap contents of two buffers. | |
| 105033 | -** dataBufferExpand - expand capacity without adding data. | |
| 105034 | -** dataBufferAppend - append data. | |
| 105035 | -** dataBufferAppend2 - append two pieces of data at once. | |
| 105036 | -** dataBufferReplace - replace buffer's data. | |
| 105037 | -*/ | |
| 105038 | -typedef struct DataBuffer { | |
| 105039 | - char *pData; /* Pointer to malloc'ed buffer. */ | |
| 105040 | - int nCapacity; /* Size of pData buffer. */ | |
| 105041 | - int nData; /* End of data loaded into pData. */ | |
| 105042 | -} DataBuffer; | |
| 105043 | - | |
| 105044 | -static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){ | |
| 105045 | - assert( nCapacity>=0 ); | |
| 105046 | - pBuffer->nData = 0; | |
| 105047 | - pBuffer->nCapacity = nCapacity; | |
| 105048 | - pBuffer->pData = nCapacity==0 ? NULL : sqlite3_malloc(nCapacity); | |
| 105049 | -} | |
| 105050 | -static void dataBufferReset(DataBuffer *pBuffer){ | |
| 105051 | - pBuffer->nData = 0; | |
| 105052 | -} | |
| 105053 | -static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){ | |
| 105054 | - assert( nAddCapacity>0 ); | |
| 105055 | - /* TODO(shess) Consider expanding more aggressively. Note that the | |
| 105056 | - ** underlying malloc implementation may take care of such things for | |
| 105057 | - ** us already. | |
| 105058 | - */ | |
| 105059 | - if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){ | |
| 105060 | - pBuffer->nCapacity = pBuffer->nData+nAddCapacity; | |
| 105061 | - pBuffer->pData = sqlite3_realloc(pBuffer->pData, pBuffer->nCapacity); | |
| 105062 | - } | |
| 105063 | -} | |
| 105064 | -static void dataBufferAppend(DataBuffer *pBuffer, | |
| 105065 | - const char *pSource, int nSource){ | |
| 105066 | - assert( nSource>0 && pSource!=NULL ); | |
| 105067 | - dataBufferExpand(pBuffer, nSource); | |
| 105068 | - memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource); | |
| 105069 | - pBuffer->nData += nSource; | |
| 105070 | -} | |
| 105071 | -static void dataBufferAppend2(DataBuffer *pBuffer, | |
| 105072 | - const char *pSource1, int nSource1, | |
| 105073 | - const char *pSource2, int nSource2){ | |
| 105074 | - assert( nSource1>0 && pSource1!=NULL ); | |
| 105075 | - assert( nSource2>0 && pSource2!=NULL ); | |
| 105076 | - dataBufferExpand(pBuffer, nSource1+nSource2); | |
| 105077 | - memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1); | |
| 105078 | - memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2); | |
| 105079 | - pBuffer->nData += nSource1+nSource2; | |
| 105080 | -} | |
| 105081 | -static void dataBufferReplace(DataBuffer *pBuffer, | |
| 105082 | - const char *pSource, int nSource){ | |
| 105083 | - dataBufferReset(pBuffer); | |
| 105084 | - dataBufferAppend(pBuffer, pSource, nSource); | |
| 105085 | -} | |
| 105086 | - | |
| 105087 | - | |
| 105088 | -/* StringBuffer is a null-terminated version of DataBuffer. */ | |
| 105447 | + | |
| 105448 | + | |
| 105449 | +/* | |
| 105450 | +** A StringBuffer object holds a zero-terminated string that grows | |
| 105451 | +** arbitrarily by appending. Space to hold the string is obtained | |
| 105452 | +** from sqlite3_malloc(). After any memory allocation failure, | |
| 105453 | +** StringBuffer.z is set to NULL and no further allocation is attempted. | |
| 105454 | +*/ | |
| 105089 | 105455 | typedef struct StringBuffer { |
| 105090 | - DataBuffer b; /* Includes null terminator. */ | |
| 105456 | + char *z; /* Text of the string. Space from malloc. */ | |
| 105457 | + int nUsed; /* Number bytes of z[] used, not counting \000 terminator */ | |
| 105458 | + int nAlloc; /* Bytes allocated for z[] */ | |
| 105091 | 105459 | } StringBuffer; |
| 105092 | 105460 | |
| 105093 | -static void initStringBuffer(StringBuffer *sb){ | |
| 105094 | - dataBufferInit(&sb->b, 100); | |
| 105095 | - dataBufferReplace(&sb->b, "", 1); | |
| 105096 | -} | |
| 105097 | -static int stringBufferLength(StringBuffer *sb){ | |
| 105098 | - return sb->b.nData-1; | |
| 105099 | -} | |
| 105100 | -static char *stringBufferData(StringBuffer *sb){ | |
| 105101 | - return sb->b.pData; | |
| 105102 | -} | |
| 105103 | - | |
| 105104 | -static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){ | |
| 105105 | - assert( sb->b.nData>0 ); | |
| 105106 | - if( nFrom>0 ){ | |
| 105107 | - sb->b.nData--; | |
| 105108 | - dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1); | |
| 105109 | - } | |
| 105110 | -} | |
| 105111 | -static void append(StringBuffer *sb, const char *zFrom){ | |
| 105112 | - nappend(sb, zFrom, strlen(zFrom)); | |
| 105113 | -} | |
| 105114 | - | |
| 105115 | -static int endsInWhiteSpace(StringBuffer *p){ | |
| 105116 | - return stringBufferLength(p)>0 && | |
| 105117 | - safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]); | |
| 105461 | + | |
| 105462 | +/* | |
| 105463 | +** Initialize a new StringBuffer. | |
| 105464 | +*/ | |
| 105465 | +static void fts3SnippetSbInit(StringBuffer *p){ | |
| 105466 | + p->nAlloc = 100; | |
| 105467 | + p->nUsed = 0; | |
| 105468 | + p->z = sqlite3_malloc( p->nAlloc ); | |
| 105469 | +} | |
| 105470 | + | |
| 105471 | +/* | |
| 105472 | +** Append text to the string buffer. | |
| 105473 | +*/ | |
| 105474 | +static void fts3SnippetAppend(StringBuffer *p, const char *zNew, int nNew){ | |
| 105475 | + if( p->z==0 ) return; | |
| 105476 | + if( nNew<0 ) nNew = (int)strlen(zNew); | |
| 105477 | + if( p->nUsed + nNew >= p->nAlloc ){ | |
| 105478 | + int nAlloc; | |
| 105479 | + char *zNew; | |
| 105480 | + | |
| 105481 | + nAlloc = p->nUsed + nNew + p->nAlloc; | |
| 105482 | + zNew = sqlite3_realloc(p->z, nAlloc); | |
| 105483 | + if( zNew==0 ){ | |
| 105484 | + sqlite3_free(p->z); | |
| 105485 | + p->z = 0; | |
| 105486 | + return; | |
| 105487 | + } | |
| 105488 | + p->z = zNew; | |
| 105489 | + p->nAlloc = nAlloc; | |
| 105490 | + } | |
| 105491 | + memcpy(&p->z[p->nUsed], zNew, nNew); | |
| 105492 | + p->nUsed += nNew; | |
| 105493 | + p->z[p->nUsed] = 0; | |
| 105118 | 105494 | } |
| 105119 | 105495 | |
| 105120 | 105496 | /* If the StringBuffer ends in something other than white space, add a |
| 105121 | 105497 | ** single space character to the end. |
| 105122 | 105498 | */ |
| 105123 | -static void appendWhiteSpace(StringBuffer *p){ | |
| 105124 | - if( stringBufferLength(p)==0 ) return; | |
| 105125 | - if( !endsInWhiteSpace(p) ) append(p, " "); | |
| 105499 | +static void fts3SnippetAppendWhiteSpace(StringBuffer *p){ | |
| 105500 | + if( p->z && p->nUsed && !fts3snippetIsspace(p->z[p->nUsed-1]) ){ | |
| 105501 | + fts3SnippetAppend(p, " ", 1); | |
| 105502 | + } | |
| 105126 | 105503 | } |
| 105127 | 105504 | |
| 105128 | 105505 | /* Remove white space from the end of the StringBuffer */ |
| 105129 | -static void trimWhiteSpace(StringBuffer *p){ | |
| 105130 | - while( endsInWhiteSpace(p) ){ | |
| 105131 | - p->b.pData[--p->b.nData-1] = '\0'; | |
| 105506 | +static void fts3SnippetTrimWhiteSpace(StringBuffer *p){ | |
| 105507 | + if( p->z ){ | |
| 105508 | + while( p->nUsed && fts3snippetIsspace(p->z[p->nUsed-1]) ){ | |
| 105509 | + p->nUsed--; | |
| 105510 | + } | |
| 105511 | + p->z[p->nUsed] = 0; | |
| 105132 | 105512 | } |
| 105133 | 105513 | } |
| 105134 | - | |
| 105135 | 105514 | |
| 105136 | 105515 | /* |
| 105137 | 105516 | ** Release all memory associated with the Snippet structure passed as |
| 105138 | 105517 | ** an argument. |
| 105139 | 105518 | */ |
| 105140 | 105519 | static void fts3SnippetFree(Snippet *p){ |
| 105141 | - sqlite3_free(p->aMatch); | |
| 105142 | - sqlite3_free(p->zOffset); | |
| 105143 | - sqlite3_free(p->zSnippet); | |
| 105144 | - sqlite3_free(p); | |
| 105520 | + if( p ){ | |
| 105521 | + sqlite3_free(p->aMatch); | |
| 105522 | + sqlite3_free(p->zOffset); | |
| 105523 | + sqlite3_free(p->zSnippet); | |
| 105524 | + sqlite3_free(p); | |
| 105525 | + } | |
| 105145 | 105526 | } |
| 105146 | 105527 | |
| 105147 | 105528 | /* |
| 105148 | 105529 | ** Append a single entry to the p->aMatch[] log. |
| 105149 | 105530 | */ |
| 105150 | -static void snippetAppendMatch( | |
| 105531 | +static int snippetAppendMatch( | |
| 105151 | 105532 | Snippet *p, /* Append the entry to this snippet */ |
| 105152 | 105533 | int iCol, int iTerm, /* The column and query term */ |
| 105153 | 105534 | int iToken, /* Matching token in document */ |
| 105154 | 105535 | int iStart, int nByte /* Offset and size of the match */ |
| 105155 | 105536 | ){ |
| 105156 | 105537 | int i; |
| 105157 | 105538 | struct snippetMatch *pMatch; |
| 105158 | 105539 | if( p->nMatch+1>=p->nAlloc ){ |
| 105540 | + struct snippetMatch *pNew; | |
| 105159 | 105541 | p->nAlloc = p->nAlloc*2 + 10; |
| 105160 | - p->aMatch = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); | |
| 105161 | - if( p->aMatch==0 ){ | |
| 105542 | + pNew = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); | |
| 105543 | + if( pNew==0 ){ | |
| 105544 | + p->aMatch = 0; | |
| 105162 | 105545 | p->nMatch = 0; |
| 105163 | 105546 | p->nAlloc = 0; |
| 105164 | - return; | |
| 105547 | + return SQLITE_NOMEM; | |
| 105165 | 105548 | } |
| 105549 | + p->aMatch = pNew; | |
| 105166 | 105550 | } |
| 105167 | 105551 | i = p->nMatch++; |
| 105168 | 105552 | pMatch = &p->aMatch[i]; |
| 105169 | - pMatch->iCol = iCol; | |
| 105170 | - pMatch->iTerm = iTerm; | |
| 105553 | + pMatch->iCol = (short)iCol; | |
| 105554 | + pMatch->iTerm = (short)iTerm; | |
| 105171 | 105555 | pMatch->iToken = iToken; |
| 105172 | 105556 | pMatch->iStart = iStart; |
| 105173 | - pMatch->nByte = nByte; | |
| 105557 | + pMatch->nByte = (short)nByte; | |
| 105558 | + return SQLITE_OK; | |
| 105174 | 105559 | } |
| 105175 | 105560 | |
| 105176 | 105561 | /* |
| 105177 | 105562 | ** Sizing information for the circular buffer used in snippetOffsetsOfColumn() |
| 105178 | 105563 | */ |
| @@ -105242,11 +105627,11 @@ | ||
| 105242 | 105627 | |
| 105243 | 105628 | /* |
| 105244 | 105629 | ** Add entries to pSnippet->aMatch[] for every match that occurs against |
| 105245 | 105630 | ** document zDoc[0..nDoc-1] which is stored in column iColumn. |
| 105246 | 105631 | */ |
| 105247 | -static void snippetOffsetsOfColumn( | |
| 105632 | +static int snippetOffsetsOfColumn( | |
| 105248 | 105633 | Fts3Cursor *pCur, /* The fulltest search cursor */ |
| 105249 | 105634 | Snippet *pSnippet, /* The Snippet object to be filled in */ |
| 105250 | 105635 | int iColumn, /* Index of fulltext table column */ |
| 105251 | 105636 | const char *zDoc, /* Text of the fulltext table column */ |
| 105252 | 105637 | int nDoc /* Length of zDoc in bytes */ |
| @@ -105272,15 +105657,16 @@ | ||
| 105272 | 105657 | pVtab = (Fts3Table *)pCur->base.pVtab; |
| 105273 | 105658 | nColumn = pVtab->nColumn; |
| 105274 | 105659 | pTokenizer = pVtab->pTokenizer; |
| 105275 | 105660 | pTModule = pTokenizer->pModule; |
| 105276 | 105661 | rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); |
| 105277 | - if( rc ) return; | |
| 105662 | + if( rc ) return rc; | |
| 105278 | 105663 | pTCursor->pTokenizer = pTokenizer; |
| 105279 | 105664 | |
| 105280 | 105665 | prevMatch = 0; |
| 105281 | - while( !pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos) ){ | |
| 105666 | + while( (rc = pTModule->xNext(pTCursor, &zToken, &nToken, | |
| 105667 | + &iBegin, &iEnd, &iPos))==SQLITE_OK ){ | |
| 105282 | 105668 | Fts3Expr *pIter = pCur->pExpr; |
| 105283 | 105669 | int iIter = -1; |
| 105284 | 105670 | iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; |
| 105285 | 105671 | iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; |
| 105286 | 105672 | match = 0; |
| @@ -105301,19 +105687,22 @@ | ||
| 105301 | 105687 | if( iIter>0 && (prevMatch & (1<<i))==0 ) continue; |
| 105302 | 105688 | match |= 1<<i; |
| 105303 | 105689 | if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){ |
| 105304 | 105690 | for(j=nPhrase-1; j>=0; j--){ |
| 105305 | 105691 | int k = (iRotor-j) & FTS3_ROTOR_MASK; |
| 105306 | - snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, | |
| 105307 | - iRotorBegin[k], iRotorLen[k]); | |
| 105692 | + rc = snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, | |
| 105693 | + iRotorBegin[k], iRotorLen[k]); | |
| 105694 | + if( rc ) goto end_offsets_of_column; | |
| 105308 | 105695 | } |
| 105309 | 105696 | } |
| 105310 | 105697 | } |
| 105311 | 105698 | prevMatch = match<<1; |
| 105312 | 105699 | iRotor++; |
| 105313 | 105700 | } |
| 105701 | +end_offsets_of_column: | |
| 105314 | 105702 | pTModule->xClose(pTCursor); |
| 105703 | + return rc==SQLITE_DONE ? SQLITE_OK : rc; | |
| 105315 | 105704 | } |
| 105316 | 105705 | |
| 105317 | 105706 | /* |
| 105318 | 105707 | ** Remove entries from the pSnippet structure to account for the NEAR |
| 105319 | 105708 | ** operator. When this is called, pSnippet contains the list of token |
| @@ -105445,16 +105834,19 @@ | ||
| 105445 | 105834 | /* |
| 105446 | 105835 | ** Compute all offsets for the current row of the query. |
| 105447 | 105836 | ** If the offsets have already been computed, this routine is a no-op. |
| 105448 | 105837 | */ |
| 105449 | 105838 | static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){ |
| 105450 | - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; | |
| 105451 | - int nColumn; | |
| 105452 | - int iColumn, i; | |
| 105453 | - int iFirst, iLast; | |
| 105839 | + Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; /* The FTS3 virtual table */ | |
| 105840 | + int nColumn; /* Number of columns. Docid does count */ | |
| 105841 | + int iColumn; /* Index of of a column */ | |
| 105842 | + int i; /* Loop index */ | |
| 105843 | + int iFirst; /* First column to search */ | |
| 105844 | + int iLast; /* Last coumn to search */ | |
| 105454 | 105845 | int iTerm = 0; |
| 105455 | 105846 | Snippet *pSnippet; |
| 105847 | + int rc = SQLITE_OK; | |
| 105456 | 105848 | |
| 105457 | 105849 | if( pCsr->pExpr==0 ){ |
| 105458 | 105850 | return SQLITE_OK; |
| 105459 | 105851 | } |
| 105460 | 105852 | |
| @@ -105464,33 +105856,37 @@ | ||
| 105464 | 105856 | return SQLITE_NOMEM; |
| 105465 | 105857 | } |
| 105466 | 105858 | memset(pSnippet, 0, sizeof(Snippet)); |
| 105467 | 105859 | |
| 105468 | 105860 | nColumn = p->nColumn; |
| 105469 | - iColumn = (pCsr->eType - 2); | |
| 105861 | + iColumn = (pCsr->eSearch - 2); | |
| 105470 | 105862 | if( iColumn<0 || iColumn>=nColumn ){ |
| 105471 | 105863 | /* Look for matches over all columns of the full-text index */ |
| 105472 | 105864 | iFirst = 0; |
| 105473 | 105865 | iLast = nColumn-1; |
| 105474 | 105866 | }else{ |
| 105475 | 105867 | /* Look for matches in the iColumn-th column of the index only */ |
| 105476 | 105868 | iFirst = iColumn; |
| 105477 | 105869 | iLast = iColumn; |
| 105478 | 105870 | } |
| 105479 | - for(i=iFirst; i<=iLast; i++){ | |
| 105871 | + for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ | |
| 105480 | 105872 | const char *zDoc; |
| 105481 | 105873 | int nDoc; |
| 105482 | 105874 | zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1); |
| 105483 | 105875 | nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1); |
| 105484 | - snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc); | |
| 105876 | + if( zDoc==0 && sqlite3_column_type(pCsr->pStmt, i+1)!=SQLITE_NULL ){ | |
| 105877 | + rc = SQLITE_NOMEM; | |
| 105878 | + }else{ | |
| 105879 | + rc = snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc); | |
| 105880 | + } | |
| 105485 | 105881 | } |
| 105486 | 105882 | |
| 105487 | 105883 | while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){ |
| 105488 | 105884 | iTerm = 0; |
| 105489 | 105885 | } |
| 105490 | 105886 | |
| 105491 | - return SQLITE_OK; | |
| 105887 | + return rc; | |
| 105492 | 105888 | } |
| 105493 | 105889 | |
| 105494 | 105890 | /* |
| 105495 | 105891 | ** Convert the information in the aMatch[] array of the snippet |
| 105496 | 105892 | ** into the string zOffset[0..nOffset-1]. This string is used as |
| @@ -105500,11 +105896,11 @@ | ||
| 105500 | 105896 | int i; |
| 105501 | 105897 | int cnt = 0; |
| 105502 | 105898 | StringBuffer sb; |
| 105503 | 105899 | char zBuf[200]; |
| 105504 | 105900 | if( p->zOffset ) return; |
| 105505 | - initStringBuffer(&sb); | |
| 105901 | + fts3SnippetSbInit(&sb); | |
| 105506 | 105902 | for(i=0; i<p->nMatch; i++){ |
| 105507 | 105903 | struct snippetMatch *pMatch = &p->aMatch[i]; |
| 105508 | 105904 | if( pMatch->iTerm>=0 ){ |
| 105509 | 105905 | /* If snippetMatch.iTerm is less than 0, then the match was |
| 105510 | 105906 | ** discarded as part of processing the NEAR operator (see the |
| @@ -105512,16 +105908,16 @@ | ||
| 105512 | 105908 | ** it in this case |
| 105513 | 105909 | */ |
| 105514 | 105910 | zBuf[0] = ' '; |
| 105515 | 105911 | sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d", |
| 105516 | 105912 | pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte); |
| 105517 | - append(&sb, zBuf); | |
| 105913 | + fts3SnippetAppend(&sb, zBuf, -1); | |
| 105518 | 105914 | cnt++; |
| 105519 | 105915 | } |
| 105520 | 105916 | } |
| 105521 | - p->zOffset = stringBufferData(&sb); | |
| 105522 | - p->nOffset = stringBufferLength(&sb); | |
| 105917 | + p->zOffset = sb.z; | |
| 105918 | + p->nOffset = sb.z ? sb.nUsed : 0; | |
| 105523 | 105919 | } |
| 105524 | 105920 | |
| 105525 | 105921 | /* |
| 105526 | 105922 | ** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set |
| 105527 | 105923 | ** of matching words some of which might be in zDoc. zDoc is column |
| @@ -105544,11 +105940,11 @@ | ||
| 105544 | 105940 | return 0; |
| 105545 | 105941 | } |
| 105546 | 105942 | if( iBreak>=nDoc-10 ){ |
| 105547 | 105943 | return nDoc; |
| 105548 | 105944 | } |
| 105549 | - for(i=0; i<nMatch && aMatch[i].iCol<iCol; i++){} | |
| 105945 | + for(i=0; ALWAYS(i<nMatch) && aMatch[i].iCol<iCol; i++){} | |
| 105550 | 105946 | while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; } |
| 105551 | 105947 | if( i<nMatch ){ |
| 105552 | 105948 | if( aMatch[i].iStart<iBreak+10 ){ |
| 105553 | 105949 | return aMatch[i].iStart; |
| 105554 | 105950 | } |
| @@ -105555,14 +105951,14 @@ | ||
| 105555 | 105951 | if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ |
| 105556 | 105952 | return aMatch[i-1].iStart; |
| 105557 | 105953 | } |
| 105558 | 105954 | } |
| 105559 | 105955 | for(i=1; i<=10; i++){ |
| 105560 | - if( safe_isspace(zDoc[iBreak-i]) ){ | |
| 105956 | + if( fts3snippetIsspace(zDoc[iBreak-i]) ){ | |
| 105561 | 105957 | return iBreak - i + 1; |
| 105562 | 105958 | } |
| 105563 | - if( safe_isspace(zDoc[iBreak+i]) ){ | |
| 105959 | + if( fts3snippetIsspace(zDoc[iBreak+i]) ){ | |
| 105564 | 105960 | return iBreak + i + 1; |
| 105565 | 105961 | } |
| 105566 | 105962 | } |
| 105567 | 105963 | return iBreak; |
| 105568 | 105964 | } |
| @@ -105602,11 +105998,11 @@ | ||
| 105602 | 105998 | |
| 105603 | 105999 | sqlite3_free(pSnippet->zSnippet); |
| 105604 | 106000 | pSnippet->zSnippet = 0; |
| 105605 | 106001 | aMatch = pSnippet->aMatch; |
| 105606 | 106002 | nMatch = pSnippet->nMatch; |
| 105607 | - initStringBuffer(&sb); | |
| 106003 | + fts3SnippetSbInit(&sb); | |
| 105608 | 106004 | |
| 105609 | 106005 | for(i=0; i<nMatch; i++){ |
| 105610 | 106006 | aMatch[i].snStatus = SNIPPET_IGNORE; |
| 105611 | 106007 | } |
| 105612 | 106008 | nDesired = 0; |
| @@ -105636,14 +106032,14 @@ | ||
| 105636 | 106032 | } |
| 105637 | 106033 | if( iCol==tailCol && iStart<=tailOffset+20 ){ |
| 105638 | 106034 | iStart = tailOffset; |
| 105639 | 106035 | } |
| 105640 | 106036 | if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ |
| 105641 | - trimWhiteSpace(&sb); | |
| 105642 | - appendWhiteSpace(&sb); | |
| 105643 | - append(&sb, zEllipsis); | |
| 105644 | - appendWhiteSpace(&sb); | |
| 106037 | + fts3SnippetTrimWhiteSpace(&sb); | |
| 106038 | + fts3SnippetAppendWhiteSpace(&sb); | |
| 106039 | + fts3SnippetAppend(&sb, zEllipsis, -1); | |
| 106040 | + fts3SnippetAppendWhiteSpace(&sb); | |
| 105645 | 106041 | } |
| 105646 | 106042 | iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; |
| 105647 | 106043 | iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); |
| 105648 | 106044 | if( iEnd>=nDoc-10 ){ |
| 105649 | 106045 | iEnd = nDoc; |
| @@ -105657,48 +106053,56 @@ | ||
| 105657 | 106053 | && aMatch[iMatch].iCol<=iCol ){ |
| 105658 | 106054 | iMatch++; |
| 105659 | 106055 | } |
| 105660 | 106056 | if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd |
| 105661 | 106057 | && aMatch[iMatch].iCol==iCol ){ |
| 105662 | - nappend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart); | |
| 106058 | + fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart); | |
| 105663 | 106059 | iStart = aMatch[iMatch].iStart; |
| 105664 | - append(&sb, zStartMark); | |
| 105665 | - nappend(&sb, &zDoc[iStart], aMatch[iMatch].nByte); | |
| 105666 | - append(&sb, zEndMark); | |
| 106060 | + fts3SnippetAppend(&sb, zStartMark, -1); | |
| 106061 | + fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].nByte); | |
| 106062 | + fts3SnippetAppend(&sb, zEndMark, -1); | |
| 105667 | 106063 | iStart += aMatch[iMatch].nByte; |
| 105668 | 106064 | for(j=iMatch+1; j<nMatch; j++){ |
| 105669 | 106065 | if( aMatch[j].iTerm==aMatch[iMatch].iTerm |
| 105670 | 106066 | && aMatch[j].snStatus==SNIPPET_DESIRED ){ |
| 105671 | 106067 | nDesired--; |
| 105672 | 106068 | aMatch[j].snStatus = SNIPPET_IGNORE; |
| 105673 | 106069 | } |
| 105674 | 106070 | } |
| 105675 | 106071 | }else{ |
| 105676 | - nappend(&sb, &zDoc[iStart], iEnd - iStart); | |
| 106072 | + fts3SnippetAppend(&sb, &zDoc[iStart], iEnd - iStart); | |
| 105677 | 106073 | iStart = iEnd; |
| 105678 | 106074 | } |
| 105679 | 106075 | } |
| 105680 | 106076 | tailCol = iCol; |
| 105681 | 106077 | tailOffset = iEnd; |
| 105682 | 106078 | } |
| 105683 | - trimWhiteSpace(&sb); | |
| 106079 | + fts3SnippetTrimWhiteSpace(&sb); | |
| 105684 | 106080 | if( tailEllipsis ){ |
| 105685 | - appendWhiteSpace(&sb); | |
| 105686 | - append(&sb, zEllipsis); | |
| 106081 | + fts3SnippetAppendWhiteSpace(&sb); | |
| 106082 | + fts3SnippetAppend(&sb, zEllipsis, -1); | |
| 105687 | 106083 | } |
| 105688 | - pSnippet->zSnippet = stringBufferData(&sb); | |
| 105689 | - pSnippet->nSnippet = stringBufferLength(&sb); | |
| 106084 | + pSnippet->zSnippet = sb.z; | |
| 106085 | + pSnippet->nSnippet = sb.z ? sb.nUsed : 0; | |
| 105690 | 106086 | } |
| 105691 | 106087 | |
| 105692 | 106088 | SQLITE_PRIVATE void sqlite3Fts3Offsets( |
| 105693 | 106089 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 105694 | 106090 | Fts3Cursor *pCsr /* Cursor object */ |
| 105695 | 106091 | ){ |
| 105696 | 106092 | Snippet *p; /* Snippet structure */ |
| 105697 | 106093 | int rc = snippetAllOffsets(pCsr, &p); |
| 105698 | - snippetOffsetText(p); | |
| 105699 | - sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT); | |
| 106094 | + if( rc==SQLITE_OK ){ | |
| 106095 | + snippetOffsetText(p); | |
| 106096 | + if( p->zOffset ){ | |
| 106097 | + sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT); | |
| 106098 | + }else{ | |
| 106099 | + sqlite3_result_error_nomem(pCtx); | |
| 106100 | + } | |
| 106101 | + }else{ | |
| 106102 | + sqlite3_result_error_nomem(pCtx); | |
| 106103 | + } | |
| 105700 | 106104 | fts3SnippetFree(p); |
| 105701 | 106105 | } |
| 105702 | 106106 | |
| 105703 | 106107 | SQLITE_PRIVATE void sqlite3Fts3Snippet( |
| 105704 | 106108 | sqlite3_context *pCtx, /* SQLite function call context */ |
| @@ -105707,12 +106111,20 @@ | ||
| 105707 | 106111 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 105708 | 106112 | const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */ |
| 105709 | 106113 | ){ |
| 105710 | 106114 | Snippet *p; /* Snippet structure */ |
| 105711 | 106115 | int rc = snippetAllOffsets(pCsr, &p); |
| 105712 | - snippetText(pCsr, p, zStart, zEnd, zEllipsis); | |
| 105713 | - sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT); | |
| 106116 | + if( rc==SQLITE_OK ){ | |
| 106117 | + snippetText(pCsr, p, zStart, zEnd, zEllipsis); | |
| 106118 | + if( p->zSnippet ){ | |
| 106119 | + sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT); | |
| 106120 | + }else{ | |
| 106121 | + sqlite3_result_error_nomem(pCtx); | |
| 106122 | + } | |
| 106123 | + }else{ | |
| 106124 | + sqlite3_result_error_nomem(pCtx); | |
| 106125 | + } | |
| 105714 | 106126 | fts3SnippetFree(p); |
| 105715 | 106127 | } |
| 105716 | 106128 | |
| 105717 | 106129 | #endif |
| 105718 | 106130 | |
| 105719 | 106131 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -643,11 +643,11 @@ | |
| 643 | ** |
| 644 | ** Requirements: [H10011] [H10014] |
| 645 | */ |
| 646 | #define SQLITE_VERSION "3.6.21" |
| 647 | #define SQLITE_VERSION_NUMBER 3006021 |
| 648 | #define SQLITE_SOURCE_ID "2009-11-25 21:05:09 5086bf8e838c824accda531afeb56a51dd40d795" |
| 649 | |
| 650 | /* |
| 651 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 652 | ** KEYWORDS: sqlite3_version |
| 653 | ** |
| @@ -1817,10 +1817,13 @@ | |
| 1817 | ** the return value of this interface. |
| 1818 | ** |
| 1819 | ** For the purposes of this routine, an [INSERT] is considered to |
| 1820 | ** be successful even if it is subsequently rolled back. |
| 1821 | ** |
| 1822 | ** Requirements: |
| 1823 | ** [H12221] [H12223] |
| 1824 | ** |
| 1825 | ** If a separate thread performs a new [INSERT] on the same |
| 1826 | ** database connection while the [sqlite3_last_insert_rowid()] |
| @@ -1874,12 +1877,12 @@ | |
| 1874 | ** changes in the most recently completed INSERT, UPDATE, or DELETE |
| 1875 | ** statement within the body of the same trigger. |
| 1876 | ** However, the number returned does not include changes |
| 1877 | ** caused by subtriggers since those have their own context. |
| 1878 | ** |
| 1879 | ** See also the [sqlite3_total_changes()] interface and the |
| 1880 | ** [count_changes pragma]. |
| 1881 | ** |
| 1882 | ** Requirements: |
| 1883 | ** [H12241] [H12243] |
| 1884 | ** |
| 1885 | ** If a separate thread makes changes on the same database connection |
| @@ -1902,12 +1905,12 @@ | |
| 1902 | ** are counted. |
| 1903 | ** The changes are counted as soon as the statement that makes them is |
| 1904 | ** completed (when the statement handle is passed to [sqlite3_reset()] or |
| 1905 | ** [sqlite3_finalize()]). |
| 1906 | ** |
| 1907 | ** See also the [sqlite3_changes()] interface and the |
| 1908 | ** [count_changes pragma]. |
| 1909 | ** |
| 1910 | ** Requirements: |
| 1911 | ** [H12261] [H12263] |
| 1912 | ** |
| 1913 | ** If a separate thread makes changes on the same database connection |
| @@ -4664,10 +4667,12 @@ | |
| 4664 | ** should free this memory by calling [sqlite3_free()]. |
| 4665 | ** |
| 4666 | ** {H12606} Extension loading must be enabled using |
| 4667 | ** [sqlite3_enable_load_extension()] prior to calling this API, |
| 4668 | ** otherwise an error will be returned. |
| 4669 | */ |
| 4670 | SQLITE_API int sqlite3_load_extension( |
| 4671 | sqlite3 *db, /* Load the extension into this database connection */ |
| 4672 | const char *zFile, /* Name of the shared library containing extension */ |
| 4673 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
| @@ -9662,19 +9667,20 @@ | |
| 9662 | ** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of |
| 9663 | ** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable. |
| 9664 | ** The Parse.pTriggerPrg list never contains two entries with the same |
| 9665 | ** values for both pTrigger and orconf. |
| 9666 | ** |
| 9667 | ** The TriggerPrg.oldmask variable is set to a mask of old.* columns |
| 9668 | ** accessed (or set to 0 for triggers fired as a result of INSERT |
| 9669 | ** statements). |
| 9670 | */ |
| 9671 | struct TriggerPrg { |
| 9672 | Trigger *pTrigger; /* Trigger this program was coded from */ |
| 9673 | int orconf; /* Default ON CONFLICT policy */ |
| 9674 | SubProgram *pProgram; /* Program implementing pTrigger/orconf */ |
| 9675 | u32 oldmask; /* Mask of old.* columns accessed */ |
| 9676 | TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ |
| 9677 | }; |
| 9678 | |
| 9679 | /* |
| 9680 | ** An SQL parser context. A copy of this structure is passed through |
| @@ -9742,10 +9748,11 @@ | |
| 9742 | |
| 9743 | /* Information used while coding trigger programs. */ |
| 9744 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 9745 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 9746 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 9747 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 9748 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 9749 | u8 disableTriggers; /* True to disable triggers */ |
| 9750 | |
| 9751 | /* Above is constant between recursions. Below is reset before and after |
| @@ -10339,11 +10346,11 @@ | |
| 10339 | ExprList*,Select*,u8); |
| 10340 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); |
| 10341 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); |
| 10342 | SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); |
| 10343 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); |
| 10344 | SQLITE_PRIVATE u32 sqlite3TriggerOldmask(Parse*,Trigger*,ExprList*,Table*,int); |
| 10345 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) |
| 10346 | #else |
| 10347 | # define sqlite3TriggersExist(B,C,D,E,F) 0 |
| 10348 | # define sqlite3DeleteTrigger(A,B) |
| 10349 | # define sqlite3DropTriggerPtr(A,B) |
| @@ -10350,11 +10357,11 @@ | |
| 10350 | # define sqlite3UnlinkAndDeleteTrigger(A,B,C) |
| 10351 | # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) |
| 10352 | # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) |
| 10353 | # define sqlite3TriggerList(X, Y) 0 |
| 10354 | # define sqlite3ParseToplevel(p) p |
| 10355 | # define sqlite3TriggerOldmask(A,B,C,D,E) 0 |
| 10356 | #endif |
| 10357 | |
| 10358 | SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); |
| 10359 | SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
| 10360 | SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); |
| @@ -10564,10 +10571,11 @@ | |
| 10564 | SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); |
| 10565 | SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); |
| 10566 | SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); |
| 10567 | SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); |
| 10568 | SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); |
| 10569 | SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); |
| 10570 | SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); |
| 10571 | SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); |
| 10572 | SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); |
| 10573 | SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); |
| @@ -14914,10 +14922,43 @@ | |
| 14914 | assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 14915 | DosCloseMutexSem( p->mutex ); |
| 14916 | sqlite3_free( p ); |
| 14917 | } |
| 14918 | |
| 14919 | /* |
| 14920 | ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt |
| 14921 | ** to enter a mutex. If another thread is already within the mutex, |
| 14922 | ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return |
| 14923 | ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK |
| @@ -14974,43 +15015,10 @@ | |
| 14974 | p->nRef--; |
| 14975 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 14976 | DosReleaseMutexSem(p->mutex); |
| 14977 | } |
| 14978 | |
| 14979 | #ifdef SQLITE_DEBUG |
| 14980 | /* |
| 14981 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 14982 | ** intended for use inside assert() statements. |
| 14983 | */ |
| 14984 | static int os2MutexHeld(sqlite3_mutex *p){ |
| 14985 | TID tid; |
| 14986 | PID pid; |
| 14987 | ULONG ulCount; |
| 14988 | PTIB ptib; |
| 14989 | if( p!=0 ) { |
| 14990 | DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); |
| 14991 | } else { |
| 14992 | DosGetInfoBlocks(&ptib, NULL); |
| 14993 | tid = ptib->tib_ptib2->tib2_ultid; |
| 14994 | } |
| 14995 | return p==0 || (p->nRef!=0 && p->owner==tid); |
| 14996 | } |
| 14997 | static int os2MutexNotheld(sqlite3_mutex *p){ |
| 14998 | TID tid; |
| 14999 | PID pid; |
| 15000 | ULONG ulCount; |
| 15001 | PTIB ptib; |
| 15002 | if( p!= 0 ) { |
| 15003 | DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); |
| 15004 | } else { |
| 15005 | DosGetInfoBlocks(&ptib, NULL); |
| 15006 | tid = ptib->tib_ptib2->tib2_ultid; |
| 15007 | } |
| 15008 | return p==0 || p->nRef==0 || p->owner!=tid; |
| 15009 | } |
| 15010 | #endif |
| 15011 | |
| 15012 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15013 | static sqlite3_mutex_methods sMutex = { |
| 15014 | os2MutexInit, |
| 15015 | os2MutexEnd, |
| 15016 | os2MutexAlloc, |
| @@ -22701,11 +22709,11 @@ | |
| 22701 | } |
| 22702 | } |
| 22703 | #endif |
| 22704 | |
| 22705 | unixLeaveMutex(); |
| 22706 | OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); |
| 22707 | |
| 22708 | *pResOut = reserved; |
| 22709 | return rc; |
| 22710 | } |
| 22711 | |
| @@ -22834,20 +22842,20 @@ | |
| 22834 | struct flock lock; |
| 22835 | int s = 0; |
| 22836 | int tErrno; |
| 22837 | |
| 22838 | assert( pFile ); |
| 22839 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, |
| 22840 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22841 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| 22842 | |
| 22843 | /* If there is already a lock of this type or more restrictive on the |
| 22844 | ** unixFile, do nothing. Don't use the end_lock: exit path, as |
| 22845 | ** unixEnterMutex() hasn't been called yet. |
| 22846 | */ |
| 22847 | if( pFile->locktype>=locktype ){ |
| 22848 | OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, |
| 22849 | locktypeName(locktype)); |
| 22850 | return SQLITE_OK; |
| 22851 | } |
| 22852 | |
| 22853 | /* Make sure the locking sequence is correct. |
| @@ -23013,11 +23021,11 @@ | |
| 23013 | pLock->locktype = PENDING_LOCK; |
| 23014 | } |
| 23015 | |
| 23016 | end_lock: |
| 23017 | unixLeaveMutex(); |
| 23018 | OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), |
| 23019 | rc==SQLITE_OK ? "ok" : "failed"); |
| 23020 | return rc; |
| 23021 | } |
| 23022 | |
| 23023 | /* |
| @@ -23077,11 +23085,11 @@ | |
| 23077 | int rc = SQLITE_OK; /* Return code from this interface */ |
| 23078 | int h; /* The underlying file descriptor */ |
| 23079 | int tErrno; /* Error code from system call errors */ |
| 23080 | |
| 23081 | assert( pFile ); |
| 23082 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, |
| 23083 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| 23084 | |
| 23085 | assert( locktype<=SHARED_LOCK ); |
| 23086 | if( pFile->locktype<=locktype ){ |
| 23087 | return SQLITE_OK; |
| @@ -23358,11 +23366,11 @@ | |
| 23358 | }else{ |
| 23359 | /* The lock is held if and only if the lockfile exists */ |
| 23360 | const char *zLockFile = (const char*)pFile->lockingContext; |
| 23361 | reserved = access(zLockFile, 0)==0; |
| 23362 | } |
| 23363 | OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); |
| 23364 | *pResOut = reserved; |
| 23365 | return rc; |
| 23366 | } |
| 23367 | |
| 23368 | /* |
| @@ -23448,11 +23456,11 @@ | |
| 23448 | static int dotlockUnlock(sqlite3_file *id, int locktype) { |
| 23449 | unixFile *pFile = (unixFile*)id; |
| 23450 | char *zLockFile = (char *)pFile->lockingContext; |
| 23451 | |
| 23452 | assert( pFile ); |
| 23453 | OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, |
| 23454 | pFile->locktype, getpid()); |
| 23455 | assert( locktype<=SHARED_LOCK ); |
| 23456 | |
| 23457 | /* no-op if possible */ |
| 23458 | if( pFile->locktype==locktype ){ |
| @@ -23562,11 +23570,11 @@ | |
| 23562 | pFile->lastErrno = tErrno; |
| 23563 | rc = lrc; |
| 23564 | } |
| 23565 | } |
| 23566 | } |
| 23567 | OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); |
| 23568 | |
| 23569 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 23570 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ |
| 23571 | rc = SQLITE_OK; |
| 23572 | reserved=1; |
| @@ -23629,11 +23637,11 @@ | |
| 23629 | } |
| 23630 | } else { |
| 23631 | /* got it, set the type and return ok */ |
| 23632 | pFile->locktype = locktype; |
| 23633 | } |
| 23634 | OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), |
| 23635 | rc==SQLITE_OK ? "ok" : "failed"); |
| 23636 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 23637 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ |
| 23638 | rc = SQLITE_BUSY; |
| 23639 | } |
| @@ -23651,11 +23659,11 @@ | |
| 23651 | */ |
| 23652 | static int flockUnlock(sqlite3_file *id, int locktype) { |
| 23653 | unixFile *pFile = (unixFile*)id; |
| 23654 | |
| 23655 | assert( pFile ); |
| 23656 | OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, |
| 23657 | pFile->locktype, getpid()); |
| 23658 | assert( locktype<=SHARED_LOCK ); |
| 23659 | |
| 23660 | /* no-op if possible */ |
| 23661 | if( pFile->locktype==locktype ){ |
| @@ -23753,11 +23761,11 @@ | |
| 23753 | }else{ |
| 23754 | /* we could have it if we want it */ |
| 23755 | sem_post(pSem); |
| 23756 | } |
| 23757 | } |
| 23758 | OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); |
| 23759 | |
| 23760 | *pResOut = reserved; |
| 23761 | return rc; |
| 23762 | } |
| 23763 | |
| @@ -23828,11 +23836,11 @@ | |
| 23828 | unixFile *pFile = (unixFile*)id; |
| 23829 | sem_t *pSem = pFile->pOpen->pSem; |
| 23830 | |
| 23831 | assert( pFile ); |
| 23832 | assert( pSem ); |
| 23833 | OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, |
| 23834 | pFile->locktype, getpid()); |
| 23835 | assert( locktype<=SHARED_LOCK ); |
| 23836 | |
| 23837 | /* no-op if possible */ |
| 23838 | if( pFile->locktype==locktype ){ |
| @@ -23998,11 +24006,11 @@ | |
| 23998 | if( IS_LOCK_ERROR(lrc) ){ |
| 23999 | rc=lrc; |
| 24000 | } |
| 24001 | } |
| 24002 | |
| 24003 | OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); |
| 24004 | |
| 24005 | *pResOut = reserved; |
| 24006 | return rc; |
| 24007 | } |
| 24008 | |
| @@ -24034,19 +24042,19 @@ | |
| 24034 | int rc = SQLITE_OK; |
| 24035 | unixFile *pFile = (unixFile*)id; |
| 24036 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24037 | |
| 24038 | assert( pFile ); |
| 24039 | OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, |
| 24040 | locktypeName(locktype), locktypeName(pFile->locktype), getpid()); |
| 24041 | |
| 24042 | /* If there is already a lock of this type or more restrictive on the |
| 24043 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 24044 | ** unixEnterMutex() hasn't been called yet. |
| 24045 | */ |
| 24046 | if( pFile->locktype>=locktype ){ |
| 24047 | OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, |
| 24048 | locktypeName(locktype)); |
| 24049 | return SQLITE_OK; |
| 24050 | } |
| 24051 | |
| 24052 | /* Make sure the locking sequence is correct |
| @@ -24161,11 +24169,11 @@ | |
| 24161 | pFile->locktype = PENDING_LOCK; |
| 24162 | } |
| 24163 | |
| 24164 | afp_end_lock: |
| 24165 | unixLeaveMutex(); |
| 24166 | OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), |
| 24167 | rc==SQLITE_OK ? "ok" : "failed"); |
| 24168 | return rc; |
| 24169 | } |
| 24170 | |
| 24171 | /* |
| @@ -24179,11 +24187,11 @@ | |
| 24179 | int rc = SQLITE_OK; |
| 24180 | unixFile *pFile = (unixFile*)id; |
| 24181 | afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext; |
| 24182 | |
| 24183 | assert( pFile ); |
| 24184 | OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, |
| 24185 | pFile->locktype, getpid()); |
| 24186 | |
| 24187 | assert( locktype<=SHARED_LOCK ); |
| 24188 | if( pFile->locktype<=locktype ){ |
| 24189 | return SQLITE_OK; |
| @@ -32430,10 +32438,11 @@ | |
| 32430 | pager_reset(pPager); |
| 32431 | } |
| 32432 | |
| 32433 | pPager->changeCountDone = 0; |
| 32434 | pPager->state = PAGER_UNLOCK; |
| 32435 | } |
| 32436 | } |
| 32437 | |
| 32438 | /* |
| 32439 | ** This function should be called when an IOERR, CORRUPT or FULL error |
| @@ -33806,12 +33815,15 @@ | |
| 33806 | /* The OS lock values must be the same as the Pager lock values */ |
| 33807 | assert( PAGER_SHARED==SHARED_LOCK ); |
| 33808 | assert( PAGER_RESERVED==RESERVED_LOCK ); |
| 33809 | assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); |
| 33810 | |
| 33811 | /* If the file is currently unlocked then the size must be unknown */ |
| 33812 | assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 ); |
| 33813 | |
| 33814 | /* Check that this is either a no-op (because the requested lock is |
| 33815 | ** already held, or one of the transistions that the busy-handler |
| 33816 | ** may be invoked during, according to the comment above |
| 33817 | ** sqlite3PagerSetBusyhandler(). |
| @@ -39966,15 +39978,12 @@ | |
| 39966 | unsigned char *data; |
| 39967 | int rc; |
| 39968 | int nPage; |
| 39969 | |
| 39970 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39971 | /* The database size has already been measured and cached, so failure |
| 39972 | ** is impossible here. If the original size measurement failed, then |
| 39973 | ** processing aborts before entering this routine. */ |
| 39974 | rc = sqlite3PagerPagecount(pBt->pPager, &nPage); |
| 39975 | if( NEVER(rc!=SQLITE_OK) || nPage>0 ){ |
| 39976 | return rc; |
| 39977 | } |
| 39978 | pP1 = pBt->pPage1; |
| 39979 | assert( pP1!=0 ); |
| 39980 | data = pP1->aData; |
| @@ -42918,12 +42927,17 @@ | |
| 42918 | if( *pRC ) return; |
| 42919 | |
| 42920 | assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); |
| 42921 | assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); |
| 42922 | assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); |
| 42923 | assert( sz==cellSizePtr(pPage, pCell) ); |
| 42924 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 42925 | if( pPage->nOverflow || sz+2>pPage->nFree ){ |
| 42926 | if( pTemp ){ |
| 42927 | memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); |
| 42928 | pCell = pTemp; |
| 42929 | } |
| @@ -51381,26 +51395,28 @@ | |
| 51381 | /* |
| 51382 | ** Given a wildcard parameter name, return the index of the variable |
| 51383 | ** with that name. If there is no variable with the given name, |
| 51384 | ** return 0. |
| 51385 | */ |
| 51386 | SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ |
| 51387 | Vdbe *p = (Vdbe*)pStmt; |
| 51388 | int i; |
| 51389 | if( p==0 ){ |
| 51390 | return 0; |
| 51391 | } |
| 51392 | createVarMap(p); |
| 51393 | if( zName ){ |
| 51394 | for(i=0; i<p->nVar; i++){ |
| 51395 | const char *z = p->azVar[i]; |
| 51396 | if( z && strcmp(z,zName)==0 ){ |
| 51397 | return i+1; |
| 51398 | } |
| 51399 | } |
| 51400 | } |
| 51401 | return 0; |
| 51402 | } |
| 51403 | |
| 51404 | /* |
| 51405 | ** Transfer all bindings from the first statement over to the second. |
| 51406 | */ |
| @@ -51509,29 +51525,33 @@ | |
| 51509 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
| 51510 | ** bytes in this text up to but excluding the first character in |
| 51511 | ** a host parameter. If the text contains no host parameters, return |
| 51512 | ** the total number of bytes in the text. |
| 51513 | */ |
| 51514 | static int findNextHostParameter(const char *zSql){ |
| 51515 | int tokenType; |
| 51516 | int nTotal = 0; |
| 51517 | int n; |
| 51518 | |
| 51519 | while( zSql[0] ){ |
| 51520 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 51521 | assert( n>0 && tokenType!=TK_ILLEGAL ); |
| 51522 | if( tokenType==TK_VARIABLE ) break; |
| 51523 | nTotal += n; |
| 51524 | zSql += n; |
| 51525 | } |
| 51526 | return nTotal; |
| 51527 | } |
| 51528 | |
| 51529 | /* |
| 51530 | ** Return a pointer to a string in memory obtained form sqlite3Malloc() which |
| 51531 | ** holds a copy of zRawSql but with host parameters expanded to their |
| 51532 | ** current values. |
| 51533 | ** |
| 51534 | ** The calling function is responsible for making sure the memory returned |
| 51535 | ** is eventually freed. |
| 51536 | ** |
| 51537 | ** ALGORITHM: Scan the input string looking for host parameters in any of |
| @@ -51545,60 +51565,46 @@ | |
| 51545 | SQLITE_PRIVATE char *sqlite3VdbeExpandSql( |
| 51546 | Vdbe *p, /* The prepared statement being evaluated */ |
| 51547 | const char *zRawSql /* Raw text of the SQL statement */ |
| 51548 | ){ |
| 51549 | sqlite3 *db; /* The database connection */ |
| 51550 | int idx; /* Index of a host parameter */ |
| 51551 | int nextIndex = 1; /* Index of next ? host parameter */ |
| 51552 | int n; /* Length of a token prefix */ |
| 51553 | int i; /* Loop counter */ |
| 51554 | int dummy; /* For holding a unused return value */ |
| 51555 | Mem *pVar; /* Value of a host parameter */ |
| 51556 | VdbeOp *pOp; /* For looping over opcodes */ |
| 51557 | StrAccum out; /* Accumulate the output here */ |
| 51558 | char zBase[100]; /* Initial working space */ |
| 51559 | |
| 51560 | db = p->db; |
| 51561 | sqlite3StrAccumInit(&out, zBase, sizeof(zBase), |
| 51562 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 51563 | out.db = db; |
| 51564 | while( zRawSql[0] ){ |
| 51565 | n = findNextHostParameter(zRawSql); |
| 51566 | assert( n>0 ); |
| 51567 | sqlite3StrAccumAppend(&out, zRawSql, n); |
| 51568 | zRawSql += n; |
| 51569 | if( zRawSql[0]==0 ) break; |
| 51570 | if( zRawSql[0]=='?' ){ |
| 51571 | zRawSql++; |
| 51572 | if( sqlite3Isdigit(zRawSql[0]) ){ |
| 51573 | idx = 0; |
| 51574 | while( sqlite3Isdigit(zRawSql[0]) ){ |
| 51575 | idx = idx*10 + zRawSql[0] - '0'; |
| 51576 | zRawSql++; |
| 51577 | } |
| 51578 | }else{ |
| 51579 | idx = nextIndex; |
| 51580 | } |
| 51581 | }else{ |
| 51582 | assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); |
| 51583 | testcase( zRawSql[0]==':' ); |
| 51584 | testcase( zRawSql[0]=='$' ); |
| 51585 | testcase( zRawSql[0]=='@' ); |
| 51586 | n = sqlite3GetToken((u8*)zRawSql, &dummy); |
| 51587 | idx = 0; |
| 51588 | for(i=0, pOp=p->aOp; ALWAYS(i<p->nOp); i++, pOp++){ |
| 51589 | if( pOp->opcode!=OP_Variable ) continue; |
| 51590 | if( pOp->p3>1 ) continue; |
| 51591 | if( pOp->p4.z==0 ) continue; |
| 51592 | if( memcmp(pOp->p4.z, zRawSql, n)==0 && pOp->p4.z[n]==0 ){ |
| 51593 | idx = pOp->p1; |
| 51594 | break; |
| 51595 | } |
| 51596 | } |
| 51597 | assert( idx>0 ); |
| 51598 | zRawSql += n; |
| 51599 | } |
| 51600 | nextIndex = idx + 1; |
| 51601 | assert( idx>0 && idx<=p->nVar ); |
| 51602 | pVar = &p->aVar[idx-1]; |
| 51603 | if( pVar->flags & MEM_Null ){ |
| 51604 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| @@ -51606,15 +51612,16 @@ | |
| 51606 | sqlite3XPrintf(&out, "%lld", pVar->u.i); |
| 51607 | }else if( pVar->flags & MEM_Real ){ |
| 51608 | sqlite3XPrintf(&out, "%!.15g", pVar->r); |
| 51609 | }else if( pVar->flags & MEM_Str ){ |
| 51610 | #ifndef SQLITE_OMIT_UTF16 |
| 51611 | if( ENC(db)!=SQLITE_UTF8 ){ |
| 51612 | Mem utf8; |
| 51613 | memset(&utf8, 0, sizeof(utf8)); |
| 51614 | utf8.db = db; |
| 51615 | sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, ENC(db), SQLITE_STATIC); |
| 51616 | sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); |
| 51617 | sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z); |
| 51618 | sqlite3VdbeMemRelease(&utf8); |
| 51619 | }else |
| 51620 | #endif |
| @@ -52272,11 +52279,11 @@ | |
| 52272 | int rc = SQLITE_OK; /* Value to return */ |
| 52273 | sqlite3 *db = p->db; /* The database */ |
| 52274 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| 52275 | u8 encoding = ENC(db); /* The database encoding */ |
| 52276 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 52277 | u8 checkProgress; /* True if progress callbacks are enabled */ |
| 52278 | int nProgressOps = 0; /* Opcodes executed since progress callback. */ |
| 52279 | #endif |
| 52280 | Mem *aMem = p->aMem; /* Copy of p->aMem */ |
| 52281 | Mem *pIn1 = 0; /* 1st input operand */ |
| 52282 | Mem *pIn2 = 0; /* 2nd input operand */ |
| @@ -55461,11 +55468,11 @@ | |
| 55461 | ** u.az.r.flags = UNPACKED_INCRKEY; |
| 55462 | ** }else{ |
| 55463 | ** u.az.r.flags = 0; |
| 55464 | ** } |
| 55465 | */ |
| 55466 | u.az.r.flags = UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt)); |
| 55467 | assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY ); |
| 55468 | assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY ); |
| 55469 | assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 ); |
| 55470 | assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 ); |
| 55471 | |
| @@ -55594,11 +55601,11 @@ | |
| 55594 | if( ALWAYS(u.bb.pC->pCursor!=0) ){ |
| 55595 | |
| 55596 | assert( u.bb.pC->isTable==0 ); |
| 55597 | if( pOp->p4.i>0 ){ |
| 55598 | u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo; |
| 55599 | u.bb.r.nField = pOp->p4.i; |
| 55600 | u.bb.r.aMem = pIn3; |
| 55601 | u.bb.r.flags = UNPACKED_PREFIX_MATCH; |
| 55602 | u.bb.pIdxKey = &u.bb.r; |
| 55603 | }else{ |
| 55604 | assert( pIn3->flags & MEM_Blob ); |
| @@ -59309,10 +59316,14 @@ | |
| 59309 | pExpr->affinity = SQLITE_AFF_INTEGER; |
| 59310 | }else if( pExpr->iTable==0 ){ |
| 59311 | testcase( iCol==31 ); |
| 59312 | testcase( iCol==32 ); |
| 59313 | pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); |
| 59314 | } |
| 59315 | pExpr->iColumn = (i16)iCol; |
| 59316 | pExpr->pTab = pTab; |
| 59317 | isTrigger = 1; |
| 59318 | } |
| @@ -70890,11 +70901,13 @@ | |
| 70890 | u32 mask; /* Mask of OLD.* columns in use */ |
| 70891 | int iCol; /* Iterator used while populating OLD.* */ |
| 70892 | |
| 70893 | /* TODO: Could use temporary registers here. Also could attempt to |
| 70894 | ** avoid copying the contents of the rowid register. */ |
| 70895 | mask = sqlite3TriggerOldmask(pParse, pTrigger, 0, pTab, onconf); |
| 70896 | mask |= sqlite3FkOldmask(pParse, pTab); |
| 70897 | iOld = pParse->nMem+1; |
| 70898 | pParse->nMem += (1 + pTab->nCol); |
| 70899 | |
| 70900 | /* Populate the OLD.* pseudo-table register array. These values will be |
| @@ -84240,11 +84253,12 @@ | |
| 84240 | pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); |
| 84241 | if( !pProgram ) return 0; |
| 84242 | pProgram->nRef = 1; |
| 84243 | pPrg->pTrigger = pTrigger; |
| 84244 | pPrg->orconf = orconf; |
| 84245 | pPrg->oldmask = 0xffffffff; |
| 84246 | |
| 84247 | /* Allocate and populate a new Parse context to use for coding the |
| 84248 | ** trigger sub-program. */ |
| 84249 | pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); |
| 84250 | if( !pSubParse ) return 0; |
| @@ -84301,11 +84315,12 @@ | |
| 84301 | pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); |
| 84302 | } |
| 84303 | pProgram->nMem = pSubParse->nMem; |
| 84304 | pProgram->nCsr = pSubParse->nTab; |
| 84305 | pProgram->token = (void *)pTrigger; |
| 84306 | pPrg->oldmask = pSubParse->oldmask; |
| 84307 | sqlite3VdbeDelete(v); |
| 84308 | } |
| 84309 | |
| 84310 | assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); |
| 84311 | assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); |
| @@ -84461,45 +84476,56 @@ | |
| 84461 | } |
| 84462 | } |
| 84463 | } |
| 84464 | |
| 84465 | /* |
| 84466 | ** Triggers fired by UPDATE or DELETE statements may access values stored |
| 84467 | ** in the old.* pseudo-table. This function returns a 32-bit bitmask |
| 84468 | ** indicating which columns of the old.* table actually are used by |
| 84469 | ** triggers. This information may be used by the caller to avoid having |
| 84470 | ** to load the entire old.* record into memory when executing an UPDATE |
| 84471 | ** or DELETE command. |
| 84472 | ** |
| 84473 | ** Bit 0 of the returned mask is set if the left-most column of the |
| 84474 | ** table may be accessed using an old.<col> reference. Bit 1 is set if |
| 84475 | ** the second leftmost column value is required, and so on. If there |
| 84476 | ** are more than 32 columns in the table, and at least one of the columns |
| 84477 | ** with an index greater than 32 may be accessed, 0xffffffff is returned. |
| 84478 | ** |
| 84479 | ** It is not possible to determine if the old.rowid column is accessed |
| 84480 | ** by triggers. The caller must always assume that it is. |
| 84481 | ** |
| 84482 | ** There is no equivalent function for new.* references. |
| 84483 | */ |
| 84484 | SQLITE_PRIVATE u32 sqlite3TriggerOldmask( |
| 84485 | Parse *pParse, /* Parse context */ |
| 84486 | Trigger *pTrigger, /* List of triggers on table pTab */ |
| 84487 | ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ |
| 84488 | Table *pTab, /* The table to code triggers from */ |
| 84489 | int orconf /* Default ON CONFLICT policy for trigger steps */ |
| 84490 | ){ |
| 84491 | const int op = pChanges ? TK_UPDATE : TK_DELETE; |
| 84492 | u32 mask = 0; |
| 84493 | Trigger *p; |
| 84494 | |
| 84495 | for(p=pTrigger; p; p=p->pNext){ |
| 84496 | if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){ |
| 84497 | TriggerPrg *pPrg; |
| 84498 | pPrg = getRowTrigger(pParse, p, pTab, orconf); |
| 84499 | if( pPrg ){ |
| 84500 | mask |= pPrg->oldmask; |
| 84501 | } |
| 84502 | } |
| 84503 | } |
| 84504 | |
| 84505 | return mask; |
| @@ -84619,18 +84645,19 @@ | |
| 84619 | Expr *pRowidExpr = 0; /* Expression defining the new record number */ |
| 84620 | int openAll = 0; /* True if all indices need to be opened */ |
| 84621 | AuthContext sContext; /* The authorization context */ |
| 84622 | NameContext sNC; /* The name-context to resolve expressions in */ |
| 84623 | int iDb; /* Database containing the table being updated */ |
| 84624 | int j1; /* Addresses of jump instructions */ |
| 84625 | int okOnePass; /* True for one-pass algorithm without the FIFO */ |
| 84626 | int hasFK; /* True if foreign key processing is required */ |
| 84627 | |
| 84628 | #ifndef SQLITE_OMIT_TRIGGER |
| 84629 | int isView; /* Trying to update a view */ |
| 84630 | Trigger *pTrigger; /* List of triggers on pTab, if required */ |
| 84631 | #endif |
| 84632 | |
| 84633 | /* Register Allocations */ |
| 84634 | int regRowCount = 0; /* A count of rows changed */ |
| 84635 | int regOldRowid; /* The old rowid */ |
| 84636 | int regNewRowid; /* The new rowid */ |
| @@ -84654,25 +84681,27 @@ | |
| 84654 | |
| 84655 | /* Figure out if we have any triggers and if the table being |
| 84656 | ** updated is a view. |
| 84657 | */ |
| 84658 | #ifndef SQLITE_OMIT_TRIGGER |
| 84659 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, 0); |
| 84660 | isView = pTab->pSelect!=0; |
| 84661 | #else |
| 84662 | # define pTrigger 0 |
| 84663 | # define isView 0 |
| 84664 | #endif |
| 84665 | #ifdef SQLITE_OMIT_VIEW |
| 84666 | # undef isView |
| 84667 | # define isView 0 |
| 84668 | #endif |
| 84669 | |
| 84670 | if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
| 84671 | goto update_cleanup; |
| 84672 | } |
| 84673 | if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ |
| 84674 | goto update_cleanup; |
| 84675 | } |
| 84676 | aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); |
| 84677 | if( aXRef==0 ) goto update_cleanup; |
| 84678 | for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; |
| @@ -84896,11 +84925,13 @@ | |
| 84896 | |
| 84897 | /* If there are triggers on this table, populate an array of registers |
| 84898 | ** with the required old.* column data. */ |
| 84899 | if( hasFK || pTrigger ){ |
| 84900 | u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); |
| 84901 | oldmask |= sqlite3TriggerOldmask(pParse, pTrigger, pChanges, pTab, onError); |
| 84902 | for(i=0; i<pTab->nCol; i++){ |
| 84903 | if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){ |
| 84904 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i); |
| 84905 | sqlite3ColumnDefault(v, pTab, i, regOld+i); |
| 84906 | }else{ |
| @@ -84913,42 +84944,76 @@ | |
| 84913 | } |
| 84914 | |
| 84915 | /* Populate the array of registers beginning at regNew with the new |
| 84916 | ** row data. This array is used to check constaints, create the new |
| 84917 | ** table and index records, and as the values for any new.* references |
| 84918 | ** made by triggers. */ |
| 84919 | for(i=0; i<pTab->nCol; i++){ |
| 84920 | if( i==pTab->iPKey ){ |
| 84921 | sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
| 84922 | }else{ |
| 84923 | j = aXRef[i]; |
| 84924 | if( j<0 ){ |
| 84925 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); |
| 84926 | sqlite3ColumnDefault(v, pTab, i, regNew+i); |
| 84927 | }else{ |
| 84928 | sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); |
| 84929 | } |
| 84930 | } |
| 84931 | } |
| 84932 | |
| 84933 | /* Fire any BEFORE UPDATE triggers. This happens before constraints are |
| 84934 | ** verified. One could argue that this is wrong. */ |
| 84935 | if( pTrigger ){ |
| 84936 | sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); |
| 84937 | sqlite3TableAffinityStr(v, pTab); |
| 84938 | sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, |
| 84939 | TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); |
| 84940 | |
| 84941 | /* The row-trigger may have deleted the row being updated. In this |
| 84942 | ** case, jump to the next row. No updates or AFTER triggers are |
| 84943 | ** required. This behaviour - what happens when the row being updated |
| 84944 | ** is deleted or renamed by a BEFORE trigger - is left undefined in the |
| 84945 | ** documentation. */ |
| 84946 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); |
| 84947 | } |
| 84948 | |
| 84949 | if( !isView ){ |
| 84950 | |
| 84951 | /* Do constraint checks. */ |
| 84952 | sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, |
| 84953 | aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0); |
| 84954 | |
| @@ -90583,11 +90648,11 @@ | |
| 90583 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 90584 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 90585 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 90586 | sqlite3 *db = pParse->db; |
| 90587 | if( db->mallocFailed==0 && pY->op==TK_NULL ){ |
| 90588 | pA->op = op; |
| 90589 | sqlite3ExprDelete(db, pA->pRight); |
| 90590 | pA->pRight = 0; |
| 90591 | } |
| 90592 | } |
| 90593 | |
| @@ -97946,11 +98011,558 @@ | |
| 97946 | |
| 97947 | #if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) |
| 97948 | # define SQLITE_CORE 1 |
| 97949 | #endif |
| 97950 | |
| 97951 | #include "fts3Int.h" |
| 97952 | |
| 97953 | |
| 97954 | #ifndef SQLITE_CORE |
| 97955 | SQLITE_EXTENSION_INIT1 |
| 97956 | #endif |
| @@ -98108,11 +98720,11 @@ | |
| 98108 | default: return; |
| 98109 | } |
| 98110 | for(i=1, j=0; z[i]; i++){ |
| 98111 | if( z[i]==quote ){ |
| 98112 | if( z[i+1]==quote ){ |
| 98113 | z[j++] = quote; |
| 98114 | i++; |
| 98115 | }else{ |
| 98116 | z[j++] = 0; |
| 98117 | break; |
| 98118 | } |
| @@ -98134,22 +98746,10 @@ | |
| 98134 | }else{ |
| 98135 | fts3GetDeltaVarint(pp, pVal); |
| 98136 | } |
| 98137 | } |
| 98138 | |
| 98139 | |
| 98140 | /* |
| 98141 | ** The Fts3Cursor.eType member is always set to one of the following. |
| 98142 | */ |
| 98143 | #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ |
| 98144 | #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ |
| 98145 | #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ |
| 98146 | |
| 98147 | static Fts3Table *cursor_vtab(Fts3Cursor *c){ |
| 98148 | return (Fts3Table *) c->base.pVtab; |
| 98149 | } |
| 98150 | |
| 98151 | /* |
| 98152 | ** The xDisconnect() virtual table method. |
| 98153 | */ |
| 98154 | static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ |
| 98155 | Fts3Table *p = (Fts3Table *)pVtab; |
| @@ -98295,11 +98895,11 @@ | |
| 98295 | ** The argv[] array contains the following: |
| 98296 | ** |
| 98297 | ** argv[0] -> module name |
| 98298 | ** argv[1] -> database name |
| 98299 | ** argv[2] -> table name |
| 98300 | ** argv[...] -> "column name" fields... |
| 98301 | */ |
| 98302 | int fts3InitVtab( |
| 98303 | int isCreate, /* True for xCreate, false for xConnect */ |
| 98304 | sqlite3 *db, /* The SQLite database connection */ |
| 98305 | void *pAux, /* Hash table containing tokenizers */ |
| @@ -98307,34 +98907,42 @@ | |
| 98307 | const char * const *argv, /* xCreate/xConnect argument array */ |
| 98308 | sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ |
| 98309 | char **pzErr /* Write any error message here */ |
| 98310 | ){ |
| 98311 | Fts3Hash *pHash = (Fts3Hash *)pAux; |
| 98312 | Fts3Table *p; /* Pointer to allocated vtab */ |
| 98313 | int rc; /* Return code */ |
| 98314 | int i; |
| 98315 | int nByte; |
| 98316 | int iCol; |
| 98317 | int nString = 0; |
| 98318 | int nCol = 0; |
| 98319 | char *zCsr; |
| 98320 | int nDb; |
| 98321 | int nName; |
| 98322 | |
| 98323 | const char *zTokenizer = 0; |
| 98324 | sqlite3_tokenizer *pTokenizer; /* Tokenizer for this table */ |
| 98325 | |
| 98326 | nDb = strlen(argv[1]) + 1; |
| 98327 | nName = strlen(argv[2]) + 1; |
| 98328 | for(i=3; i<argc; i++){ |
| 98329 | char const *z = argv[i]; |
| 98330 | rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr); |
| 98331 | if( rc!=SQLITE_OK ){ |
| 98332 | return rc; |
| 98333 | } |
| 98334 | if( z!=zTokenizer ){ |
| 98335 | nString += strlen(z) + 1; |
| 98336 | } |
| 98337 | } |
| 98338 | nCol = argc - 3 - (zTokenizer!=0); |
| 98339 | if( zTokenizer==0 ){ |
| 98340 | rc = sqlite3Fts3InitTokenizer(pHash, 0, &pTokenizer, 0, pzErr); |
| @@ -98341,10 +98949,14 @@ | |
| 98341 | if( rc!=SQLITE_OK ){ |
| 98342 | return rc; |
| 98343 | } |
| 98344 | assert( pTokenizer ); |
| 98345 | } |
| 98346 | |
| 98347 | /* Allocate and populate the Fts3Table structure. */ |
| 98348 | nByte = sizeof(Fts3Table) + /* Fts3Table */ |
| 98349 | nCol * sizeof(char *) + /* azColumn */ |
| 98350 | nName + /* zName */ |
| @@ -98360,10 +98972,11 @@ | |
| 98360 | p->db = db; |
| 98361 | p->nColumn = nCol; |
| 98362 | p->nPendingData = 0; |
| 98363 | p->azColumn = (char **)&p[1]; |
| 98364 | p->pTokenizer = pTokenizer; |
| 98365 | zCsr = (char *)&p->azColumn[nCol]; |
| 98366 | |
| 98367 | fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1); |
| 98368 | |
| 98369 | /* Fill in the zName and zDb fields of the vtab structure. */ |
| @@ -98387,10 +99000,14 @@ | |
| 98387 | p->azColumn[iCol++] = zCsr; |
| 98388 | zCsr += n+1; |
| 98389 | assert( zCsr <= &((char *)p)[nByte] ); |
| 98390 | } |
| 98391 | } |
| 98392 | |
| 98393 | /* If this is an xCreate call, create the underlying tables in the |
| 98394 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 98395 | */ |
| 98396 | if( isCreate ){ |
| @@ -98399,16 +99016,25 @@ | |
| 98399 | } |
| 98400 | |
| 98401 | rc = fts3DeclareVtab(p); |
| 98402 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 98403 | |
| 98404 | *ppVTab = &p->base; |
| 98405 | |
| 98406 | fts3_init_out: |
| 98407 | if( rc!=SQLITE_OK ){ |
| 98408 | if( p ) fts3DisconnectMethod((sqlite3_vtab *)p); |
| 98409 | else if( pTokenizer ) pTokenizer->pModule->xDestroy(pTokenizer); |
| 98410 | } |
| 98411 | return rc; |
| 98412 | } |
| 98413 | |
| 98414 | /* |
| @@ -98497,10 +99123,12 @@ | |
| 98497 | /* |
| 98498 | ** Implementation of xOpen method. |
| 98499 | */ |
| 98500 | static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ |
| 98501 | sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ |
| 98502 | |
| 98503 | /* Allocate a buffer large enough for an Fts3Cursor structure. If the |
| 98504 | ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, |
| 98505 | ** if the allocation fails, return SQLITE_NOMEM. |
| 98506 | */ |
| @@ -98664,16 +99292,20 @@ | |
| 98664 | } |
| 98665 | sqlite3_free(zBuffer); |
| 98666 | return rc; |
| 98667 | } |
| 98668 | |
| 98669 | static void fts3PutDeltaVarint( |
| 98670 | char **pp, |
| 98671 | sqlite3_int64 *piPrev, |
| 98672 | sqlite3_int64 iVal |
| 98673 | ){ |
| 98674 | assert( iVal-*piPrev > 0 ); |
| 98675 | *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); |
| 98676 | *piPrev = iVal; |
| 98677 | } |
| 98678 | |
| 98679 | static void fts3PoslistCopy(char **pp, char **ppPoslist){ |
| @@ -98680,11 +99312,11 @@ | |
| 98680 | char *pEnd = *ppPoslist; |
| 98681 | char c = 0; |
| 98682 | while( *pEnd | c ) c = *pEnd++ & 0x80; |
| 98683 | pEnd++; |
| 98684 | if( pp ){ |
| 98685 | int n = pEnd - *ppPoslist; |
| 98686 | char *p = *pp; |
| 98687 | memcpy(p, *ppPoslist, n); |
| 98688 | p += n; |
| 98689 | *pp = p; |
| 98690 | } |
| @@ -98694,11 +99326,11 @@ | |
| 98694 | static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ |
| 98695 | char *pEnd = *ppPoslist; |
| 98696 | char c = 0; |
| 98697 | while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; |
| 98698 | if( pp ){ |
| 98699 | int n = pEnd - *ppPoslist; |
| 98700 | char *p = *pp; |
| 98701 | memcpy(p, *ppPoslist, n); |
| 98702 | p += n; |
| 98703 | *pp = p; |
| 98704 | } |
| @@ -99081,11 +99713,11 @@ | |
| 99081 | |
| 99082 | default: |
| 99083 | assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); |
| 99084 | } |
| 99085 | |
| 99086 | *pnBuffer = (p-aBuffer); |
| 99087 | return SQLITE_OK; |
| 99088 | } |
| 99089 | |
| 99090 | /* |
| 99091 | ** A pointer to an instance of this structure is used as the context |
| @@ -99113,10 +99745,14 @@ | |
| 99113 | ){ |
| 99114 | TermSelect *pTS = (TermSelect *)pContext; |
| 99115 | int nNew = pTS->nOutput + nDoclist; |
| 99116 | char *aNew = sqlite3_malloc(nNew); |
| 99117 | |
| 99118 | if( !aNew ){ |
| 99119 | return SQLITE_NOMEM; |
| 99120 | } |
| 99121 | |
| 99122 | if( pTS->nOutput==0 ){ |
| @@ -99194,25 +99830,38 @@ | |
| 99194 | ** leaf). Do not bother inspecting any data in this case, just |
| 99195 | ** create a Fts3SegReader to scan the single leaf. |
| 99196 | */ |
| 99197 | rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew); |
| 99198 | }else{ |
| 99199 | sqlite3_int64 i1; |
| 99200 | rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1); |
| 99201 | if( rc==SQLITE_OK ){ |
| 99202 | sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2); |
| 99203 | rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew); |
| 99204 | } |
| 99205 | } |
| 99206 | iAge++; |
| 99207 | |
| 99208 | /* If a new Fts3SegReader was allocated, add it to the apSegment array. */ |
| 99209 | assert( (rc==SQLITE_OK)==(pNew!=0) ); |
| 99210 | if( pNew ){ |
| 99211 | if( nSegment==nAlloc ){ |
| 99212 | nAlloc += 16; |
| 99213 | Fts3SegReader **pArray = (Fts3SegReader **)sqlite3_realloc( |
| 99214 | apSegment, nAlloc*sizeof(Fts3SegReader *) |
| 99215 | ); |
| 99216 | if( !pArray ){ |
| 99217 | sqlite3Fts3SegReaderFree(p, pNew); |
| 99218 | rc = SQLITE_NOMEM; |
| @@ -99348,10 +99997,13 @@ | |
| 99348 | int nRight; |
| 99349 | |
| 99350 | if( SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pRight, &aRight, &nRight)) |
| 99351 | && SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pLeft, &aLeft, &nLeft)) |
| 99352 | ){ |
| 99353 | switch( pExpr->eType ){ |
| 99354 | case FTSQUERY_NEAR: { |
| 99355 | Fts3Expr *pLeft; |
| 99356 | Fts3Expr *pRight; |
| 99357 | int mergetype = MERGE_NEAR; |
| @@ -99398,12 +100050,11 @@ | |
| 99398 | *paOut = aBuffer; |
| 99399 | sqlite3_free(aLeft); |
| 99400 | break; |
| 99401 | } |
| 99402 | |
| 99403 | case FTSQUERY_AND: |
| 99404 | case FTSQUERY_NOT: { |
| 99405 | assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND ); |
| 99406 | fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut, |
| 99407 | aLeft, nLeft, aRight, nRight |
| 99408 | ); |
| 99409 | *paOut = aLeft; |
| @@ -99452,10 +100103,13 @@ | |
| 99452 | }; |
| 99453 | int rc; /* Return code */ |
| 99454 | char *zSql; /* SQL statement used to access %_content */ |
| 99455 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 99456 | Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
| 99457 | |
| 99458 | assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
| 99459 | assert( nVal==0 || nVal==1 ); |
| 99460 | assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); |
| 99461 | |
| @@ -99475,18 +100129,21 @@ | |
| 99475 | }else{ |
| 99476 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
| 99477 | sqlite3_free(zSql); |
| 99478 | } |
| 99479 | if( rc!=SQLITE_OK ) return rc; |
| 99480 | pCsr->eType = idxNum; |
| 99481 | |
| 99482 | if( idxNum==FTS3_DOCID_SEARCH ){ |
| 99483 | rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); |
| 99484 | }else if( idxNum!=FTS3_FULLSCAN_SEARCH ){ |
| 99485 | int iCol = idxNum-FTS3_FULLTEXT_SEARCH; |
| 99486 | const char *zQuery = (const char *)sqlite3_value_text(apVal[0]); |
| 99487 | |
| 99488 | rc = sqlite3Fts3PendingTermsFlush(p); |
| 99489 | if( rc!=SQLITE_OK ) return rc; |
| 99490 | |
| 99491 | rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn, |
| 99492 | iCol, zQuery, -1, &pCsr->pExpr |
| @@ -99508,42 +100165,10 @@ | |
| 99508 | */ |
| 99509 | static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ |
| 99510 | return ((Fts3Cursor *)pCursor)->isEof; |
| 99511 | } |
| 99512 | |
| 99513 | /* |
| 99514 | ** This is the xColumn method of the virtual table. The SQLite |
| 99515 | ** core calls this method during a query when it needs the value |
| 99516 | ** of a column from the virtual table. This method needs to use |
| 99517 | ** one of the sqlite3_result_*() routines to store the requested |
| 99518 | ** value back in the pContext. |
| 99519 | */ |
| 99520 | static int fts3ColumnMethod(sqlite3_vtab_cursor *pCursor, |
| 99521 | sqlite3_context *pContext, int idxCol){ |
| 99522 | Fts3Cursor *c = (Fts3Cursor *) pCursor; |
| 99523 | Fts3Table *v = cursor_vtab(c); |
| 99524 | int rc = fts3CursorSeek(c); |
| 99525 | if( rc!=SQLITE_OK ){ |
| 99526 | return rc; |
| 99527 | } |
| 99528 | |
| 99529 | if( idxCol<v->nColumn ){ |
| 99530 | sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); |
| 99531 | sqlite3_result_value(pContext, pVal); |
| 99532 | }else if( idxCol==v->nColumn ){ |
| 99533 | /* The extra column whose name is the same as the table. |
| 99534 | ** Return a blob which is a pointer to the cursor |
| 99535 | */ |
| 99536 | sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); |
| 99537 | }else if( idxCol==v->nColumn+1 ){ |
| 99538 | /* The docid column, which is an alias for rowid. */ |
| 99539 | sqlite3_value *pVal = sqlite3_column_value(c->pStmt, 0); |
| 99540 | sqlite3_result_value(pContext, pVal); |
| 99541 | } |
| 99542 | return SQLITE_OK; |
| 99543 | } |
| 99544 | |
| 99545 | /* |
| 99546 | ** This is the xRowid method. The SQLite core calls this routine to |
| 99547 | ** retrieve the rowid for the current row of the result set. fts3 |
| 99548 | ** exposes %_content.docid as the rowid for the virtual table. The |
| 99549 | ** rowid should be written to *pRowid. |
| @@ -99555,10 +100180,47 @@ | |
| 99555 | }else{ |
| 99556 | *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); |
| 99557 | } |
| 99558 | return SQLITE_OK; |
| 99559 | } |
| 99560 | |
| 99561 | /* |
| 99562 | ** This function is the implementation of the xUpdate callback used by |
| 99563 | ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be |
| 99564 | ** inserted, updated or deleted. |
| @@ -99582,10 +100244,11 @@ | |
| 99582 | |
| 99583 | /* |
| 99584 | ** Implementation of xBegin() method. This is a no-op. |
| 99585 | */ |
| 99586 | static int fts3BeginMethod(sqlite3_vtab *pVtab){ |
| 99587 | assert( ((Fts3Table *)pVtab)->nPendingData==0 ); |
| 99588 | return SQLITE_OK; |
| 99589 | } |
| 99590 | |
| 99591 | /* |
| @@ -99592,10 +100255,11 @@ | |
| 99592 | ** Implementation of xCommit() method. This is a no-op. The contents of |
| 99593 | ** the pending-terms hash-table have already been flushed into the database |
| 99594 | ** by fts3SyncMethod(). |
| 99595 | */ |
| 99596 | static int fts3CommitMethod(sqlite3_vtab *pVtab){ |
| 99597 | assert( ((Fts3Table *)pVtab)->nPendingData==0 ); |
| 99598 | return SQLITE_OK; |
| 99599 | } |
| 99600 | |
| 99601 | /* |
| @@ -99670,10 +100334,12 @@ | |
| 99670 | int nVal, /* Size of argument array */ |
| 99671 | sqlite3_value **apVal /* Array of arguments */ |
| 99672 | ){ |
| 99673 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 99674 | |
| 99675 | assert( nVal==1 ); |
| 99676 | if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return; |
| 99677 | assert( pCsr ); |
| 99678 | sqlite3Fts3Offsets(pContext, pCsr); |
| 99679 | } |
| @@ -99693,10 +100359,12 @@ | |
| 99693 | sqlite3_value **apVal /* Array of arguments */ |
| 99694 | ){ |
| 99695 | int rc; /* Return code */ |
| 99696 | Fts3Table *p; /* Virtual table handle */ |
| 99697 | Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */ |
| 99698 | |
| 99699 | assert( nVal==1 ); |
| 99700 | if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return; |
| 99701 | p = (Fts3Table *)pCursor->base.pVtab; |
| 99702 | assert( p ); |
| @@ -99734,10 +100402,15 @@ | |
| 99734 | { "snippet", fts3SnippetFunc }, |
| 99735 | { "offsets", fts3OffsetsFunc }, |
| 99736 | { "optimize", fts3OptimizeFunc }, |
| 99737 | }; |
| 99738 | int i; /* Iterator variable */ |
| 99739 | for(i=0; i<SizeofArray(aOverload); i++){ |
| 99740 | if( strcmp(zName, aOverload[i].zName)==0 ){ |
| 99741 | *pxFunc = aOverload[i].xFunc; |
| 99742 | return 1; |
| 99743 | } |
| @@ -100150,11 +100823,11 @@ | |
| 100150 | pCursor = 0; |
| 100151 | } |
| 100152 | |
| 100153 | if( rc==SQLITE_DONE ){ |
| 100154 | int jj; |
| 100155 | char *zNew; |
| 100156 | int nNew = 0; |
| 100157 | int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase); |
| 100158 | nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(struct PhraseToken); |
| 100159 | p = fts3ReallocOrFree(p, nByte + nTemp); |
| 100160 | if( !p ){ |
| @@ -100209,11 +100882,11 @@ | |
| 100209 | const char *z, int n, /* Input string */ |
| 100210 | Fts3Expr **ppExpr, /* OUT: expression */ |
| 100211 | int *pnConsumed /* OUT: Number of bytes consumed */ |
| 100212 | ){ |
| 100213 | static const struct Fts3Keyword { |
| 100214 | char z[4]; /* Keyword text */ |
| 100215 | unsigned char n; /* Length of the keyword */ |
| 100216 | unsigned char parenOnly; /* Only valid in paren mode */ |
| 100217 | unsigned char eType; /* Keyword code */ |
| 100218 | } aKeyword[] = { |
| 100219 | { "OR" , 2, 0, FTSQUERY_OR }, |
| @@ -100279,11 +100952,11 @@ | |
| 100279 | } |
| 100280 | memset(pRet, 0, sizeof(Fts3Expr)); |
| 100281 | pRet->eType = pKey->eType; |
| 100282 | pRet->nNear = nNear; |
| 100283 | *ppExpr = pRet; |
| 100284 | *pnConsumed = (zInput - z) + nKey; |
| 100285 | return SQLITE_OK; |
| 100286 | } |
| 100287 | |
| 100288 | /* Turns out that wasn't a keyword after all. This happens if the |
| 100289 | ** user has supplied a token such as "ORacle". Continue. |
| @@ -100299,18 +100972,18 @@ | |
| 100299 | pParse->nNest++; |
| 100300 | rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); |
| 100301 | if( rc==SQLITE_OK && !*ppExpr ){ |
| 100302 | rc = SQLITE_DONE; |
| 100303 | } |
| 100304 | *pnConsumed = (zInput - z) + 1 + nConsumed; |
| 100305 | return rc; |
| 100306 | } |
| 100307 | |
| 100308 | /* Check for a close bracket. */ |
| 100309 | if( *zInput==')' ){ |
| 100310 | pParse->nNest--; |
| 100311 | *pnConsumed = (zInput - z) + 1; |
| 100312 | return SQLITE_DONE; |
| 100313 | } |
| 100314 | } |
| 100315 | |
| 100316 | /* See if we are dealing with a quoted phrase. If this is the case, then |
| @@ -100318,11 +100991,11 @@ | |
| 100318 | ** for processing. This is easy to do, as fts3 has no syntax for escaping |
| 100319 | ** a quote character embedded in a string. |
| 100320 | */ |
| 100321 | if( *zInput=='"' ){ |
| 100322 | for(ii=1; ii<nInput && zInput[ii]!='"'; ii++); |
| 100323 | *pnConsumed = (zInput - z) + ii + 1; |
| 100324 | if( ii==nInput ){ |
| 100325 | return SQLITE_ERROR; |
| 100326 | } |
| 100327 | return getNextString(pParse, &zInput[1], ii-1, ppExpr); |
| 100328 | } |
| @@ -100341,16 +101014,16 @@ | |
| 100341 | */ |
| 100342 | iCol = pParse->iDefaultCol; |
| 100343 | iColLen = 0; |
| 100344 | for(ii=0; ii<pParse->nCol; ii++){ |
| 100345 | const char *zStr = pParse->azCol[ii]; |
| 100346 | int nStr = strlen(zStr); |
| 100347 | if( nInput>nStr && zInput[nStr]==':' |
| 100348 | && sqlite3_strnicmp(zStr, zInput, nStr)==0 |
| 100349 | ){ |
| 100350 | iCol = ii; |
| 100351 | iColLen = ((zInput - z) + nStr + 1); |
| 100352 | break; |
| 100353 | } |
| 100354 | } |
| 100355 | rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed); |
| 100356 | *pnConsumed += iColLen; |
| @@ -100612,11 +101285,11 @@ | |
| 100612 | if( z==0 ){ |
| 100613 | *ppExpr = 0; |
| 100614 | return SQLITE_OK; |
| 100615 | } |
| 100616 | if( n<0 ){ |
| 100617 | n = strlen(z); |
| 100618 | } |
| 100619 | rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); |
| 100620 | |
| 100621 | /* Check for mismatched parenthesis */ |
| 100622 | if( rc==SQLITE_OK && sParse.nNest ){ |
| @@ -100666,11 +101339,11 @@ | |
| 100666 | } |
| 100667 | |
| 100668 | sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 100669 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 100670 | if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 100671 | memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); |
| 100672 | } |
| 100673 | } |
| 100674 | |
| 100675 | return sqlite3_finalize(pStmt); |
| 100676 | } |
| @@ -100849,125 +101522,10 @@ | |
| 100849 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 100850 | */ |
| 100851 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 100852 | |
| 100853 | |
| 100854 | /************** Include fts3_hash.h in the middle of fts3_hash.c *************/ |
| 100855 | /************** Begin file fts3_hash.h ***************************************/ |
| 100856 | /* |
| 100857 | ** 2001 September 22 |
| 100858 | ** |
| 100859 | ** The author disclaims copyright to this source code. In place of |
| 100860 | ** a legal notice, here is a blessing: |
| 100861 | ** |
| 100862 | ** May you do good and not evil. |
| 100863 | ** May you find forgiveness for yourself and forgive others. |
| 100864 | ** May you share freely, never taking more than you give. |
| 100865 | ** |
| 100866 | ************************************************************************* |
| 100867 | ** This is the header file for the generic hash-table implemenation |
| 100868 | ** used in SQLite. We've modified it slightly to serve as a standalone |
| 100869 | ** hash table implementation for the full-text indexing module. |
| 100870 | ** |
| 100871 | */ |
| 100872 | #ifndef _FTS3_HASH_H_ |
| 100873 | #define _FTS3_HASH_H_ |
| 100874 | |
| 100875 | /* Forward declarations of structures. */ |
| 100876 | typedef struct Fts3Hash Fts3Hash; |
| 100877 | typedef struct Fts3HashElem Fts3HashElem; |
| 100878 | |
| 100879 | /* A complete hash table is an instance of the following structure. |
| 100880 | ** The internals of this structure are intended to be opaque -- client |
| 100881 | ** code should not attempt to access or modify the fields of this structure |
| 100882 | ** directly. Change this structure only by using the routines below. |
| 100883 | ** However, many of the "procedures" and "functions" for modifying and |
| 100884 | ** accessing this structure are really macros, so we can't really make |
| 100885 | ** this structure opaque. |
| 100886 | */ |
| 100887 | struct Fts3Hash { |
| 100888 | char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ |
| 100889 | char copyKey; /* True if copy of key made on insert */ |
| 100890 | int count; /* Number of entries in this table */ |
| 100891 | Fts3HashElem *first; /* The first element of the array */ |
| 100892 | int htsize; /* Number of buckets in the hash table */ |
| 100893 | struct _fts3ht { /* the hash table */ |
| 100894 | int count; /* Number of entries with this hash */ |
| 100895 | Fts3HashElem *chain; /* Pointer to first entry with this hash */ |
| 100896 | } *ht; |
| 100897 | }; |
| 100898 | |
| 100899 | /* Each element in the hash table is an instance of the following |
| 100900 | ** structure. All elements are stored on a single doubly-linked list. |
| 100901 | ** |
| 100902 | ** Again, this structure is intended to be opaque, but it can't really |
| 100903 | ** be opaque because it is used by macros. |
| 100904 | */ |
| 100905 | struct Fts3HashElem { |
| 100906 | Fts3HashElem *next, *prev; /* Next and previous elements in the table */ |
| 100907 | void *data; /* Data associated with this element */ |
| 100908 | void *pKey; int nKey; /* Key associated with this element */ |
| 100909 | }; |
| 100910 | |
| 100911 | /* |
| 100912 | ** There are 2 different modes of operation for a hash table: |
| 100913 | ** |
| 100914 | ** FTS3_HASH_STRING pKey points to a string that is nKey bytes long |
| 100915 | ** (including the null-terminator, if any). Case |
| 100916 | ** is respected in comparisons. |
| 100917 | ** |
| 100918 | ** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. |
| 100919 | ** memcmp() is used to compare keys. |
| 100920 | ** |
| 100921 | ** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. |
| 100922 | */ |
| 100923 | #define FTS3_HASH_STRING 1 |
| 100924 | #define FTS3_HASH_BINARY 2 |
| 100925 | |
| 100926 | /* |
| 100927 | ** Access routines. To delete, insert a NULL pointer. |
| 100928 | */ |
| 100929 | SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash*, int keytype, int copyKey); |
| 100930 | SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); |
| 100931 | SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); |
| 100932 | SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*); |
| 100933 | |
| 100934 | /* |
| 100935 | ** Shorthand for the functions above |
| 100936 | */ |
| 100937 | #define fts3HashInit sqlite3Fts3HashInit |
| 100938 | #define fts3HashInsert sqlite3Fts3HashInsert |
| 100939 | #define fts3HashFind sqlite3Fts3HashFind |
| 100940 | #define fts3HashClear sqlite3Fts3HashClear |
| 100941 | |
| 100942 | /* |
| 100943 | ** Macros for looping over all elements of a hash table. The idiom is |
| 100944 | ** like this: |
| 100945 | ** |
| 100946 | ** Fts3Hash h; |
| 100947 | ** Fts3HashElem *p; |
| 100948 | ** ... |
| 100949 | ** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ |
| 100950 | ** SomeStructure *pData = fts3HashData(p); |
| 100951 | ** // do something with pData |
| 100952 | ** } |
| 100953 | */ |
| 100954 | #define fts3HashFirst(H) ((H)->first) |
| 100955 | #define fts3HashNext(E) ((E)->next) |
| 100956 | #define fts3HashData(E) ((E)->data) |
| 100957 | #define fts3HashKey(E) ((E)->pKey) |
| 100958 | #define fts3HashKeysize(E) ((E)->nKey) |
| 100959 | |
| 100960 | /* |
| 100961 | ** Number of entries in a hash table |
| 100962 | */ |
| 100963 | #define fts3HashCount(H) ((H)->count) |
| 100964 | |
| 100965 | #endif /* _FTS3_HASH_H_ */ |
| 100966 | |
| 100967 | /************** End of fts3_hash.h *******************************************/ |
| 100968 | /************** Continuing where we left off in fts3_hash.c ******************/ |
| 100969 | |
| 100970 | /* |
| 100971 | ** Malloc and Free functions |
| 100972 | */ |
| 100973 | static void *fts3HashMalloc(int n){ |
| @@ -100989,11 +101547,11 @@ | |
| 100989 | ** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass |
| 100990 | ** determines what kind of key the hash table will use. "copyKey" is |
| 100991 | ** true if the hash table should make its own private copy of keys and |
| 100992 | ** false if it should just use the supplied pointer. |
| 100993 | */ |
| 100994 | SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, int keyClass, int copyKey){ |
| 100995 | assert( pNew!=0 ); |
| 100996 | assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); |
| 100997 | pNew->keyClass = keyClass; |
| 100998 | pNew->copyKey = copyKey; |
| 100999 | pNew->first = 0; |
| @@ -101123,28 +101681,31 @@ | |
| 101123 | |
| 101124 | |
| 101125 | /* Resize the hash table so that it cantains "new_size" buckets. |
| 101126 | ** "new_size" must be a power of 2. The hash table might fail |
| 101127 | ** to resize if sqliteMalloc() fails. |
| 101128 | */ |
| 101129 | static void fts3Rehash(Fts3Hash *pH, int new_size){ |
| 101130 | struct _fts3ht *new_ht; /* The new hash table */ |
| 101131 | Fts3HashElem *elem, *next_elem; /* For looping over existing elements */ |
| 101132 | int (*xHash)(const void*,int); /* The hash function */ |
| 101133 | |
| 101134 | assert( (new_size & (new_size-1))==0 ); |
| 101135 | new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); |
| 101136 | if( new_ht==0 ) return; |
| 101137 | fts3HashFree(pH->ht); |
| 101138 | pH->ht = new_ht; |
| 101139 | pH->htsize = new_size; |
| 101140 | xHash = ftsHashFunction(pH->keyClass); |
| 101141 | for(elem=pH->first, pH->first=0; elem; elem = next_elem){ |
| 101142 | int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); |
| 101143 | next_elem = elem->next; |
| 101144 | fts3HashInsertElement(pH, &new_ht[h], elem); |
| 101145 | } |
| 101146 | } |
| 101147 | |
| 101148 | /* This function (for internal use only) locates an element in an |
| 101149 | ** hash table that matches the given key. The hash for this key has |
| 101150 | ** already been computed and is passed as the 4th parameter. |
| @@ -101271,17 +101832,17 @@ | |
| 101271 | elem->data = data; |
| 101272 | } |
| 101273 | return old_data; |
| 101274 | } |
| 101275 | if( data==0 ) return 0; |
| 101276 | if( pH->htsize==0 ){ |
| 101277 | fts3Rehash(pH,8); |
| 101278 | if( pH->htsize==0 ){ |
| 101279 | pH->count = 0; |
| 101280 | return data; |
| 101281 | } |
| 101282 | } |
| 101283 | new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) ); |
| 101284 | if( new_elem==0 ) return data; |
| 101285 | if( pH->copyKey && pKey!=0 ){ |
| 101286 | new_elem->pKey = fts3HashMalloc( nKey ); |
| 101287 | if( new_elem->pKey==0 ){ |
| @@ -101292,13 +101853,10 @@ | |
| 101292 | }else{ |
| 101293 | new_elem->pKey = (void*)pKey; |
| 101294 | } |
| 101295 | new_elem->nKey = nKey; |
| 101296 | pH->count++; |
| 101297 | if( pH->count > pH->htsize ){ |
| 101298 | fts3Rehash(pH,pH->htsize*2); |
| 101299 | } |
| 101300 | assert( pH->htsize>0 ); |
| 101301 | assert( (pH->htsize & (pH->htsize-1))==0 ); |
| 101302 | h = hraw & (pH->htsize-1); |
| 101303 | fts3HashInsertElement(pH, &pH->ht[h], new_elem); |
| 101304 | new_elem->data = data; |
| @@ -101335,162 +101893,10 @@ | |
| 101335 | */ |
| 101336 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 101337 | |
| 101338 | |
| 101339 | |
| 101340 | /************** Include fts3_tokenizer.h in the middle of fts3_porter.c ******/ |
| 101341 | /************** Begin file fts3_tokenizer.h **********************************/ |
| 101342 | /* |
| 101343 | ** 2006 July 10 |
| 101344 | ** |
| 101345 | ** The author disclaims copyright to this source code. |
| 101346 | ** |
| 101347 | ************************************************************************* |
| 101348 | ** Defines the interface to tokenizers used by fulltext-search. There |
| 101349 | ** are three basic components: |
| 101350 | ** |
| 101351 | ** sqlite3_tokenizer_module is a singleton defining the tokenizer |
| 101352 | ** interface functions. This is essentially the class structure for |
| 101353 | ** tokenizers. |
| 101354 | ** |
| 101355 | ** sqlite3_tokenizer is used to define a particular tokenizer, perhaps |
| 101356 | ** including customization information defined at creation time. |
| 101357 | ** |
| 101358 | ** sqlite3_tokenizer_cursor is generated by a tokenizer to generate |
| 101359 | ** tokens from a particular input. |
| 101360 | */ |
| 101361 | #ifndef _FTS3_TOKENIZER_H_ |
| 101362 | #define _FTS3_TOKENIZER_H_ |
| 101363 | |
| 101364 | /* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. |
| 101365 | ** If tokenizers are to be allowed to call sqlite3_*() functions, then |
| 101366 | ** we will need a way to register the API consistently. |
| 101367 | */ |
| 101368 | |
| 101369 | /* |
| 101370 | ** Structures used by the tokenizer interface. When a new tokenizer |
| 101371 | ** implementation is registered, the caller provides a pointer to |
| 101372 | ** an sqlite3_tokenizer_module containing pointers to the callback |
| 101373 | ** functions that make up an implementation. |
| 101374 | ** |
| 101375 | ** When an fts3 table is created, it passes any arguments passed to |
| 101376 | ** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the |
| 101377 | ** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer |
| 101378 | ** implementation. The xCreate() function in turn returns an |
| 101379 | ** sqlite3_tokenizer structure representing the specific tokenizer to |
| 101380 | ** be used for the fts3 table (customized by the tokenizer clause arguments). |
| 101381 | ** |
| 101382 | ** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() |
| 101383 | ** method is called. It returns an sqlite3_tokenizer_cursor object |
| 101384 | ** that may be used to tokenize a specific input buffer based on |
| 101385 | ** the tokenization rules supplied by a specific sqlite3_tokenizer |
| 101386 | ** object. |
| 101387 | */ |
| 101388 | typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; |
| 101389 | typedef struct sqlite3_tokenizer sqlite3_tokenizer; |
| 101390 | typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; |
| 101391 | |
| 101392 | struct sqlite3_tokenizer_module { |
| 101393 | |
| 101394 | /* |
| 101395 | ** Structure version. Should always be set to 0. |
| 101396 | */ |
| 101397 | int iVersion; |
| 101398 | |
| 101399 | /* |
| 101400 | ** Create a new tokenizer. The values in the argv[] array are the |
| 101401 | ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL |
| 101402 | ** TABLE statement that created the fts3 table. For example, if |
| 101403 | ** the following SQL is executed: |
| 101404 | ** |
| 101405 | ** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2) |
| 101406 | ** |
| 101407 | ** then argc is set to 2, and the argv[] array contains pointers |
| 101408 | ** to the strings "arg1" and "arg2". |
| 101409 | ** |
| 101410 | ** This method should return either SQLITE_OK (0), or an SQLite error |
| 101411 | ** code. If SQLITE_OK is returned, then *ppTokenizer should be set |
| 101412 | ** to point at the newly created tokenizer structure. The generic |
| 101413 | ** sqlite3_tokenizer.pModule variable should not be initialised by |
| 101414 | ** this callback. The caller will do so. |
| 101415 | */ |
| 101416 | int (*xCreate)( |
| 101417 | int argc, /* Size of argv array */ |
| 101418 | const char *const*argv, /* Tokenizer argument strings */ |
| 101419 | sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ |
| 101420 | ); |
| 101421 | |
| 101422 | /* |
| 101423 | ** Destroy an existing tokenizer. The fts3 module calls this method |
| 101424 | ** exactly once for each successful call to xCreate(). |
| 101425 | */ |
| 101426 | int (*xDestroy)(sqlite3_tokenizer *pTokenizer); |
| 101427 | |
| 101428 | /* |
| 101429 | ** Create a tokenizer cursor to tokenize an input buffer. The caller |
| 101430 | ** is responsible for ensuring that the input buffer remains valid |
| 101431 | ** until the cursor is closed (using the xClose() method). |
| 101432 | */ |
| 101433 | int (*xOpen)( |
| 101434 | sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ |
| 101435 | const char *pInput, int nBytes, /* Input buffer */ |
| 101436 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ |
| 101437 | ); |
| 101438 | |
| 101439 | /* |
| 101440 | ** Destroy an existing tokenizer cursor. The fts3 module calls this |
| 101441 | ** method exactly once for each successful call to xOpen(). |
| 101442 | */ |
| 101443 | int (*xClose)(sqlite3_tokenizer_cursor *pCursor); |
| 101444 | |
| 101445 | /* |
| 101446 | ** Retrieve the next token from the tokenizer cursor pCursor. This |
| 101447 | ** method should either return SQLITE_OK and set the values of the |
| 101448 | ** "OUT" variables identified below, or SQLITE_DONE to indicate that |
| 101449 | ** the end of the buffer has been reached, or an SQLite error code. |
| 101450 | ** |
| 101451 | ** *ppToken should be set to point at a buffer containing the |
| 101452 | ** normalized version of the token (i.e. after any case-folding and/or |
| 101453 | ** stemming has been performed). *pnBytes should be set to the length |
| 101454 | ** of this buffer in bytes. The input text that generated the token is |
| 101455 | ** identified by the byte offsets returned in *piStartOffset and |
| 101456 | ** *piEndOffset. *piStartOffset should be set to the index of the first |
| 101457 | ** byte of the token in the input buffer. *piEndOffset should be set |
| 101458 | ** to the index of the first byte just past the end of the token in |
| 101459 | ** the input buffer. |
| 101460 | ** |
| 101461 | ** The buffer *ppToken is set to point at is managed by the tokenizer |
| 101462 | ** implementation. It is only required to be valid until the next call |
| 101463 | ** to xNext() or xClose(). |
| 101464 | */ |
| 101465 | /* TODO(shess) current implementation requires pInput to be |
| 101466 | ** nul-terminated. This should either be fixed, or pInput/nBytes |
| 101467 | ** should be converted to zInput. |
| 101468 | */ |
| 101469 | int (*xNext)( |
| 101470 | sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ |
| 101471 | const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ |
| 101472 | int *piStartOffset, /* OUT: Byte offset of token in input buffer */ |
| 101473 | int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ |
| 101474 | int *piPosition /* OUT: Number of tokens returned before this one */ |
| 101475 | ); |
| 101476 | }; |
| 101477 | |
| 101478 | struct sqlite3_tokenizer { |
| 101479 | const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ |
| 101480 | /* Tokenizer implementations will typically add additional fields */ |
| 101481 | }; |
| 101482 | |
| 101483 | struct sqlite3_tokenizer_cursor { |
| 101484 | sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ |
| 101485 | /* Tokenizer implementations will typically add additional fields */ |
| 101486 | }; |
| 101487 | |
| 101488 | #endif /* _FTS3_TOKENIZER_H_ */ |
| 101489 | |
| 101490 | /************** End of fts3_tokenizer.h **************************************/ |
| 101491 | /************** Continuing where we left off in fts3_porter.c ****************/ |
| 101492 | |
| 101493 | /* |
| 101494 | ** Class derived from sqlite3_tokenizer |
| 101495 | */ |
| 101496 | typedef struct porter_tokenizer { |
| @@ -101508,23 +101914,23 @@ | |
| 101508 | int iToken; /* index of next token to be returned */ |
| 101509 | char *zToken; /* storage for current token */ |
| 101510 | int nAllocated; /* space allocated to zToken buffer */ |
| 101511 | } porter_tokenizer_cursor; |
| 101512 | |
| 101513 | |
| 101514 | /* Forward declaration */ |
| 101515 | static const sqlite3_tokenizer_module porterTokenizerModule; |
| 101516 | |
| 101517 | |
| 101518 | /* |
| 101519 | ** Create a new tokenizer instance. |
| 101520 | */ |
| 101521 | static int porterCreate( |
| 101522 | int argc, const char * const *argv, |
| 101523 | sqlite3_tokenizer **ppTokenizer |
| 101524 | ){ |
| 101525 | porter_tokenizer *t; |
| 101526 | t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); |
| 101527 | if( t==NULL ) return SQLITE_NOMEM; |
| 101528 | memset(t, 0, sizeof(*t)); |
| 101529 | *ppTokenizer = &t->base; |
| 101530 | return SQLITE_OK; |
| @@ -101548,10 +101954,12 @@ | |
| 101548 | sqlite3_tokenizer *pTokenizer, /* The tokenizer */ |
| 101549 | const char *zInput, int nInput, /* String to be tokenized */ |
| 101550 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ |
| 101551 | ){ |
| 101552 | porter_tokenizer_cursor *c; |
| 101553 | |
| 101554 | c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); |
| 101555 | if( c==NULL ) return SQLITE_NOMEM; |
| 101556 | |
| 101557 | c->zInput = zInput; |
| @@ -101689,11 +102097,11 @@ | |
| 101689 | ** |
| 101690 | ** The text is reversed here. So we are really looking at |
| 101691 | ** the first two characters of z[]. |
| 101692 | */ |
| 101693 | static int doubleConsonant(const char *z){ |
| 101694 | return isConsonant(z) && z[0]==z[1] && isConsonant(z+1); |
| 101695 | } |
| 101696 | |
| 101697 | /* |
| 101698 | ** Return TRUE if the word ends with three letters which |
| 101699 | ** are consonant-vowel-consonent and where the final consonant |
| @@ -101702,14 +102110,14 @@ | |
| 101702 | ** The word is reversed here. So we are really checking the |
| 101703 | ** first three letters and the first one cannot be in [wxy]. |
| 101704 | */ |
| 101705 | static int star_oh(const char *z){ |
| 101706 | return |
| 101707 | z[0]!=0 && isConsonant(z) && |
| 101708 | z[0]!='w' && z[0]!='x' && z[0]!='y' && |
| 101709 | z[1]!=0 && isVowel(z+1) && |
| 101710 | z[2]!=0 && isConsonant(z+2); |
| 101711 | } |
| 101712 | |
| 101713 | /* |
| 101714 | ** If the word ends with zFrom and xCond() is true for the stem |
| 101715 | ** of the word that preceeds the zFrom ending, then change the |
| @@ -101749,11 +102157,11 @@ | |
| 101749 | */ |
| 101750 | static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 101751 | int i, mx, j; |
| 101752 | int hasDigit = 0; |
| 101753 | for(i=0; i<nIn; i++){ |
| 101754 | int c = zIn[i]; |
| 101755 | if( c>='A' && c<='Z' ){ |
| 101756 | zOut[i] = c - 'A' + 'a'; |
| 101757 | }else{ |
| 101758 | if( c>='0' && c<='9' ) hasDigit = 1; |
| 101759 | zOut[i] = c; |
| @@ -101793,21 +102201,21 @@ | |
| 101793 | ** |
| 101794 | ** Stemming never increases the length of the word. So there is |
| 101795 | ** no chance of overflowing the zOut buffer. |
| 101796 | */ |
| 101797 | static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 101798 | int i, j, c; |
| 101799 | char zReverse[28]; |
| 101800 | char *z, *z2; |
| 101801 | if( nIn<3 || nIn>=sizeof(zReverse)-7 ){ |
| 101802 | /* The word is too big or too small for the porter stemmer. |
| 101803 | ** Fallback to the copy stemmer */ |
| 101804 | copy_stemmer(zIn, nIn, zOut, pnOut); |
| 101805 | return; |
| 101806 | } |
| 101807 | for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){ |
| 101808 | c = zIn[i]; |
| 101809 | if( c>='A' && c<='Z' ){ |
| 101810 | zReverse[j] = c + 'a' - 'A'; |
| 101811 | }else if( c>='a' && c<='z' ){ |
| 101812 | zReverse[j] = c; |
| 101813 | }else{ |
| @@ -102002,11 +102410,11 @@ | |
| 102002 | } |
| 102003 | |
| 102004 | /* z[] is now the stemmed word in reverse order. Flip it back |
| 102005 | ** around into forward order and return. |
| 102006 | */ |
| 102007 | *pnOut = i = strlen(z); |
| 102008 | zOut[i] = 0; |
| 102009 | while( *z ){ |
| 102010 | zOut[--i] = *(z++); |
| 102011 | } |
| 102012 | } |
| @@ -102240,11 +102648,11 @@ | |
| 102240 | z1++; |
| 102241 | } |
| 102242 | } |
| 102243 | } |
| 102244 | |
| 102245 | *pn = (z2-z1); |
| 102246 | return z1; |
| 102247 | } |
| 102248 | |
| 102249 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( |
| 102250 | Fts3Hash *pHash, /* Tokenizer hash table */ |
| @@ -102278,24 +102686,24 @@ | |
| 102278 | |
| 102279 | z = (char *)sqlite3Fts3NextToken(zCopy, &n); |
| 102280 | z[n] = '\0'; |
| 102281 | sqlite3Fts3Dequote(z); |
| 102282 | |
| 102283 | m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, strlen(z)+1); |
| 102284 | if( !m ){ |
| 102285 | *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); |
| 102286 | rc = SQLITE_ERROR; |
| 102287 | }else{ |
| 102288 | char const **aArg = 0; |
| 102289 | int iArg = 0; |
| 102290 | z = &z[n+1]; |
| 102291 | while( z<zEnd && (z = (char *)sqlite3Fts3NextToken(z, &n)) ){ |
| 102292 | int nNew = sizeof(char *)*(iArg+1); |
| 102293 | char const **aNew = (const char **)sqlite3_realloc(aArg, nNew); |
| 102294 | if( !aNew ){ |
| 102295 | sqlite3_free(zCopy); |
| 102296 | sqlite3_free(aArg); |
| 102297 | return SQLITE_NOMEM; |
| 102298 | } |
| 102299 | aArg = aNew; |
| 102300 | aArg[iArg++] = z; |
| 102301 | z[n] = '\0'; |
| @@ -102303,15 +102711,15 @@ | |
| 102303 | z = &z[n+1]; |
| 102304 | } |
| 102305 | rc = m->xCreate(iArg, aArg, ppTok); |
| 102306 | assert( rc!=SQLITE_OK || *ppTok ); |
| 102307 | if( rc!=SQLITE_OK ){ |
| 102308 | *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); |
| 102309 | }else{ |
| 102310 | (*ppTok)->pModule = m; |
| 102311 | } |
| 102312 | sqlite3_free(aArg); |
| 102313 | } |
| 102314 | |
| 102315 | sqlite3_free(zCopy); |
| 102316 | return rc; |
| 102317 | } |
| @@ -102473,11 +102881,11 @@ | |
| 102473 | } |
| 102474 | |
| 102475 | sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 102476 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 102477 | if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 102478 | memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); |
| 102479 | } |
| 102480 | } |
| 102481 | |
| 102482 | return sqlite3_finalize(pStmt); |
| 102483 | } |
| @@ -102509,10 +102917,13 @@ | |
| 102509 | ){ |
| 102510 | int rc; |
| 102511 | const sqlite3_tokenizer_module *p1; |
| 102512 | const sqlite3_tokenizer_module *p2; |
| 102513 | sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); |
| 102514 | |
| 102515 | /* Test the query function */ |
| 102516 | sqlite3Fts3SimpleTokenizerModule(&p1); |
| 102517 | rc = queryTokenizer(db, "simple", &p2); |
| 102518 | assert( rc==SQLITE_OK ); |
| @@ -102569,17 +102980,17 @@ | |
| 102569 | if( !zTest || !zTest2 ){ |
| 102570 | rc = SQLITE_NOMEM; |
| 102571 | } |
| 102572 | #endif |
| 102573 | |
| 102574 | if( rc!=SQLITE_OK |
| 102575 | || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) |
| 102576 | || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) |
| 102577 | #ifdef SQLITE_TEST |
| 102578 | || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) |
| 102579 | || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) |
| 102580 | || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) |
| 102581 | #endif |
| 102582 | ); |
| 102583 | |
| 102584 | sqlite3_free(zTest); |
| 102585 | sqlite3_free(zTest2); |
| @@ -102633,13 +103044,10 @@ | |
| 102633 | char *pToken; /* storage for current token */ |
| 102634 | int nTokenAllocated; /* space allocated to zToken buffer */ |
| 102635 | } simple_tokenizer_cursor; |
| 102636 | |
| 102637 | |
| 102638 | /* Forward declaration */ |
| 102639 | static const sqlite3_tokenizer_module simpleTokenizerModule; |
| 102640 | |
| 102641 | static int simpleDelim(simple_tokenizer *t, unsigned char c){ |
| 102642 | return c<0x80 && t->delim[c]; |
| 102643 | } |
| 102644 | |
| 102645 | /* |
| @@ -102659,11 +103067,11 @@ | |
| 102659 | ** else we need to reindex. One solution would be a meta-table to |
| 102660 | ** track such information in the database, then we'd only want this |
| 102661 | ** information on the initial create. |
| 102662 | */ |
| 102663 | if( argc>1 ){ |
| 102664 | int i, n = strlen(argv[1]); |
| 102665 | for(i=0; i<n; i++){ |
| 102666 | unsigned char ch = argv[1][i]; |
| 102667 | /* We explicitly don't support UTF-8 delimiters for now. */ |
| 102668 | if( ch>=0x80 ){ |
| 102669 | sqlite3_free(t); |
| @@ -102673,11 +103081,11 @@ | |
| 102673 | } |
| 102674 | } else { |
| 102675 | /* Mark non-alphanumeric ASCII characters as delimiters */ |
| 102676 | int i; |
| 102677 | for(i=1; i<0x80; i++){ |
| 102678 | t->delim[i] = !isalnum(i); |
| 102679 | } |
| 102680 | } |
| 102681 | |
| 102682 | *ppTokenizer = &t->base; |
| 102683 | return SQLITE_OK; |
| @@ -102701,10 +103109,12 @@ | |
| 102701 | sqlite3_tokenizer *pTokenizer, /* The tokenizer */ |
| 102702 | const char *pInput, int nBytes, /* String to be tokenized */ |
| 102703 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ |
| 102704 | ){ |
| 102705 | simple_tokenizer_cursor *c; |
| 102706 | |
| 102707 | c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); |
| 102708 | if( c==NULL ) return SQLITE_NOMEM; |
| 102709 | |
| 102710 | c->pInput = pInput; |
| @@ -102775,11 +103185,11 @@ | |
| 102775 | for(i=0; i<n; i++){ |
| 102776 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 102777 | ** case-insensitivity. |
| 102778 | */ |
| 102779 | unsigned char ch = p[iStartOffset+i]; |
| 102780 | c->pToken[i] = ch<0x80 ? tolower(ch) : ch; |
| 102781 | } |
| 102782 | *ppToken = c->pToken; |
| 102783 | *pnBytes = n; |
| 102784 | *piStartOffset = iStartOffset; |
| 102785 | *piEndOffset = c->iOffset; |
| @@ -102837,13 +103247,10 @@ | |
| 102837 | */ |
| 102838 | |
| 102839 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 102840 | |
| 102841 | |
| 102842 | #define INTERIOR_MAX 2048 /* Soft limit for segment node size */ |
| 102843 | #define LEAF_MAX 2048 /* Soft limit for segment leaf size */ |
| 102844 | |
| 102845 | typedef struct PendingList PendingList; |
| 102846 | typedef struct SegmentNode SegmentNode; |
| 102847 | typedef struct SegmentWriter SegmentWriter; |
| 102848 | |
| 102849 | /* |
| @@ -103092,20 +103499,22 @@ | |
| 103092 | sqlite3_stmt *pStmt; |
| 103093 | int rc = fts3SqlStmt(p, SQL_GET_BLOCK, &pStmt, 0); |
| 103094 | if( rc!=SQLITE_OK ) return rc; |
| 103095 | sqlite3_reset(pStmt); |
| 103096 | |
| 103097 | sqlite3_bind_int64(pStmt, 1, iBlock); |
| 103098 | rc = sqlite3_step(pStmt); |
| 103099 | if( rc!=SQLITE_ROW ){ |
| 103100 | return SQLITE_CORRUPT; |
| 103101 | } |
| 103102 | |
| 103103 | *pnBlock = sqlite3_column_bytes(pStmt, 0); |
| 103104 | *pzBlock = (char *)sqlite3_column_blob(pStmt, 0); |
| 103105 | if( !*pzBlock ){ |
| 103106 | return SQLITE_NOMEM; |
| 103107 | } |
| 103108 | return SQLITE_OK; |
| 103109 | } |
| 103110 | |
| 103111 | /* |
| @@ -103222,11 +103631,13 @@ | |
| 103222 | p->iLastPos = 0; |
| 103223 | } |
| 103224 | if( iCol>=0 ){ |
| 103225 | assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) ); |
| 103226 | rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos); |
| 103227 | p->iLastPos = iPos; |
| 103228 | } |
| 103229 | |
| 103230 | pendinglistappend_out: |
| 103231 | *pRc = rc; |
| 103232 | if( p!=*pp ){ |
| @@ -103371,11 +103782,10 @@ | |
| 103371 | Fts3Table *p, /* Full-text table */ |
| 103372 | sqlite3_value **apVal, /* Array of values to insert */ |
| 103373 | sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ |
| 103374 | ){ |
| 103375 | int rc; /* Return code */ |
| 103376 | int i; /* Iterator variable */ |
| 103377 | sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */ |
| 103378 | |
| 103379 | /* Locate the statement handle used to insert data into the %_content |
| 103380 | ** table. The SQL for this statement is: |
| 103381 | ** |
| @@ -103394,14 +103804,20 @@ | |
| 103394 | ** Which is a problem, since "rowid" and "docid" are aliases for the |
| 103395 | ** same value. For example: |
| 103396 | ** |
| 103397 | ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2); |
| 103398 | ** |
| 103399 | ** In FTS3, if a non-NULL docid value is specified, it is the value |
| 103400 | ** inserted. Otherwise, the rowid value is used. |
| 103401 | */ |
| 103402 | if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){ |
| 103403 | rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); |
| 103404 | if( rc!=SQLITE_OK ) return rc; |
| 103405 | } |
| 103406 | |
| 103407 | /* Execute the statement to insert the record. Set *piDocid to the |
| @@ -103457,13 +103873,15 @@ | |
| 103457 | sqlite3_reset(pSelect); |
| 103458 | return rc; |
| 103459 | } |
| 103460 | } |
| 103461 | } |
| 103462 | } |
| 103463 | |
| 103464 | return sqlite3_reset(pSelect); |
| 103465 | } |
| 103466 | |
| 103467 | /* |
| 103468 | ** Forward declaration to account for the circular dependency between |
| 103469 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| @@ -103486,18 +103904,18 @@ | |
| 103486 | ** returned. Otherwise, an SQLite error code is returned. |
| 103487 | */ |
| 103488 | static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){ |
| 103489 | int rc; /* Return Code */ |
| 103490 | sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ |
| 103491 | int iNext; /* Result of query pNextIdx */ |
| 103492 | |
| 103493 | /* Set variable iNext to the next available segdir index at level iLevel. */ |
| 103494 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); |
| 103495 | if( rc==SQLITE_OK ){ |
| 103496 | sqlite3_bind_int(pNextIdx, 1, iLevel); |
| 103497 | if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ |
| 103498 | iNext = sqlite3_column_int64(pNextIdx, 0); |
| 103499 | } |
| 103500 | rc = sqlite3_reset(pNextIdx); |
| 103501 | } |
| 103502 | |
| 103503 | if( rc==SQLITE_OK ){ |
| @@ -103611,11 +104029,11 @@ | |
| 103611 | /* If required, populate the output variables with a pointer to and the |
| 103612 | ** size of the previous offset-list. |
| 103613 | */ |
| 103614 | if( ppOffsetList ){ |
| 103615 | *ppOffsetList = pReader->pOffsetList; |
| 103616 | *pnOffsetList = p - pReader->pOffsetList - 1; |
| 103617 | } |
| 103618 | |
| 103619 | /* If there are no more entries in the doclist, set pOffsetList to |
| 103620 | ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and |
| 103621 | ** Fts3SegReader.pOffsetList to point to the next offset list before |
| @@ -103683,12 +104101,10 @@ | |
| 103683 | /* The entire segment is stored in the root node. */ |
| 103684 | pReader->aNode = (char *)&pReader[1]; |
| 103685 | pReader->nNode = nRoot; |
| 103686 | memcpy(pReader->aNode, zRoot, nRoot); |
| 103687 | }else{ |
| 103688 | sqlite3_stmt *pStmt; |
| 103689 | |
| 103690 | /* If the text of the SQL statement to iterate through a contiguous |
| 103691 | ** set of entries in the %_segments table has not yet been composed, |
| 103692 | ** compose it now. |
| 103693 | */ |
| 103694 | if( !p->zSelectLeaves ){ |
| @@ -103966,10 +104382,11 @@ | |
| 103966 | int nPrev, /* Size of buffer zPrev in bytes */ |
| 103967 | const char *zNext, /* Buffer containing next term */ |
| 103968 | int nNext /* Size of buffer zNext in bytes */ |
| 103969 | ){ |
| 103970 | int n; |
| 103971 | for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++); |
| 103972 | return n; |
| 103973 | } |
| 103974 | |
| 103975 | /* |
| @@ -103998,17 +104415,17 @@ | |
| 103998 | |
| 103999 | nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); |
| 104000 | nSuffix = nTerm-nPrefix; |
| 104001 | |
| 104002 | nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; |
| 104003 | if( nReq<=INTERIOR_MAX || !pTree->zTerm ){ |
| 104004 | |
| 104005 | if( nReq>INTERIOR_MAX ){ |
| 104006 | /* An unusual case: this is the first term to be added to the node |
| 104007 | ** and the static node buffer (INTERIOR_MAX bytes) is not large |
| 104008 | ** enough. Use a separately malloced buffer instead This wastes |
| 104009 | ** INTERIOR_MAX bytes, but since this scenario only comes about when |
| 104010 | ** the database contain two terms that share a prefix of almost 2KB, |
| 104011 | ** this is not expected to be a serious problem. |
| 104012 | */ |
| 104013 | assert( pTree->aData==(char *)&pTree[1] ); |
| 104014 | pTree->aData = (char *)sqlite3_malloc(nReq); |
| @@ -104053,11 +104470,11 @@ | |
| 104053 | ** |
| 104054 | ** Otherwise, the term is not added to the new node, it is left empty for |
| 104055 | ** now. Instead, the term is inserted into the parent of pTree. If pTree |
| 104056 | ** has no parent, one is created here. |
| 104057 | */ |
| 104058 | pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + INTERIOR_MAX); |
| 104059 | if( !pNew ){ |
| 104060 | return SQLITE_NOMEM; |
| 104061 | } |
| 104062 | memset(pNew, 0, sizeof(SegmentNode)); |
| 104063 | pNew->nData = 1 + FTS3_VARINT_MAX; |
| @@ -104206,13 +104623,13 @@ | |
| 104206 | if( !pWriter ) return SQLITE_NOMEM; |
| 104207 | memset(pWriter, 0, sizeof(SegmentWriter)); |
| 104208 | *ppWriter = pWriter; |
| 104209 | |
| 104210 | /* Allocate a buffer in which to accumulate data */ |
| 104211 | pWriter->aData = (char *)sqlite3_malloc(LEAF_MAX); |
| 104212 | if( !pWriter->aData ) return SQLITE_NOMEM; |
| 104213 | pWriter->nSize = LEAF_MAX; |
| 104214 | |
| 104215 | /* Find the next free blockid in the %_segments table */ |
| 104216 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); |
| 104217 | if( rc!=SQLITE_OK ) return rc; |
| 104218 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| @@ -104232,11 +104649,11 @@ | |
| 104232 | sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ |
| 104233 | nSuffix + /* Term suffix */ |
| 104234 | sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ |
| 104235 | nDoclist; /* Doclist data */ |
| 104236 | |
| 104237 | if( nData>0 && nData+nReq>LEAF_MAX ){ |
| 104238 | int rc; |
| 104239 | |
| 104240 | /* The current leaf node is full. Write it out to the database. */ |
| 104241 | rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); |
| 104242 | if( rc!=SQLITE_OK ) return rc; |
| @@ -104326,14 +104743,14 @@ | |
| 104326 | int iLevel, /* Value for 'level' column of %_segdir */ |
| 104327 | int iIdx /* Value for 'idx' column of %_segdir */ |
| 104328 | ){ |
| 104329 | int rc; /* Return code */ |
| 104330 | if( pWriter->pTree ){ |
| 104331 | sqlite3_int64 iLast; /* Largest block id written to database */ |
| 104332 | sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ |
| 104333 | char *zRoot; /* Pointer to buffer containing root node */ |
| 104334 | int nRoot; /* Size of buffer zRoot */ |
| 104335 | |
| 104336 | iLastLeaf = pWriter->iFree; |
| 104337 | rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); |
| 104338 | if( rc==SQLITE_OK ){ |
| 104339 | rc = fts3NodeWrite(p, pWriter->pTree, 1, |
| @@ -104502,15 +104919,15 @@ | |
| 104502 | while( 1 ){ |
| 104503 | char c = 0; |
| 104504 | while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80; |
| 104505 | |
| 104506 | if( iCol==iCurrent ){ |
| 104507 | nList = (p - pList); |
| 104508 | break; |
| 104509 | } |
| 104510 | |
| 104511 | nList -= (p - pList); |
| 104512 | pList = p; |
| 104513 | if( nList==0 ){ |
| 104514 | break; |
| 104515 | } |
| 104516 | p = &pList[1]; |
| @@ -104577,10 +104994,15 @@ | |
| 104577 | |
| 104578 | int isIgnoreEmpty = (pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); |
| 104579 | int isRequirePos = (pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); |
| 104580 | int isColFilter = (pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); |
| 104581 | int isPrefix = (pFilter->flags & FTS3_SEGMENT_PREFIX); |
| 104582 | |
| 104583 | /* If the Fts3SegFilter defines a specific term (or term prefix) to search |
| 104584 | ** for, then advance each segment iterator until it points to a term of |
| 104585 | ** equal or greater value than the specified term. This prevents many |
| 104586 | ** unnecessary merge/sort operations for the case where single segment |
| @@ -104906,11 +105328,11 @@ | |
| 104906 | sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ |
| 104907 | ){ |
| 104908 | Fts3Table *p = (Fts3Table *)pVtab; |
| 104909 | int rc = SQLITE_OK; /* Return Code */ |
| 104910 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 104911 | sqlite3_int64 iRemove; /* Rowid removed by UPDATE or DELETE */ |
| 104912 | |
| 104913 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 104914 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 104915 | int isEmpty; |
| 104916 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| @@ -104953,13 +105375,22 @@ | |
| 104953 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| 104954 | ** merge all segments in the database (including the new segment, if |
| 104955 | ** there was any data to flush) into a single segment. |
| 104956 | */ |
| 104957 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ |
| 104958 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 104959 | if( rc==SQLITE_OK ){ |
| 104960 | rc = fts3SegmentMerge(p, -1); |
| 104961 | } |
| 104962 | return rc; |
| 104963 | } |
| 104964 | |
| 104965 | #endif |
| @@ -104991,14 +105422,14 @@ | |
| 104991 | struct Snippet { |
| 104992 | int nMatch; /* Total number of matches */ |
| 104993 | int nAlloc; /* Space allocated for aMatch[] */ |
| 104994 | struct snippetMatch { /* One entry for each matching term */ |
| 104995 | char snStatus; /* Status flag for use while constructing snippets */ |
| 104996 | short int iCol; /* The column that contains the match */ |
| 104997 | short int iTerm; /* The index in Query.pTerms[] of the matching term */ |
| 104998 | int iToken; /* The index of the matching document token */ |
| 104999 | short int nByte; /* Number of bytes in the term */ |
| 105000 | int iStart; /* The offset to the first character of the term */ |
| 105001 | } *aMatch; /* Points to space obtained from malloc */ |
| 105002 | char *zOffset; /* Text rendering of aMatch[] */ |
| 105003 | int nOffset; /* strlen(zOffset) */ |
| 105004 | char *zSnippet; /* Snippet text */ |
| @@ -105008,171 +105439,125 @@ | |
| 105008 | |
| 105009 | /* It is not safe to call isspace(), tolower(), or isalnum() on |
| 105010 | ** hi-bit-set characters. This is the same solution used in the |
| 105011 | ** tokenizer. |
| 105012 | */ |
| 105013 | /* TODO(shess) The snippet-generation code should be using the |
| 105014 | ** tokenizer-generated tokens rather than doing its own local |
| 105015 | ** tokenization. |
| 105016 | */ |
| 105017 | /* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ |
| 105018 | static int safe_isspace(char c){ |
| 105019 | return (c&0x80)==0 ? isspace(c) : 0; |
| 105020 | } |
| 105021 | static int safe_isalnum(char c){ |
| 105022 | return (c&0x80)==0 ? isalnum(c) : 0; |
| 105023 | } |
| 105024 | |
| 105025 | /*******************************************************************/ |
| 105026 | /* DataBuffer is used to collect data into a buffer in piecemeal |
| 105027 | ** fashion. It implements the usual distinction between amount of |
| 105028 | ** data currently stored (nData) and buffer capacity (nCapacity). |
| 105029 | ** |
| 105030 | ** dataBufferInit - create a buffer with given initial capacity. |
| 105031 | ** dataBufferReset - forget buffer's data, retaining capacity. |
| 105032 | ** dataBufferSwap - swap contents of two buffers. |
| 105033 | ** dataBufferExpand - expand capacity without adding data. |
| 105034 | ** dataBufferAppend - append data. |
| 105035 | ** dataBufferAppend2 - append two pieces of data at once. |
| 105036 | ** dataBufferReplace - replace buffer's data. |
| 105037 | */ |
| 105038 | typedef struct DataBuffer { |
| 105039 | char *pData; /* Pointer to malloc'ed buffer. */ |
| 105040 | int nCapacity; /* Size of pData buffer. */ |
| 105041 | int nData; /* End of data loaded into pData. */ |
| 105042 | } DataBuffer; |
| 105043 | |
| 105044 | static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){ |
| 105045 | assert( nCapacity>=0 ); |
| 105046 | pBuffer->nData = 0; |
| 105047 | pBuffer->nCapacity = nCapacity; |
| 105048 | pBuffer->pData = nCapacity==0 ? NULL : sqlite3_malloc(nCapacity); |
| 105049 | } |
| 105050 | static void dataBufferReset(DataBuffer *pBuffer){ |
| 105051 | pBuffer->nData = 0; |
| 105052 | } |
| 105053 | static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){ |
| 105054 | assert( nAddCapacity>0 ); |
| 105055 | /* TODO(shess) Consider expanding more aggressively. Note that the |
| 105056 | ** underlying malloc implementation may take care of such things for |
| 105057 | ** us already. |
| 105058 | */ |
| 105059 | if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){ |
| 105060 | pBuffer->nCapacity = pBuffer->nData+nAddCapacity; |
| 105061 | pBuffer->pData = sqlite3_realloc(pBuffer->pData, pBuffer->nCapacity); |
| 105062 | } |
| 105063 | } |
| 105064 | static void dataBufferAppend(DataBuffer *pBuffer, |
| 105065 | const char *pSource, int nSource){ |
| 105066 | assert( nSource>0 && pSource!=NULL ); |
| 105067 | dataBufferExpand(pBuffer, nSource); |
| 105068 | memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource); |
| 105069 | pBuffer->nData += nSource; |
| 105070 | } |
| 105071 | static void dataBufferAppend2(DataBuffer *pBuffer, |
| 105072 | const char *pSource1, int nSource1, |
| 105073 | const char *pSource2, int nSource2){ |
| 105074 | assert( nSource1>0 && pSource1!=NULL ); |
| 105075 | assert( nSource2>0 && pSource2!=NULL ); |
| 105076 | dataBufferExpand(pBuffer, nSource1+nSource2); |
| 105077 | memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1); |
| 105078 | memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2); |
| 105079 | pBuffer->nData += nSource1+nSource2; |
| 105080 | } |
| 105081 | static void dataBufferReplace(DataBuffer *pBuffer, |
| 105082 | const char *pSource, int nSource){ |
| 105083 | dataBufferReset(pBuffer); |
| 105084 | dataBufferAppend(pBuffer, pSource, nSource); |
| 105085 | } |
| 105086 | |
| 105087 | |
| 105088 | /* StringBuffer is a null-terminated version of DataBuffer. */ |
| 105089 | typedef struct StringBuffer { |
| 105090 | DataBuffer b; /* Includes null terminator. */ |
| 105091 | } StringBuffer; |
| 105092 | |
| 105093 | static void initStringBuffer(StringBuffer *sb){ |
| 105094 | dataBufferInit(&sb->b, 100); |
| 105095 | dataBufferReplace(&sb->b, "", 1); |
| 105096 | } |
| 105097 | static int stringBufferLength(StringBuffer *sb){ |
| 105098 | return sb->b.nData-1; |
| 105099 | } |
| 105100 | static char *stringBufferData(StringBuffer *sb){ |
| 105101 | return sb->b.pData; |
| 105102 | } |
| 105103 | |
| 105104 | static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){ |
| 105105 | assert( sb->b.nData>0 ); |
| 105106 | if( nFrom>0 ){ |
| 105107 | sb->b.nData--; |
| 105108 | dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1); |
| 105109 | } |
| 105110 | } |
| 105111 | static void append(StringBuffer *sb, const char *zFrom){ |
| 105112 | nappend(sb, zFrom, strlen(zFrom)); |
| 105113 | } |
| 105114 | |
| 105115 | static int endsInWhiteSpace(StringBuffer *p){ |
| 105116 | return stringBufferLength(p)>0 && |
| 105117 | safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]); |
| 105118 | } |
| 105119 | |
| 105120 | /* If the StringBuffer ends in something other than white space, add a |
| 105121 | ** single space character to the end. |
| 105122 | */ |
| 105123 | static void appendWhiteSpace(StringBuffer *p){ |
| 105124 | if( stringBufferLength(p)==0 ) return; |
| 105125 | if( !endsInWhiteSpace(p) ) append(p, " "); |
| 105126 | } |
| 105127 | |
| 105128 | /* Remove white space from the end of the StringBuffer */ |
| 105129 | static void trimWhiteSpace(StringBuffer *p){ |
| 105130 | while( endsInWhiteSpace(p) ){ |
| 105131 | p->b.pData[--p->b.nData-1] = '\0'; |
| 105132 | } |
| 105133 | } |
| 105134 | |
| 105135 | |
| 105136 | /* |
| 105137 | ** Release all memory associated with the Snippet structure passed as |
| 105138 | ** an argument. |
| 105139 | */ |
| 105140 | static void fts3SnippetFree(Snippet *p){ |
| 105141 | sqlite3_free(p->aMatch); |
| 105142 | sqlite3_free(p->zOffset); |
| 105143 | sqlite3_free(p->zSnippet); |
| 105144 | sqlite3_free(p); |
| 105145 | } |
| 105146 | |
| 105147 | /* |
| 105148 | ** Append a single entry to the p->aMatch[] log. |
| 105149 | */ |
| 105150 | static void snippetAppendMatch( |
| 105151 | Snippet *p, /* Append the entry to this snippet */ |
| 105152 | int iCol, int iTerm, /* The column and query term */ |
| 105153 | int iToken, /* Matching token in document */ |
| 105154 | int iStart, int nByte /* Offset and size of the match */ |
| 105155 | ){ |
| 105156 | int i; |
| 105157 | struct snippetMatch *pMatch; |
| 105158 | if( p->nMatch+1>=p->nAlloc ){ |
| 105159 | p->nAlloc = p->nAlloc*2 + 10; |
| 105160 | p->aMatch = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); |
| 105161 | if( p->aMatch==0 ){ |
| 105162 | p->nMatch = 0; |
| 105163 | p->nAlloc = 0; |
| 105164 | return; |
| 105165 | } |
| 105166 | } |
| 105167 | i = p->nMatch++; |
| 105168 | pMatch = &p->aMatch[i]; |
| 105169 | pMatch->iCol = iCol; |
| 105170 | pMatch->iTerm = iTerm; |
| 105171 | pMatch->iToken = iToken; |
| 105172 | pMatch->iStart = iStart; |
| 105173 | pMatch->nByte = nByte; |
| 105174 | } |
| 105175 | |
| 105176 | /* |
| 105177 | ** Sizing information for the circular buffer used in snippetOffsetsOfColumn() |
| 105178 | */ |
| @@ -105242,11 +105627,11 @@ | |
| 105242 | |
| 105243 | /* |
| 105244 | ** Add entries to pSnippet->aMatch[] for every match that occurs against |
| 105245 | ** document zDoc[0..nDoc-1] which is stored in column iColumn. |
| 105246 | */ |
| 105247 | static void snippetOffsetsOfColumn( |
| 105248 | Fts3Cursor *pCur, /* The fulltest search cursor */ |
| 105249 | Snippet *pSnippet, /* The Snippet object to be filled in */ |
| 105250 | int iColumn, /* Index of fulltext table column */ |
| 105251 | const char *zDoc, /* Text of the fulltext table column */ |
| 105252 | int nDoc /* Length of zDoc in bytes */ |
| @@ -105272,15 +105657,16 @@ | |
| 105272 | pVtab = (Fts3Table *)pCur->base.pVtab; |
| 105273 | nColumn = pVtab->nColumn; |
| 105274 | pTokenizer = pVtab->pTokenizer; |
| 105275 | pTModule = pTokenizer->pModule; |
| 105276 | rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); |
| 105277 | if( rc ) return; |
| 105278 | pTCursor->pTokenizer = pTokenizer; |
| 105279 | |
| 105280 | prevMatch = 0; |
| 105281 | while( !pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos) ){ |
| 105282 | Fts3Expr *pIter = pCur->pExpr; |
| 105283 | int iIter = -1; |
| 105284 | iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; |
| 105285 | iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; |
| 105286 | match = 0; |
| @@ -105301,19 +105687,22 @@ | |
| 105301 | if( iIter>0 && (prevMatch & (1<<i))==0 ) continue; |
| 105302 | match |= 1<<i; |
| 105303 | if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){ |
| 105304 | for(j=nPhrase-1; j>=0; j--){ |
| 105305 | int k = (iRotor-j) & FTS3_ROTOR_MASK; |
| 105306 | snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, |
| 105307 | iRotorBegin[k], iRotorLen[k]); |
| 105308 | } |
| 105309 | } |
| 105310 | } |
| 105311 | prevMatch = match<<1; |
| 105312 | iRotor++; |
| 105313 | } |
| 105314 | pTModule->xClose(pTCursor); |
| 105315 | } |
| 105316 | |
| 105317 | /* |
| 105318 | ** Remove entries from the pSnippet structure to account for the NEAR |
| 105319 | ** operator. When this is called, pSnippet contains the list of token |
| @@ -105445,16 +105834,19 @@ | |
| 105445 | /* |
| 105446 | ** Compute all offsets for the current row of the query. |
| 105447 | ** If the offsets have already been computed, this routine is a no-op. |
| 105448 | */ |
| 105449 | static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){ |
| 105450 | Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
| 105451 | int nColumn; |
| 105452 | int iColumn, i; |
| 105453 | int iFirst, iLast; |
| 105454 | int iTerm = 0; |
| 105455 | Snippet *pSnippet; |
| 105456 | |
| 105457 | if( pCsr->pExpr==0 ){ |
| 105458 | return SQLITE_OK; |
| 105459 | } |
| 105460 | |
| @@ -105464,33 +105856,37 @@ | |
| 105464 | return SQLITE_NOMEM; |
| 105465 | } |
| 105466 | memset(pSnippet, 0, sizeof(Snippet)); |
| 105467 | |
| 105468 | nColumn = p->nColumn; |
| 105469 | iColumn = (pCsr->eType - 2); |
| 105470 | if( iColumn<0 || iColumn>=nColumn ){ |
| 105471 | /* Look for matches over all columns of the full-text index */ |
| 105472 | iFirst = 0; |
| 105473 | iLast = nColumn-1; |
| 105474 | }else{ |
| 105475 | /* Look for matches in the iColumn-th column of the index only */ |
| 105476 | iFirst = iColumn; |
| 105477 | iLast = iColumn; |
| 105478 | } |
| 105479 | for(i=iFirst; i<=iLast; i++){ |
| 105480 | const char *zDoc; |
| 105481 | int nDoc; |
| 105482 | zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1); |
| 105483 | nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1); |
| 105484 | snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc); |
| 105485 | } |
| 105486 | |
| 105487 | while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){ |
| 105488 | iTerm = 0; |
| 105489 | } |
| 105490 | |
| 105491 | return SQLITE_OK; |
| 105492 | } |
| 105493 | |
| 105494 | /* |
| 105495 | ** Convert the information in the aMatch[] array of the snippet |
| 105496 | ** into the string zOffset[0..nOffset-1]. This string is used as |
| @@ -105500,11 +105896,11 @@ | |
| 105500 | int i; |
| 105501 | int cnt = 0; |
| 105502 | StringBuffer sb; |
| 105503 | char zBuf[200]; |
| 105504 | if( p->zOffset ) return; |
| 105505 | initStringBuffer(&sb); |
| 105506 | for(i=0; i<p->nMatch; i++){ |
| 105507 | struct snippetMatch *pMatch = &p->aMatch[i]; |
| 105508 | if( pMatch->iTerm>=0 ){ |
| 105509 | /* If snippetMatch.iTerm is less than 0, then the match was |
| 105510 | ** discarded as part of processing the NEAR operator (see the |
| @@ -105512,16 +105908,16 @@ | |
| 105512 | ** it in this case |
| 105513 | */ |
| 105514 | zBuf[0] = ' '; |
| 105515 | sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d", |
| 105516 | pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte); |
| 105517 | append(&sb, zBuf); |
| 105518 | cnt++; |
| 105519 | } |
| 105520 | } |
| 105521 | p->zOffset = stringBufferData(&sb); |
| 105522 | p->nOffset = stringBufferLength(&sb); |
| 105523 | } |
| 105524 | |
| 105525 | /* |
| 105526 | ** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set |
| 105527 | ** of matching words some of which might be in zDoc. zDoc is column |
| @@ -105544,11 +105940,11 @@ | |
| 105544 | return 0; |
| 105545 | } |
| 105546 | if( iBreak>=nDoc-10 ){ |
| 105547 | return nDoc; |
| 105548 | } |
| 105549 | for(i=0; i<nMatch && aMatch[i].iCol<iCol; i++){} |
| 105550 | while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; } |
| 105551 | if( i<nMatch ){ |
| 105552 | if( aMatch[i].iStart<iBreak+10 ){ |
| 105553 | return aMatch[i].iStart; |
| 105554 | } |
| @@ -105555,14 +105951,14 @@ | |
| 105555 | if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ |
| 105556 | return aMatch[i-1].iStart; |
| 105557 | } |
| 105558 | } |
| 105559 | for(i=1; i<=10; i++){ |
| 105560 | if( safe_isspace(zDoc[iBreak-i]) ){ |
| 105561 | return iBreak - i + 1; |
| 105562 | } |
| 105563 | if( safe_isspace(zDoc[iBreak+i]) ){ |
| 105564 | return iBreak + i + 1; |
| 105565 | } |
| 105566 | } |
| 105567 | return iBreak; |
| 105568 | } |
| @@ -105602,11 +105998,11 @@ | |
| 105602 | |
| 105603 | sqlite3_free(pSnippet->zSnippet); |
| 105604 | pSnippet->zSnippet = 0; |
| 105605 | aMatch = pSnippet->aMatch; |
| 105606 | nMatch = pSnippet->nMatch; |
| 105607 | initStringBuffer(&sb); |
| 105608 | |
| 105609 | for(i=0; i<nMatch; i++){ |
| 105610 | aMatch[i].snStatus = SNIPPET_IGNORE; |
| 105611 | } |
| 105612 | nDesired = 0; |
| @@ -105636,14 +106032,14 @@ | |
| 105636 | } |
| 105637 | if( iCol==tailCol && iStart<=tailOffset+20 ){ |
| 105638 | iStart = tailOffset; |
| 105639 | } |
| 105640 | if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ |
| 105641 | trimWhiteSpace(&sb); |
| 105642 | appendWhiteSpace(&sb); |
| 105643 | append(&sb, zEllipsis); |
| 105644 | appendWhiteSpace(&sb); |
| 105645 | } |
| 105646 | iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; |
| 105647 | iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); |
| 105648 | if( iEnd>=nDoc-10 ){ |
| 105649 | iEnd = nDoc; |
| @@ -105657,48 +106053,56 @@ | |
| 105657 | && aMatch[iMatch].iCol<=iCol ){ |
| 105658 | iMatch++; |
| 105659 | } |
| 105660 | if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd |
| 105661 | && aMatch[iMatch].iCol==iCol ){ |
| 105662 | nappend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart); |
| 105663 | iStart = aMatch[iMatch].iStart; |
| 105664 | append(&sb, zStartMark); |
| 105665 | nappend(&sb, &zDoc[iStart], aMatch[iMatch].nByte); |
| 105666 | append(&sb, zEndMark); |
| 105667 | iStart += aMatch[iMatch].nByte; |
| 105668 | for(j=iMatch+1; j<nMatch; j++){ |
| 105669 | if( aMatch[j].iTerm==aMatch[iMatch].iTerm |
| 105670 | && aMatch[j].snStatus==SNIPPET_DESIRED ){ |
| 105671 | nDesired--; |
| 105672 | aMatch[j].snStatus = SNIPPET_IGNORE; |
| 105673 | } |
| 105674 | } |
| 105675 | }else{ |
| 105676 | nappend(&sb, &zDoc[iStart], iEnd - iStart); |
| 105677 | iStart = iEnd; |
| 105678 | } |
| 105679 | } |
| 105680 | tailCol = iCol; |
| 105681 | tailOffset = iEnd; |
| 105682 | } |
| 105683 | trimWhiteSpace(&sb); |
| 105684 | if( tailEllipsis ){ |
| 105685 | appendWhiteSpace(&sb); |
| 105686 | append(&sb, zEllipsis); |
| 105687 | } |
| 105688 | pSnippet->zSnippet = stringBufferData(&sb); |
| 105689 | pSnippet->nSnippet = stringBufferLength(&sb); |
| 105690 | } |
| 105691 | |
| 105692 | SQLITE_PRIVATE void sqlite3Fts3Offsets( |
| 105693 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 105694 | Fts3Cursor *pCsr /* Cursor object */ |
| 105695 | ){ |
| 105696 | Snippet *p; /* Snippet structure */ |
| 105697 | int rc = snippetAllOffsets(pCsr, &p); |
| 105698 | snippetOffsetText(p); |
| 105699 | sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT); |
| 105700 | fts3SnippetFree(p); |
| 105701 | } |
| 105702 | |
| 105703 | SQLITE_PRIVATE void sqlite3Fts3Snippet( |
| 105704 | sqlite3_context *pCtx, /* SQLite function call context */ |
| @@ -105707,12 +106111,20 @@ | |
| 105707 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 105708 | const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */ |
| 105709 | ){ |
| 105710 | Snippet *p; /* Snippet structure */ |
| 105711 | int rc = snippetAllOffsets(pCsr, &p); |
| 105712 | snippetText(pCsr, p, zStart, zEnd, zEllipsis); |
| 105713 | sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT); |
| 105714 | fts3SnippetFree(p); |
| 105715 | } |
| 105716 | |
| 105717 | #endif |
| 105718 | |
| 105719 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -643,11 +643,11 @@ | |
| 643 | ** |
| 644 | ** Requirements: [H10011] [H10014] |
| 645 | */ |
| 646 | #define SQLITE_VERSION "3.6.21" |
| 647 | #define SQLITE_VERSION_NUMBER 3006021 |
| 648 | #define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" |
| 649 | |
| 650 | /* |
| 651 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 652 | ** KEYWORDS: sqlite3_version |
| 653 | ** |
| @@ -1817,10 +1817,13 @@ | |
| 1817 | ** the return value of this interface. |
| 1818 | ** |
| 1819 | ** For the purposes of this routine, an [INSERT] is considered to |
| 1820 | ** be successful even if it is subsequently rolled back. |
| 1821 | ** |
| 1822 | ** This function is accessible to SQL statements via the |
| 1823 | ** [last_insert_rowid() SQL function]. |
| 1824 | ** |
| 1825 | ** Requirements: |
| 1826 | ** [H12221] [H12223] |
| 1827 | ** |
| 1828 | ** If a separate thread performs a new [INSERT] on the same |
| 1829 | ** database connection while the [sqlite3_last_insert_rowid()] |
| @@ -1874,12 +1877,12 @@ | |
| 1877 | ** changes in the most recently completed INSERT, UPDATE, or DELETE |
| 1878 | ** statement within the body of the same trigger. |
| 1879 | ** However, the number returned does not include changes |
| 1880 | ** caused by subtriggers since those have their own context. |
| 1881 | ** |
| 1882 | ** See also the [sqlite3_total_changes()] interface, the |
| 1883 | ** [count_changes pragma], and the [changes() SQL function]. |
| 1884 | ** |
| 1885 | ** Requirements: |
| 1886 | ** [H12241] [H12243] |
| 1887 | ** |
| 1888 | ** If a separate thread makes changes on the same database connection |
| @@ -1902,12 +1905,12 @@ | |
| 1905 | ** are counted. |
| 1906 | ** The changes are counted as soon as the statement that makes them is |
| 1907 | ** completed (when the statement handle is passed to [sqlite3_reset()] or |
| 1908 | ** [sqlite3_finalize()]). |
| 1909 | ** |
| 1910 | ** See also the [sqlite3_changes()] interface, the |
| 1911 | ** [count_changes pragma], and the [total_changes() SQL function]. |
| 1912 | ** |
| 1913 | ** Requirements: |
| 1914 | ** [H12261] [H12263] |
| 1915 | ** |
| 1916 | ** If a separate thread makes changes on the same database connection |
| @@ -4664,10 +4667,12 @@ | |
| 4667 | ** should free this memory by calling [sqlite3_free()]. |
| 4668 | ** |
| 4669 | ** {H12606} Extension loading must be enabled using |
| 4670 | ** [sqlite3_enable_load_extension()] prior to calling this API, |
| 4671 | ** otherwise an error will be returned. |
| 4672 | ** |
| 4673 | ** See also the [load_extension() SQL function]. |
| 4674 | */ |
| 4675 | SQLITE_API int sqlite3_load_extension( |
| 4676 | sqlite3 *db, /* Load the extension into this database connection */ |
| 4677 | const char *zFile, /* Name of the shared library containing extension */ |
| 4678 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
| @@ -9662,19 +9667,20 @@ | |
| 9667 | ** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of |
| 9668 | ** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable. |
| 9669 | ** The Parse.pTriggerPrg list never contains two entries with the same |
| 9670 | ** values for both pTrigger and orconf. |
| 9671 | ** |
| 9672 | ** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns |
| 9673 | ** accessed (or set to 0 for triggers fired as a result of INSERT |
| 9674 | ** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to |
| 9675 | ** a mask of new.* columns used by the program. |
| 9676 | */ |
| 9677 | struct TriggerPrg { |
| 9678 | Trigger *pTrigger; /* Trigger this program was coded from */ |
| 9679 | int orconf; /* Default ON CONFLICT policy */ |
| 9680 | SubProgram *pProgram; /* Program implementing pTrigger/orconf */ |
| 9681 | u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ |
| 9682 | TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ |
| 9683 | }; |
| 9684 | |
| 9685 | /* |
| 9686 | ** An SQL parser context. A copy of this structure is passed through |
| @@ -9742,10 +9748,11 @@ | |
| 9748 | |
| 9749 | /* Information used while coding trigger programs. */ |
| 9750 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 9751 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 9752 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 9753 | u32 newmask; /* Mask of new.* columns referenced */ |
| 9754 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 9755 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 9756 | u8 disableTriggers; /* True to disable triggers */ |
| 9757 | |
| 9758 | /* Above is constant between recursions. Below is reset before and after |
| @@ -10339,11 +10346,11 @@ | |
| 10346 | ExprList*,Select*,u8); |
| 10347 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); |
| 10348 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); |
| 10349 | SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); |
| 10350 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); |
| 10351 | SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); |
| 10352 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) |
| 10353 | #else |
| 10354 | # define sqlite3TriggersExist(B,C,D,E,F) 0 |
| 10355 | # define sqlite3DeleteTrigger(A,B) |
| 10356 | # define sqlite3DropTriggerPtr(A,B) |
| @@ -10350,11 +10357,11 @@ | |
| 10357 | # define sqlite3UnlinkAndDeleteTrigger(A,B,C) |
| 10358 | # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) |
| 10359 | # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) |
| 10360 | # define sqlite3TriggerList(X, Y) 0 |
| 10361 | # define sqlite3ParseToplevel(p) p |
| 10362 | # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 |
| 10363 | #endif |
| 10364 | |
| 10365 | SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); |
| 10366 | SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
| 10367 | SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); |
| @@ -10564,10 +10571,11 @@ | |
| 10571 | SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); |
| 10572 | SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); |
| 10573 | SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); |
| 10574 | SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); |
| 10575 | SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); |
| 10576 | SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); |
| 10577 | SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); |
| 10578 | SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); |
| 10579 | SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); |
| 10580 | SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); |
| 10581 | SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); |
| @@ -14914,10 +14922,43 @@ | |
| 14922 | assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 14923 | DosCloseMutexSem( p->mutex ); |
| 14924 | sqlite3_free( p ); |
| 14925 | } |
| 14926 | |
| 14927 | #ifdef SQLITE_DEBUG |
| 14928 | /* |
| 14929 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 14930 | ** intended for use inside assert() statements. |
| 14931 | */ |
| 14932 | static int os2MutexHeld(sqlite3_mutex *p){ |
| 14933 | TID tid; |
| 14934 | PID pid; |
| 14935 | ULONG ulCount; |
| 14936 | PTIB ptib; |
| 14937 | if( p!=0 ) { |
| 14938 | DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); |
| 14939 | } else { |
| 14940 | DosGetInfoBlocks(&ptib, NULL); |
| 14941 | tid = ptib->tib_ptib2->tib2_ultid; |
| 14942 | } |
| 14943 | return p==0 || (p->nRef!=0 && p->owner==tid); |
| 14944 | } |
| 14945 | static int os2MutexNotheld(sqlite3_mutex *p){ |
| 14946 | TID tid; |
| 14947 | PID pid; |
| 14948 | ULONG ulCount; |
| 14949 | PTIB ptib; |
| 14950 | if( p!= 0 ) { |
| 14951 | DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); |
| 14952 | } else { |
| 14953 | DosGetInfoBlocks(&ptib, NULL); |
| 14954 | tid = ptib->tib_ptib2->tib2_ultid; |
| 14955 | } |
| 14956 | return p==0 || p->nRef==0 || p->owner!=tid; |
| 14957 | } |
| 14958 | #endif |
| 14959 | |
| 14960 | /* |
| 14961 | ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt |
| 14962 | ** to enter a mutex. If another thread is already within the mutex, |
| 14963 | ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return |
| 14964 | ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK |
| @@ -14974,43 +15015,10 @@ | |
| 15015 | p->nRef--; |
| 15016 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 15017 | DosReleaseMutexSem(p->mutex); |
| 15018 | } |
| 15019 | |
| 15020 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15021 | static sqlite3_mutex_methods sMutex = { |
| 15022 | os2MutexInit, |
| 15023 | os2MutexEnd, |
| 15024 | os2MutexAlloc, |
| @@ -22701,11 +22709,11 @@ | |
| 22709 | } |
| 22710 | } |
| 22711 | #endif |
| 22712 | |
| 22713 | unixLeaveMutex(); |
| 22714 | OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved); |
| 22715 | |
| 22716 | *pResOut = reserved; |
| 22717 | return rc; |
| 22718 | } |
| 22719 | |
| @@ -22834,20 +22842,20 @@ | |
| 22842 | struct flock lock; |
| 22843 | int s = 0; |
| 22844 | int tErrno; |
| 22845 | |
| 22846 | assert( pFile ); |
| 22847 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, |
| 22848 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22849 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| 22850 | |
| 22851 | /* If there is already a lock of this type or more restrictive on the |
| 22852 | ** unixFile, do nothing. Don't use the end_lock: exit path, as |
| 22853 | ** unixEnterMutex() hasn't been called yet. |
| 22854 | */ |
| 22855 | if( pFile->locktype>=locktype ){ |
| 22856 | OSTRACE3("LOCK %d %s ok (already held) (unix)\n", pFile->h, |
| 22857 | locktypeName(locktype)); |
| 22858 | return SQLITE_OK; |
| 22859 | } |
| 22860 | |
| 22861 | /* Make sure the locking sequence is correct. |
| @@ -23013,11 +23021,11 @@ | |
| 23021 | pLock->locktype = PENDING_LOCK; |
| 23022 | } |
| 23023 | |
| 23024 | end_lock: |
| 23025 | unixLeaveMutex(); |
| 23026 | OSTRACE4("LOCK %d %s %s (unix)\n", pFile->h, locktypeName(locktype), |
| 23027 | rc==SQLITE_OK ? "ok" : "failed"); |
| 23028 | return rc; |
| 23029 | } |
| 23030 | |
| 23031 | /* |
| @@ -23077,11 +23085,11 @@ | |
| 23085 | int rc = SQLITE_OK; /* Return code from this interface */ |
| 23086 | int h; /* The underlying file descriptor */ |
| 23087 | int tErrno; /* Error code from system call errors */ |
| 23088 | |
| 23089 | assert( pFile ); |
| 23090 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype, |
| 23091 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| 23092 | |
| 23093 | assert( locktype<=SHARED_LOCK ); |
| 23094 | if( pFile->locktype<=locktype ){ |
| 23095 | return SQLITE_OK; |
| @@ -23358,11 +23366,11 @@ | |
| 23366 | }else{ |
| 23367 | /* The lock is held if and only if the lockfile exists */ |
| 23368 | const char *zLockFile = (const char*)pFile->lockingContext; |
| 23369 | reserved = access(zLockFile, 0)==0; |
| 23370 | } |
| 23371 | OSTRACE4("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved); |
| 23372 | *pResOut = reserved; |
| 23373 | return rc; |
| 23374 | } |
| 23375 | |
| 23376 | /* |
| @@ -23448,11 +23456,11 @@ | |
| 23456 | static int dotlockUnlock(sqlite3_file *id, int locktype) { |
| 23457 | unixFile *pFile = (unixFile*)id; |
| 23458 | char *zLockFile = (char *)pFile->lockingContext; |
| 23459 | |
| 23460 | assert( pFile ); |
| 23461 | OSTRACE5("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, locktype, |
| 23462 | pFile->locktype, getpid()); |
| 23463 | assert( locktype<=SHARED_LOCK ); |
| 23464 | |
| 23465 | /* no-op if possible */ |
| 23466 | if( pFile->locktype==locktype ){ |
| @@ -23562,11 +23570,11 @@ | |
| 23570 | pFile->lastErrno = tErrno; |
| 23571 | rc = lrc; |
| 23572 | } |
| 23573 | } |
| 23574 | } |
| 23575 | OSTRACE4("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved); |
| 23576 | |
| 23577 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 23578 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ |
| 23579 | rc = SQLITE_OK; |
| 23580 | reserved=1; |
| @@ -23629,11 +23637,11 @@ | |
| 23637 | } |
| 23638 | } else { |
| 23639 | /* got it, set the type and return ok */ |
| 23640 | pFile->locktype = locktype; |
| 23641 | } |
| 23642 | OSTRACE4("LOCK %d %s %s (flock)\n", pFile->h, locktypeName(locktype), |
| 23643 | rc==SQLITE_OK ? "ok" : "failed"); |
| 23644 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 23645 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ |
| 23646 | rc = SQLITE_BUSY; |
| 23647 | } |
| @@ -23651,11 +23659,11 @@ | |
| 23659 | */ |
| 23660 | static int flockUnlock(sqlite3_file *id, int locktype) { |
| 23661 | unixFile *pFile = (unixFile*)id; |
| 23662 | |
| 23663 | assert( pFile ); |
| 23664 | OSTRACE5("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, locktype, |
| 23665 | pFile->locktype, getpid()); |
| 23666 | assert( locktype<=SHARED_LOCK ); |
| 23667 | |
| 23668 | /* no-op if possible */ |
| 23669 | if( pFile->locktype==locktype ){ |
| @@ -23753,11 +23761,11 @@ | |
| 23761 | }else{ |
| 23762 | /* we could have it if we want it */ |
| 23763 | sem_post(pSem); |
| 23764 | } |
| 23765 | } |
| 23766 | OSTRACE4("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved); |
| 23767 | |
| 23768 | *pResOut = reserved; |
| 23769 | return rc; |
| 23770 | } |
| 23771 | |
| @@ -23828,11 +23836,11 @@ | |
| 23836 | unixFile *pFile = (unixFile*)id; |
| 23837 | sem_t *pSem = pFile->pOpen->pSem; |
| 23838 | |
| 23839 | assert( pFile ); |
| 23840 | assert( pSem ); |
| 23841 | OSTRACE5("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, locktype, |
| 23842 | pFile->locktype, getpid()); |
| 23843 | assert( locktype<=SHARED_LOCK ); |
| 23844 | |
| 23845 | /* no-op if possible */ |
| 23846 | if( pFile->locktype==locktype ){ |
| @@ -23998,11 +24006,11 @@ | |
| 24006 | if( IS_LOCK_ERROR(lrc) ){ |
| 24007 | rc=lrc; |
| 24008 | } |
| 24009 | } |
| 24010 | |
| 24011 | OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved); |
| 24012 | |
| 24013 | *pResOut = reserved; |
| 24014 | return rc; |
| 24015 | } |
| 24016 | |
| @@ -24034,19 +24042,19 @@ | |
| 24042 | int rc = SQLITE_OK; |
| 24043 | unixFile *pFile = (unixFile*)id; |
| 24044 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24045 | |
| 24046 | assert( pFile ); |
| 24047 | OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h, |
| 24048 | locktypeName(locktype), locktypeName(pFile->locktype), getpid()); |
| 24049 | |
| 24050 | /* If there is already a lock of this type or more restrictive on the |
| 24051 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 24052 | ** unixEnterMutex() hasn't been called yet. |
| 24053 | */ |
| 24054 | if( pFile->locktype>=locktype ){ |
| 24055 | OSTRACE3("LOCK %d %s ok (already held) (afp)\n", pFile->h, |
| 24056 | locktypeName(locktype)); |
| 24057 | return SQLITE_OK; |
| 24058 | } |
| 24059 | |
| 24060 | /* Make sure the locking sequence is correct |
| @@ -24161,11 +24169,11 @@ | |
| 24169 | pFile->locktype = PENDING_LOCK; |
| 24170 | } |
| 24171 | |
| 24172 | afp_end_lock: |
| 24173 | unixLeaveMutex(); |
| 24174 | OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype), |
| 24175 | rc==SQLITE_OK ? "ok" : "failed"); |
| 24176 | return rc; |
| 24177 | } |
| 24178 | |
| 24179 | /* |
| @@ -24179,11 +24187,11 @@ | |
| 24187 | int rc = SQLITE_OK; |
| 24188 | unixFile *pFile = (unixFile*)id; |
| 24189 | afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext; |
| 24190 | |
| 24191 | assert( pFile ); |
| 24192 | OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype, |
| 24193 | pFile->locktype, getpid()); |
| 24194 | |
| 24195 | assert( locktype<=SHARED_LOCK ); |
| 24196 | if( pFile->locktype<=locktype ){ |
| 24197 | return SQLITE_OK; |
| @@ -32430,10 +32438,11 @@ | |
| 32438 | pager_reset(pPager); |
| 32439 | } |
| 32440 | |
| 32441 | pPager->changeCountDone = 0; |
| 32442 | pPager->state = PAGER_UNLOCK; |
| 32443 | pPager->dbModified = 0; |
| 32444 | } |
| 32445 | } |
| 32446 | |
| 32447 | /* |
| 32448 | ** This function should be called when an IOERR, CORRUPT or FULL error |
| @@ -33806,12 +33815,15 @@ | |
| 33815 | /* The OS lock values must be the same as the Pager lock values */ |
| 33816 | assert( PAGER_SHARED==SHARED_LOCK ); |
| 33817 | assert( PAGER_RESERVED==RESERVED_LOCK ); |
| 33818 | assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); |
| 33819 | |
| 33820 | /* If the file is currently unlocked then the size must be unknown. It |
| 33821 | ** must not have been modified at this point. |
| 33822 | */ |
| 33823 | assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 ); |
| 33824 | assert( pPager->state>=PAGER_SHARED || pPager->dbModified==0 ); |
| 33825 | |
| 33826 | /* Check that this is either a no-op (because the requested lock is |
| 33827 | ** already held, or one of the transistions that the busy-handler |
| 33828 | ** may be invoked during, according to the comment above |
| 33829 | ** sqlite3PagerSetBusyhandler(). |
| @@ -39966,15 +39978,12 @@ | |
| 39978 | unsigned char *data; |
| 39979 | int rc; |
| 39980 | int nPage; |
| 39981 | |
| 39982 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39983 | rc = sqlite3PagerPagecount(pBt->pPager, &nPage); |
| 39984 | if( rc!=SQLITE_OK || nPage>0 ){ |
| 39985 | return rc; |
| 39986 | } |
| 39987 | pP1 = pBt->pPage1; |
| 39988 | assert( pP1!=0 ); |
| 39989 | data = pP1->aData; |
| @@ -42918,12 +42927,17 @@ | |
| 42927 | if( *pRC ) return; |
| 42928 | |
| 42929 | assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); |
| 42930 | assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); |
| 42931 | assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); |
| 42932 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 42933 | /* The cell should normally be sized correctly. However, when moving a |
| 42934 | ** malformed cell from a leaf page to an interior page, if the cell size |
| 42935 | ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size |
| 42936 | ** might be less than 8 (leaf-size + pointer) on the interior node. Hence |
| 42937 | ** the term after the || in the following assert(). */ |
| 42938 | assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) ); |
| 42939 | if( pPage->nOverflow || sz+2>pPage->nFree ){ |
| 42940 | if( pTemp ){ |
| 42941 | memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); |
| 42942 | pCell = pTemp; |
| 42943 | } |
| @@ -51381,26 +51395,28 @@ | |
| 51395 | /* |
| 51396 | ** Given a wildcard parameter name, return the index of the variable |
| 51397 | ** with that name. If there is no variable with the given name, |
| 51398 | ** return 0. |
| 51399 | */ |
| 51400 | SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ |
| 51401 | int i; |
| 51402 | if( p==0 ){ |
| 51403 | return 0; |
| 51404 | } |
| 51405 | createVarMap(p); |
| 51406 | if( zName ){ |
| 51407 | for(i=0; i<p->nVar; i++){ |
| 51408 | const char *z = p->azVar[i]; |
| 51409 | if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){ |
| 51410 | return i+1; |
| 51411 | } |
| 51412 | } |
| 51413 | } |
| 51414 | return 0; |
| 51415 | } |
| 51416 | SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ |
| 51417 | return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); |
| 51418 | } |
| 51419 | |
| 51420 | /* |
| 51421 | ** Transfer all bindings from the first statement over to the second. |
| 51422 | */ |
| @@ -51509,29 +51525,33 @@ | |
| 51525 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
| 51526 | ** bytes in this text up to but excluding the first character in |
| 51527 | ** a host parameter. If the text contains no host parameters, return |
| 51528 | ** the total number of bytes in the text. |
| 51529 | */ |
| 51530 | static int findNextHostParameter(const char *zSql, int *pnToken){ |
| 51531 | int tokenType; |
| 51532 | int nTotal = 0; |
| 51533 | int n; |
| 51534 | |
| 51535 | *pnToken = 0; |
| 51536 | while( zSql[0] ){ |
| 51537 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 51538 | assert( n>0 && tokenType!=TK_ILLEGAL ); |
| 51539 | if( tokenType==TK_VARIABLE ){ |
| 51540 | *pnToken = n; |
| 51541 | break; |
| 51542 | } |
| 51543 | nTotal += n; |
| 51544 | zSql += n; |
| 51545 | } |
| 51546 | return nTotal; |
| 51547 | } |
| 51548 | |
| 51549 | /* |
| 51550 | ** Return a pointer to a string in memory obtained form sqlite3DbMalloc() which |
| 51551 | ** holds a copy of zRawSql but with host parameters expanded to their |
| 51552 | ** current bindings. |
| 51553 | ** |
| 51554 | ** The calling function is responsible for making sure the memory returned |
| 51555 | ** is eventually freed. |
| 51556 | ** |
| 51557 | ** ALGORITHM: Scan the input string looking for host parameters in any of |
| @@ -51545,60 +51565,46 @@ | |
| 51565 | SQLITE_PRIVATE char *sqlite3VdbeExpandSql( |
| 51566 | Vdbe *p, /* The prepared statement being evaluated */ |
| 51567 | const char *zRawSql /* Raw text of the SQL statement */ |
| 51568 | ){ |
| 51569 | sqlite3 *db; /* The database connection */ |
| 51570 | int idx = 0; /* Index of a host parameter */ |
| 51571 | int nextIndex = 1; /* Index of next ? host parameter */ |
| 51572 | int n; /* Length of a token prefix */ |
| 51573 | int nToken; /* Length of the parameter token */ |
| 51574 | int i; /* Loop counter */ |
| 51575 | Mem *pVar; /* Value of a host parameter */ |
| 51576 | StrAccum out; /* Accumulate the output here */ |
| 51577 | char zBase[100]; /* Initial working space */ |
| 51578 | |
| 51579 | db = p->db; |
| 51580 | sqlite3StrAccumInit(&out, zBase, sizeof(zBase), |
| 51581 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 51582 | out.db = db; |
| 51583 | while( zRawSql[0] ){ |
| 51584 | n = findNextHostParameter(zRawSql, &nToken); |
| 51585 | assert( n>0 ); |
| 51586 | sqlite3StrAccumAppend(&out, zRawSql, n); |
| 51587 | zRawSql += n; |
| 51588 | assert( zRawSql[0] || nToken==0 ); |
| 51589 | if( nToken==0 ) break; |
| 51590 | if( zRawSql[0]=='?' ){ |
| 51591 | if( nToken>1 ){ |
| 51592 | assert( sqlite3Isdigit(zRawSql[1]) ); |
| 51593 | sqlite3GetInt32(&zRawSql[1], &idx); |
| 51594 | }else{ |
| 51595 | idx = nextIndex; |
| 51596 | } |
| 51597 | }else{ |
| 51598 | assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); |
| 51599 | testcase( zRawSql[0]==':' ); |
| 51600 | testcase( zRawSql[0]=='$' ); |
| 51601 | testcase( zRawSql[0]=='@' ); |
| 51602 | idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); |
| 51603 | assert( idx>0 ); |
| 51604 | } |
| 51605 | zRawSql += nToken; |
| 51606 | nextIndex = idx + 1; |
| 51607 | assert( idx>0 && idx<=p->nVar ); |
| 51608 | pVar = &p->aVar[idx-1]; |
| 51609 | if( pVar->flags & MEM_Null ){ |
| 51610 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| @@ -51606,15 +51612,16 @@ | |
| 51612 | sqlite3XPrintf(&out, "%lld", pVar->u.i); |
| 51613 | }else if( pVar->flags & MEM_Real ){ |
| 51614 | sqlite3XPrintf(&out, "%!.15g", pVar->r); |
| 51615 | }else if( pVar->flags & MEM_Str ){ |
| 51616 | #ifndef SQLITE_OMIT_UTF16 |
| 51617 | u8 enc = ENC(db); |
| 51618 | if( enc!=SQLITE_UTF8 ){ |
| 51619 | Mem utf8; |
| 51620 | memset(&utf8, 0, sizeof(utf8)); |
| 51621 | utf8.db = db; |
| 51622 | sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); |
| 51623 | sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); |
| 51624 | sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z); |
| 51625 | sqlite3VdbeMemRelease(&utf8); |
| 51626 | }else |
| 51627 | #endif |
| @@ -52272,11 +52279,11 @@ | |
| 52279 | int rc = SQLITE_OK; /* Value to return */ |
| 52280 | sqlite3 *db = p->db; /* The database */ |
| 52281 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| 52282 | u8 encoding = ENC(db); /* The database encoding */ |
| 52283 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 52284 | int checkProgress; /* True if progress callbacks are enabled */ |
| 52285 | int nProgressOps = 0; /* Opcodes executed since progress callback. */ |
| 52286 | #endif |
| 52287 | Mem *aMem = p->aMem; /* Copy of p->aMem */ |
| 52288 | Mem *pIn1 = 0; /* 1st input operand */ |
| 52289 | Mem *pIn2 = 0; /* 2nd input operand */ |
| @@ -55461,11 +55468,11 @@ | |
| 55468 | ** u.az.r.flags = UNPACKED_INCRKEY; |
| 55469 | ** }else{ |
| 55470 | ** u.az.r.flags = 0; |
| 55471 | ** } |
| 55472 | */ |
| 55473 | u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt))); |
| 55474 | assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY ); |
| 55475 | assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY ); |
| 55476 | assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 ); |
| 55477 | assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 ); |
| 55478 | |
| @@ -55594,11 +55601,11 @@ | |
| 55601 | if( ALWAYS(u.bb.pC->pCursor!=0) ){ |
| 55602 | |
| 55603 | assert( u.bb.pC->isTable==0 ); |
| 55604 | if( pOp->p4.i>0 ){ |
| 55605 | u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo; |
| 55606 | u.bb.r.nField = (u16)pOp->p4.i; |
| 55607 | u.bb.r.aMem = pIn3; |
| 55608 | u.bb.r.flags = UNPACKED_PREFIX_MATCH; |
| 55609 | u.bb.pIdxKey = &u.bb.r; |
| 55610 | }else{ |
| 55611 | assert( pIn3->flags & MEM_Blob ); |
| @@ -59309,10 +59316,14 @@ | |
| 59316 | pExpr->affinity = SQLITE_AFF_INTEGER; |
| 59317 | }else if( pExpr->iTable==0 ){ |
| 59318 | testcase( iCol==31 ); |
| 59319 | testcase( iCol==32 ); |
| 59320 | pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); |
| 59321 | }else{ |
| 59322 | testcase( iCol==31 ); |
| 59323 | testcase( iCol==32 ); |
| 59324 | pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); |
| 59325 | } |
| 59326 | pExpr->iColumn = (i16)iCol; |
| 59327 | pExpr->pTab = pTab; |
| 59328 | isTrigger = 1; |
| 59329 | } |
| @@ -70890,11 +70901,13 @@ | |
| 70901 | u32 mask; /* Mask of OLD.* columns in use */ |
| 70902 | int iCol; /* Iterator used while populating OLD.* */ |
| 70903 | |
| 70904 | /* TODO: Could use temporary registers here. Also could attempt to |
| 70905 | ** avoid copying the contents of the rowid register. */ |
| 70906 | mask = sqlite3TriggerColmask( |
| 70907 | pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf |
| 70908 | ); |
| 70909 | mask |= sqlite3FkOldmask(pParse, pTab); |
| 70910 | iOld = pParse->nMem+1; |
| 70911 | pParse->nMem += (1 + pTab->nCol); |
| 70912 | |
| 70913 | /* Populate the OLD.* pseudo-table register array. These values will be |
| @@ -84240,11 +84253,12 @@ | |
| 84253 | pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); |
| 84254 | if( !pProgram ) return 0; |
| 84255 | pProgram->nRef = 1; |
| 84256 | pPrg->pTrigger = pTrigger; |
| 84257 | pPrg->orconf = orconf; |
| 84258 | pPrg->aColmask[0] = 0xffffffff; |
| 84259 | pPrg->aColmask[1] = 0xffffffff; |
| 84260 | |
| 84261 | /* Allocate and populate a new Parse context to use for coding the |
| 84262 | ** trigger sub-program. */ |
| 84263 | pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); |
| 84264 | if( !pSubParse ) return 0; |
| @@ -84301,11 +84315,12 @@ | |
| 84315 | pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); |
| 84316 | } |
| 84317 | pProgram->nMem = pSubParse->nMem; |
| 84318 | pProgram->nCsr = pSubParse->nTab; |
| 84319 | pProgram->token = (void *)pTrigger; |
| 84320 | pPrg->aColmask[0] = pSubParse->oldmask; |
| 84321 | pPrg->aColmask[1] = pSubParse->newmask; |
| 84322 | sqlite3VdbeDelete(v); |
| 84323 | } |
| 84324 | |
| 84325 | assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); |
| 84326 | assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); |
| @@ -84461,45 +84476,56 @@ | |
| 84476 | } |
| 84477 | } |
| 84478 | } |
| 84479 | |
| 84480 | /* |
| 84481 | ** Triggers may access values stored in the old.* or new.* pseudo-table. |
| 84482 | ** This function returns a 32-bit bitmask indicating which columns of the |
| 84483 | ** old.* or new.* tables actually are used by triggers. This information |
| 84484 | ** may be used by the caller, for example, to avoid having to load the entire |
| 84485 | ** old.* record into memory when executing an UPDATE or DELETE command. |
| 84486 | ** |
| 84487 | ** Bit 0 of the returned mask is set if the left-most column of the |
| 84488 | ** table may be accessed using an [old|new].<col> reference. Bit 1 is set if |
| 84489 | ** the second leftmost column value is required, and so on. If there |
| 84490 | ** are more than 32 columns in the table, and at least one of the columns |
| 84491 | ** with an index greater than 32 may be accessed, 0xffffffff is returned. |
| 84492 | ** |
| 84493 | ** It is not possible to determine if the old.rowid or new.rowid column is |
| 84494 | ** accessed by triggers. The caller must always assume that it is. |
| 84495 | ** |
| 84496 | ** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned |
| 84497 | ** applies to the old.* table. If 1, the new.* table. |
| 84498 | ** |
| 84499 | ** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE |
| 84500 | ** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only |
| 84501 | ** included in the returned mask if the TRIGGER_BEFORE bit is set in the |
| 84502 | ** tr_tm parameter. Similarly, values accessed by AFTER triggers are only |
| 84503 | ** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. |
| 84504 | */ |
| 84505 | SQLITE_PRIVATE u32 sqlite3TriggerColmask( |
| 84506 | Parse *pParse, /* Parse context */ |
| 84507 | Trigger *pTrigger, /* List of triggers on table pTab */ |
| 84508 | ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ |
| 84509 | int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ |
| 84510 | int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ |
| 84511 | Table *pTab, /* The table to code triggers from */ |
| 84512 | int orconf /* Default ON CONFLICT policy for trigger steps */ |
| 84513 | ){ |
| 84514 | const int op = pChanges ? TK_UPDATE : TK_DELETE; |
| 84515 | u32 mask = 0; |
| 84516 | Trigger *p; |
| 84517 | |
| 84518 | assert( isNew==1 || isNew==0 ); |
| 84519 | for(p=pTrigger; p; p=p->pNext){ |
| 84520 | if( p->op==op && (tr_tm&p->tr_tm) |
| 84521 | && checkColumnOverlap(p->pColumns,pChanges) |
| 84522 | ){ |
| 84523 | TriggerPrg *pPrg; |
| 84524 | pPrg = getRowTrigger(pParse, p, pTab, orconf); |
| 84525 | if( pPrg ){ |
| 84526 | mask |= pPrg->aColmask[isNew]; |
| 84527 | } |
| 84528 | } |
| 84529 | } |
| 84530 | |
| 84531 | return mask; |
| @@ -84619,18 +84645,19 @@ | |
| 84645 | Expr *pRowidExpr = 0; /* Expression defining the new record number */ |
| 84646 | int openAll = 0; /* True if all indices need to be opened */ |
| 84647 | AuthContext sContext; /* The authorization context */ |
| 84648 | NameContext sNC; /* The name-context to resolve expressions in */ |
| 84649 | int iDb; /* Database containing the table being updated */ |
| 84650 | int okOnePass; /* True for one-pass algorithm without the FIFO */ |
| 84651 | int hasFK; /* True if foreign key processing is required */ |
| 84652 | |
| 84653 | #ifndef SQLITE_OMIT_TRIGGER |
| 84654 | int isView; /* True when updating a view (INSTEAD OF trigger) */ |
| 84655 | Trigger *pTrigger; /* List of triggers on pTab, if required */ |
| 84656 | int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ |
| 84657 | #endif |
| 84658 | int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ |
| 84659 | |
| 84660 | /* Register Allocations */ |
| 84661 | int regRowCount = 0; /* A count of rows changed */ |
| 84662 | int regOldRowid; /* The old rowid */ |
| 84663 | int regNewRowid; /* The new rowid */ |
| @@ -84654,25 +84681,27 @@ | |
| 84681 | |
| 84682 | /* Figure out if we have any triggers and if the table being |
| 84683 | ** updated is a view. |
| 84684 | */ |
| 84685 | #ifndef SQLITE_OMIT_TRIGGER |
| 84686 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); |
| 84687 | isView = pTab->pSelect!=0; |
| 84688 | assert( pTrigger || tmask==0 ); |
| 84689 | #else |
| 84690 | # define pTrigger 0 |
| 84691 | # define isView 0 |
| 84692 | # define tmask 0 |
| 84693 | #endif |
| 84694 | #ifdef SQLITE_OMIT_VIEW |
| 84695 | # undef isView |
| 84696 | # define isView 0 |
| 84697 | #endif |
| 84698 | |
| 84699 | if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
| 84700 | goto update_cleanup; |
| 84701 | } |
| 84702 | if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ |
| 84703 | goto update_cleanup; |
| 84704 | } |
| 84705 | aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); |
| 84706 | if( aXRef==0 ) goto update_cleanup; |
| 84707 | for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; |
| @@ -84896,11 +84925,13 @@ | |
| 84925 | |
| 84926 | /* If there are triggers on this table, populate an array of registers |
| 84927 | ** with the required old.* column data. */ |
| 84928 | if( hasFK || pTrigger ){ |
| 84929 | u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); |
| 84930 | oldmask |= sqlite3TriggerColmask(pParse, |
| 84931 | pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError |
| 84932 | ); |
| 84933 | for(i=0; i<pTab->nCol; i++){ |
| 84934 | if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){ |
| 84935 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i); |
| 84936 | sqlite3ColumnDefault(v, pTab, i, regOld+i); |
| 84937 | }else{ |
| @@ -84913,42 +84944,76 @@ | |
| 84944 | } |
| 84945 | |
| 84946 | /* Populate the array of registers beginning at regNew with the new |
| 84947 | ** row data. This array is used to check constaints, create the new |
| 84948 | ** table and index records, and as the values for any new.* references |
| 84949 | ** made by triggers. |
| 84950 | ** |
| 84951 | ** If there are one or more BEFORE triggers, then do not populate the |
| 84952 | ** registers associated with columns that are (a) not modified by |
| 84953 | ** this UPDATE statement and (b) not accessed by new.* references. The |
| 84954 | ** values for registers not modified by the UPDATE must be reloaded from |
| 84955 | ** the database after the BEFORE triggers are fired anyway (as the trigger |
| 84956 | ** may have modified them). So not loading those that are not going to |
| 84957 | ** be used eliminates some redundant opcodes. |
| 84958 | */ |
| 84959 | newmask = sqlite3TriggerColmask( |
| 84960 | pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError |
| 84961 | ); |
| 84962 | for(i=0; i<pTab->nCol; i++){ |
| 84963 | if( i==pTab->iPKey ){ |
| 84964 | sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
| 84965 | }else{ |
| 84966 | j = aXRef[i]; |
| 84967 | if( j>=0 ){ |
| 84968 | sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); |
| 84969 | }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){ |
| 84970 | /* This branch loads the value of a column that will not be changed |
| 84971 | ** into a register. This is done if there are no BEFORE triggers, or |
| 84972 | ** if there are one or more BEFORE triggers that use this value via |
| 84973 | ** a new.* reference in a trigger program. |
| 84974 | */ |
| 84975 | testcase( i==31 ); |
| 84976 | testcase( i==32 ); |
| 84977 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); |
| 84978 | sqlite3ColumnDefault(v, pTab, i, regNew+i); |
| 84979 | } |
| 84980 | } |
| 84981 | } |
| 84982 | |
| 84983 | /* Fire any BEFORE UPDATE triggers. This happens before constraints are |
| 84984 | ** verified. One could argue that this is wrong. |
| 84985 | */ |
| 84986 | if( tmask&TRIGGER_BEFORE ){ |
| 84987 | sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); |
| 84988 | sqlite3TableAffinityStr(v, pTab); |
| 84989 | sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, |
| 84990 | TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); |
| 84991 | |
| 84992 | /* The row-trigger may have deleted the row being updated. In this |
| 84993 | ** case, jump to the next row. No updates or AFTER triggers are |
| 84994 | ** required. This behaviour - what happens when the row being updated |
| 84995 | ** is deleted or renamed by a BEFORE trigger - is left undefined in the |
| 84996 | ** documentation. |
| 84997 | */ |
| 84998 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); |
| 84999 | |
| 85000 | /* If it did not delete it, the row-trigger may still have modified |
| 85001 | ** some of the columns of the row being updated. Load the values for |
| 85002 | ** all columns not modified by the update statement into their |
| 85003 | ** registers in case this has happened. |
| 85004 | */ |
| 85005 | for(i=0; i<pTab->nCol; i++){ |
| 85006 | if( aXRef[i]<0 && i!=pTab->iPKey ){ |
| 85007 | sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); |
| 85008 | sqlite3ColumnDefault(v, pTab, i, regNew+i); |
| 85009 | } |
| 85010 | } |
| 85011 | } |
| 85012 | |
| 85013 | if( !isView ){ |
| 85014 | int j1; /* Address of jump instruction */ |
| 85015 | |
| 85016 | /* Do constraint checks. */ |
| 85017 | sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, |
| 85018 | aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0); |
| 85019 | |
| @@ -90583,11 +90648,11 @@ | |
| 90648 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 90649 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 90650 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 90651 | sqlite3 *db = pParse->db; |
| 90652 | if( db->mallocFailed==0 && pY->op==TK_NULL ){ |
| 90653 | pA->op = (u8)op; |
| 90654 | sqlite3ExprDelete(db, pA->pRight); |
| 90655 | pA->pRight = 0; |
| 90656 | } |
| 90657 | } |
| 90658 | |
| @@ -97946,11 +98011,558 @@ | |
| 98011 | |
| 98012 | #if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) |
| 98013 | # define SQLITE_CORE 1 |
| 98014 | #endif |
| 98015 | |
| 98016 | /************** Include fts3Int.h in the middle of fts3.c ********************/ |
| 98017 | /************** Begin file fts3Int.h *****************************************/ |
| 98018 | /* |
| 98019 | ** 2009 Nov 12 |
| 98020 | ** |
| 98021 | ** The author disclaims copyright to this source code. In place of |
| 98022 | ** a legal notice, here is a blessing: |
| 98023 | ** |
| 98024 | ** May you do good and not evil. |
| 98025 | ** May you find forgiveness for yourself and forgive others. |
| 98026 | ** May you share freely, never taking more than you give. |
| 98027 | ** |
| 98028 | ****************************************************************************** |
| 98029 | ** |
| 98030 | */ |
| 98031 | |
| 98032 | #ifndef _FTSINT_H |
| 98033 | #define _FTSINT_H |
| 98034 | |
| 98035 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 98036 | # define NDEBUG 1 |
| 98037 | #endif |
| 98038 | |
| 98039 | /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ |
| 98040 | /************** Begin file fts3_tokenizer.h **********************************/ |
| 98041 | /* |
| 98042 | ** 2006 July 10 |
| 98043 | ** |
| 98044 | ** The author disclaims copyright to this source code. |
| 98045 | ** |
| 98046 | ************************************************************************* |
| 98047 | ** Defines the interface to tokenizers used by fulltext-search. There |
| 98048 | ** are three basic components: |
| 98049 | ** |
| 98050 | ** sqlite3_tokenizer_module is a singleton defining the tokenizer |
| 98051 | ** interface functions. This is essentially the class structure for |
| 98052 | ** tokenizers. |
| 98053 | ** |
| 98054 | ** sqlite3_tokenizer is used to define a particular tokenizer, perhaps |
| 98055 | ** including customization information defined at creation time. |
| 98056 | ** |
| 98057 | ** sqlite3_tokenizer_cursor is generated by a tokenizer to generate |
| 98058 | ** tokens from a particular input. |
| 98059 | */ |
| 98060 | #ifndef _FTS3_TOKENIZER_H_ |
| 98061 | #define _FTS3_TOKENIZER_H_ |
| 98062 | |
| 98063 | /* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. |
| 98064 | ** If tokenizers are to be allowed to call sqlite3_*() functions, then |
| 98065 | ** we will need a way to register the API consistently. |
| 98066 | */ |
| 98067 | |
| 98068 | /* |
| 98069 | ** Structures used by the tokenizer interface. When a new tokenizer |
| 98070 | ** implementation is registered, the caller provides a pointer to |
| 98071 | ** an sqlite3_tokenizer_module containing pointers to the callback |
| 98072 | ** functions that make up an implementation. |
| 98073 | ** |
| 98074 | ** When an fts3 table is created, it passes any arguments passed to |
| 98075 | ** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the |
| 98076 | ** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer |
| 98077 | ** implementation. The xCreate() function in turn returns an |
| 98078 | ** sqlite3_tokenizer structure representing the specific tokenizer to |
| 98079 | ** be used for the fts3 table (customized by the tokenizer clause arguments). |
| 98080 | ** |
| 98081 | ** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() |
| 98082 | ** method is called. It returns an sqlite3_tokenizer_cursor object |
| 98083 | ** that may be used to tokenize a specific input buffer based on |
| 98084 | ** the tokenization rules supplied by a specific sqlite3_tokenizer |
| 98085 | ** object. |
| 98086 | */ |
| 98087 | typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; |
| 98088 | typedef struct sqlite3_tokenizer sqlite3_tokenizer; |
| 98089 | typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; |
| 98090 | |
| 98091 | struct sqlite3_tokenizer_module { |
| 98092 | |
| 98093 | /* |
| 98094 | ** Structure version. Should always be set to 0. |
| 98095 | */ |
| 98096 | int iVersion; |
| 98097 | |
| 98098 | /* |
| 98099 | ** Create a new tokenizer. The values in the argv[] array are the |
| 98100 | ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL |
| 98101 | ** TABLE statement that created the fts3 table. For example, if |
| 98102 | ** the following SQL is executed: |
| 98103 | ** |
| 98104 | ** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2) |
| 98105 | ** |
| 98106 | ** then argc is set to 2, and the argv[] array contains pointers |
| 98107 | ** to the strings "arg1" and "arg2". |
| 98108 | ** |
| 98109 | ** This method should return either SQLITE_OK (0), or an SQLite error |
| 98110 | ** code. If SQLITE_OK is returned, then *ppTokenizer should be set |
| 98111 | ** to point at the newly created tokenizer structure. The generic |
| 98112 | ** sqlite3_tokenizer.pModule variable should not be initialised by |
| 98113 | ** this callback. The caller will do so. |
| 98114 | */ |
| 98115 | int (*xCreate)( |
| 98116 | int argc, /* Size of argv array */ |
| 98117 | const char *const*argv, /* Tokenizer argument strings */ |
| 98118 | sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ |
| 98119 | ); |
| 98120 | |
| 98121 | /* |
| 98122 | ** Destroy an existing tokenizer. The fts3 module calls this method |
| 98123 | ** exactly once for each successful call to xCreate(). |
| 98124 | */ |
| 98125 | int (*xDestroy)(sqlite3_tokenizer *pTokenizer); |
| 98126 | |
| 98127 | /* |
| 98128 | ** Create a tokenizer cursor to tokenize an input buffer. The caller |
| 98129 | ** is responsible for ensuring that the input buffer remains valid |
| 98130 | ** until the cursor is closed (using the xClose() method). |
| 98131 | */ |
| 98132 | int (*xOpen)( |
| 98133 | sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ |
| 98134 | const char *pInput, int nBytes, /* Input buffer */ |
| 98135 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ |
| 98136 | ); |
| 98137 | |
| 98138 | /* |
| 98139 | ** Destroy an existing tokenizer cursor. The fts3 module calls this |
| 98140 | ** method exactly once for each successful call to xOpen(). |
| 98141 | */ |
| 98142 | int (*xClose)(sqlite3_tokenizer_cursor *pCursor); |
| 98143 | |
| 98144 | /* |
| 98145 | ** Retrieve the next token from the tokenizer cursor pCursor. This |
| 98146 | ** method should either return SQLITE_OK and set the values of the |
| 98147 | ** "OUT" variables identified below, or SQLITE_DONE to indicate that |
| 98148 | ** the end of the buffer has been reached, or an SQLite error code. |
| 98149 | ** |
| 98150 | ** *ppToken should be set to point at a buffer containing the |
| 98151 | ** normalized version of the token (i.e. after any case-folding and/or |
| 98152 | ** stemming has been performed). *pnBytes should be set to the length |
| 98153 | ** of this buffer in bytes. The input text that generated the token is |
| 98154 | ** identified by the byte offsets returned in *piStartOffset and |
| 98155 | ** *piEndOffset. *piStartOffset should be set to the index of the first |
| 98156 | ** byte of the token in the input buffer. *piEndOffset should be set |
| 98157 | ** to the index of the first byte just past the end of the token in |
| 98158 | ** the input buffer. |
| 98159 | ** |
| 98160 | ** The buffer *ppToken is set to point at is managed by the tokenizer |
| 98161 | ** implementation. It is only required to be valid until the next call |
| 98162 | ** to xNext() or xClose(). |
| 98163 | */ |
| 98164 | /* TODO(shess) current implementation requires pInput to be |
| 98165 | ** nul-terminated. This should either be fixed, or pInput/nBytes |
| 98166 | ** should be converted to zInput. |
| 98167 | */ |
| 98168 | int (*xNext)( |
| 98169 | sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ |
| 98170 | const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ |
| 98171 | int *piStartOffset, /* OUT: Byte offset of token in input buffer */ |
| 98172 | int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ |
| 98173 | int *piPosition /* OUT: Number of tokens returned before this one */ |
| 98174 | ); |
| 98175 | }; |
| 98176 | |
| 98177 | struct sqlite3_tokenizer { |
| 98178 | const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ |
| 98179 | /* Tokenizer implementations will typically add additional fields */ |
| 98180 | }; |
| 98181 | |
| 98182 | struct sqlite3_tokenizer_cursor { |
| 98183 | sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ |
| 98184 | /* Tokenizer implementations will typically add additional fields */ |
| 98185 | }; |
| 98186 | |
| 98187 | #endif /* _FTS3_TOKENIZER_H_ */ |
| 98188 | |
| 98189 | /************** End of fts3_tokenizer.h **************************************/ |
| 98190 | /************** Continuing where we left off in fts3Int.h ********************/ |
| 98191 | /************** Include fts3_hash.h in the middle of fts3Int.h ***************/ |
| 98192 | /************** Begin file fts3_hash.h ***************************************/ |
| 98193 | /* |
| 98194 | ** 2001 September 22 |
| 98195 | ** |
| 98196 | ** The author disclaims copyright to this source code. In place of |
| 98197 | ** a legal notice, here is a blessing: |
| 98198 | ** |
| 98199 | ** May you do good and not evil. |
| 98200 | ** May you find forgiveness for yourself and forgive others. |
| 98201 | ** May you share freely, never taking more than you give. |
| 98202 | ** |
| 98203 | ************************************************************************* |
| 98204 | ** This is the header file for the generic hash-table implemenation |
| 98205 | ** used in SQLite. We've modified it slightly to serve as a standalone |
| 98206 | ** hash table implementation for the full-text indexing module. |
| 98207 | ** |
| 98208 | */ |
| 98209 | #ifndef _FTS3_HASH_H_ |
| 98210 | #define _FTS3_HASH_H_ |
| 98211 | |
| 98212 | /* Forward declarations of structures. */ |
| 98213 | typedef struct Fts3Hash Fts3Hash; |
| 98214 | typedef struct Fts3HashElem Fts3HashElem; |
| 98215 | |
| 98216 | /* A complete hash table is an instance of the following structure. |
| 98217 | ** The internals of this structure are intended to be opaque -- client |
| 98218 | ** code should not attempt to access or modify the fields of this structure |
| 98219 | ** directly. Change this structure only by using the routines below. |
| 98220 | ** However, many of the "procedures" and "functions" for modifying and |
| 98221 | ** accessing this structure are really macros, so we can't really make |
| 98222 | ** this structure opaque. |
| 98223 | */ |
| 98224 | struct Fts3Hash { |
| 98225 | char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ |
| 98226 | char copyKey; /* True if copy of key made on insert */ |
| 98227 | int count; /* Number of entries in this table */ |
| 98228 | Fts3HashElem *first; /* The first element of the array */ |
| 98229 | int htsize; /* Number of buckets in the hash table */ |
| 98230 | struct _fts3ht { /* the hash table */ |
| 98231 | int count; /* Number of entries with this hash */ |
| 98232 | Fts3HashElem *chain; /* Pointer to first entry with this hash */ |
| 98233 | } *ht; |
| 98234 | }; |
| 98235 | |
| 98236 | /* Each element in the hash table is an instance of the following |
| 98237 | ** structure. All elements are stored on a single doubly-linked list. |
| 98238 | ** |
| 98239 | ** Again, this structure is intended to be opaque, but it can't really |
| 98240 | ** be opaque because it is used by macros. |
| 98241 | */ |
| 98242 | struct Fts3HashElem { |
| 98243 | Fts3HashElem *next, *prev; /* Next and previous elements in the table */ |
| 98244 | void *data; /* Data associated with this element */ |
| 98245 | void *pKey; int nKey; /* Key associated with this element */ |
| 98246 | }; |
| 98247 | |
| 98248 | /* |
| 98249 | ** There are 2 different modes of operation for a hash table: |
| 98250 | ** |
| 98251 | ** FTS3_HASH_STRING pKey points to a string that is nKey bytes long |
| 98252 | ** (including the null-terminator, if any). Case |
| 98253 | ** is respected in comparisons. |
| 98254 | ** |
| 98255 | ** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. |
| 98256 | ** memcmp() is used to compare keys. |
| 98257 | ** |
| 98258 | ** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. |
| 98259 | */ |
| 98260 | #define FTS3_HASH_STRING 1 |
| 98261 | #define FTS3_HASH_BINARY 2 |
| 98262 | |
| 98263 | /* |
| 98264 | ** Access routines. To delete, insert a NULL pointer. |
| 98265 | */ |
| 98266 | SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey); |
| 98267 | SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); |
| 98268 | SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); |
| 98269 | SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*); |
| 98270 | |
| 98271 | /* |
| 98272 | ** Shorthand for the functions above |
| 98273 | */ |
| 98274 | #define fts3HashInit sqlite3Fts3HashInit |
| 98275 | #define fts3HashInsert sqlite3Fts3HashInsert |
| 98276 | #define fts3HashFind sqlite3Fts3HashFind |
| 98277 | #define fts3HashClear sqlite3Fts3HashClear |
| 98278 | |
| 98279 | /* |
| 98280 | ** Macros for looping over all elements of a hash table. The idiom is |
| 98281 | ** like this: |
| 98282 | ** |
| 98283 | ** Fts3Hash h; |
| 98284 | ** Fts3HashElem *p; |
| 98285 | ** ... |
| 98286 | ** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ |
| 98287 | ** SomeStructure *pData = fts3HashData(p); |
| 98288 | ** // do something with pData |
| 98289 | ** } |
| 98290 | */ |
| 98291 | #define fts3HashFirst(H) ((H)->first) |
| 98292 | #define fts3HashNext(E) ((E)->next) |
| 98293 | #define fts3HashData(E) ((E)->data) |
| 98294 | #define fts3HashKey(E) ((E)->pKey) |
| 98295 | #define fts3HashKeysize(E) ((E)->nKey) |
| 98296 | |
| 98297 | /* |
| 98298 | ** Number of entries in a hash table |
| 98299 | */ |
| 98300 | #define fts3HashCount(H) ((H)->count) |
| 98301 | |
| 98302 | #endif /* _FTS3_HASH_H_ */ |
| 98303 | |
| 98304 | /************** End of fts3_hash.h *******************************************/ |
| 98305 | /************** Continuing where we left off in fts3Int.h ********************/ |
| 98306 | |
| 98307 | /* |
| 98308 | ** This constant controls how often segments are merged. Once there are |
| 98309 | ** FTS3_MERGE_COUNT segments of level N, they are merged into a single |
| 98310 | ** segment of level N+1. |
| 98311 | */ |
| 98312 | #define FTS3_MERGE_COUNT 16 |
| 98313 | |
| 98314 | /* |
| 98315 | ** This is the maximum amount of data (in bytes) to store in the |
| 98316 | ** Fts3Table.pendingTerms hash table. Normally, the hash table is |
| 98317 | ** populated as documents are inserted/updated/deleted in a transaction |
| 98318 | ** and used to create a new segment when the transaction is committed. |
| 98319 | ** However if this limit is reached midway through a transaction, a new |
| 98320 | ** segment is created and the hash table cleared immediately. |
| 98321 | */ |
| 98322 | #define FTS3_MAX_PENDING_DATA (1*1024*1024) |
| 98323 | |
| 98324 | /* |
| 98325 | ** Macro to return the number of elements in an array. SQLite has a |
| 98326 | ** similar macro called ArraySize(). Use a different name to avoid |
| 98327 | ** a collision when building an amalgamation with built-in FTS3. |
| 98328 | */ |
| 98329 | #define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0]))) |
| 98330 | |
| 98331 | /* |
| 98332 | ** Maximum length of a varint encoded integer. The varint format is different |
| 98333 | ** from that used by SQLite, so the maximum length is 10, not 9. |
| 98334 | */ |
| 98335 | #define FTS3_VARINT_MAX 10 |
| 98336 | |
| 98337 | /* |
| 98338 | ** This section provides definitions to allow the |
| 98339 | ** FTS3 extension to be compiled outside of the |
| 98340 | ** amalgamation. |
| 98341 | */ |
| 98342 | #ifndef SQLITE_AMALGAMATION |
| 98343 | /* |
| 98344 | ** Macros indicating that conditional expressions are always true or |
| 98345 | ** false. |
| 98346 | */ |
| 98347 | # define ALWAYS(x) (x) |
| 98348 | # define NEVER(X) (x) |
| 98349 | /* |
| 98350 | ** Internal types used by SQLite. |
| 98351 | */ |
| 98352 | typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ |
| 98353 | typedef short int i16; /* 2-byte (or larger) signed integer */ |
| 98354 | /* |
| 98355 | ** Macro used to suppress compiler warnings for unused parameters. |
| 98356 | */ |
| 98357 | #define UNUSED_PARAMETER(x) (void)(x) |
| 98358 | #endif |
| 98359 | |
| 98360 | typedef struct Fts3Table Fts3Table; |
| 98361 | typedef struct Fts3Cursor Fts3Cursor; |
| 98362 | typedef struct Fts3Expr Fts3Expr; |
| 98363 | typedef struct Fts3Phrase Fts3Phrase; |
| 98364 | typedef struct Fts3SegReader Fts3SegReader; |
| 98365 | typedef struct Fts3SegFilter Fts3SegFilter; |
| 98366 | |
| 98367 | /* |
| 98368 | ** A connection to a fulltext index is an instance of the following |
| 98369 | ** structure. The xCreate and xConnect methods create an instance |
| 98370 | ** of this structure and xDestroy and xDisconnect free that instance. |
| 98371 | ** All other methods receive a pointer to the structure as one of their |
| 98372 | ** arguments. |
| 98373 | */ |
| 98374 | struct Fts3Table { |
| 98375 | sqlite3_vtab base; /* Base class used by SQLite core */ |
| 98376 | sqlite3 *db; /* The database connection */ |
| 98377 | const char *zDb; /* logical database name */ |
| 98378 | const char *zName; /* virtual table name */ |
| 98379 | int nColumn; /* number of named columns in virtual table */ |
| 98380 | char **azColumn; /* column names. malloced */ |
| 98381 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 98382 | |
| 98383 | /* Precompiled statements used by the implementation. Each of these |
| 98384 | ** statements is run and reset within a single virtual table API call. |
| 98385 | */ |
| 98386 | sqlite3_stmt *aStmt[18]; |
| 98387 | |
| 98388 | /* Pointer to string containing the SQL: |
| 98389 | ** |
| 98390 | ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? |
| 98391 | ** ORDER BY blockid" |
| 98392 | */ |
| 98393 | char *zSelectLeaves; |
| 98394 | int nLeavesStmt; /* Valid statements in aLeavesStmt */ |
| 98395 | int nLeavesTotal; /* Total number of prepared leaves stmts */ |
| 98396 | int nLeavesAlloc; /* Allocated size of aLeavesStmt */ |
| 98397 | sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ |
| 98398 | |
| 98399 | int nNodeSize; /* Soft limit for node size */ |
| 98400 | |
| 98401 | /* The following hash table is used to buffer pending index updates during |
| 98402 | ** transactions. Variable nPendingData estimates the memory size of the |
| 98403 | ** pending data, including hash table overhead, but not malloc overhead. |
| 98404 | ** When nPendingData exceeds FTS3_MAX_PENDING_DATA, the buffer is flushed |
| 98405 | ** automatically. Variable iPrevDocid is the docid of the most recently |
| 98406 | ** inserted record. |
| 98407 | */ |
| 98408 | int nPendingData; |
| 98409 | sqlite_int64 iPrevDocid; |
| 98410 | Fts3Hash pendingTerms; |
| 98411 | }; |
| 98412 | |
| 98413 | /* |
| 98414 | ** When the core wants to read from the virtual table, it creates a |
| 98415 | ** virtual table cursor (an instance of the following structure) using |
| 98416 | ** the xOpen method. Cursors are destroyed using the xClose method. |
| 98417 | */ |
| 98418 | struct Fts3Cursor { |
| 98419 | sqlite3_vtab_cursor base; /* Base class used by SQLite core */ |
| 98420 | i16 eSearch; /* Search strategy (see below) */ |
| 98421 | u8 isEof; /* True if at End Of Results */ |
| 98422 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 98423 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 98424 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 98425 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 98426 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 98427 | char *aDoclist; /* List of docids for full-text queries */ |
| 98428 | int nDoclist; /* Size of buffer at aDoclist */ |
| 98429 | }; |
| 98430 | |
| 98431 | /* |
| 98432 | ** The Fts3Cursor.eSearch member is always set to one of the following. |
| 98433 | ** Actualy, Fts3Cursor.eSearch can be greater than or equal to |
| 98434 | ** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index |
| 98435 | ** of the column to be searched. For example, in |
| 98436 | ** |
| 98437 | ** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d); |
| 98438 | ** SELECT docid FROM ex1 WHERE b MATCH 'one two three'; |
| 98439 | ** |
| 98440 | ** Because the LHS of the MATCH operator is 2nd column "b", |
| 98441 | ** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a, |
| 98442 | ** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" |
| 98443 | ** indicating that all columns should be searched, |
| 98444 | ** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. |
| 98445 | */ |
| 98446 | #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ |
| 98447 | #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ |
| 98448 | #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ |
| 98449 | |
| 98450 | /* |
| 98451 | ** A "phrase" is a sequence of one or more tokens that must match in |
| 98452 | ** sequence. A single token is the base case and the most common case. |
| 98453 | ** For a sequence of tokens contained in "...", nToken will be the number |
| 98454 | ** of tokens in the string. |
| 98455 | */ |
| 98456 | struct Fts3Phrase { |
| 98457 | int nToken; /* Number of tokens in the phrase */ |
| 98458 | int iColumn; /* Index of column this phrase must match */ |
| 98459 | int isNot; /* Phrase prefixed by unary not (-) operator */ |
| 98460 | struct PhraseToken { |
| 98461 | char *z; /* Text of the token */ |
| 98462 | int n; /* Number of bytes in buffer pointed to by z */ |
| 98463 | int isPrefix; /* True if token ends in with a "*" character */ |
| 98464 | } aToken[1]; /* One entry for each token in the phrase */ |
| 98465 | }; |
| 98466 | |
| 98467 | /* |
| 98468 | ** A tree of these objects forms the RHS of a MATCH operator. |
| 98469 | */ |
| 98470 | struct Fts3Expr { |
| 98471 | int eType; /* One of the FTSQUERY_XXX values defined below */ |
| 98472 | int nNear; /* Valid if eType==FTSQUERY_NEAR */ |
| 98473 | Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */ |
| 98474 | Fts3Expr *pLeft; /* Left operand */ |
| 98475 | Fts3Expr *pRight; /* Right operand */ |
| 98476 | Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */ |
| 98477 | }; |
| 98478 | |
| 98479 | /* |
| 98480 | ** Candidate values for Fts3Query.eType. Note that the order of the first |
| 98481 | ** four values is in order of precedence when parsing expressions. For |
| 98482 | ** example, the following: |
| 98483 | ** |
| 98484 | ** "a OR b AND c NOT d NEAR e" |
| 98485 | ** |
| 98486 | ** is equivalent to: |
| 98487 | ** |
| 98488 | ** "a OR (b AND (c NOT (d NEAR e)))" |
| 98489 | */ |
| 98490 | #define FTSQUERY_NEAR 1 |
| 98491 | #define FTSQUERY_NOT 2 |
| 98492 | #define FTSQUERY_AND 3 |
| 98493 | #define FTSQUERY_OR 4 |
| 98494 | #define FTSQUERY_PHRASE 5 |
| 98495 | |
| 98496 | |
| 98497 | /* fts3_init.c */ |
| 98498 | SQLITE_PRIVATE int sqlite3Fts3DeleteVtab(int, sqlite3_vtab *); |
| 98499 | SQLITE_PRIVATE int sqlite3Fts3InitVtab(int, sqlite3*, void*, int, const char*const*, |
| 98500 | sqlite3_vtab **, char **); |
| 98501 | |
| 98502 | /* fts3_write.c */ |
| 98503 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); |
| 98504 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); |
| 98505 | SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); |
| 98506 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); |
| 98507 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64, |
| 98508 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 98509 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); |
| 98510 | SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( |
| 98511 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 98512 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 98513 | ); |
| 98514 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); |
| 98515 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 98516 | |
| 98517 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 98518 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 98519 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 98520 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| 98521 | #define FTS3_SEGMENT_PREFIX 0x00000008 |
| 98522 | |
| 98523 | /* Type passed as 4th argument to SegmentReaderIterate() */ |
| 98524 | struct Fts3SegFilter { |
| 98525 | const char *zTerm; |
| 98526 | int nTerm; |
| 98527 | int iCol; |
| 98528 | int flags; |
| 98529 | }; |
| 98530 | |
| 98531 | /* fts3.c */ |
| 98532 | SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); |
| 98533 | SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); |
| 98534 | SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); |
| 98535 | SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); |
| 98536 | SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); |
| 98537 | |
| 98538 | /* fts3_tokenizer.c */ |
| 98539 | SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); |
| 98540 | SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); |
| 98541 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, |
| 98542 | const char *, sqlite3_tokenizer **, const char **, char ** |
| 98543 | ); |
| 98544 | |
| 98545 | /* fts3_snippet.c */ |
| 98546 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 98547 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*, |
| 98548 | const char *, const char *, const char * |
| 98549 | ); |
| 98550 | |
| 98551 | /* fts3_expr.c */ |
| 98552 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, |
| 98553 | char **, int, int, const char *, int, Fts3Expr ** |
| 98554 | ); |
| 98555 | SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); |
| 98556 | #ifdef SQLITE_TEST |
| 98557 | SQLITE_PRIVATE void sqlite3Fts3ExprInitTestInterface(sqlite3 *db); |
| 98558 | #endif |
| 98559 | |
| 98560 | #endif /* _FTSINT_H */ |
| 98561 | |
| 98562 | /************** End of fts3Int.h *********************************************/ |
| 98563 | /************** Continuing where we left off in fts3.c ***********************/ |
| 98564 | |
| 98565 | |
| 98566 | #ifndef SQLITE_CORE |
| 98567 | SQLITE_EXTENSION_INIT1 |
| 98568 | #endif |
| @@ -98108,11 +98720,11 @@ | |
| 98720 | default: return; |
| 98721 | } |
| 98722 | for(i=1, j=0; z[i]; i++){ |
| 98723 | if( z[i]==quote ){ |
| 98724 | if( z[i+1]==quote ){ |
| 98725 | z[j++] = (char)quote; |
| 98726 | i++; |
| 98727 | }else{ |
| 98728 | z[j++] = 0; |
| 98729 | break; |
| 98730 | } |
| @@ -98134,22 +98746,10 @@ | |
| 98746 | }else{ |
| 98747 | fts3GetDeltaVarint(pp, pVal); |
| 98748 | } |
| 98749 | } |
| 98750 | |
| 98751 | /* |
| 98752 | ** The xDisconnect() virtual table method. |
| 98753 | */ |
| 98754 | static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ |
| 98755 | Fts3Table *p = (Fts3Table *)pVtab; |
| @@ -98295,11 +98895,11 @@ | |
| 98895 | ** The argv[] array contains the following: |
| 98896 | ** |
| 98897 | ** argv[0] -> module name |
| 98898 | ** argv[1] -> database name |
| 98899 | ** argv[2] -> table name |
| 98900 | ** argv[...] -> "column name" and other module argument fields. |
| 98901 | */ |
| 98902 | int fts3InitVtab( |
| 98903 | int isCreate, /* True for xCreate, false for xConnect */ |
| 98904 | sqlite3 *db, /* The SQLite database connection */ |
| 98905 | void *pAux, /* Hash table containing tokenizers */ |
| @@ -98307,34 +98907,42 @@ | |
| 98907 | const char * const *argv, /* xCreate/xConnect argument array */ |
| 98908 | sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ |
| 98909 | char **pzErr /* Write any error message here */ |
| 98910 | ){ |
| 98911 | Fts3Hash *pHash = (Fts3Hash *)pAux; |
| 98912 | Fts3Table *p; /* Pointer to allocated vtab */ |
| 98913 | int rc; /* Return code */ |
| 98914 | int i; /* Iterator variable */ |
| 98915 | int nByte; /* Size of allocation used for *p */ |
| 98916 | int iCol; |
| 98917 | int nString = 0; |
| 98918 | int nCol = 0; |
| 98919 | char *zCsr; |
| 98920 | int nDb; |
| 98921 | int nName; |
| 98922 | |
| 98923 | #ifdef SQLITE_TEST |
| 98924 | char *zTestParam = 0; |
| 98925 | if( strncmp(argv[argc-1], "test:", 5)==0 ){ |
| 98926 | zTestParam = argv[argc-1]; |
| 98927 | argc--; |
| 98928 | } |
| 98929 | #endif |
| 98930 | |
| 98931 | const char *zTokenizer = 0; /* Name of tokenizer to use */ |
| 98932 | sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ |
| 98933 | |
| 98934 | nDb = (int)strlen(argv[1]) + 1; |
| 98935 | nName = (int)strlen(argv[2]) + 1; |
| 98936 | for(i=3; i<argc; i++){ |
| 98937 | char const *z = argv[i]; |
| 98938 | rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr); |
| 98939 | if( rc!=SQLITE_OK ){ |
| 98940 | return rc; |
| 98941 | } |
| 98942 | if( z!=zTokenizer ){ |
| 98943 | nString += (int)(strlen(z) + 1); |
| 98944 | } |
| 98945 | } |
| 98946 | nCol = argc - 3 - (zTokenizer!=0); |
| 98947 | if( zTokenizer==0 ){ |
| 98948 | rc = sqlite3Fts3InitTokenizer(pHash, 0, &pTokenizer, 0, pzErr); |
| @@ -98341,10 +98949,14 @@ | |
| 98949 | if( rc!=SQLITE_OK ){ |
| 98950 | return rc; |
| 98951 | } |
| 98952 | assert( pTokenizer ); |
| 98953 | } |
| 98954 | |
| 98955 | if( nCol==0 ){ |
| 98956 | nCol = 1; |
| 98957 | } |
| 98958 | |
| 98959 | /* Allocate and populate the Fts3Table structure. */ |
| 98960 | nByte = sizeof(Fts3Table) + /* Fts3Table */ |
| 98961 | nCol * sizeof(char *) + /* azColumn */ |
| 98962 | nName + /* zName */ |
| @@ -98360,10 +98972,11 @@ | |
| 98972 | p->db = db; |
| 98973 | p->nColumn = nCol; |
| 98974 | p->nPendingData = 0; |
| 98975 | p->azColumn = (char **)&p[1]; |
| 98976 | p->pTokenizer = pTokenizer; |
| 98977 | p->nNodeSize = 1000; |
| 98978 | zCsr = (char *)&p->azColumn[nCol]; |
| 98979 | |
| 98980 | fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1); |
| 98981 | |
| 98982 | /* Fill in the zName and zDb fields of the vtab structure. */ |
| @@ -98387,10 +99000,14 @@ | |
| 99000 | p->azColumn[iCol++] = zCsr; |
| 99001 | zCsr += n+1; |
| 99002 | assert( zCsr <= &((char *)p)[nByte] ); |
| 99003 | } |
| 99004 | } |
| 99005 | if( iCol==0 ){ |
| 99006 | assert( nCol==1 ); |
| 99007 | p->azColumn[0] = "content"; |
| 99008 | } |
| 99009 | |
| 99010 | /* If this is an xCreate call, create the underlying tables in the |
| 99011 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 99012 | */ |
| 99013 | if( isCreate ){ |
| @@ -98399,16 +99016,25 @@ | |
| 99016 | } |
| 99017 | |
| 99018 | rc = fts3DeclareVtab(p); |
| 99019 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 99020 | |
| 99021 | #ifdef SQLITE_TEST |
| 99022 | if( zTestParam ){ |
| 99023 | p->nNodeSize = atoi(&zTestParam[5]); |
| 99024 | } |
| 99025 | #endif |
| 99026 | *ppVTab = &p->base; |
| 99027 | |
| 99028 | fts3_init_out: |
| 99029 | assert( p || (pTokenizer && rc!=SQLITE_OK) ); |
| 99030 | if( rc!=SQLITE_OK ){ |
| 99031 | if( p ){ |
| 99032 | fts3DisconnectMethod((sqlite3_vtab *)p); |
| 99033 | }else{ |
| 99034 | pTokenizer->pModule->xDestroy(pTokenizer); |
| 99035 | } |
| 99036 | } |
| 99037 | return rc; |
| 99038 | } |
| 99039 | |
| 99040 | /* |
| @@ -98497,10 +99123,12 @@ | |
| 99123 | /* |
| 99124 | ** Implementation of xOpen method. |
| 99125 | */ |
| 99126 | static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ |
| 99127 | sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ |
| 99128 | |
| 99129 | UNUSED_PARAMETER(pVTab); |
| 99130 | |
| 99131 | /* Allocate a buffer large enough for an Fts3Cursor structure. If the |
| 99132 | ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, |
| 99133 | ** if the allocation fails, return SQLITE_NOMEM. |
| 99134 | */ |
| @@ -98664,16 +99292,20 @@ | |
| 99292 | } |
| 99293 | sqlite3_free(zBuffer); |
| 99294 | return rc; |
| 99295 | } |
| 99296 | |
| 99297 | /* |
| 99298 | ** This function is used to create delta-encoded serialized lists of FTS3 |
| 99299 | ** varints. Each call to this function appends a single varint to a list. |
| 99300 | */ |
| 99301 | static void fts3PutDeltaVarint( |
| 99302 | char **pp, /* IN/OUT: Output pointer */ |
| 99303 | sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ |
| 99304 | sqlite3_int64 iVal /* Write this value to the list */ |
| 99305 | ){ |
| 99306 | assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); |
| 99307 | *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); |
| 99308 | *piPrev = iVal; |
| 99309 | } |
| 99310 | |
| 99311 | static void fts3PoslistCopy(char **pp, char **ppPoslist){ |
| @@ -98680,11 +99312,11 @@ | |
| 99312 | char *pEnd = *ppPoslist; |
| 99313 | char c = 0; |
| 99314 | while( *pEnd | c ) c = *pEnd++ & 0x80; |
| 99315 | pEnd++; |
| 99316 | if( pp ){ |
| 99317 | int n = (int)(pEnd - *ppPoslist); |
| 99318 | char *p = *pp; |
| 99319 | memcpy(p, *ppPoslist, n); |
| 99320 | p += n; |
| 99321 | *pp = p; |
| 99322 | } |
| @@ -98694,11 +99326,11 @@ | |
| 99326 | static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ |
| 99327 | char *pEnd = *ppPoslist; |
| 99328 | char c = 0; |
| 99329 | while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; |
| 99330 | if( pp ){ |
| 99331 | int n = (int)(pEnd - *ppPoslist); |
| 99332 | char *p = *pp; |
| 99333 | memcpy(p, *ppPoslist, n); |
| 99334 | p += n; |
| 99335 | *pp = p; |
| 99336 | } |
| @@ -99081,11 +99713,11 @@ | |
| 99713 | |
| 99714 | default: |
| 99715 | assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); |
| 99716 | } |
| 99717 | |
| 99718 | *pnBuffer = (int)(p-aBuffer); |
| 99719 | return SQLITE_OK; |
| 99720 | } |
| 99721 | |
| 99722 | /* |
| 99723 | ** A pointer to an instance of this structure is used as the context |
| @@ -99113,10 +99745,14 @@ | |
| 99745 | ){ |
| 99746 | TermSelect *pTS = (TermSelect *)pContext; |
| 99747 | int nNew = pTS->nOutput + nDoclist; |
| 99748 | char *aNew = sqlite3_malloc(nNew); |
| 99749 | |
| 99750 | UNUSED_PARAMETER(p); |
| 99751 | UNUSED_PARAMETER(zTerm); |
| 99752 | UNUSED_PARAMETER(nTerm); |
| 99753 | |
| 99754 | if( !aNew ){ |
| 99755 | return SQLITE_NOMEM; |
| 99756 | } |
| 99757 | |
| 99758 | if( pTS->nOutput==0 ){ |
| @@ -99194,25 +99830,38 @@ | |
| 99830 | ** leaf). Do not bother inspecting any data in this case, just |
| 99831 | ** create a Fts3SegReader to scan the single leaf. |
| 99832 | */ |
| 99833 | rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew); |
| 99834 | }else{ |
| 99835 | int rc2; /* Return value of sqlite3Fts3ReadBlock() */ |
| 99836 | sqlite3_int64 i1; /* Blockid of leaf that may contain zTerm */ |
| 99837 | rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1); |
| 99838 | if( rc==SQLITE_OK ){ |
| 99839 | sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2); |
| 99840 | rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew); |
| 99841 | } |
| 99842 | |
| 99843 | /* The following call to ReadBlock() serves to reset the SQL statement |
| 99844 | ** used to retrieve blocks of data from the %_segments table. If it is |
| 99845 | ** not reset here, then it may remain classified as an active statement |
| 99846 | ** by SQLite, which may lead to "DROP TABLE" or "DETACH" commands |
| 99847 | ** failing. |
| 99848 | */ |
| 99849 | rc2 = sqlite3Fts3ReadBlock(p, 0, 0, 0); |
| 99850 | if( rc==SQLITE_OK ){ |
| 99851 | rc = rc2; |
| 99852 | } |
| 99853 | } |
| 99854 | iAge++; |
| 99855 | |
| 99856 | /* If a new Fts3SegReader was allocated, add it to the apSegment array. */ |
| 99857 | assert( pNew!=0 || rc!=SQLITE_OK ); |
| 99858 | if( pNew ){ |
| 99859 | if( nSegment==nAlloc ){ |
| 99860 | Fts3SegReader **pArray; |
| 99861 | nAlloc += 16; |
| 99862 | pArray = (Fts3SegReader **)sqlite3_realloc( |
| 99863 | apSegment, nAlloc*sizeof(Fts3SegReader *) |
| 99864 | ); |
| 99865 | if( !pArray ){ |
| 99866 | sqlite3Fts3SegReaderFree(p, pNew); |
| 99867 | rc = SQLITE_NOMEM; |
| @@ -99348,10 +99997,13 @@ | |
| 99997 | int nRight; |
| 99998 | |
| 99999 | if( SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pRight, &aRight, &nRight)) |
| 100000 | && SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pLeft, &aLeft, &nLeft)) |
| 100001 | ){ |
| 100002 | assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR |
| 100003 | || pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT |
| 100004 | ); |
| 100005 | switch( pExpr->eType ){ |
| 100006 | case FTSQUERY_NEAR: { |
| 100007 | Fts3Expr *pLeft; |
| 100008 | Fts3Expr *pRight; |
| 100009 | int mergetype = MERGE_NEAR; |
| @@ -99398,12 +100050,11 @@ | |
| 100050 | *paOut = aBuffer; |
| 100051 | sqlite3_free(aLeft); |
| 100052 | break; |
| 100053 | } |
| 100054 | |
| 100055 | default: { |
| 100056 | assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND ); |
| 100057 | fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut, |
| 100058 | aLeft, nLeft, aRight, nRight |
| 100059 | ); |
| 100060 | *paOut = aLeft; |
| @@ -99452,10 +100103,13 @@ | |
| 100103 | }; |
| 100104 | int rc; /* Return code */ |
| 100105 | char *zSql; /* SQL statement used to access %_content */ |
| 100106 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 100107 | Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
| 100108 | |
| 100109 | UNUSED_PARAMETER(idxStr); |
| 100110 | UNUSED_PARAMETER(nVal); |
| 100111 | |
| 100112 | assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
| 100113 | assert( nVal==0 || nVal==1 ); |
| 100114 | assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); |
| 100115 | |
| @@ -99475,18 +100129,21 @@ | |
| 100129 | }else{ |
| 100130 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
| 100131 | sqlite3_free(zSql); |
| 100132 | } |
| 100133 | if( rc!=SQLITE_OK ) return rc; |
| 100134 | pCsr->eSearch = (i16)idxNum; |
| 100135 | |
| 100136 | if( idxNum==FTS3_DOCID_SEARCH ){ |
| 100137 | rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); |
| 100138 | }else if( idxNum!=FTS3_FULLSCAN_SEARCH ){ |
| 100139 | int iCol = idxNum-FTS3_FULLTEXT_SEARCH; |
| 100140 | const char *zQuery = (const char *)sqlite3_value_text(apVal[0]); |
| 100141 | |
| 100142 | if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 100143 | return SQLITE_NOMEM; |
| 100144 | } |
| 100145 | rc = sqlite3Fts3PendingTermsFlush(p); |
| 100146 | if( rc!=SQLITE_OK ) return rc; |
| 100147 | |
| 100148 | rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn, |
| 100149 | iCol, zQuery, -1, &pCsr->pExpr |
| @@ -99508,42 +100165,10 @@ | |
| 100165 | */ |
| 100166 | static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ |
| 100167 | return ((Fts3Cursor *)pCursor)->isEof; |
| 100168 | } |
| 100169 | |
| 100170 | /* |
| 100171 | ** This is the xRowid method. The SQLite core calls this routine to |
| 100172 | ** retrieve the rowid for the current row of the result set. fts3 |
| 100173 | ** exposes %_content.docid as the rowid for the virtual table. The |
| 100174 | ** rowid should be written to *pRowid. |
| @@ -99555,10 +100180,47 @@ | |
| 100180 | }else{ |
| 100181 | *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); |
| 100182 | } |
| 100183 | return SQLITE_OK; |
| 100184 | } |
| 100185 | |
| 100186 | /* |
| 100187 | ** This is the xColumn method, called by SQLite to request a value from |
| 100188 | ** the row that the supplied cursor currently points to. |
| 100189 | */ |
| 100190 | static int fts3ColumnMethod( |
| 100191 | sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 100192 | sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ |
| 100193 | int iCol /* Index of column to read value from */ |
| 100194 | ){ |
| 100195 | int rc; /* Return Code */ |
| 100196 | Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; |
| 100197 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 100198 | |
| 100199 | /* The column value supplied by SQLite must be in range. */ |
| 100200 | assert( iCol>=0 && iCol<=p->nColumn+1 ); |
| 100201 | |
| 100202 | rc = fts3CursorSeek(pCsr); |
| 100203 | if( rc==SQLITE_OK ){ |
| 100204 | if( iCol==p->nColumn+1 ){ |
| 100205 | /* This call is a request for the "docid" column. Since "docid" is an |
| 100206 | ** alias for "rowid", use the xRowid() method to obtain the value. |
| 100207 | */ |
| 100208 | sqlite3_int64 iRowid; |
| 100209 | rc = fts3RowidMethod(pCursor, &iRowid); |
| 100210 | sqlite3_result_int64(pContext, iRowid); |
| 100211 | }else if( iCol==p->nColumn ){ |
| 100212 | /* The extra column whose name is the same as the table. |
| 100213 | ** Return a blob which is a pointer to the cursor. |
| 100214 | */ |
| 100215 | sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); |
| 100216 | }else{ |
| 100217 | sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1)); |
| 100218 | } |
| 100219 | } |
| 100220 | return rc; |
| 100221 | } |
| 100222 | |
| 100223 | /* |
| 100224 | ** This function is the implementation of the xUpdate callback used by |
| 100225 | ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be |
| 100226 | ** inserted, updated or deleted. |
| @@ -99582,10 +100244,11 @@ | |
| 100244 | |
| 100245 | /* |
| 100246 | ** Implementation of xBegin() method. This is a no-op. |
| 100247 | */ |
| 100248 | static int fts3BeginMethod(sqlite3_vtab *pVtab){ |
| 100249 | UNUSED_PARAMETER(pVtab); |
| 100250 | assert( ((Fts3Table *)pVtab)->nPendingData==0 ); |
| 100251 | return SQLITE_OK; |
| 100252 | } |
| 100253 | |
| 100254 | /* |
| @@ -99592,10 +100255,11 @@ | |
| 100255 | ** Implementation of xCommit() method. This is a no-op. The contents of |
| 100256 | ** the pending-terms hash-table have already been flushed into the database |
| 100257 | ** by fts3SyncMethod(). |
| 100258 | */ |
| 100259 | static int fts3CommitMethod(sqlite3_vtab *pVtab){ |
| 100260 | UNUSED_PARAMETER(pVtab); |
| 100261 | assert( ((Fts3Table *)pVtab)->nPendingData==0 ); |
| 100262 | return SQLITE_OK; |
| 100263 | } |
| 100264 | |
| 100265 | /* |
| @@ -99670,10 +100334,12 @@ | |
| 100334 | int nVal, /* Size of argument array */ |
| 100335 | sqlite3_value **apVal /* Array of arguments */ |
| 100336 | ){ |
| 100337 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100338 | |
| 100339 | UNUSED_PARAMETER(nVal); |
| 100340 | |
| 100341 | assert( nVal==1 ); |
| 100342 | if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return; |
| 100343 | assert( pCsr ); |
| 100344 | sqlite3Fts3Offsets(pContext, pCsr); |
| 100345 | } |
| @@ -99693,10 +100359,12 @@ | |
| 100359 | sqlite3_value **apVal /* Array of arguments */ |
| 100360 | ){ |
| 100361 | int rc; /* Return code */ |
| 100362 | Fts3Table *p; /* Virtual table handle */ |
| 100363 | Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */ |
| 100364 | |
| 100365 | UNUSED_PARAMETER(nVal); |
| 100366 | |
| 100367 | assert( nVal==1 ); |
| 100368 | if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return; |
| 100369 | p = (Fts3Table *)pCursor->base.pVtab; |
| 100370 | assert( p ); |
| @@ -99734,10 +100402,15 @@ | |
| 100402 | { "snippet", fts3SnippetFunc }, |
| 100403 | { "offsets", fts3OffsetsFunc }, |
| 100404 | { "optimize", fts3OptimizeFunc }, |
| 100405 | }; |
| 100406 | int i; /* Iterator variable */ |
| 100407 | |
| 100408 | UNUSED_PARAMETER(pVtab); |
| 100409 | UNUSED_PARAMETER(nArg); |
| 100410 | UNUSED_PARAMETER(ppArg); |
| 100411 | |
| 100412 | for(i=0; i<SizeofArray(aOverload); i++){ |
| 100413 | if( strcmp(zName, aOverload[i].zName)==0 ){ |
| 100414 | *pxFunc = aOverload[i].xFunc; |
| 100415 | return 1; |
| 100416 | } |
| @@ -100150,11 +100823,11 @@ | |
| 100823 | pCursor = 0; |
| 100824 | } |
| 100825 | |
| 100826 | if( rc==SQLITE_DONE ){ |
| 100827 | int jj; |
| 100828 | char *zNew = NULL; |
| 100829 | int nNew = 0; |
| 100830 | int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase); |
| 100831 | nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(struct PhraseToken); |
| 100832 | p = fts3ReallocOrFree(p, nByte + nTemp); |
| 100833 | if( !p ){ |
| @@ -100209,11 +100882,11 @@ | |
| 100882 | const char *z, int n, /* Input string */ |
| 100883 | Fts3Expr **ppExpr, /* OUT: expression */ |
| 100884 | int *pnConsumed /* OUT: Number of bytes consumed */ |
| 100885 | ){ |
| 100886 | static const struct Fts3Keyword { |
| 100887 | char *z; /* Keyword text */ |
| 100888 | unsigned char n; /* Length of the keyword */ |
| 100889 | unsigned char parenOnly; /* Only valid in paren mode */ |
| 100890 | unsigned char eType; /* Keyword code */ |
| 100891 | } aKeyword[] = { |
| 100892 | { "OR" , 2, 0, FTSQUERY_OR }, |
| @@ -100279,11 +100952,11 @@ | |
| 100952 | } |
| 100953 | memset(pRet, 0, sizeof(Fts3Expr)); |
| 100954 | pRet->eType = pKey->eType; |
| 100955 | pRet->nNear = nNear; |
| 100956 | *ppExpr = pRet; |
| 100957 | *pnConsumed = (int)((zInput - z) + nKey); |
| 100958 | return SQLITE_OK; |
| 100959 | } |
| 100960 | |
| 100961 | /* Turns out that wasn't a keyword after all. This happens if the |
| 100962 | ** user has supplied a token such as "ORacle". Continue. |
| @@ -100299,18 +100972,18 @@ | |
| 100972 | pParse->nNest++; |
| 100973 | rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); |
| 100974 | if( rc==SQLITE_OK && !*ppExpr ){ |
| 100975 | rc = SQLITE_DONE; |
| 100976 | } |
| 100977 | *pnConsumed = (int)((zInput - z) + 1 + nConsumed); |
| 100978 | return rc; |
| 100979 | } |
| 100980 | |
| 100981 | /* Check for a close bracket. */ |
| 100982 | if( *zInput==')' ){ |
| 100983 | pParse->nNest--; |
| 100984 | *pnConsumed = (int)((zInput - z) + 1); |
| 100985 | return SQLITE_DONE; |
| 100986 | } |
| 100987 | } |
| 100988 | |
| 100989 | /* See if we are dealing with a quoted phrase. If this is the case, then |
| @@ -100318,11 +100991,11 @@ | |
| 100991 | ** for processing. This is easy to do, as fts3 has no syntax for escaping |
| 100992 | ** a quote character embedded in a string. |
| 100993 | */ |
| 100994 | if( *zInput=='"' ){ |
| 100995 | for(ii=1; ii<nInput && zInput[ii]!='"'; ii++); |
| 100996 | *pnConsumed = (int)((zInput - z) + ii + 1); |
| 100997 | if( ii==nInput ){ |
| 100998 | return SQLITE_ERROR; |
| 100999 | } |
| 101000 | return getNextString(pParse, &zInput[1], ii-1, ppExpr); |
| 101001 | } |
| @@ -100341,16 +101014,16 @@ | |
| 101014 | */ |
| 101015 | iCol = pParse->iDefaultCol; |
| 101016 | iColLen = 0; |
| 101017 | for(ii=0; ii<pParse->nCol; ii++){ |
| 101018 | const char *zStr = pParse->azCol[ii]; |
| 101019 | int nStr = (int)strlen(zStr); |
| 101020 | if( nInput>nStr && zInput[nStr]==':' |
| 101021 | && sqlite3_strnicmp(zStr, zInput, nStr)==0 |
| 101022 | ){ |
| 101023 | iCol = ii; |
| 101024 | iColLen = (int)((zInput - z) + nStr + 1); |
| 101025 | break; |
| 101026 | } |
| 101027 | } |
| 101028 | rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed); |
| 101029 | *pnConsumed += iColLen; |
| @@ -100612,11 +101285,11 @@ | |
| 101285 | if( z==0 ){ |
| 101286 | *ppExpr = 0; |
| 101287 | return SQLITE_OK; |
| 101288 | } |
| 101289 | if( n<0 ){ |
| 101290 | n = (int)strlen(z); |
| 101291 | } |
| 101292 | rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); |
| 101293 | |
| 101294 | /* Check for mismatched parenthesis */ |
| 101295 | if( rc==SQLITE_OK && sParse.nNest ){ |
| @@ -100666,11 +101339,11 @@ | |
| 101339 | } |
| 101340 | |
| 101341 | sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 101342 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 101343 | if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 101344 | memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); |
| 101345 | } |
| 101346 | } |
| 101347 | |
| 101348 | return sqlite3_finalize(pStmt); |
| 101349 | } |
| @@ -100849,125 +101522,10 @@ | |
| 101522 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 101523 | */ |
| 101524 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 101525 | |
| 101526 | |
| 101527 | |
| 101528 | /* |
| 101529 | ** Malloc and Free functions |
| 101530 | */ |
| 101531 | static void *fts3HashMalloc(int n){ |
| @@ -100989,11 +101547,11 @@ | |
| 101547 | ** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass |
| 101548 | ** determines what kind of key the hash table will use. "copyKey" is |
| 101549 | ** true if the hash table should make its own private copy of keys and |
| 101550 | ** false if it should just use the supplied pointer. |
| 101551 | */ |
| 101552 | SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){ |
| 101553 | assert( pNew!=0 ); |
| 101554 | assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); |
| 101555 | pNew->keyClass = keyClass; |
| 101556 | pNew->copyKey = copyKey; |
| 101557 | pNew->first = 0; |
| @@ -101123,28 +101681,31 @@ | |
| 101681 | |
| 101682 | |
| 101683 | /* Resize the hash table so that it cantains "new_size" buckets. |
| 101684 | ** "new_size" must be a power of 2. The hash table might fail |
| 101685 | ** to resize if sqliteMalloc() fails. |
| 101686 | ** |
| 101687 | ** Return non-zero if a memory allocation error occurs. |
| 101688 | */ |
| 101689 | static int fts3Rehash(Fts3Hash *pH, int new_size){ |
| 101690 | struct _fts3ht *new_ht; /* The new hash table */ |
| 101691 | Fts3HashElem *elem, *next_elem; /* For looping over existing elements */ |
| 101692 | int (*xHash)(const void*,int); /* The hash function */ |
| 101693 | |
| 101694 | assert( (new_size & (new_size-1))==0 ); |
| 101695 | new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); |
| 101696 | if( new_ht==0 ) return 1; |
| 101697 | fts3HashFree(pH->ht); |
| 101698 | pH->ht = new_ht; |
| 101699 | pH->htsize = new_size; |
| 101700 | xHash = ftsHashFunction(pH->keyClass); |
| 101701 | for(elem=pH->first, pH->first=0; elem; elem = next_elem){ |
| 101702 | int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); |
| 101703 | next_elem = elem->next; |
| 101704 | fts3HashInsertElement(pH, &new_ht[h], elem); |
| 101705 | } |
| 101706 | return 0; |
| 101707 | } |
| 101708 | |
| 101709 | /* This function (for internal use only) locates an element in an |
| 101710 | ** hash table that matches the given key. The hash for this key has |
| 101711 | ** already been computed and is passed as the 4th parameter. |
| @@ -101271,17 +101832,17 @@ | |
| 101832 | elem->data = data; |
| 101833 | } |
| 101834 | return old_data; |
| 101835 | } |
| 101836 | if( data==0 ) return 0; |
| 101837 | if( (pH->htsize==0 && fts3Rehash(pH,8)) |
| 101838 | || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2)) |
| 101839 | ){ |
| 101840 | pH->count = 0; |
| 101841 | return data; |
| 101842 | } |
| 101843 | assert( pH->htsize>0 ); |
| 101844 | new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) ); |
| 101845 | if( new_elem==0 ) return data; |
| 101846 | if( pH->copyKey && pKey!=0 ){ |
| 101847 | new_elem->pKey = fts3HashMalloc( nKey ); |
| 101848 | if( new_elem->pKey==0 ){ |
| @@ -101292,13 +101853,10 @@ | |
| 101853 | }else{ |
| 101854 | new_elem->pKey = (void*)pKey; |
| 101855 | } |
| 101856 | new_elem->nKey = nKey; |
| 101857 | pH->count++; |
| 101858 | assert( pH->htsize>0 ); |
| 101859 | assert( (pH->htsize & (pH->htsize-1))==0 ); |
| 101860 | h = hraw & (pH->htsize-1); |
| 101861 | fts3HashInsertElement(pH, &pH->ht[h], new_elem); |
| 101862 | new_elem->data = data; |
| @@ -101335,162 +101893,10 @@ | |
| 101893 | */ |
| 101894 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 101895 | |
| 101896 | |
| 101897 | |
| 101898 | |
| 101899 | /* |
| 101900 | ** Class derived from sqlite3_tokenizer |
| 101901 | */ |
| 101902 | typedef struct porter_tokenizer { |
| @@ -101508,23 +101914,23 @@ | |
| 101914 | int iToken; /* index of next token to be returned */ |
| 101915 | char *zToken; /* storage for current token */ |
| 101916 | int nAllocated; /* space allocated to zToken buffer */ |
| 101917 | } porter_tokenizer_cursor; |
| 101918 | |
| 101919 | |
| 101920 | /* |
| 101921 | ** Create a new tokenizer instance. |
| 101922 | */ |
| 101923 | static int porterCreate( |
| 101924 | int argc, const char * const *argv, |
| 101925 | sqlite3_tokenizer **ppTokenizer |
| 101926 | ){ |
| 101927 | porter_tokenizer *t; |
| 101928 | |
| 101929 | UNUSED_PARAMETER(argc); |
| 101930 | UNUSED_PARAMETER(argv); |
| 101931 | |
| 101932 | t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); |
| 101933 | if( t==NULL ) return SQLITE_NOMEM; |
| 101934 | memset(t, 0, sizeof(*t)); |
| 101935 | *ppTokenizer = &t->base; |
| 101936 | return SQLITE_OK; |
| @@ -101548,10 +101954,12 @@ | |
| 101954 | sqlite3_tokenizer *pTokenizer, /* The tokenizer */ |
| 101955 | const char *zInput, int nInput, /* String to be tokenized */ |
| 101956 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ |
| 101957 | ){ |
| 101958 | porter_tokenizer_cursor *c; |
| 101959 | |
| 101960 | UNUSED_PARAMETER(pTokenizer); |
| 101961 | |
| 101962 | c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); |
| 101963 | if( c==NULL ) return SQLITE_NOMEM; |
| 101964 | |
| 101965 | c->zInput = zInput; |
| @@ -101689,11 +102097,11 @@ | |
| 102097 | ** |
| 102098 | ** The text is reversed here. So we are really looking at |
| 102099 | ** the first two characters of z[]. |
| 102100 | */ |
| 102101 | static int doubleConsonant(const char *z){ |
| 102102 | return isConsonant(z) && z[0]==z[1]; |
| 102103 | } |
| 102104 | |
| 102105 | /* |
| 102106 | ** Return TRUE if the word ends with three letters which |
| 102107 | ** are consonant-vowel-consonent and where the final consonant |
| @@ -101702,14 +102110,14 @@ | |
| 102110 | ** The word is reversed here. So we are really checking the |
| 102111 | ** first three letters and the first one cannot be in [wxy]. |
| 102112 | */ |
| 102113 | static int star_oh(const char *z){ |
| 102114 | return |
| 102115 | isConsonant(z) && |
| 102116 | z[0]!='w' && z[0]!='x' && z[0]!='y' && |
| 102117 | isVowel(z+1) && |
| 102118 | isConsonant(z+2); |
| 102119 | } |
| 102120 | |
| 102121 | /* |
| 102122 | ** If the word ends with zFrom and xCond() is true for the stem |
| 102123 | ** of the word that preceeds the zFrom ending, then change the |
| @@ -101749,11 +102157,11 @@ | |
| 102157 | */ |
| 102158 | static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 102159 | int i, mx, j; |
| 102160 | int hasDigit = 0; |
| 102161 | for(i=0; i<nIn; i++){ |
| 102162 | char c = zIn[i]; |
| 102163 | if( c>='A' && c<='Z' ){ |
| 102164 | zOut[i] = c - 'A' + 'a'; |
| 102165 | }else{ |
| 102166 | if( c>='0' && c<='9' ) hasDigit = 1; |
| 102167 | zOut[i] = c; |
| @@ -101793,21 +102201,21 @@ | |
| 102201 | ** |
| 102202 | ** Stemming never increases the length of the word. So there is |
| 102203 | ** no chance of overflowing the zOut buffer. |
| 102204 | */ |
| 102205 | static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 102206 | int i, j; |
| 102207 | char zReverse[28]; |
| 102208 | char *z, *z2; |
| 102209 | if( nIn<3 || nIn>=sizeof(zReverse)-7 ){ |
| 102210 | /* The word is too big or too small for the porter stemmer. |
| 102211 | ** Fallback to the copy stemmer */ |
| 102212 | copy_stemmer(zIn, nIn, zOut, pnOut); |
| 102213 | return; |
| 102214 | } |
| 102215 | for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){ |
| 102216 | char c = zIn[i]; |
| 102217 | if( c>='A' && c<='Z' ){ |
| 102218 | zReverse[j] = c + 'a' - 'A'; |
| 102219 | }else if( c>='a' && c<='z' ){ |
| 102220 | zReverse[j] = c; |
| 102221 | }else{ |
| @@ -102002,11 +102410,11 @@ | |
| 102410 | } |
| 102411 | |
| 102412 | /* z[] is now the stemmed word in reverse order. Flip it back |
| 102413 | ** around into forward order and return. |
| 102414 | */ |
| 102415 | *pnOut = i = (int)strlen(z); |
| 102416 | zOut[i] = 0; |
| 102417 | while( *z ){ |
| 102418 | zOut[--i] = *(z++); |
| 102419 | } |
| 102420 | } |
| @@ -102240,11 +102648,11 @@ | |
| 102648 | z1++; |
| 102649 | } |
| 102650 | } |
| 102651 | } |
| 102652 | |
| 102653 | *pn = (int)(z2-z1); |
| 102654 | return z1; |
| 102655 | } |
| 102656 | |
| 102657 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( |
| 102658 | Fts3Hash *pHash, /* Tokenizer hash table */ |
| @@ -102278,24 +102686,24 @@ | |
| 102686 | |
| 102687 | z = (char *)sqlite3Fts3NextToken(zCopy, &n); |
| 102688 | z[n] = '\0'; |
| 102689 | sqlite3Fts3Dequote(z); |
| 102690 | |
| 102691 | m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, (int)strlen(z)+1); |
| 102692 | if( !m ){ |
| 102693 | *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); |
| 102694 | rc = SQLITE_ERROR; |
| 102695 | }else{ |
| 102696 | char const **aArg = 0; |
| 102697 | int iArg = 0; |
| 102698 | z = &z[n+1]; |
| 102699 | while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){ |
| 102700 | int nNew = sizeof(char *)*(iArg+1); |
| 102701 | char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew); |
| 102702 | if( !aNew ){ |
| 102703 | sqlite3_free(zCopy); |
| 102704 | sqlite3_free((void *)aArg); |
| 102705 | return SQLITE_NOMEM; |
| 102706 | } |
| 102707 | aArg = aNew; |
| 102708 | aArg[iArg++] = z; |
| 102709 | z[n] = '\0'; |
| @@ -102303,15 +102711,15 @@ | |
| 102711 | z = &z[n+1]; |
| 102712 | } |
| 102713 | rc = m->xCreate(iArg, aArg, ppTok); |
| 102714 | assert( rc!=SQLITE_OK || *ppTok ); |
| 102715 | if( rc!=SQLITE_OK ){ |
| 102716 | *pzErr = sqlite3_mprintf("unknown tokenizer"); |
| 102717 | }else{ |
| 102718 | (*ppTok)->pModule = m; |
| 102719 | } |
| 102720 | sqlite3_free((void *)aArg); |
| 102721 | } |
| 102722 | |
| 102723 | sqlite3_free(zCopy); |
| 102724 | return rc; |
| 102725 | } |
| @@ -102473,11 +102881,11 @@ | |
| 102881 | } |
| 102882 | |
| 102883 | sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 102884 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 102885 | if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 102886 | memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); |
| 102887 | } |
| 102888 | } |
| 102889 | |
| 102890 | return sqlite3_finalize(pStmt); |
| 102891 | } |
| @@ -102509,10 +102917,13 @@ | |
| 102917 | ){ |
| 102918 | int rc; |
| 102919 | const sqlite3_tokenizer_module *p1; |
| 102920 | const sqlite3_tokenizer_module *p2; |
| 102921 | sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); |
| 102922 | |
| 102923 | UNUSED_PARAMETER(argc); |
| 102924 | UNUSED_PARAMETER(argv); |
| 102925 | |
| 102926 | /* Test the query function */ |
| 102927 | sqlite3Fts3SimpleTokenizerModule(&p1); |
| 102928 | rc = queryTokenizer(db, "simple", &p2); |
| 102929 | assert( rc==SQLITE_OK ); |
| @@ -102569,17 +102980,17 @@ | |
| 102980 | if( !zTest || !zTest2 ){ |
| 102981 | rc = SQLITE_NOMEM; |
| 102982 | } |
| 102983 | #endif |
| 102984 | |
| 102985 | if( SQLITE_OK!=rc |
| 102986 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) |
| 102987 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) |
| 102988 | #ifdef SQLITE_TEST |
| 102989 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) |
| 102990 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) |
| 102991 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) |
| 102992 | #endif |
| 102993 | ); |
| 102994 | |
| 102995 | sqlite3_free(zTest); |
| 102996 | sqlite3_free(zTest2); |
| @@ -102633,13 +103044,10 @@ | |
| 103044 | char *pToken; /* storage for current token */ |
| 103045 | int nTokenAllocated; /* space allocated to zToken buffer */ |
| 103046 | } simple_tokenizer_cursor; |
| 103047 | |
| 103048 | |
| 103049 | static int simpleDelim(simple_tokenizer *t, unsigned char c){ |
| 103050 | return c<0x80 && t->delim[c]; |
| 103051 | } |
| 103052 | |
| 103053 | /* |
| @@ -102659,11 +103067,11 @@ | |
| 103067 | ** else we need to reindex. One solution would be a meta-table to |
| 103068 | ** track such information in the database, then we'd only want this |
| 103069 | ** information on the initial create. |
| 103070 | */ |
| 103071 | if( argc>1 ){ |
| 103072 | int i, n = (int)strlen(argv[1]); |
| 103073 | for(i=0; i<n; i++){ |
| 103074 | unsigned char ch = argv[1][i]; |
| 103075 | /* We explicitly don't support UTF-8 delimiters for now. */ |
| 103076 | if( ch>=0x80 ){ |
| 103077 | sqlite3_free(t); |
| @@ -102673,11 +103081,11 @@ | |
| 103081 | } |
| 103082 | } else { |
| 103083 | /* Mark non-alphanumeric ASCII characters as delimiters */ |
| 103084 | int i; |
| 103085 | for(i=1; i<0x80; i++){ |
| 103086 | t->delim[i] = !isalnum(i) ? -1 : 0; |
| 103087 | } |
| 103088 | } |
| 103089 | |
| 103090 | *ppTokenizer = &t->base; |
| 103091 | return SQLITE_OK; |
| @@ -102701,10 +103109,12 @@ | |
| 103109 | sqlite3_tokenizer *pTokenizer, /* The tokenizer */ |
| 103110 | const char *pInput, int nBytes, /* String to be tokenized */ |
| 103111 | sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ |
| 103112 | ){ |
| 103113 | simple_tokenizer_cursor *c; |
| 103114 | |
| 103115 | UNUSED_PARAMETER(pTokenizer); |
| 103116 | |
| 103117 | c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); |
| 103118 | if( c==NULL ) return SQLITE_NOMEM; |
| 103119 | |
| 103120 | c->pInput = pInput; |
| @@ -102775,11 +103185,11 @@ | |
| 103185 | for(i=0; i<n; i++){ |
| 103186 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 103187 | ** case-insensitivity. |
| 103188 | */ |
| 103189 | unsigned char ch = p[iStartOffset+i]; |
| 103190 | c->pToken[i] = (char)(ch<0x80 ? tolower(ch) : ch); |
| 103191 | } |
| 103192 | *ppToken = c->pToken; |
| 103193 | *pnBytes = n; |
| 103194 | *piStartOffset = iStartOffset; |
| 103195 | *piEndOffset = c->iOffset; |
| @@ -102837,13 +103247,10 @@ | |
| 103247 | */ |
| 103248 | |
| 103249 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 103250 | |
| 103251 | |
| 103252 | typedef struct PendingList PendingList; |
| 103253 | typedef struct SegmentNode SegmentNode; |
| 103254 | typedef struct SegmentWriter SegmentWriter; |
| 103255 | |
| 103256 | /* |
| @@ -103092,20 +103499,22 @@ | |
| 103499 | sqlite3_stmt *pStmt; |
| 103500 | int rc = fts3SqlStmt(p, SQL_GET_BLOCK, &pStmt, 0); |
| 103501 | if( rc!=SQLITE_OK ) return rc; |
| 103502 | sqlite3_reset(pStmt); |
| 103503 | |
| 103504 | if( pzBlock ){ |
| 103505 | sqlite3_bind_int64(pStmt, 1, iBlock); |
| 103506 | rc = sqlite3_step(pStmt); |
| 103507 | if( rc!=SQLITE_ROW ){ |
| 103508 | return SQLITE_CORRUPT; |
| 103509 | } |
| 103510 | |
| 103511 | *pnBlock = sqlite3_column_bytes(pStmt, 0); |
| 103512 | *pzBlock = (char *)sqlite3_column_blob(pStmt, 0); |
| 103513 | if( !*pzBlock ){ |
| 103514 | return SQLITE_NOMEM; |
| 103515 | } |
| 103516 | } |
| 103517 | return SQLITE_OK; |
| 103518 | } |
| 103519 | |
| 103520 | /* |
| @@ -103222,11 +103631,13 @@ | |
| 103631 | p->iLastPos = 0; |
| 103632 | } |
| 103633 | if( iCol>=0 ){ |
| 103634 | assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) ); |
| 103635 | rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos); |
| 103636 | if( rc==SQLITE_OK ){ |
| 103637 | p->iLastPos = iPos; |
| 103638 | } |
| 103639 | } |
| 103640 | |
| 103641 | pendinglistappend_out: |
| 103642 | *pRc = rc; |
| 103643 | if( p!=*pp ){ |
| @@ -103371,11 +103782,10 @@ | |
| 103782 | Fts3Table *p, /* Full-text table */ |
| 103783 | sqlite3_value **apVal, /* Array of values to insert */ |
| 103784 | sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ |
| 103785 | ){ |
| 103786 | int rc; /* Return code */ |
| 103787 | sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */ |
| 103788 | |
| 103789 | /* Locate the statement handle used to insert data into the %_content |
| 103790 | ** table. The SQL for this statement is: |
| 103791 | ** |
| @@ -103394,14 +103804,20 @@ | |
| 103804 | ** Which is a problem, since "rowid" and "docid" are aliases for the |
| 103805 | ** same value. For example: |
| 103806 | ** |
| 103807 | ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2); |
| 103808 | ** |
| 103809 | ** In FTS3, this is an error. It is an error to specify non-NULL values |
| 103810 | ** for both docid and some other rowid alias. |
| 103811 | */ |
| 103812 | if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){ |
| 103813 | if( SQLITE_NULL==sqlite3_value_type(apVal[0]) |
| 103814 | && SQLITE_NULL!=sqlite3_value_type(apVal[1]) |
| 103815 | ){ |
| 103816 | /* A rowid/docid conflict. */ |
| 103817 | return SQLITE_ERROR; |
| 103818 | } |
| 103819 | rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); |
| 103820 | if( rc!=SQLITE_OK ) return rc; |
| 103821 | } |
| 103822 | |
| 103823 | /* Execute the statement to insert the record. Set *piDocid to the |
| @@ -103457,13 +103873,15 @@ | |
| 103873 | sqlite3_reset(pSelect); |
| 103874 | return rc; |
| 103875 | } |
| 103876 | } |
| 103877 | } |
| 103878 | rc = sqlite3_reset(pSelect); |
| 103879 | }else{ |
| 103880 | sqlite3_reset(pSelect); |
| 103881 | } |
| 103882 | return rc; |
| 103883 | } |
| 103884 | |
| 103885 | /* |
| 103886 | ** Forward declaration to account for the circular dependency between |
| 103887 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| @@ -103486,18 +103904,18 @@ | |
| 103904 | ** returned. Otherwise, an SQLite error code is returned. |
| 103905 | */ |
| 103906 | static int fts3AllocateSegdirIdx(Fts3Table *p, int iLevel, int *piIdx){ |
| 103907 | int rc; /* Return Code */ |
| 103908 | sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ |
| 103909 | int iNext = 0; /* Result of query pNextIdx */ |
| 103910 | |
| 103911 | /* Set variable iNext to the next available segdir index at level iLevel. */ |
| 103912 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); |
| 103913 | if( rc==SQLITE_OK ){ |
| 103914 | sqlite3_bind_int(pNextIdx, 1, iLevel); |
| 103915 | if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ |
| 103916 | iNext = sqlite3_column_int(pNextIdx, 0); |
| 103917 | } |
| 103918 | rc = sqlite3_reset(pNextIdx); |
| 103919 | } |
| 103920 | |
| 103921 | if( rc==SQLITE_OK ){ |
| @@ -103611,11 +104029,11 @@ | |
| 104029 | /* If required, populate the output variables with a pointer to and the |
| 104030 | ** size of the previous offset-list. |
| 104031 | */ |
| 104032 | if( ppOffsetList ){ |
| 104033 | *ppOffsetList = pReader->pOffsetList; |
| 104034 | *pnOffsetList = (int)(p - pReader->pOffsetList - 1); |
| 104035 | } |
| 104036 | |
| 104037 | /* If there are no more entries in the doclist, set pOffsetList to |
| 104038 | ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and |
| 104039 | ** Fts3SegReader.pOffsetList to point to the next offset list before |
| @@ -103683,12 +104101,10 @@ | |
| 104101 | /* The entire segment is stored in the root node. */ |
| 104102 | pReader->aNode = (char *)&pReader[1]; |
| 104103 | pReader->nNode = nRoot; |
| 104104 | memcpy(pReader->aNode, zRoot, nRoot); |
| 104105 | }else{ |
| 104106 | /* If the text of the SQL statement to iterate through a contiguous |
| 104107 | ** set of entries in the %_segments table has not yet been composed, |
| 104108 | ** compose it now. |
| 104109 | */ |
| 104110 | if( !p->zSelectLeaves ){ |
| @@ -103966,10 +104382,11 @@ | |
| 104382 | int nPrev, /* Size of buffer zPrev in bytes */ |
| 104383 | const char *zNext, /* Buffer containing next term */ |
| 104384 | int nNext /* Size of buffer zNext in bytes */ |
| 104385 | ){ |
| 104386 | int n; |
| 104387 | UNUSED_PARAMETER(nNext); |
| 104388 | for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++); |
| 104389 | return n; |
| 104390 | } |
| 104391 | |
| 104392 | /* |
| @@ -103998,17 +104415,17 @@ | |
| 104415 | |
| 104416 | nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); |
| 104417 | nSuffix = nTerm-nPrefix; |
| 104418 | |
| 104419 | nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; |
| 104420 | if( nReq<=p->nNodeSize || !pTree->zTerm ){ |
| 104421 | |
| 104422 | if( nReq>p->nNodeSize ){ |
| 104423 | /* An unusual case: this is the first term to be added to the node |
| 104424 | ** and the static node buffer (p->nNodeSize bytes) is not large |
| 104425 | ** enough. Use a separately malloced buffer instead This wastes |
| 104426 | ** p->nNodeSize bytes, but since this scenario only comes about when |
| 104427 | ** the database contain two terms that share a prefix of almost 2KB, |
| 104428 | ** this is not expected to be a serious problem. |
| 104429 | */ |
| 104430 | assert( pTree->aData==(char *)&pTree[1] ); |
| 104431 | pTree->aData = (char *)sqlite3_malloc(nReq); |
| @@ -104053,11 +104470,11 @@ | |
| 104470 | ** |
| 104471 | ** Otherwise, the term is not added to the new node, it is left empty for |
| 104472 | ** now. Instead, the term is inserted into the parent of pTree. If pTree |
| 104473 | ** has no parent, one is created here. |
| 104474 | */ |
| 104475 | pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); |
| 104476 | if( !pNew ){ |
| 104477 | return SQLITE_NOMEM; |
| 104478 | } |
| 104479 | memset(pNew, 0, sizeof(SegmentNode)); |
| 104480 | pNew->nData = 1 + FTS3_VARINT_MAX; |
| @@ -104206,13 +104623,13 @@ | |
| 104623 | if( !pWriter ) return SQLITE_NOMEM; |
| 104624 | memset(pWriter, 0, sizeof(SegmentWriter)); |
| 104625 | *ppWriter = pWriter; |
| 104626 | |
| 104627 | /* Allocate a buffer in which to accumulate data */ |
| 104628 | pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize); |
| 104629 | if( !pWriter->aData ) return SQLITE_NOMEM; |
| 104630 | pWriter->nSize = p->nNodeSize; |
| 104631 | |
| 104632 | /* Find the next free blockid in the %_segments table */ |
| 104633 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); |
| 104634 | if( rc!=SQLITE_OK ) return rc; |
| 104635 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| @@ -104232,11 +104649,11 @@ | |
| 104649 | sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ |
| 104650 | nSuffix + /* Term suffix */ |
| 104651 | sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ |
| 104652 | nDoclist; /* Doclist data */ |
| 104653 | |
| 104654 | if( nData>0 && nData+nReq>p->nNodeSize ){ |
| 104655 | int rc; |
| 104656 | |
| 104657 | /* The current leaf node is full. Write it out to the database. */ |
| 104658 | rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); |
| 104659 | if( rc!=SQLITE_OK ) return rc; |
| @@ -104326,14 +104743,14 @@ | |
| 104743 | int iLevel, /* Value for 'level' column of %_segdir */ |
| 104744 | int iIdx /* Value for 'idx' column of %_segdir */ |
| 104745 | ){ |
| 104746 | int rc; /* Return code */ |
| 104747 | if( pWriter->pTree ){ |
| 104748 | sqlite3_int64 iLast = 0; /* Largest block id written to database */ |
| 104749 | sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ |
| 104750 | char *zRoot = NULL; /* Pointer to buffer containing root node */ |
| 104751 | int nRoot = 0; /* Size of buffer zRoot */ |
| 104752 | |
| 104753 | iLastLeaf = pWriter->iFree; |
| 104754 | rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); |
| 104755 | if( rc==SQLITE_OK ){ |
| 104756 | rc = fts3NodeWrite(p, pWriter->pTree, 1, |
| @@ -104502,15 +104919,15 @@ | |
| 104919 | while( 1 ){ |
| 104920 | char c = 0; |
| 104921 | while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80; |
| 104922 | |
| 104923 | if( iCol==iCurrent ){ |
| 104924 | nList = (int)(p - pList); |
| 104925 | break; |
| 104926 | } |
| 104927 | |
| 104928 | nList -= (int)(p - pList); |
| 104929 | pList = p; |
| 104930 | if( nList==0 ){ |
| 104931 | break; |
| 104932 | } |
| 104933 | p = &pList[1]; |
| @@ -104577,10 +104994,15 @@ | |
| 104994 | |
| 104995 | int isIgnoreEmpty = (pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); |
| 104996 | int isRequirePos = (pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); |
| 104997 | int isColFilter = (pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); |
| 104998 | int isPrefix = (pFilter->flags & FTS3_SEGMENT_PREFIX); |
| 104999 | |
| 105000 | /* If there are zero segments, this function is a no-op. This scenario |
| 105001 | ** comes about only when reading from an empty database. |
| 105002 | */ |
| 105003 | if( nSegment==0 ) goto finished; |
| 105004 | |
| 105005 | /* If the Fts3SegFilter defines a specific term (or term prefix) to search |
| 105006 | ** for, then advance each segment iterator until it points to a term of |
| 105007 | ** equal or greater value than the specified term. This prevents many |
| 105008 | ** unnecessary merge/sort operations for the case where single segment |
| @@ -104906,11 +105328,11 @@ | |
| 105328 | sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ |
| 105329 | ){ |
| 105330 | Fts3Table *p = (Fts3Table *)pVtab; |
| 105331 | int rc = SQLITE_OK; /* Return Code */ |
| 105332 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 105333 | sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */ |
| 105334 | |
| 105335 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 105336 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 105337 | int isEmpty; |
| 105338 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| @@ -104953,13 +105375,22 @@ | |
| 105375 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| 105376 | ** merge all segments in the database (including the new segment, if |
| 105377 | ** there was any data to flush) into a single segment. |
| 105378 | */ |
| 105379 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ |
| 105380 | int rc; |
| 105381 | rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); |
| 105382 | if( rc==SQLITE_OK ){ |
| 105383 | rc = sqlite3Fts3PendingTermsFlush(p); |
| 105384 | if( rc==SQLITE_OK ){ |
| 105385 | rc = fts3SegmentMerge(p, -1); |
| 105386 | } |
| 105387 | if( rc==SQLITE_OK ){ |
| 105388 | rc = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); |
| 105389 | }else{ |
| 105390 | sqlite3_exec(p->db, "ROLLBACK TO fts3 ; RELEASE fts3", 0, 0, 0); |
| 105391 | } |
| 105392 | } |
| 105393 | return rc; |
| 105394 | } |
| 105395 | |
| 105396 | #endif |
| @@ -104991,14 +105422,14 @@ | |
| 105422 | struct Snippet { |
| 105423 | int nMatch; /* Total number of matches */ |
| 105424 | int nAlloc; /* Space allocated for aMatch[] */ |
| 105425 | struct snippetMatch { /* One entry for each matching term */ |
| 105426 | char snStatus; /* Status flag for use while constructing snippets */ |
| 105427 | short int nByte; /* Number of bytes in the term */ |
| 105428 | short int iCol; /* The column that contains the match */ |
| 105429 | short int iTerm; /* The index in Query.pTerms[] of the matching term */ |
| 105430 | int iToken; /* The index of the matching document token */ |
| 105431 | int iStart; /* The offset to the first character of the term */ |
| 105432 | } *aMatch; /* Points to space obtained from malloc */ |
| 105433 | char *zOffset; /* Text rendering of aMatch[] */ |
| 105434 | int nOffset; /* strlen(zOffset) */ |
| 105435 | char *zSnippet; /* Snippet text */ |
| @@ -105008,171 +105439,125 @@ | |
| 105439 | |
| 105440 | /* It is not safe to call isspace(), tolower(), or isalnum() on |
| 105441 | ** hi-bit-set characters. This is the same solution used in the |
| 105442 | ** tokenizer. |
| 105443 | */ |
| 105444 | static int fts3snippetIsspace(char c){ |
| 105445 | return (c&0x80)==0 ? isspace(c) : 0; |
| 105446 | } |
| 105447 | |
| 105448 | |
| 105449 | /* |
| 105450 | ** A StringBuffer object holds a zero-terminated string that grows |
| 105451 | ** arbitrarily by appending. Space to hold the string is obtained |
| 105452 | ** from sqlite3_malloc(). After any memory allocation failure, |
| 105453 | ** StringBuffer.z is set to NULL and no further allocation is attempted. |
| 105454 | */ |
| 105455 | typedef struct StringBuffer { |
| 105456 | char *z; /* Text of the string. Space from malloc. */ |
| 105457 | int nUsed; /* Number bytes of z[] used, not counting \000 terminator */ |
| 105458 | int nAlloc; /* Bytes allocated for z[] */ |
| 105459 | } StringBuffer; |
| 105460 | |
| 105461 | |
| 105462 | /* |
| 105463 | ** Initialize a new StringBuffer. |
| 105464 | */ |
| 105465 | static void fts3SnippetSbInit(StringBuffer *p){ |
| 105466 | p->nAlloc = 100; |
| 105467 | p->nUsed = 0; |
| 105468 | p->z = sqlite3_malloc( p->nAlloc ); |
| 105469 | } |
| 105470 | |
| 105471 | /* |
| 105472 | ** Append text to the string buffer. |
| 105473 | */ |
| 105474 | static void fts3SnippetAppend(StringBuffer *p, const char *zNew, int nNew){ |
| 105475 | if( p->z==0 ) return; |
| 105476 | if( nNew<0 ) nNew = (int)strlen(zNew); |
| 105477 | if( p->nUsed + nNew >= p->nAlloc ){ |
| 105478 | int nAlloc; |
| 105479 | char *zNew; |
| 105480 | |
| 105481 | nAlloc = p->nUsed + nNew + p->nAlloc; |
| 105482 | zNew = sqlite3_realloc(p->z, nAlloc); |
| 105483 | if( zNew==0 ){ |
| 105484 | sqlite3_free(p->z); |
| 105485 | p->z = 0; |
| 105486 | return; |
| 105487 | } |
| 105488 | p->z = zNew; |
| 105489 | p->nAlloc = nAlloc; |
| 105490 | } |
| 105491 | memcpy(&p->z[p->nUsed], zNew, nNew); |
| 105492 | p->nUsed += nNew; |
| 105493 | p->z[p->nUsed] = 0; |
| 105494 | } |
| 105495 | |
| 105496 | /* If the StringBuffer ends in something other than white space, add a |
| 105497 | ** single space character to the end. |
| 105498 | */ |
| 105499 | static void fts3SnippetAppendWhiteSpace(StringBuffer *p){ |
| 105500 | if( p->z && p->nUsed && !fts3snippetIsspace(p->z[p->nUsed-1]) ){ |
| 105501 | fts3SnippetAppend(p, " ", 1); |
| 105502 | } |
| 105503 | } |
| 105504 | |
| 105505 | /* Remove white space from the end of the StringBuffer */ |
| 105506 | static void fts3SnippetTrimWhiteSpace(StringBuffer *p){ |
| 105507 | if( p->z ){ |
| 105508 | while( p->nUsed && fts3snippetIsspace(p->z[p->nUsed-1]) ){ |
| 105509 | p->nUsed--; |
| 105510 | } |
| 105511 | p->z[p->nUsed] = 0; |
| 105512 | } |
| 105513 | } |
| 105514 | |
| 105515 | /* |
| 105516 | ** Release all memory associated with the Snippet structure passed as |
| 105517 | ** an argument. |
| 105518 | */ |
| 105519 | static void fts3SnippetFree(Snippet *p){ |
| 105520 | if( p ){ |
| 105521 | sqlite3_free(p->aMatch); |
| 105522 | sqlite3_free(p->zOffset); |
| 105523 | sqlite3_free(p->zSnippet); |
| 105524 | sqlite3_free(p); |
| 105525 | } |
| 105526 | } |
| 105527 | |
| 105528 | /* |
| 105529 | ** Append a single entry to the p->aMatch[] log. |
| 105530 | */ |
| 105531 | static int snippetAppendMatch( |
| 105532 | Snippet *p, /* Append the entry to this snippet */ |
| 105533 | int iCol, int iTerm, /* The column and query term */ |
| 105534 | int iToken, /* Matching token in document */ |
| 105535 | int iStart, int nByte /* Offset and size of the match */ |
| 105536 | ){ |
| 105537 | int i; |
| 105538 | struct snippetMatch *pMatch; |
| 105539 | if( p->nMatch+1>=p->nAlloc ){ |
| 105540 | struct snippetMatch *pNew; |
| 105541 | p->nAlloc = p->nAlloc*2 + 10; |
| 105542 | pNew = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); |
| 105543 | if( pNew==0 ){ |
| 105544 | p->aMatch = 0; |
| 105545 | p->nMatch = 0; |
| 105546 | p->nAlloc = 0; |
| 105547 | return SQLITE_NOMEM; |
| 105548 | } |
| 105549 | p->aMatch = pNew; |
| 105550 | } |
| 105551 | i = p->nMatch++; |
| 105552 | pMatch = &p->aMatch[i]; |
| 105553 | pMatch->iCol = (short)iCol; |
| 105554 | pMatch->iTerm = (short)iTerm; |
| 105555 | pMatch->iToken = iToken; |
| 105556 | pMatch->iStart = iStart; |
| 105557 | pMatch->nByte = (short)nByte; |
| 105558 | return SQLITE_OK; |
| 105559 | } |
| 105560 | |
| 105561 | /* |
| 105562 | ** Sizing information for the circular buffer used in snippetOffsetsOfColumn() |
| 105563 | */ |
| @@ -105242,11 +105627,11 @@ | |
| 105627 | |
| 105628 | /* |
| 105629 | ** Add entries to pSnippet->aMatch[] for every match that occurs against |
| 105630 | ** document zDoc[0..nDoc-1] which is stored in column iColumn. |
| 105631 | */ |
| 105632 | static int snippetOffsetsOfColumn( |
| 105633 | Fts3Cursor *pCur, /* The fulltest search cursor */ |
| 105634 | Snippet *pSnippet, /* The Snippet object to be filled in */ |
| 105635 | int iColumn, /* Index of fulltext table column */ |
| 105636 | const char *zDoc, /* Text of the fulltext table column */ |
| 105637 | int nDoc /* Length of zDoc in bytes */ |
| @@ -105272,15 +105657,16 @@ | |
| 105657 | pVtab = (Fts3Table *)pCur->base.pVtab; |
| 105658 | nColumn = pVtab->nColumn; |
| 105659 | pTokenizer = pVtab->pTokenizer; |
| 105660 | pTModule = pTokenizer->pModule; |
| 105661 | rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); |
| 105662 | if( rc ) return rc; |
| 105663 | pTCursor->pTokenizer = pTokenizer; |
| 105664 | |
| 105665 | prevMatch = 0; |
| 105666 | while( (rc = pTModule->xNext(pTCursor, &zToken, &nToken, |
| 105667 | &iBegin, &iEnd, &iPos))==SQLITE_OK ){ |
| 105668 | Fts3Expr *pIter = pCur->pExpr; |
| 105669 | int iIter = -1; |
| 105670 | iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; |
| 105671 | iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; |
| 105672 | match = 0; |
| @@ -105301,19 +105687,22 @@ | |
| 105687 | if( iIter>0 && (prevMatch & (1<<i))==0 ) continue; |
| 105688 | match |= 1<<i; |
| 105689 | if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){ |
| 105690 | for(j=nPhrase-1; j>=0; j--){ |
| 105691 | int k = (iRotor-j) & FTS3_ROTOR_MASK; |
| 105692 | rc = snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, |
| 105693 | iRotorBegin[k], iRotorLen[k]); |
| 105694 | if( rc ) goto end_offsets_of_column; |
| 105695 | } |
| 105696 | } |
| 105697 | } |
| 105698 | prevMatch = match<<1; |
| 105699 | iRotor++; |
| 105700 | } |
| 105701 | end_offsets_of_column: |
| 105702 | pTModule->xClose(pTCursor); |
| 105703 | return rc==SQLITE_DONE ? SQLITE_OK : rc; |
| 105704 | } |
| 105705 | |
| 105706 | /* |
| 105707 | ** Remove entries from the pSnippet structure to account for the NEAR |
| 105708 | ** operator. When this is called, pSnippet contains the list of token |
| @@ -105445,16 +105834,19 @@ | |
| 105834 | /* |
| 105835 | ** Compute all offsets for the current row of the query. |
| 105836 | ** If the offsets have already been computed, this routine is a no-op. |
| 105837 | */ |
| 105838 | static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){ |
| 105839 | Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; /* The FTS3 virtual table */ |
| 105840 | int nColumn; /* Number of columns. Docid does count */ |
| 105841 | int iColumn; /* Index of of a column */ |
| 105842 | int i; /* Loop index */ |
| 105843 | int iFirst; /* First column to search */ |
| 105844 | int iLast; /* Last coumn to search */ |
| 105845 | int iTerm = 0; |
| 105846 | Snippet *pSnippet; |
| 105847 | int rc = SQLITE_OK; |
| 105848 | |
| 105849 | if( pCsr->pExpr==0 ){ |
| 105850 | return SQLITE_OK; |
| 105851 | } |
| 105852 | |
| @@ -105464,33 +105856,37 @@ | |
| 105856 | return SQLITE_NOMEM; |
| 105857 | } |
| 105858 | memset(pSnippet, 0, sizeof(Snippet)); |
| 105859 | |
| 105860 | nColumn = p->nColumn; |
| 105861 | iColumn = (pCsr->eSearch - 2); |
| 105862 | if( iColumn<0 || iColumn>=nColumn ){ |
| 105863 | /* Look for matches over all columns of the full-text index */ |
| 105864 | iFirst = 0; |
| 105865 | iLast = nColumn-1; |
| 105866 | }else{ |
| 105867 | /* Look for matches in the iColumn-th column of the index only */ |
| 105868 | iFirst = iColumn; |
| 105869 | iLast = iColumn; |
| 105870 | } |
| 105871 | for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ |
| 105872 | const char *zDoc; |
| 105873 | int nDoc; |
| 105874 | zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1); |
| 105875 | nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1); |
| 105876 | if( zDoc==0 && sqlite3_column_type(pCsr->pStmt, i+1)!=SQLITE_NULL ){ |
| 105877 | rc = SQLITE_NOMEM; |
| 105878 | }else{ |
| 105879 | rc = snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc); |
| 105880 | } |
| 105881 | } |
| 105882 | |
| 105883 | while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){ |
| 105884 | iTerm = 0; |
| 105885 | } |
| 105886 | |
| 105887 | return rc; |
| 105888 | } |
| 105889 | |
| 105890 | /* |
| 105891 | ** Convert the information in the aMatch[] array of the snippet |
| 105892 | ** into the string zOffset[0..nOffset-1]. This string is used as |
| @@ -105500,11 +105896,11 @@ | |
| 105896 | int i; |
| 105897 | int cnt = 0; |
| 105898 | StringBuffer sb; |
| 105899 | char zBuf[200]; |
| 105900 | if( p->zOffset ) return; |
| 105901 | fts3SnippetSbInit(&sb); |
| 105902 | for(i=0; i<p->nMatch; i++){ |
| 105903 | struct snippetMatch *pMatch = &p->aMatch[i]; |
| 105904 | if( pMatch->iTerm>=0 ){ |
| 105905 | /* If snippetMatch.iTerm is less than 0, then the match was |
| 105906 | ** discarded as part of processing the NEAR operator (see the |
| @@ -105512,16 +105908,16 @@ | |
| 105908 | ** it in this case |
| 105909 | */ |
| 105910 | zBuf[0] = ' '; |
| 105911 | sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d", |
| 105912 | pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte); |
| 105913 | fts3SnippetAppend(&sb, zBuf, -1); |
| 105914 | cnt++; |
| 105915 | } |
| 105916 | } |
| 105917 | p->zOffset = sb.z; |
| 105918 | p->nOffset = sb.z ? sb.nUsed : 0; |
| 105919 | } |
| 105920 | |
| 105921 | /* |
| 105922 | ** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set |
| 105923 | ** of matching words some of which might be in zDoc. zDoc is column |
| @@ -105544,11 +105940,11 @@ | |
| 105940 | return 0; |
| 105941 | } |
| 105942 | if( iBreak>=nDoc-10 ){ |
| 105943 | return nDoc; |
| 105944 | } |
| 105945 | for(i=0; ALWAYS(i<nMatch) && aMatch[i].iCol<iCol; i++){} |
| 105946 | while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; } |
| 105947 | if( i<nMatch ){ |
| 105948 | if( aMatch[i].iStart<iBreak+10 ){ |
| 105949 | return aMatch[i].iStart; |
| 105950 | } |
| @@ -105555,14 +105951,14 @@ | |
| 105951 | if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ |
| 105952 | return aMatch[i-1].iStart; |
| 105953 | } |
| 105954 | } |
| 105955 | for(i=1; i<=10; i++){ |
| 105956 | if( fts3snippetIsspace(zDoc[iBreak-i]) ){ |
| 105957 | return iBreak - i + 1; |
| 105958 | } |
| 105959 | if( fts3snippetIsspace(zDoc[iBreak+i]) ){ |
| 105960 | return iBreak + i + 1; |
| 105961 | } |
| 105962 | } |
| 105963 | return iBreak; |
| 105964 | } |
| @@ -105602,11 +105998,11 @@ | |
| 105998 | |
| 105999 | sqlite3_free(pSnippet->zSnippet); |
| 106000 | pSnippet->zSnippet = 0; |
| 106001 | aMatch = pSnippet->aMatch; |
| 106002 | nMatch = pSnippet->nMatch; |
| 106003 | fts3SnippetSbInit(&sb); |
| 106004 | |
| 106005 | for(i=0; i<nMatch; i++){ |
| 106006 | aMatch[i].snStatus = SNIPPET_IGNORE; |
| 106007 | } |
| 106008 | nDesired = 0; |
| @@ -105636,14 +106032,14 @@ | |
| 106032 | } |
| 106033 | if( iCol==tailCol && iStart<=tailOffset+20 ){ |
| 106034 | iStart = tailOffset; |
| 106035 | } |
| 106036 | if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ |
| 106037 | fts3SnippetTrimWhiteSpace(&sb); |
| 106038 | fts3SnippetAppendWhiteSpace(&sb); |
| 106039 | fts3SnippetAppend(&sb, zEllipsis, -1); |
| 106040 | fts3SnippetAppendWhiteSpace(&sb); |
| 106041 | } |
| 106042 | iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; |
| 106043 | iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); |
| 106044 | if( iEnd>=nDoc-10 ){ |
| 106045 | iEnd = nDoc; |
| @@ -105657,48 +106053,56 @@ | |
| 106053 | && aMatch[iMatch].iCol<=iCol ){ |
| 106054 | iMatch++; |
| 106055 | } |
| 106056 | if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd |
| 106057 | && aMatch[iMatch].iCol==iCol ){ |
| 106058 | fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart); |
| 106059 | iStart = aMatch[iMatch].iStart; |
| 106060 | fts3SnippetAppend(&sb, zStartMark, -1); |
| 106061 | fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].nByte); |
| 106062 | fts3SnippetAppend(&sb, zEndMark, -1); |
| 106063 | iStart += aMatch[iMatch].nByte; |
| 106064 | for(j=iMatch+1; j<nMatch; j++){ |
| 106065 | if( aMatch[j].iTerm==aMatch[iMatch].iTerm |
| 106066 | && aMatch[j].snStatus==SNIPPET_DESIRED ){ |
| 106067 | nDesired--; |
| 106068 | aMatch[j].snStatus = SNIPPET_IGNORE; |
| 106069 | } |
| 106070 | } |
| 106071 | }else{ |
| 106072 | fts3SnippetAppend(&sb, &zDoc[iStart], iEnd - iStart); |
| 106073 | iStart = iEnd; |
| 106074 | } |
| 106075 | } |
| 106076 | tailCol = iCol; |
| 106077 | tailOffset = iEnd; |
| 106078 | } |
| 106079 | fts3SnippetTrimWhiteSpace(&sb); |
| 106080 | if( tailEllipsis ){ |
| 106081 | fts3SnippetAppendWhiteSpace(&sb); |
| 106082 | fts3SnippetAppend(&sb, zEllipsis, -1); |
| 106083 | } |
| 106084 | pSnippet->zSnippet = sb.z; |
| 106085 | pSnippet->nSnippet = sb.z ? sb.nUsed : 0; |
| 106086 | } |
| 106087 | |
| 106088 | SQLITE_PRIVATE void sqlite3Fts3Offsets( |
| 106089 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 106090 | Fts3Cursor *pCsr /* Cursor object */ |
| 106091 | ){ |
| 106092 | Snippet *p; /* Snippet structure */ |
| 106093 | int rc = snippetAllOffsets(pCsr, &p); |
| 106094 | if( rc==SQLITE_OK ){ |
| 106095 | snippetOffsetText(p); |
| 106096 | if( p->zOffset ){ |
| 106097 | sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT); |
| 106098 | }else{ |
| 106099 | sqlite3_result_error_nomem(pCtx); |
| 106100 | } |
| 106101 | }else{ |
| 106102 | sqlite3_result_error_nomem(pCtx); |
| 106103 | } |
| 106104 | fts3SnippetFree(p); |
| 106105 | } |
| 106106 | |
| 106107 | SQLITE_PRIVATE void sqlite3Fts3Snippet( |
| 106108 | sqlite3_context *pCtx, /* SQLite function call context */ |
| @@ -105707,12 +106111,20 @@ | |
| 106111 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 106112 | const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */ |
| 106113 | ){ |
| 106114 | Snippet *p; /* Snippet structure */ |
| 106115 | int rc = snippetAllOffsets(pCsr, &p); |
| 106116 | if( rc==SQLITE_OK ){ |
| 106117 | snippetText(pCsr, p, zStart, zEnd, zEllipsis); |
| 106118 | if( p->zSnippet ){ |
| 106119 | sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT); |
| 106120 | }else{ |
| 106121 | sqlite3_result_error_nomem(pCtx); |
| 106122 | } |
| 106123 | }else{ |
| 106124 | sqlite3_result_error_nomem(pCtx); |
| 106125 | } |
| 106126 | fts3SnippetFree(p); |
| 106127 | } |
| 106128 | |
| 106129 | #endif |
| 106130 | |
| 106131 |
+10
-5
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -119,11 +119,11 @@ | ||
| 119 | 119 | ** |
| 120 | 120 | ** Requirements: [H10011] [H10014] |
| 121 | 121 | */ |
| 122 | 122 | #define SQLITE_VERSION "3.6.21" |
| 123 | 123 | #define SQLITE_VERSION_NUMBER 3006021 |
| 124 | -#define SQLITE_SOURCE_ID "2009-11-25 21:05:09 5086bf8e838c824accda531afeb56a51dd40d795" | |
| 124 | +#define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" | |
| 125 | 125 | |
| 126 | 126 | /* |
| 127 | 127 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 128 | 128 | ** KEYWORDS: sqlite3_version |
| 129 | 129 | ** |
| @@ -1293,10 +1293,13 @@ | ||
| 1293 | 1293 | ** the return value of this interface. |
| 1294 | 1294 | ** |
| 1295 | 1295 | ** For the purposes of this routine, an [INSERT] is considered to |
| 1296 | 1296 | ** be successful even if it is subsequently rolled back. |
| 1297 | 1297 | ** |
| 1298 | +** This function is accessible to SQL statements via the | |
| 1299 | +** [last_insert_rowid() SQL function]. | |
| 1300 | +** | |
| 1298 | 1301 | ** Requirements: |
| 1299 | 1302 | ** [H12221] [H12223] |
| 1300 | 1303 | ** |
| 1301 | 1304 | ** If a separate thread performs a new [INSERT] on the same |
| 1302 | 1305 | ** database connection while the [sqlite3_last_insert_rowid()] |
| @@ -1350,12 +1353,12 @@ | ||
| 1350 | 1353 | ** changes in the most recently completed INSERT, UPDATE, or DELETE |
| 1351 | 1354 | ** statement within the body of the same trigger. |
| 1352 | 1355 | ** However, the number returned does not include changes |
| 1353 | 1356 | ** caused by subtriggers since those have their own context. |
| 1354 | 1357 | ** |
| 1355 | -** See also the [sqlite3_total_changes()] interface and the | |
| 1356 | -** [count_changes pragma]. | |
| 1358 | +** See also the [sqlite3_total_changes()] interface, the | |
| 1359 | +** [count_changes pragma], and the [changes() SQL function]. | |
| 1357 | 1360 | ** |
| 1358 | 1361 | ** Requirements: |
| 1359 | 1362 | ** [H12241] [H12243] |
| 1360 | 1363 | ** |
| 1361 | 1364 | ** If a separate thread makes changes on the same database connection |
| @@ -1378,12 +1381,12 @@ | ||
| 1378 | 1381 | ** are counted. |
| 1379 | 1382 | ** The changes are counted as soon as the statement that makes them is |
| 1380 | 1383 | ** completed (when the statement handle is passed to [sqlite3_reset()] or |
| 1381 | 1384 | ** [sqlite3_finalize()]). |
| 1382 | 1385 | ** |
| 1383 | -** See also the [sqlite3_changes()] interface and the | |
| 1384 | -** [count_changes pragma]. | |
| 1386 | +** See also the [sqlite3_changes()] interface, the | |
| 1387 | +** [count_changes pragma], and the [total_changes() SQL function]. | |
| 1385 | 1388 | ** |
| 1386 | 1389 | ** Requirements: |
| 1387 | 1390 | ** [H12261] [H12263] |
| 1388 | 1391 | ** |
| 1389 | 1392 | ** If a separate thread makes changes on the same database connection |
| @@ -4140,10 +4143,12 @@ | ||
| 4140 | 4143 | ** should free this memory by calling [sqlite3_free()]. |
| 4141 | 4144 | ** |
| 4142 | 4145 | ** {H12606} Extension loading must be enabled using |
| 4143 | 4146 | ** [sqlite3_enable_load_extension()] prior to calling this API, |
| 4144 | 4147 | ** otherwise an error will be returned. |
| 4148 | +** | |
| 4149 | +** See also the [load_extension() SQL function]. | |
| 4145 | 4150 | */ |
| 4146 | 4151 | SQLITE_API int sqlite3_load_extension( |
| 4147 | 4152 | sqlite3 *db, /* Load the extension into this database connection */ |
| 4148 | 4153 | const char *zFile, /* Name of the shared library containing extension */ |
| 4149 | 4154 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
| 4150 | 4155 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,11 +119,11 @@ | |
| 119 | ** |
| 120 | ** Requirements: [H10011] [H10014] |
| 121 | */ |
| 122 | #define SQLITE_VERSION "3.6.21" |
| 123 | #define SQLITE_VERSION_NUMBER 3006021 |
| 124 | #define SQLITE_SOURCE_ID "2009-11-25 21:05:09 5086bf8e838c824accda531afeb56a51dd40d795" |
| 125 | |
| 126 | /* |
| 127 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 128 | ** KEYWORDS: sqlite3_version |
| 129 | ** |
| @@ -1293,10 +1293,13 @@ | |
| 1293 | ** the return value of this interface. |
| 1294 | ** |
| 1295 | ** For the purposes of this routine, an [INSERT] is considered to |
| 1296 | ** be successful even if it is subsequently rolled back. |
| 1297 | ** |
| 1298 | ** Requirements: |
| 1299 | ** [H12221] [H12223] |
| 1300 | ** |
| 1301 | ** If a separate thread performs a new [INSERT] on the same |
| 1302 | ** database connection while the [sqlite3_last_insert_rowid()] |
| @@ -1350,12 +1353,12 @@ | |
| 1350 | ** changes in the most recently completed INSERT, UPDATE, or DELETE |
| 1351 | ** statement within the body of the same trigger. |
| 1352 | ** However, the number returned does not include changes |
| 1353 | ** caused by subtriggers since those have their own context. |
| 1354 | ** |
| 1355 | ** See also the [sqlite3_total_changes()] interface and the |
| 1356 | ** [count_changes pragma]. |
| 1357 | ** |
| 1358 | ** Requirements: |
| 1359 | ** [H12241] [H12243] |
| 1360 | ** |
| 1361 | ** If a separate thread makes changes on the same database connection |
| @@ -1378,12 +1381,12 @@ | |
| 1378 | ** are counted. |
| 1379 | ** The changes are counted as soon as the statement that makes them is |
| 1380 | ** completed (when the statement handle is passed to [sqlite3_reset()] or |
| 1381 | ** [sqlite3_finalize()]). |
| 1382 | ** |
| 1383 | ** See also the [sqlite3_changes()] interface and the |
| 1384 | ** [count_changes pragma]. |
| 1385 | ** |
| 1386 | ** Requirements: |
| 1387 | ** [H12261] [H12263] |
| 1388 | ** |
| 1389 | ** If a separate thread makes changes on the same database connection |
| @@ -4140,10 +4143,12 @@ | |
| 4140 | ** should free this memory by calling [sqlite3_free()]. |
| 4141 | ** |
| 4142 | ** {H12606} Extension loading must be enabled using |
| 4143 | ** [sqlite3_enable_load_extension()] prior to calling this API, |
| 4144 | ** otherwise an error will be returned. |
| 4145 | */ |
| 4146 | SQLITE_API int sqlite3_load_extension( |
| 4147 | sqlite3 *db, /* Load the extension into this database connection */ |
| 4148 | const char *zFile, /* Name of the shared library containing extension */ |
| 4149 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
| 4150 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,11 +119,11 @@ | |
| 119 | ** |
| 120 | ** Requirements: [H10011] [H10014] |
| 121 | */ |
| 122 | #define SQLITE_VERSION "3.6.21" |
| 123 | #define SQLITE_VERSION_NUMBER 3006021 |
| 124 | #define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" |
| 125 | |
| 126 | /* |
| 127 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 128 | ** KEYWORDS: sqlite3_version |
| 129 | ** |
| @@ -1293,10 +1293,13 @@ | |
| 1293 | ** the return value of this interface. |
| 1294 | ** |
| 1295 | ** For the purposes of this routine, an [INSERT] is considered to |
| 1296 | ** be successful even if it is subsequently rolled back. |
| 1297 | ** |
| 1298 | ** This function is accessible to SQL statements via the |
| 1299 | ** [last_insert_rowid() SQL function]. |
| 1300 | ** |
| 1301 | ** Requirements: |
| 1302 | ** [H12221] [H12223] |
| 1303 | ** |
| 1304 | ** If a separate thread performs a new [INSERT] on the same |
| 1305 | ** database connection while the [sqlite3_last_insert_rowid()] |
| @@ -1350,12 +1353,12 @@ | |
| 1353 | ** changes in the most recently completed INSERT, UPDATE, or DELETE |
| 1354 | ** statement within the body of the same trigger. |
| 1355 | ** However, the number returned does not include changes |
| 1356 | ** caused by subtriggers since those have their own context. |
| 1357 | ** |
| 1358 | ** See also the [sqlite3_total_changes()] interface, the |
| 1359 | ** [count_changes pragma], and the [changes() SQL function]. |
| 1360 | ** |
| 1361 | ** Requirements: |
| 1362 | ** [H12241] [H12243] |
| 1363 | ** |
| 1364 | ** If a separate thread makes changes on the same database connection |
| @@ -1378,12 +1381,12 @@ | |
| 1381 | ** are counted. |
| 1382 | ** The changes are counted as soon as the statement that makes them is |
| 1383 | ** completed (when the statement handle is passed to [sqlite3_reset()] or |
| 1384 | ** [sqlite3_finalize()]). |
| 1385 | ** |
| 1386 | ** See also the [sqlite3_changes()] interface, the |
| 1387 | ** [count_changes pragma], and the [total_changes() SQL function]. |
| 1388 | ** |
| 1389 | ** Requirements: |
| 1390 | ** [H12261] [H12263] |
| 1391 | ** |
| 1392 | ** If a separate thread makes changes on the same database connection |
| @@ -4140,10 +4143,12 @@ | |
| 4143 | ** should free this memory by calling [sqlite3_free()]. |
| 4144 | ** |
| 4145 | ** {H12606} Extension loading must be enabled using |
| 4146 | ** [sqlite3_enable_load_extension()] prior to calling this API, |
| 4147 | ** otherwise an error will be returned. |
| 4148 | ** |
| 4149 | ** See also the [load_extension() SQL function]. |
| 4150 | */ |
| 4151 | SQLITE_API int sqlite3_load_extension( |
| 4152 | sqlite3 *db, /* Load the extension into this database connection */ |
| 4153 | const char *zFile, /* Name of the shared library containing extension */ |
| 4154 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
| 4155 |