Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge trunk changes into experimental branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | experimental |
Files: | files | file ages | folders |
SHA1: |
fd1e5cade04961c2f5438a1dfcc2e15e |
User & Date: | dan 2010-10-21 15:49:47.000 |
Context
2010-10-22
| ||
16:44 | Add missing comments and fix compiler warnings in new FTS3/4 code. Other minor fixes too. (check-in: 1c9c70fec3 user: dan tags: experimental) | |
2010-10-21
| ||
15:49 | Merge trunk changes into experimental branch. (check-in: fd1e5cade0 user: dan tags: experimental) | |
15:12 | Fix some segfaults that could occur in obscure circumstances where error messages contained characters that could be mistaken for printf format specifiers. (check-in: f91471e723 user: dan tags: trunk) | |
2010-10-20
| ||
18:56 | Updates to FTS4 to improve performance and make more accurate cost estimates for prefix terms. (check-in: d0a450ce78 user: dan tags: experimental) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
163 164 165 166 167 168 169 | USE_AMALGAMATION = @USE_AMALGAMATION@ # Object files for the SQLite library (non-amalgamation). # LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ backup.lo bitvec.lo btmutex.lo btree.lo build.lo \ | | > | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | USE_AMALGAMATION = @USE_AMALGAMATION@ # Object files for the SQLite library (non-amalgamation). # LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ backup.lo bitvec.lo btmutex.lo btree.lo build.lo \ callback.lo complete.lo ctime.lo date.lo delete.lo \ expr.lo fault.lo fkey.lo \ fts3.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo fts3_porter.lo \ fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo fts3_write.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo journal.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_os2.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbetrace.lo \ wal.lo walker.lo where.lo utf.lo vtab.lo # Object files for the amalgamation. # LIBOBJS1 = sqlite3.lo # Determine the real value of LIBOBJ based on the 'configure' script # |
︙ | ︙ |
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
437 438 439 440 441 442 443 444 445 446 447 448 449 450 | ** The xDisconnect() virtual table method. */ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ Fts3Table *p = (Fts3Table *)pVtab; int i; assert( p->nPendingData==0 ); /* Free any prepared statements held */ for(i=0; i<SizeofArray(p->aStmt); i++){ sqlite3_finalize(p->aStmt[i]); } sqlite3_free(p->zSegmentsTbl); | > | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | ** The xDisconnect() virtual table method. */ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ Fts3Table *p = (Fts3Table *)pVtab; int i; assert( p->nPendingData==0 ); assert( p->pSegments==0 ); /* Free any prepared statements held */ for(i=0; i<SizeofArray(p->aStmt); i++){ sqlite3_finalize(p->aStmt[i]); } sqlite3_free(p->zSegmentsTbl); |
︙ | ︙ | |||
2057 2058 2059 2060 2061 2062 2063 | ** If the isPoslist argument is true, then it is assumed that the doclist ** contains a position-list following each docid. Otherwise, it is assumed ** that the doclist is simply a list of docids stored as delta encoded ** varints. */ static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){ int nDoc = 0; /* Return value */ | < | 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 | ** If the isPoslist argument is true, then it is assumed that the doclist ** contains a position-list following each docid. Otherwise, it is assumed ** that the doclist is simply a list of docids stored as delta encoded ** varints. */ static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){ int nDoc = 0; /* Return value */ if( aList ){ char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */ char *p = aList; /* Cursor */ if( !isPoslist ){ /* The number of docids in the list is the same as the number of ** varints. In FTS3 a varint consists of a single byte with the 0x80 ** bit cleared and zero or more bytes with the 0x80 bit set. So to |
︙ | ︙ |
Changes to ext/fts3/fts3Int.h.
︙ | ︙ | |||
125 126 127 128 129 130 131 | sqlite3_stmt *aStmt[25]; char *zSegmentsTbl; /* Name of %_segments table */ int nPgsz; /* Page size for host database */ int nNodeSize; /* Soft limit for node size */ u8 bHasContent; /* True if %_content table exists */ u8 bHasDocsize; /* True if %_docsize table exists */ | < | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | sqlite3_stmt *aStmt[25]; char *zSegmentsTbl; /* Name of %_segments table */ int nPgsz; /* Page size for host database */ int nNodeSize; /* Soft limit for node size */ u8 bHasContent; /* True if %_content table exists */ u8 bHasDocsize; /* True if %_docsize table exists */ sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ /* The following hash table is used to buffer pending index updates during ** transactions. Variable nPendingData estimates the memory size of the ** pending data, including hash table overhead, but not malloc overhead. ** When nPendingData exceeds nMaxPendingData, the buffer is flushed ** automatically. Variable iPrevDocid is the docid of the most recently |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
281 282 283 284 285 286 287 | pBlob->iCol = iCol; pBlob->db = db; sqlite3BtreeLeaveAll(db); v = 0; if( db->mallocFailed ){ goto blob_open_out; } | < < | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | pBlob->iCol = iCol; pBlob->db = db; sqlite3BtreeLeaveAll(db); v = 0; if( db->mallocFailed ){ goto blob_open_out; } sqlite3_bind_int64(pBlob->pStmt, 1, iRow); rc = blobSeekToRow(pBlob, iRow, &zErr); } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA ); blob_open_out: if( rc==SQLITE_OK && db->mallocFailed==0 ){ *ppBlob = (sqlite3_blob *)pBlob; }else{ if( v ) sqlite3VdbeFinalize(v); if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
668 669 670 671 672 673 674 | pTab->aCol = pParse->pNewTable->aCol; pTab->nCol = pParse->pNewTable->nCol; pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } db->pVTab = 0; }else{ | | | 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | pTab->aCol = pParse->pNewTable->aCol; pTab->nCol = pParse->pNewTable->nCol; pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } db->pVTab = 0; }else{ sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } pParse->declareVtab = 0; if( pParse->pVdbe ){ sqlite3VdbeFinalize(pParse->pVdbe); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
231 232 233 234 235 236 237 | #define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */ #define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */ #define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ | | | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | #define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */ #define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */ #define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ #define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ #define WHERE_IDX_ONLY 0x00800000 /* Use index only - omit table */ #define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */ #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */ |
︙ | ︙ | |||
1577 1578 1579 1580 1581 1582 1583 | ){ #ifndef SQLITE_OMIT_OR_OPTIMIZATION const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ WhereTerm *pTerm; /* A single term of the WHERE clause */ | | > | | 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 | ){ #ifndef SQLITE_OMIT_OR_OPTIMIZATION const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ WhereTerm *pTerm; /* A single term of the WHERE clause */ /* No OR-clause optimization allowed if the INDEXED BY or NOT INDEXED clauses ** are used */ if( pSrc->notIndexed || pSrc->pIndex!=0 ){ return; } /* Search the WHERE clause terms for a usable WO_OR term. */ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( pTerm->eOperator==WO_OR && ((pTerm->prereqAll & ~maskSrc) & notReady)==0 |
︙ | ︙ | |||
4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 | Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ int nUnconstrained; /* Number tables without INDEXED BY */ Bitmask notIndexed; /* Mask of tables that cannot use an index */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; /* Loop through the remaining entries in the FROM clause to find the ** next nested loop. The loop tests all FROM clause entries ** either once or twice. ** ** The first test is always performed if there are two or more entries ** remaining and never performed if there is only one FROM clause entry | > | 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 | Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ int nUnconstrained; /* Number tables without INDEXED BY */ Bitmask notIndexed; /* Mask of tables that cannot use an index */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; WHERETRACE(("*** Begin search for loop %d ***\n", i)); /* Loop through the remaining entries in the FROM clause to find the ** next nested loop. The loop tests all FROM clause entries ** either once or twice. ** ** The first test is always performed if there are two or more entries ** remaining and never performed if there is only one FROM clause entry |
︙ | ︙ | |||
4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 | if( j==iFrom ) iFrom++; continue; } mask = (isOptimal ? m : notReady); pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); if( pTabItem->pIndex==0 ) nUnconstrained++; assert( pTabItem->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTabItem->pTab) ){ sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo; bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, &sCost, pp); }else | > > | 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 | if( j==iFrom ) iFrom++; continue; } mask = (isOptimal ? m : notReady); pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); if( pTabItem->pIndex==0 ) nUnconstrained++; WHERETRACE(("=== trying table %d with isOptimal=%d ===\n", j, isOptimal)); assert( pTabItem->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTabItem->pTab) ){ sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo; bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, &sCost, pp); }else |
︙ | ︙ | |||
4178 4179 4180 4181 4182 4183 4184 | && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) && (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */ || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || sCost.rCost<bestPlan.rCost /* (4) */ || (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow)) ){ | > | | | > | | 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 | && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) && (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */ || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || sCost.rCost<bestPlan.rCost /* (4) */ || (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow)) ){ WHERETRACE(("=== table %d is best so far" " with cost=%g and nRow=%g\n", j, sCost.rCost, sCost.nRow)); bestPlan = sCost; bestJ = j; } if( doNotReorder ) break; } } assert( bestJ>=0 ); assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); WHERETRACE(("*** Optimizer selects table %d for loop %d" " with cost=%g and nRow=%g\n", bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.nRow)); if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){ *ppOrderBy = 0; } andFlags &= bestPlan.plan.wsFlags; pLevel->plan = bestPlan.plan; testcase( bestPlan.plan.wsFlags & WHERE_INDEXED ); testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX ); |
︙ | ︙ |
Changes to test/incrblob.test.
︙ | ︙ | |||
672 673 674 675 676 677 678 679 680 681 | do_test incrblob-8.6 { set rc [catch {sqlite3_blob_write $::b 0 etilqs 6} msg] lappend rc $msg } {0 {}} do_test incrblob-8.7 { execsql {SELECT b FROM t1 WHERE a = 314159} } {etilqs} finish_test | > > > > > > > > > | 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | do_test incrblob-8.6 { set rc [catch {sqlite3_blob_write $::b 0 etilqs 6} msg] lappend rc $msg } {0 {}} do_test incrblob-8.7 { execsql {SELECT b FROM t1 WHERE a = 314159} } {etilqs} # The following test case exposes an instance in the blob code where # an error message was set using a call similar to sqlite3_mprintf(zErr), # where zErr is an arbitrary string. This is no good if the string contains # characters that can be mistaken for printf() formatting directives. # do_test incrblob-9.1 { list [catch { db incrblob t1 "A tricky column name %s%s" 1 } msg] $msg } {1 {no such column: "A tricky column name %s%s"}} finish_test |
Changes to test/vtab1.test.
︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | do_test vtab1-16.$tn { set echo_module_fail(xRename,t2) "the xRename method has failed" catchsql { ALTER TABLE echo_t2 RENAME TO another_name } } "1 {echo-vtab-error: the xRename method has failed}" unset echo_module_fail(xRename,t2) incr tn } unset -nocomplain echo_module_begin_fail finish_test | > > > > > > > > > > > > > > > | 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 | do_test vtab1-16.$tn { set echo_module_fail(xRename,t2) "the xRename method has failed" catchsql { ALTER TABLE echo_t2 RENAME TO another_name } } "1 {echo-vtab-error: the xRename method has failed}" unset echo_module_fail(xRename,t2) incr tn } # The following test case exposes an instance in sqlite3_declare_vtab() # an error message was set using a call similar to sqlite3_mprintf(zErr), # where zErr is an arbitrary string. This is no good if the string contains # characters that can be mistaken for printf() formatting directives. # do_test vtab1-17.1 { execsql { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES( 'table', 't3', 't3', 0, 'INSERT INTO "%s%s" VALUES(1)' ); } catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); } } {1 {vtable constructor failed: t4}} unset -nocomplain echo_module_begin_fail finish_test |
Changes to test/where7.test.
︙ | ︙ | |||
23295 23296 23297 23298 23299 23300 23301 | OR a=23 OR (f GLOB '?defg*' AND f GLOB 'cdef*') OR d<0.0 OR (d>=22.0 AND d<23.0 AND d NOT NULL) OR a=91 } } {2 22 23 28 54 80 91 scan 0 sort 0} | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 23295 23296 23297 23298 23299 23300 23301 23302 23303 23304 23305 23306 23307 23308 23309 23310 23311 23312 23313 23314 23315 23316 23317 23318 23319 23320 23321 23322 23323 23324 23325 23326 23327 23328 23329 23330 23331 23332 23333 23334 23335 23336 23337 23338 23339 23340 23341 23342 23343 23344 23345 23346 23347 | OR a=23 OR (f GLOB '?defg*' AND f GLOB 'cdef*') OR d<0.0 OR (d>=22.0 AND d<23.0 AND d NOT NULL) OR a=91 } } {2 22 23 28 54 80 91 scan 0 sort 0} # test case for the performance regression fixed by # check-in 28ba6255282b on 2010-10-21 02:05:06 # # The test case that follows is code from an actual # application with identifiers change and unused columns # remove. # do_test where7-3.1 { db eval { CREATE TABLE t301 ( c8 INTEGER PRIMARY KEY, c6 INTEGER, c4 INTEGER, c7 INTEGER, FOREIGN KEY (c4) REFERENCES series(c4) ); CREATE INDEX t301_c6 on t301(c6); CREATE INDEX t301_c4 on t301(c4); CREATE INDEX t301_c7 on t301(c7); CREATE TABLE t302 ( c1 INTEGER PRIMARY KEY, c8 INTEGER, c5 INTEGER, c3 INTEGER, c2 INTEGER, c4 INTEGER, FOREIGN KEY (c8) REFERENCES t301(c8) ); CREATE INDEX t302_c3 on t302(c3); CREATE INDEX t302_c8_c3 on t302(c8, c3); CREATE INDEX t302_c5 on t302(c5); EXPLAIN QUERY PLAN SELECT t302.c1 FROM t302 JOIN t301 ON t302.c8 = t301.c8 WHERE t302.c2 = 19571 AND t302.c3 > 1287603136 AND (t301.c4 = 1407449685622784 OR t301.c8 = 1407424651264000) ORDER BY t302.c5 LIMIT 200; } } {0 1 {TABLE t301 VIA MULTI-INDEX UNION} 1 0 {TABLE t302 WITH INDEX t302_c8_c3} 0 0 {TABLE t301 WITH INDEX t301_c4} 0 0 {TABLE t301 USING PRIMARY KEY}} finish_test |