Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest updates from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | memjournal-exp |
Files: | files | file ages | folders |
SHA1: |
55c00f716dc98b188c91f3a5a010242c |
User & Date: | drh 2016-03-03 21:29:10.682 |
Context
2016-03-04
| ||
00:13 | Get in-memory subjournals working for builds without SQLITE_ENABLE_ATOMIC_WRITE. (check-in: b5378dcea5 user: drh tags: memjournal-exp) | |
2016-03-03
| ||
21:29 | Merge the latest updates from trunk. (check-in: 55c00f716d user: drh tags: memjournal-exp) | |
21:22 | Reduce the amount of heap memory required to store many schemas by storing the column datatype appended to the column name (with a \000 separator), rather than in separate memory allocation. (check-in: 16fbf2e19c user: drh tags: trunk) | |
2016-02-29
| ||
20:18 | When using a temporary file for a statement journal, store the first 64KiB in memory. If the file grows larger than that, flush it to disk and free the memory. Hardcoding to 64KiB is just an experiment to check that the memjournal.c code works. (check-in: 44b2dc18e2 user: dan tags: memjournal-exp) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | # fixture. Otherwise link against libsqlite3.la. (This distinction is # necessary because the test fixture requires non-API symbols which are # hidden when the library is built via the amalgamation). # TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_FLAGS += -DBUILD_sqlite TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la TESTFIXTURE_SRC1 = sqlite3.c TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) testfixture$(TEXE): $(TESTFIXTURE_SRC) | > | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | # fixture. Otherwise link against libsqlite3.la. (This distinction is # necessary because the test fixture requires non-API symbols which are # hidden when the library is built via the amalgamation). # TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_FLAGS += -DBUILD_sqlite TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la TESTFIXTURE_SRC1 = sqlite3.c TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) testfixture$(TEXE): $(TESTFIXTURE_SRC) |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 | # fixture. Otherwise link against libsqlite3.lib. (This distinction is # necessary because the test fixture requires non-API symbols which are # hidden when the library is built via the amalgamation). # TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) !ELSE TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1) | > | 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 | # fixture. Otherwise link against libsqlite3.lib. (This distinction is # necessary because the test fixture requires non-API symbols which are # hidden when the library is built via the amalgamation). # TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) !ELSE TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1) |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
693 694 695 696 697 698 699 700 701 702 703 704 705 706 | p->rc = rc; p->nRead++; } assert( (pRet==0)==(p->rc!=SQLITE_OK) ); return pRet; } /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). */ static void fts5DataRelease(Fts5Data *pData){ sqlite3_free(pData); | > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | p->rc = rc; p->nRead++; } assert( (pRet==0)==(p->rc!=SQLITE_OK) ); return pRet; } /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). */ static void fts5DataRelease(Fts5Data *pData){ sqlite3_free(pData); |
︙ | ︙ | |||
2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 | int bEndOfPage = 0; assert( p->rc==SQLITE_OK ); iPgidx = szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; while( 1 ){ /* Figure out how many new bytes are in this term */ fts5FastGetVarint32(a, iOff, nNew); if( nKeep<nMatch ){ goto search_failed; | > > > > | 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 | int bEndOfPage = 0; assert( p->rc==SQLITE_OK ); iPgidx = szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; if( iOff>n ){ p->rc = FTS5_CORRUPT; return; } while( 1 ){ /* Figure out how many new bytes are in this term */ fts5FastGetVarint32(a, iOff, nNew); if( nKeep<nMatch ){ goto search_failed; |
︙ | ︙ | |||
4495 4496 4497 4498 4499 4500 4501 | pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; pLvl = &pNew->aLevel[pStruct->nLevel]; pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pLvl->aSeg ){ int iLvl, iSeg; int iSegOut = 0; | > > > | | 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 | pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; pLvl = &pNew->aLevel[pStruct->nLevel]; pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pLvl->aSeg ){ int iLvl, iSeg; int iSegOut = 0; /* Iterate through all segments, from oldest to newest. Add them to ** the new Fts5Level object so that pLvl->aSeg[0] is the oldest ** segment in the data structure. */ for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){ for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){ pLvl->aSeg[iSegOut] = pStruct->aLevel[iLvl].aSeg[iSeg]; iSegOut++; } } pNew->nSegment = pLvl->nSeg = nSeg; }else{ |
︙ | ︙ |
Changes to ext/fts5/test/fts5_common.tcl.
︙ | ︙ | |||
12 13 14 15 16 17 18 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. .. test] } source $testdir/tester.tcl ifcapable !fts5 { | > | > > > > < < < < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. .. test] } source $testdir/tester.tcl ifcapable !fts5 { proc return_if_no_fts5 {} { finish_test return -code return } return } else { proc return_if_no_fts5 {} {} } catch { sqlite3_fts5_may_be_corrupt 0 reset_db } proc fts5_test_poslist {cmd} { set res [list] for {set i 0} {$i < [$cmd xInstCount]} {incr i} { lappend res [string map {{ } .} [$cmd xInst $i]] } set res } |
︙ | ︙ |
Changes to ext/fts5/test/fts5bigtok.test.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing the FTS5 module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5bigtok proc rndterm {} { set L [list a b c d e f g h i j k l m n o p q r s t u v w x y z] set l [lindex $L [expr int(rand() * [llength $L])]] string repeat $l [expr int(rand() * 5) + 60] } | > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing the FTS5 module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5bigtok return_if_no_fts5 proc rndterm {} { set L [list a b c d e f g h i j k l m n o p q r s t u v w x y z] set l [lindex $L [expr int(rand() * [llength $L])]] string repeat $l [expr int(rand() * 5) + 60] } |
︙ | ︙ |
Changes to ext/fts5/test/fts5merge2.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # # Test that focus on incremental merges of segments. # source [file join [file dirname [info script]] fts5_common.tcl] | | > < < | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # #*********************************************************************** # # Test that focus on incremental merges of segments. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5merge2 return_if_no_fts5 proc dump_structure {} { db eval {SELECT fts5_decode(id, block) AS t FROM t1_data WHERE id=10} { foreach lvl [lrange $t 1 end] { set seg [string repeat . [expr [llength $lvl]-2]] puts "[lrange $lvl 0 1] $seg" } } } foreach_detail_mode $testprefix { do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); INSERT INTO t1(t1, rank) VALUES('crisismerge', 2); INSERT INTO t1 VALUES('1 2 3 4'); } |
︙ | ︙ |
Changes to ext/fts5/test/fts5simple.test.
︙ | ︙ | |||
405 406 407 408 409 410 411 | CREATE VIRTUAL TABLE x1 USING fts5(a,b,c); } do_catchsql_test 19.2 { SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; } {1 {fts5: parser stack overflow}} | > > > > > > > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | CREATE VIRTUAL TABLE x1 USING fts5(a,b,c); } do_catchsql_test 19.2 { SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; } {1 {fts5: parser stack overflow}} #------------------------------------------------------------------------- reset_db breakpoint do_execsql_test 20.0 { CREATE VIRTUAL TABLE x1 USING fts5(x); INSERT INTO x1(x1, rank) VALUES('pgsz', 32); INSERT INTO x1(rowid, x) VALUES(11111, 'onetwothree'); } do_test 20.1 { for {set i 1} {$i <= 200} {incr i} { execsql { INSERT INTO x1(rowid, x) VALUES($i, 'one two three'); } } execsql { INSERT INTO x1(x1) VALUES('optimize'); } execsql { DELETE FROM x1 WHERE rowid = 4; } } {} do_execsql_test 20.2 { INSERT INTO x1(x1) VALUES('optimize'); INSERT INTO x1(x1) VALUES('integrity-check'); } {} #------------------------------------------------------------------------- reset_db do_execsql_test 20.0 { CREATE VIRTUAL TABLE x1 USING fts5(x); INSERT INTO x1(x1, rank) VALUES('pgsz', 32); INSERT INTO x1(rowid, x) VALUES(11111, 'onetwothree'); } do_test 20.1 { for {set i 1} {$i <= 200} {incr i} { execsql { INSERT INTO x1(rowid, x) VALUES($i, 'one two three'); } } execsql { INSERT INTO x1(x1) VALUES('optimize'); } execsql { DELETE FROM x1 WHERE rowid = 4; } } {} do_execsql_test 20.2 { INSERT INTO x1(x1) VALUES('optimize'); INSERT INTO x1(x1) VALUES('integrity-check'); } {} finish_test |
Changes to ext/misc/series.c.
︙ | ︙ | |||
213 214 215 216 217 218 219 220 221 222 223 224 225 226 | if( pCur->isDesc ){ return pCur->iValue < pCur->mnValue; }else{ return pCur->iValue > pCur->mxValue; } } /* ** This method is called to "rewind" the series_cursor object back ** to the first row of output. This method is always called at least ** once prior to any call to seriesColumn() or seriesRowid() or ** seriesEof(). ** ** The query plan selected by seriesBestIndex is passed in the idxNum | > > > > > > > > | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | if( pCur->isDesc ){ return pCur->iValue < pCur->mnValue; }else{ return pCur->iValue > pCur->mxValue; } } /* True to cause run-time checking of the start=, stop=, and/or step= ** parameters. The only reason to do this is for testing the ** constraint checking logic for virtual tables in the SQLite core. */ #ifndef SQLITE_SERIES_CONSTRAINT_VERIFY # define SQLITE_SERIES_CONSTRAINT_VERIFY 0 #endif /* ** This method is called to "rewind" the series_cursor object back ** to the first row of output. This method is always called at least ** once prior to any call to seriesColumn() or seriesRowid() or ** seriesEof(). ** ** The query plan selected by seriesBestIndex is passed in the idxNum |
︙ | ︙ | |||
320 321 322 323 324 325 326 | stepIdx = i; idxNum |= 4; break; } } if( startIdx>=0 ){ pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg; | | | | | | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | stepIdx = i; idxNum |= 4; break; } } if( startIdx>=0 ){ pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY; } if( stopIdx>=0 ){ pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } if( stepIdx>=0 ){ pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the ** the preferred case */ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); pIdxInfo->estimatedRows = 1000; if( pIdxInfo->nOrderBy==1 ){ if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8; pIdxInfo->orderByConsumed = 1; } }else{ /* If either boundary is missing, we have to generate a huge span |
︙ | ︙ |
Changes to ext/misc/spellfix.c.
︙ | ︙ | |||
1771 1772 1773 1774 1775 1776 1777 | /* End transliterate ****************************************************************************** ****************************************************************************** ** Begin spellfix1 virtual table. */ /* Maximum length of a phonehash used for querying the shadow table */ | | | 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 | /* End transliterate ****************************************************************************** ****************************************************************************** ** Begin spellfix1 virtual table. */ /* Maximum length of a phonehash used for querying the shadow table */ #define SPELLFIX_MX_HASH 32 /* Maximum number of hash strings to examine per query */ #define SPELLFIX_MX_RUN 1 typedef struct spellfix1_vtab spellfix1_vtab; typedef struct spellfix1_cursor spellfix1_cursor; |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 | $(TOP)/src/test6.c \ $(TOP)/src/test7.c \ $(TOP)/src/test8.c \ $(TOP)/src/test9.c \ $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_blob.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_fs.c \ $(TOP)/src/test_func.c \ | > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | $(TOP)/src/test6.c \ $(TOP)/src/test7.c \ $(TOP)/src/test8.c \ $(TOP)/src/test9.c \ $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_bestindex.c \ $(TOP)/src/test_blob.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_fs.c \ $(TOP)/src/test_func.c \ |
︙ | ︙ | |||
721 722 723 724 725 726 727 | sqlite3_analyzer$(EXE): sqlite3_analyzer.c $(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB) # Rules to build the 'testfixture' application. # TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 | | > | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | sqlite3_analyzer$(EXE): sqlite3_analyzer.c $(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB) # Rules to build the 'testfixture' application. # TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ -o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB) amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c |
︙ | ︙ |
Changes to src/alter.c.
︙ | ︙ | |||
624 625 626 627 628 629 630 | } #endif /* If the default value for the new column was specified with a ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. */ | > | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | } #endif /* If the default value for the new column was specified with a ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. */ assert( pDflt==0 || pDflt->op==TK_SPAN ); if( pDflt && pDflt->pLeft->op==TK_NULL ){ pDflt = 0; } /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. ** If there is a NOT NULL constraint, then the default value for the ** column must not be NULL. */ |
︙ | ︙ | |||
781 782 783 784 785 786 787 | goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; i<pNew->nCol; i++){ Column *pCol = &pNew->aCol[i]; pCol->zName = sqlite3DbStrDup(db, pCol->zName); pCol->zColl = 0; | < < | 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 | goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; i<pNew->nCol; i++){ Column *pCol = &pNew->aCol[i]; pCol->zName = sqlite3DbStrDup(db, pCol->zName); pCol->zColl = 0; pCol->pDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nRef = 1; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
567 568 569 570 571 572 573 | int i; Column *pCol; assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; i<pTable->nCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); | < < | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | int i; Column *pCol; assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; i<pTable->nCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); sqlite3DbFree(db, pCol->zColl); } sqlite3DbFree(db, pTable->aCol); } } /* |
︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 | ** Add a new column to the table currently being constructed. ** ** The parser calls this routine once for each column declaration ** in a CREATE TABLE statement. sqlite3StartTable() gets called ** first to get things going. Then this routine is called for each ** column. */ | | > | > > > > > > | 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 | ** Add a new column to the table currently being constructed. ** ** The parser calls this routine once for each column declaration ** in a CREATE TABLE statement. sqlite3StartTable() gets called ** first to get things going. Then this routine is called for each ** column. */ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ Table *p; int i; char *z; char *zType; Column *pCol; sqlite3 *db = pParse->db; if( (p = pParse->pNewTable)==0 ) return; #if SQLITE_MAX_COLUMN if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); return; } #endif z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); if( z==0 ) return; memcpy(z, pName->z, pName->n); z[pName->n] = 0; sqlite3Dequote(z); zType = z + sqlite3Strlen30(z) + 1; memcpy(zType, pType->z, pType->n); zType[pType->n] = 0; for(i=0; i<p->nCol; i++){ if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); sqlite3DbFree(db, z); return; } } |
︙ | ︙ | |||
1071 1072 1073 1074 1075 1076 1077 | p->aCol = aNew; } pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); | > | | < < | | > > > > | 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 | p->aCol = aNew; } pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); if( pType->n==0 ){ /* If there is no type specified, columns have the default affinity ** 'BLOB'. */ pCol->affinity = SQLITE_AFF_BLOB; pCol->szEst = 1; }else{ pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); } p->nCol++; pParse->constraintName.n = 0; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has ** been seen on a column. This routine sets the notNull flag on ** the column currently under construction. |
︙ | ︙ | |||
1180 1181 1182 1183 1184 1185 1186 | *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ } } } return aff; } | < < < < < < < < < < < < < < < < < < < < < < | 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 | *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ } } } return aff; } /* ** The expression is the default value for the most recently added column ** of the table currently under construction. ** ** Default value expressions must be constant. Raise an exception if this ** is not the case. ** |
︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 1234 | sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains ** tokens that point to volatile memory. The 'span' of the expression ** is required by pragma table_info. */ sqlite3ExprDelete(db, pCol->pDflt); | > < | > | | > > > > | 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 | sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains ** tokens that point to volatile memory. The 'span' of the expression ** is required by pragma table_info. */ Expr x; sqlite3ExprDelete(db, pCol->pDflt); memset(&x, 0, sizeof(x)); x.op = TK_SPAN; x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart, (int)(pSpan->zEnd - pSpan->zStart)); x.pLeft = pSpan->pExpr; x.flags = EP_Skip; pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); sqlite3DbFree(db, x.u.zToken); } } sqlite3ExprDelete(db, pSpan->pExpr); } /* ** Backwards Compatibility Hack: |
︙ | ︙ | |||
1287 1288 1289 1290 1291 1292 1293 | Parse *pParse, /* Parsing context */ ExprList *pList, /* List of field names to be indexed */ int onError, /* What to do with a uniqueness conflict */ int autoInc, /* True if the AUTOINCREMENT keyword is present */ int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; | | | | > | | 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 | Parse *pParse, /* Parsing context */ ExprList *pList, /* List of field names to be indexed */ int onError, /* What to do with a uniqueness conflict */ int autoInc, /* True if the AUTOINCREMENT keyword is present */ int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; const char *zName = 0; int iCol = -1, i; int nTerm; if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; if( pTab->tabFlags & TF_HasPrimaryKey ){ sqlite3ErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); goto primary_key_exit; } pTab->tabFlags |= TF_HasPrimaryKey; if( pList==0 ){ iCol = pTab->nCol - 1; pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; zName = pTab->aCol[iCol].zName; nTerm = 1; }else{ nTerm = pList->nExpr; for(i=0; i<nTerm; i++){ Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr); assert( pCExpr!=0 ); sqlite3StringToId(pCExpr); if( pCExpr->op==TK_ID ){ const char *zCName = pCExpr->u.zToken; for(iCol=0; iCol<pTab->nCol; iCol++){ if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; zName = pTab->aCol[iCol].zName; break; } } } } } if( nTerm==1 && zName && sqlite3StrICmp(sqlite3StrNext(zName), "INTEGER")==0 && sortOrder!=SQLITE_SO_DESC ){ pTab->iPKey = iCol; pTab->keyConf = (u8)onError; assert( autoInc==0 || autoInc==1 ); pTab->tabFlags |= autoInc*TF_Autoincrement; if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder; |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 | codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); break; } case TK_COLLATE: case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } case TK_TRIGGER: { | > | 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 | codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); break; } case TK_SPAN: case TK_COLLATE: case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } case TK_TRIGGER: { |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
1995 1996 1997 1998 1999 2000 2001 | if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){ return 0; /* Collating sequence must be the same on all columns */ } if( pDestCol->notNull && !pSrcCol->notNull ){ return 0; /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ | | > > | | > | | > | 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 | if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){ return 0; /* Collating sequence must be the same on all columns */ } if( pDestCol->notNull && !pSrcCol->notNull ){ return 0; /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ if( i>0 ){ assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN ); assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN ); if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0) || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken, pSrcCol->pDflt->u.zToken)!=0) ){ return 0; /* Default values must be the same for all columns */ } } } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ if( IsUniqueIndex(pDestIdx) ){ destHasUniqueIdx = 1; } for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
3331 3332 3333 3334 3335 3336 3337 | ** 1. The specified column name was rowid", "oid" or "_rowid_" ** and there is no explicitly declared IPK column. ** ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ | > | | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 | ** 1. The specified column name was rowid", "oid" or "_rowid_" ** and there is no explicitly declared IPK column. ** ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ zDataType = sqlite3StrNext(pCol->zName); if( zDataType[0]==0 ) zDataType = 0; zCollSeq = pCol->zColl; notnull = pCol->notNull!=0; primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0; }else{ zDataType = "INTEGER"; primarykey = 1; |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
186 187 188 189 190 191 192 | if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){ A = TF_WithoutRowid | TF_NoVisibleRowid; }else{ A = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z); } } | | | < < < < < < < < < < | < < < | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){ A = TF_WithoutRowid | TF_NoVisibleRowid; }else{ A = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z); } } columnlist ::= columnlist COMMA columnname carglist. columnlist ::= columnname carglist. columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %token_class id ID|INDEXED. // The following directive causes tokens ABORT, AFTER, ASC, etc. to |
︙ | ︙ | |||
260 261 262 263 264 265 266 | // The name of a column or table can be any of the following: // %type nm {Token} nm(A) ::= id(A). nm(A) ::= STRING(A). nm(A) ::= JOIN_KW(A). | | | < | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | // The name of a column or table can be any of the following: // %type nm {Token} nm(A) ::= id(A). nm(A) ::= STRING(A). nm(A) ::= JOIN_KW(A). // A typetoken is really zero or more tokens that form a type name such // as can be found after the column name in a CREATE TABLE statement. // Multiple tokens are concatenated to form the value of the typetoken. // %type typetoken {Token} typetoken(A) ::= . {A.n = 0; A.z = 0;} typetoken(A) ::= typename(A). typetoken(A) ::= typename(A) LP signed RP(Y). { A.n = (int)(&Y.z[Y.n] - A.z); } typetoken(A) ::= typename(A) LP signed COMMA signed RP(Y). { A.n = (int)(&Y.z[Y.n] - A.z); } |
︙ | ︙ | |||
576 577 578 579 580 581 582 | // An option "AS <id>" phrase that can follow one of the expressions that // define the result set, or one of the tables in the FROM clause. // %type as {Token} as(X) ::= AS nm(Y). {X = Y;} as(X) ::= ids(X). | | | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | // An option "AS <id>" phrase that can follow one of the expressions that // define the result set, or one of the tables in the FROM clause. // %type as {Token} as(X) ::= AS nm(Y). {X = Y;} as(X) ::= ids(X). as(X) ::= . {X.n = 0; X.z = 0;} %type seltablist {SrcList*} %destructor seltablist {sqlite3SrcListDelete(pParse->db, $$);} %type stl_prefix {SrcList*} %destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);} %type from {SrcList*} |
︙ | ︙ | |||
1495 1496 1497 1498 1499 1500 1501 | %endif //////////////////////// ALTER TABLE table ... //////////////////////////////// %ifndef SQLITE_OMIT_ALTERTABLE cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { sqlite3AlterRenameTable(pParse,X,&Z); } | | > > | 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | %endif //////////////////////// ALTER TABLE table ... //////////////////////////////// %ifndef SQLITE_OMIT_ALTERTABLE cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { sqlite3AlterRenameTable(pParse,X,&Z); } cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname(Y) carglist. { Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &Y); } add_column_fullname ::= fullname(X). { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, X); } kwcolumn_opt ::= . |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 | Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ if( IsHiddenColumn(pCol) ){ nHidden++; continue; } if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } sqlite3VdbeMultiLoad(v, 1, "issisi", i-nHidden, | > > > | < > | | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 | Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ const char *zName; if( IsHiddenColumn(pCol) ){ nHidden++; continue; } if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); zName = pCol->zName; sqlite3VdbeMultiLoad(v, 1, "issisi", i-nHidden, zName, sqlite3StrNext(zName), pCol->notNull ? 1 : 0, pCol->pDflt ? pCol->pDflt->u.zToken : 0, k); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } } break; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1425 1426 1427 1428 1429 1430 1431 | if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); #ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ | < > | | 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 | if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); #ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ zOrigCol = pTab->aCol[iCol].zName; zType = sqlite3StrNext(zOrigCol); estWidth = pTab->aCol[iCol].szEst; } zOrigTab = pTab->zName; if( pNC->pParse ){ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); zOrigDb = pNC->pParse->db->aDb[iDb].zName; } #else if( iCol<0 ){ zType = "INTEGER"; }else{ zType = sqlite3StrNext(pTab->aCol[iCol].zName); estWidth = pTab->aCol[iCol].szEst; } #endif } break; } #ifndef SQLITE_OMIT_SUBQUERY |
︙ | ︙ | |||
1723 1724 1725 1726 1727 1728 1729 | assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); if( db->mallocFailed ) return; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ p = a[i].pExpr; | < < | < | 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 | assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); if( db->mallocFailed ) return; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ p = a[i].pExpr; columnType(&sNC, p, 0, 0, 0, &pCol->szEst); szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl && pCol->zColl==0 ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1539 1540 1541 1542 1543 1544 1545 | }; /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { | | < < | 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 | }; /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { char *zName; /* Name of this column, \000, then the type */ Expr *pDflt; /* Default value of this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; |
︙ | ︙ | |||
3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 | #endif /* ** Internal function prototypes */ int sqlite3StrICmp(const char*,const char*); int sqlite3Strlen30(const char*); #define sqlite3StrNICmp sqlite3_strnicmp int sqlite3MallocInit(void); void sqlite3MallocEnd(void); void *sqlite3Malloc(u64); void *sqlite3MallocZero(u64); void *sqlite3DbMallocZero(sqlite3*, u64); | > | 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 | #endif /* ** Internal function prototypes */ int sqlite3StrICmp(const char*,const char*); int sqlite3Strlen30(const char*); const char *sqlite3StrNext(const char*); #define sqlite3StrNICmp sqlite3_strnicmp int sqlite3MallocInit(void); void sqlite3MallocEnd(void); void *sqlite3Malloc(u64); void *sqlite3MallocZero(u64); void *sqlite3DbMallocZero(sqlite3*, u64); |
︙ | ︙ | |||
3410 3411 3412 3413 3414 3415 3416 | i16 sqlite3ColumnOfIndex(Index*, i16); void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); #if SQLITE_ENABLE_HIDDEN_COLUMNS void sqlite3ColumnPropertiesFromName(Table*, Column*); #else # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ #endif | | < | 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 | i16 sqlite3ColumnOfIndex(Index*, i16); void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); #if SQLITE_ENABLE_HIDDEN_COLUMNS void sqlite3ColumnPropertiesFromName(Table*, Column*); #else # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ #endif void sqlite3AddColumn(Parse*,Token*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddDefaultValue(Parse*,ExprSpan*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); Btree *sqlite3DbNameToBtree(sqlite3*,const char*); int sqlite3CodeOnce(Parse *); |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 | extern int Sqlitetestrtree_Init(Tcl_Interp*); extern int Sqlitequota_Init(Tcl_Interp*); extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); extern int SqlitetestSyscall_Init(Tcl_Interp*); extern int Fts5tcl_Init(Tcl_Interp *); extern int SqliteRbu_Init(Tcl_Interp*); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) extern int Sqlitetestfts3_Init(Tcl_Interp *interp); #endif #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); Zipvfs_Init(interp); | > | 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 | extern int Sqlitetestrtree_Init(Tcl_Interp*); extern int Sqlitequota_Init(Tcl_Interp*); extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); extern int SqlitetestSyscall_Init(Tcl_Interp*); extern int Fts5tcl_Init(Tcl_Interp *); extern int SqliteRbu_Init(Tcl_Interp*); extern int Sqlitetesttcl_Init(Tcl_Interp*); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) extern int Sqlitetestfts3_Init(Tcl_Interp *interp); #endif #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); Zipvfs_Init(interp); |
︙ | ︙ | |||
3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 | Sqlitetestrtree_Init(interp); Sqlitequota_Init(interp); Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); SqlitetestSyscall_Init(interp); Fts5tcl_Init(interp); SqliteRbu_Init(interp); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) Sqlitetestfts3_Init(interp); #endif Tcl_CreateObjCommand( interp, "load_testfixture_extensions", init_all_cmd, 0, 0 | > | 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 | Sqlitetestrtree_Init(interp); Sqlitequota_Init(interp); Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); SqlitetestSyscall_Init(interp); Fts5tcl_Init(interp); SqliteRbu_Init(interp); Sqlitetesttcl_Init(interp); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) Sqlitetestfts3_Init(interp); #endif Tcl_CreateObjCommand( interp, "load_testfixture_extensions", init_all_cmd, 0, 0 |
︙ | ︙ |
Added src/test_bestindex.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | /* ** 2016-03-01 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the virtual table xBestIndex method and the query ** planner. */ /* ** INSTRUCTIONS ** ** This module exports a single tcl command - [register_tcl_module]. When ** invoked, it registers a special virtual table module with a database ** connection. ** ** The virtual table is currently read-only. And always returns zero rows. ** It is created with a single argument - the name of a Tcl command - as ** follows: ** ** CREATE VIRTUAL TABLE x1 USING tcl(tcl_command); ** ** The command [tcl_command] is invoked when the table is first created (or ** connected), when the xBestIndex() method is invoked and when the xFilter() ** method is called. When it is created (or connected), it is invoked as ** follows: ** ** tcl_command xConnect ** ** In this case the return value of the script is passed to the ** sqlite3_declare_vtab() function to create the virtual table schema. ** ** When the xBestIndex() method is called by SQLite, the Tcl command is ** invoked as: ** ** tcl_command xBestIndex CONSTRAINTS ORDERBY MASK ** ** where CONSTRAINTS is a tcl representation of the aConstraints[] array, ** ORDERBY is a representation of the contents of the aOrderBy[] array and ** MASK is a copy of sqlite3_index_info.colUsed. For example if the virtual ** table is declared as: ** ** CREATE TABLE x1(a, b, c) ** ** and the query is: ** ** SELECT * FROM x1 WHERE a=? AND c<? ORDER BY b, c; ** ** then the Tcl command is: ** ** tcl_command xBestIndex \ ** {{op eq column 0 usable 1} {op lt column 2 usable 1}} \ ** {{column 1 desc 0} {column 2 desc 0}} \ ** 7 ** ** The return value of the script is a list of key-value pairs used to ** populate the output fields of the sqlite3_index_info structure. Possible ** keys and the usage of the accompanying values are: ** ** "orderby" (value of orderByConsumed flag) ** "cost" (value of estimatedCost field) ** "rows" (value of estimatedRows field) ** "use" (index of used constraint in aConstraint[]) ** "omit" (like "use", but also sets omit flag) ** "idxnum" (value of idxNum field) ** "idxstr" (value of idxStr field) ** ** Refer to code below for further details. ** ** When SQLite calls the xFilter() method, this module invokes the following ** Tcl script: ** ** tcl_command xFilter IDXNUM IDXSTR ARGLIST ** ** IDXNUM and IDXSTR are the values of the idxNum and idxStr parameters ** passed to xFilter. ARGLIST is a Tcl list containing each of the arguments ** passed to xFilter in text form. ** ** As with xBestIndex(), the return value of the script is interpreted as a ** list of key-value pairs. There is currently only one key defined - "sql". ** The value must be the full text of an SQL statement that returns the data ** for the current scan. The leftmost column returned by the SELECT is assumed ** to contain the rowid. Other columns must follow, in order from left to ** right. */ #include "sqliteInt.h" #include "tcl.h" #ifndef SQLITE_OMIT_VIRTUALTABLE typedef struct tcl_vtab tcl_vtab; typedef struct tcl_cursor tcl_cursor; /* ** A fs virtual-table object */ struct tcl_vtab { sqlite3_vtab base; Tcl_Interp *interp; Tcl_Obj *pCmd; sqlite3 *db; }; /* A tcl cursor object */ struct tcl_cursor { sqlite3_vtab_cursor base; sqlite3_stmt *pStmt; /* Read data from here */ }; /* ** This function is the implementation of both the xConnect and xCreate ** methods of the fs virtual table. ** ** The argv[] array contains the following: ** ** argv[0] -> module name ("fs") ** argv[1] -> database name ** argv[2] -> table name ** argv[...] -> other module argument fields. */ static int tclConnect( sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr ){ Tcl_Interp *interp = (Tcl_Interp*)pAux; tcl_vtab *pTab; const char *zCmd; Tcl_Obj *pScript = 0; int rc; if( argc!=4 ){ *pzErr = sqlite3_mprintf("wrong number of arguments"); return SQLITE_ERROR; } zCmd = argv[3]; pTab = (tcl_vtab*)sqlite3_malloc(sizeof(tcl_vtab)); if( pTab==0 ) return SQLITE_NOMEM; memset(pTab, 0, sizeof(tcl_vtab)); pTab->pCmd = Tcl_NewStringObj(zCmd, -1); pTab->interp = interp; pTab->db = db; Tcl_IncrRefCount(pTab->pCmd); pScript = Tcl_DuplicateObj(pTab->pCmd); Tcl_IncrRefCount(pScript); Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xConnect", -1)); rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); if( rc!=TCL_OK ){ *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); rc = SQLITE_ERROR; }else{ rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); } if( rc!=SQLITE_OK ){ sqlite3_free(pTab); pTab = 0; } *ppVtab = &pTab->base; return rc; } /* The xDisconnect and xDestroy methods are also the same */ static int tclDisconnect(sqlite3_vtab *pVtab){ tcl_vtab *pTab = (tcl_vtab*)pVtab; Tcl_DecrRefCount(pTab->pCmd); sqlite3_free(pTab); return SQLITE_OK; } /* ** Open a new tcl cursor. */ static int tclOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ tcl_cursor *pCur; pCur = sqlite3_malloc(sizeof(tcl_cursor)); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(tcl_cursor)); *ppCursor = &pCur->base; return SQLITE_OK; } /* ** Close a tcl cursor. */ static int tclClose(sqlite3_vtab_cursor *cur){ tcl_cursor *pCur = (tcl_cursor *)cur; if( pCur ){ sqlite3_finalize(pCur->pStmt); sqlite3_free(pCur); } return SQLITE_OK; } static int tclNext(sqlite3_vtab_cursor *pVtabCursor){ tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; if( pCsr->pStmt ){ tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); int rc = sqlite3_step(pCsr->pStmt); if( rc!=SQLITE_ROW ){ const char *zErr; rc = sqlite3_finalize(pCsr->pStmt); pCsr->pStmt = 0; if( rc!=SQLITE_OK ){ zErr = sqlite3_errmsg(pTab->db); pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); } } } return SQLITE_OK; } static int tclFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; tcl_vtab *pTab = (tcl_vtab*)(pVtabCursor->pVtab); Tcl_Interp *interp = pTab->interp; Tcl_Obj *pScript; Tcl_Obj *pArg; int ii; int rc; pScript = Tcl_DuplicateObj(pTab->pCmd); Tcl_IncrRefCount(pScript); Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xFilter", -1)); Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(idxNum)); if( idxStr ){ Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(idxStr, -1)); }else{ Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("", -1)); } pArg = Tcl_NewObj(); Tcl_IncrRefCount(pArg); for(ii=0; ii<argc; ii++){ const char *zVal = (const char*)sqlite3_value_text(argv[ii]); Tcl_Obj *pVal; if( zVal==0 ){ pVal = Tcl_NewObj(); }else{ pVal = Tcl_NewStringObj(zVal, -1); } Tcl_ListObjAppendElement(interp, pArg, pVal); } Tcl_ListObjAppendElement(interp, pScript, pArg); Tcl_DecrRefCount(pArg); rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); if( rc!=TCL_OK ){ const char *zErr = Tcl_GetStringResult(interp); rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); }else{ /* Analyze the scripts return value. The return value should be a tcl ** list object with an even number of elements. The first element of each ** pair must be one of: ** ** "sql" (SQL statement to return data) */ Tcl_Obj *pRes = Tcl_GetObjResult(interp); Tcl_Obj **apElem = 0; int nElem; rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem); if( rc!=TCL_OK ){ const char *zErr = Tcl_GetStringResult(interp); rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); }else{ for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){ const char *zCmd = Tcl_GetString(apElem[ii]); Tcl_Obj *p = apElem[ii+1]; if( sqlite3_stricmp("sql", zCmd)==0 ){ const char *zSql = Tcl_GetString(p); rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0); if( rc!=SQLITE_OK ){ const char *zErr = sqlite3_errmsg(pTab->db); pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zErr); } }else{ rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd); } } } } if( rc==SQLITE_OK ){ rc = tclNext(pVtabCursor); } return rc; } static int tclColumn( sqlite3_vtab_cursor *pVtabCursor, sqlite3_context *ctx, int i ){ tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1)); return SQLITE_OK; } static int tclRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); return SQLITE_OK; } static int tclEof(sqlite3_vtab_cursor *pVtabCursor){ tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor; return (pCsr->pStmt==0); } static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ tcl_vtab *pTab = (tcl_vtab*)tab; Tcl_Interp *interp = pTab->interp; Tcl_Obj *pArg; Tcl_Obj *pScript; int ii; int rc = SQLITE_OK; pScript = Tcl_DuplicateObj(pTab->pCmd); Tcl_IncrRefCount(pScript); Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1)); pArg = Tcl_NewObj(); Tcl_IncrRefCount(pArg); for(ii=0; ii<pIdxInfo->nConstraint; ii++){ struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; Tcl_Obj *pElem = Tcl_NewObj(); const char *zOp = "?"; Tcl_IncrRefCount(pElem); switch( pCons->op ){ case SQLITE_INDEX_CONSTRAINT_EQ: zOp = "eq"; break; case SQLITE_INDEX_CONSTRAINT_GT: zOp = "gt"; break; case SQLITE_INDEX_CONSTRAINT_LE: zOp = "le"; break; case SQLITE_INDEX_CONSTRAINT_LT: zOp = "lt"; break; case SQLITE_INDEX_CONSTRAINT_GE: zOp = "ge"; break; case SQLITE_INDEX_CONSTRAINT_MATCH: zOp = "match"; break; case SQLITE_INDEX_CONSTRAINT_LIKE: zOp = "like"; break; case SQLITE_INDEX_CONSTRAINT_GLOB: zOp = "glob"; break; case SQLITE_INDEX_CONSTRAINT_REGEXP: zOp = "regexp"; break; } Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->iColumn)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->usable)); Tcl_ListObjAppendElement(0, pArg, pElem); Tcl_DecrRefCount(pElem); } Tcl_ListObjAppendElement(0, pScript, pArg); Tcl_DecrRefCount(pArg); pArg = Tcl_NewObj(); Tcl_IncrRefCount(pArg); for(ii=0; ii<pIdxInfo->nOrderBy; ii++){ struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[ii]; Tcl_Obj *pElem = Tcl_NewObj(); Tcl_IncrRefCount(pElem); Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->iColumn)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("desc", -1)); Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->desc)); Tcl_ListObjAppendElement(0, pArg, pElem); Tcl_DecrRefCount(pElem); } Tcl_ListObjAppendElement(0, pScript, pArg); Tcl_DecrRefCount(pArg); Tcl_ListObjAppendElement(0, pScript, Tcl_NewWideIntObj(pIdxInfo->colUsed)); rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(pScript); if( rc!=TCL_OK ){ const char *zErr = Tcl_GetStringResult(interp); rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); }else{ /* Analyze the scripts return value. The return value should be a tcl ** list object with an even number of elements. The first element of each ** pair must be one of: ** ** "orderby" (value of orderByConsumed flag) ** "cost" (value of estimatedCost field) ** "rows" (value of estimatedRows field) ** "use" (index of used constraint in aConstraint[]) ** "idxnum" (value of idxNum field) ** "idxstr" (value of idxStr field) ** "omit" (index of omitted constraint in aConstraint[]) */ Tcl_Obj *pRes = Tcl_GetObjResult(interp); Tcl_Obj **apElem = 0; int nElem; rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem); if( rc!=TCL_OK ){ const char *zErr = Tcl_GetStringResult(interp); rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); }else{ int iArgv = 1; for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){ const char *zCmd = Tcl_GetString(apElem[ii]); Tcl_Obj *p = apElem[ii+1]; if( sqlite3_stricmp("cost", zCmd)==0 ){ rc = Tcl_GetDoubleFromObj(interp, p, &pIdxInfo->estimatedCost); }else if( sqlite3_stricmp("orderby", zCmd)==0 ){ rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->orderByConsumed); }else if( sqlite3_stricmp("idxnum", zCmd)==0 ){ rc = Tcl_GetIntFromObj(interp, p, &pIdxInfo->idxNum); }else if( sqlite3_stricmp("idxstr", zCmd)==0 ){ sqlite3_free(pIdxInfo->idxStr); pIdxInfo->idxStr = sqlite3_mprintf("%s", Tcl_GetString(p)); pIdxInfo->needToFreeIdxStr = 1; }else if( sqlite3_stricmp("rows", zCmd)==0 ){ rc = Tcl_GetWideIntFromObj(interp, p, &pIdxInfo->estimatedRows); }else if( sqlite3_stricmp("use", zCmd)==0 || sqlite3_stricmp("omit", zCmd)==0 ){ int iCons; rc = Tcl_GetIntFromObj(interp, p, &iCons); if( rc==SQLITE_OK ){ if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %d", iCons); }else{ int bOmit = (zCmd[0]=='o' || zCmd[0]=='O'); pIdxInfo->aConstraintUsage[iCons].argvIndex = iArgv++; pIdxInfo->aConstraintUsage[iCons].omit = bOmit; } } }else{ rc = SQLITE_ERROR; pTab->base.zErrMsg = sqlite3_mprintf("unexpected: %s", zCmd); } if( rc!=SQLITE_OK && pTab->base.zErrMsg==0 ){ const char *zErr = Tcl_GetStringResult(interp); pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr); } } } } return rc; } /* ** A virtual table module that provides read-only access to a ** Tcl global variable namespace. */ static sqlite3_module tclModule = { 0, /* iVersion */ tclConnect, tclConnect, tclBestIndex, tclDisconnect, tclDisconnect, tclOpen, /* xOpen - open a cursor */ tclClose, /* xClose - close a cursor */ tclFilter, /* xFilter - configure scan constraints */ tclNext, /* xNext - advance a cursor */ tclEof, /* xEof - check for end of scan */ tclColumn, /* xColumn - read data */ tclRowid, /* xRowid - read data */ 0, /* xUpdate */ 0, /* xBegin */ 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ }; /* ** Decode a pointer to an sqlite3 object. */ extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); /* ** Register the echo virtual table module. */ static int register_tcl_module( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3 *db; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_create_module(db, "tcl", &tclModule, (void *)interp); #endif return TCL_OK; } #endif /* ** Register commands with the TCL interpreter. */ int Sqlitetesttcl_Init(Tcl_Interp *interp){ #ifndef SQLITE_OMIT_VIRTUALTABLE static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { { "register_tcl_module", register_tcl_module, 0 }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, aObjCmd[i].clientData, 0); } #endif return TCL_OK; } |
Changes to src/treeview.c.
︙ | ︙ | |||
334 335 336 337 338 339 340 341 342 343 344 345 346 347 | case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; case TK_COLLATE: { sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } | > > > > > > | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; case TK_SPAN: { sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } case TK_COLLATE: { sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 | ** than the actual length of the string. For very long strings (greater ** than 1GiB) the value returned might be less than the true string length. */ int sqlite3Strlen30(const char *z){ if( z==0 ) return 0; return 0x3fffffff & (int)strlen(z); } /* ** Set the current error code to err_code and clear any prior error message. */ void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; | > > > > > > > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | ** than the actual length of the string. For very long strings (greater ** than 1GiB) the value returned might be less than the true string length. */ int sqlite3Strlen30(const char *z){ if( z==0 ) return 0; return 0x3fffffff & (int)strlen(z); } /* ** The string z[] is followed immediately by another string. Return ** a poiner to that other string. */ const char *sqlite3StrNext(const char *z){ return z + strlen(z) + 1; } /* ** Set the current error code to err_code and clear any prior error message. */ void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 | const char *zNeg = ""; int rc = SQLITE_OK; if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } | | | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 | const char *zNeg = ""; int rc = SQLITE_OK; if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; /* Compressed expressions only appear when parsing the DEFAULT clause ** on a table column definition, and hence only when pCtx==0. This ** check ensures that an EP_TokenOnly expression is never passed down ** into valueFromFunction(). */ assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
560 561 562 563 564 565 566 | ** columns of the table to see if any of them contain the token "hidden". ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from ** the type string. */ pVTable->pNext = pTab->pVTable; pTab->pVTable = pVTable; for(iCol=0; iCol<pTab->nCol; iCol++){ | | | | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 | ** columns of the table to see if any of them contain the token "hidden". ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from ** the type string. */ pVTable->pNext = pTab->pVTable; pTab->pVTable = pVTable; for(iCol=0; iCol<pTab->nCol; iCol++){ char *zType = (char*)sqlite3StrNext(pTab->aCol[iCol].zName); int nType; int i = 0; if( !zType[0] ){ pTab->tabFlags |= oooHidden; continue; } nType = sqlite3Strlen30(zType); if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ for(i=0; i<nType; i++){ if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7)) |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
1557 1558 1559 1560 1561 1562 1563 | rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); pBuilder->pRec = pRec; if( rc!=SQLITE_OK ) return rc; if( bOk==0 ) return SQLITE_NOTFOUND; pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); | | > | 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 | rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); pBuilder->pRec = pRec; if( rc!=SQLITE_OK ) return rc; if( bOk==0 ) return SQLITE_NOTFOUND; pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); WHERETRACE(0x10,("equality scan regions %s(%d): %d\n", p->zName, nEq-1, (int)a[1])); *pnRow = a[1]; return rc; } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
︙ | ︙ | |||
2893 2894 2895 2896 2897 2898 2899 | assert( iTerm<pNew->nLSlot ); pNew->aLTerm[iTerm] = pTerm; if( iTerm>mxTerm ) mxTerm = iTerm; testcase( iTerm==15 ); testcase( iTerm==16 ); if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm; if( (pTerm->eOperator & WO_IN)!=0 ){ | < < < < < < < | 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 | assert( iTerm<pNew->nLSlot ); pNew->aLTerm[iTerm] = pTerm; if( iTerm>mxTerm ) mxTerm = iTerm; testcase( iTerm==15 ); testcase( iTerm==16 ); if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm; if( (pTerm->eOperator & WO_IN)!=0 ){ /* A virtual table that is constrained by an IN clause may not ** consume the ORDER BY clause because (1) the order of IN terms ** is not necessarily related to the order of output terms and ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
870 871 872 873 874 875 876 877 878 879 880 881 882 883 | if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 1: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; j<nConstraint; j++){ int iTarget = iReg+j+2; pTerm = pLoop->aLTerm[j]; | > | 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 | if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 1: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; int iIn; /* Counter for IN constraints */ sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; j<nConstraint; j++){ int iTarget = iReg+j+2; pTerm = pLoop->aLTerm[j]; |
︙ | ︙ | |||
892 893 894 895 896 897 898 | sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; | > > > > | > | | > > > > | > > > > > > > > > > > > > | | > > > > > > > > | > | > > > | 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 | sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; pLevel->p1 = iCur; pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); iIn = pLevel->u.in.nIn; for(j=nConstraint-1; j>=0; j--){ pTerm = pLoop->aLTerm[j]; if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ disableTerm(pLevel, pTerm); }else if( (pTerm->eOperator & WO_IN)!=0 ){ Expr *pCompare; /* The comparison operator */ Expr *pRight; /* RHS of the comparison */ VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ /* Reload the constraint value into reg[iReg+j+2]. The same value ** was loaded into the same register prior to the OP_VFilter, but ** the xFilter implementation might have changed the datatype or ** encoding of the value in the register, so it *must* be reloaded. */ assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); if( pLevel->u.in.aInLoop!=0 ){ assert( iIn>0 ); pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop); assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 ); assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 ); testcase( pOp->opcode==OP_Rowid ); sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); } /* Generate code that will continue to the next row if ** the IN constraint is not satisfied */ pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0, 0); assert( pCompare!=0 || db->mallocFailed ); if( pCompare ){ pCompare->pLeft = pTerm->pExpr->pLeft; pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); if( pRight ) pRight->iTable = iReg+j+2; sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); pCompare->pLeft = 0; sqlite3ExprDelete(db, pCompare); } } } sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite3ExprCachePop(pParse); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ if( (pLoop->wsFlags & WHERE_IPK)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0 |
︙ | ︙ |
Changes to test/analyze9.test.
︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 | # # And it should be. The analyzer has a stat4 sample as follows: # # sample=(x=10000, y=100) nLt=(10000 10099) # # There should be no other samples that start with (x=10000). So it knows # that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but | | | 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 | # # And it should be. The analyzer has a stat4 sample as follows: # # sample=(x=10000, y=100) nLt=(10000 10099) # # There should be no other samples that start with (x=10000). So it knows # that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but # no more than that. Guessing less than 20 is therefore unreasonable. # # At one point though, due to a problem in whereKeyStats(), the planner was # estimating that (x=10000 AND y<50) would match only 2 rows. # do_eqp_test 26.1.4 { SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444; } { |
︙ | ︙ |
Changes to test/analyzeD.test.
|
| | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2014-10-04 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # This file implements tests for the ANALYZE command. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix analyzeD ifcapable {!stat4} { finish_test |
︙ | ︙ | |||
71 72 73 74 75 76 77 | do_test 1.3 { execsql { DELETE FROM sqlite_stat1 } db close sqlite3 db test.db } {} # Without stat1, because 3001 is larger than all samples in the stat4 | | | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | do_test 1.3 { execsql { DELETE FROM sqlite_stat1 } db close sqlite3 db test.db } {} # Without stat1, because 3001 is larger than all samples in the stat4 # table, SQLite thinks that a=3001 matches just 1 row. So it (incorrectly) # chooses it over the c=150 index (5 rows). Even with stat1 data, things # worked this way before commit [e6f7f97dbc]. # do_eqp_test 1.4 { SELECT * FROM t1 WHERE a=3001 AND c=150; } { 0 0 0 {SEARCH TABLE t1 USING INDEX t1_ab (a=?)} |
︙ | ︙ |
Added test/bestindex1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | # 2016-03-01 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix bestindex1 register_tcl_module db proc vtab_command {method args} { switch -- $method { xConnect { return "CREATE TABLE t1(a, b, c)" } xBestIndex { set clist [lindex $args 0] if {[llength $clist]!=1} { error "unexpected constraint list" } catch { array unset C } array set C [lindex $clist 0] if {$C(usable)} { return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!" } else { return "cost 1000000 rows 0 idxnum 0 idxstr scan..." } } } return {} } do_execsql_test 1.0 { CREATE VIRTUAL TABLE x1 USING tcl(vtab_command); } {} do_eqp_test 1.1 { SELECT * FROM x1 WHERE a = 'abc' } { 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} } do_eqp_test 1.2 { SELECT * FROM x1 WHERE a IN ('abc', 'def'); } { 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} 0 0 0 {EXECUTE LIST SUBQUERY 1} } #------------------------------------------------------------------------- # reset_db register_tcl_module db # Parameter $mode may be one of: # # "omit" - Implement filtering. Set the omit flag. # "use" - Implement filtering. Use the constraint, but do not set omit. # "use2" - Do not implement filtering. Use the constraint anyway. # # proc t1_vtab {mode method args} { switch -- $method { xConnect { return "CREATE TABLE t1(a, b)" } xBestIndex { set SQL_FILTER {SELECT * FROM t1x WHERE a='%1%'} set SQL_SCAN {SELECT * FROM t1x} set clist [lindex $args 0] set idx 0 for {set idx 0} {$idx < [llength $clist]} {incr idx} { array unset C array set C [lindex $clist $idx] if {$C(column)==0 && $C(op)=="eq" && $C(usable)} { switch -- $mode { "omit" { return [list omit $idx rows 10 cost 10 idxstr $SQL_FILTER] } "use" { return [list use $idx rows 10 cost 10 idxstr $SQL_FILTER] } "use2" { return [list use $idx rows 10 cost 10 idxstr $SQL_SCAN] } default { error "Bad mode - $mode" } } } } return [list idxstr {SELECT * FROM t1x}] } xFilter { set map [list %1% [lindex $args 2 0]] set sql [string map $map [lindex $args 1]] return [list sql $sql] } } return {} } do_execsql_test 2.1 { CREATE TABLE t1x(i INTEGER PRIMARY KEY, a, b); INSERT INTO t1x VALUES(1, 'one', 1); INSERT INTO t1x VALUES(2, 'two', 2); INSERT INTO t1x VALUES(3, 'three', 3); INSERT INTO t1x VALUES(4, 'four', 4); } foreach {tn mode} { 1 use 2 omit 3 use2 } { do_execsql_test 2.2.$mode.1 " DROP TABLE IF EXISTS t1; CREATE VIRTUAL TABLE t1 USING tcl(t1_vtab $mode); " do_execsql_test 2.2.$mode.2 {SELECT * FROM t1} {one 1 two 2 three 3 four 4} do_execsql_test 2.2.$mode.3 {SELECT rowid FROM t1} {1 2 3 4} do_execsql_test 2.2.$mode.4 {SELECT rowid FROM t1 WHERE a='two'} {2} do_execsql_test 2.2.$mode.5 { SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid } {1 4} set plan(use) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} 0 0 0 {EXECUTE LIST SUBQUERY 1} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } set plan(omit) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} 0 0 0 {EXECUTE LIST SUBQUERY 1} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } set plan(use2) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x} 0 0 0 {EXECUTE LIST SUBQUERY 1} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } do_eqp_test 2.2.$mode.6 { SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid } $plan($mode) } finish_test |
Changes to test/permutations.test.
︙ | ︙ | |||
82 83 84 85 86 87 88 | # various test scripts: # # $alltests # $allquicktests # set alltests [list] foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] } | | > > > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | # various test scripts: # # $alltests # $allquicktests # set alltests [list] foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] } foreach f [glob -nocomplain \ $testdir/../ext/rtree/*.test \ $testdir/../ext/fts5/test/*.test \ ] { lappend alltests $f } if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude crash.test crash2.test] } set alltests [test_set $alltests -exclude { |
︙ | ︙ | |||
153 154 155 156 157 158 159 | lappend ::testsuitelist xxx test_suite "veryquick" -prefix "" -description { "Very" quick test suite. Runs in minutes on a workstation. This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ | | > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | lappend ::testsuitelist xxx test_suite "veryquick" -prefix "" -description { "Very" quick test suite. Runs in minutes on a workstation. This test suite is the same as the "quick" tests, except that some files that test malloc and IO errors are omitted. } -files [ test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \ *fts5corrupt* *fts5big* *fts5aj* ] test_suite "extraquick" -prefix "" -description { "Extra" quick test suite. Runs in a few minutes on a workstation. This test suite is the same as the "veryquick" tests, except that slower tests are omitted. } -files [ |
︙ | ︙ | |||
608 609 610 611 612 613 614 615 616 617 618 619 620 621 | memdb.test minmax.test misc1.test misc2.test misc3.test notnull.test null.test progress.test quote.test rowid.test select1.test select2.test select3.test select4.test select5.test select6.test sort.test subselect.test tableapi.test table.test temptable.test trace.test trigger1.test trigger2.test trigger3.test trigger4.test types2.test types.test unique.test update.test vacuum.test view.test where.test } # Run some tests in exclusive locking mode. # test_suite "exclusive" -description { Run tests in exclusive locking mode. } -presql { | > | 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 | memdb.test minmax.test misc1.test misc2.test misc3.test notnull.test null.test progress.test quote.test rowid.test select1.test select2.test select3.test select4.test select5.test select6.test sort.test subselect.test tableapi.test table.test temptable.test trace.test trigger1.test trigger2.test trigger3.test trigger4.test types2.test types.test unique.test update.test vacuum.test view.test where.test bestindex1.test } # Run some tests in exclusive locking mode. # test_suite "exclusive" -description { Run tests in exclusive locking mode. } -presql { |
︙ | ︙ |
Changes to test/releasetest.tcl.
︙ | ︙ | |||
199 200 201 202 203 204 205 206 207 208 209 210 211 212 | -DSQLITE_MAX_ATTACHED=62 } "Devkit" { -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_MAX_ATTACHED=30 -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS4_PARENTHESIS -DSQLITE_DISABLE_FTS4_DEFERRED -DSQLITE_ENABLE_RTREE --enable-json1 --enable-fts5 } "No-lookaside" { -DSQLITE_TEST_REALLOC_STRESS=1 | > | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | -DSQLITE_MAX_ATTACHED=62 } "Devkit" { -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_MAX_ATTACHED=30 -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS4_PARENTHESIS -DSQLITE_DISABLE_FTS4_DEFERRED -DSQLITE_ENABLE_RTREE --enable-json1 --enable-fts5 } "No-lookaside" { -DSQLITE_TEST_REALLOC_STRESS=1 |
︙ | ︙ |
Changes to test/tabfunc01.test.
︙ | ︙ | |||
115 116 117 118 119 120 121 122 123 | SELECT * FROM temp.generate_series(1,4) } {1 {no such table: temp.generate_series}} do_catchsql_test tabfunc01-4.3 { ATTACH ':memory:' AS aux1; CREATE TABLE aux1.t1(a,b,c); SELECT * FROM aux1.generate_series(1,4) } {1 {no such table: aux1.generate_series}} finish_test | > > > > > > > > > > > > > > > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | SELECT * FROM temp.generate_series(1,4) } {1 {no such table: temp.generate_series}} do_catchsql_test tabfunc01-4.3 { ATTACH ':memory:' AS aux1; CREATE TABLE aux1.t1(a,b,c); SELECT * FROM aux1.generate_series(1,4) } {1 {no such table: aux1.generate_series}} # The next series of tests is verifying that virtual table are able # to optimize the IN operator, even on terms that are not marked "omit". # When the generate_series virtual table is compiled for the testfixture, # the special -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 option is used, which # causes the xBestIndex method of generate_series to leave the # sqlite3_index_constraint_usage.omit flag set to 0, which should cause # the SQLite core to verify the start=, stop=, and step= constraints on # each step of output. At one point, the IN operator could not be used # by virtual tables unless omit was set. # do_execsql_test tabfunc01-500 { SELECT * FROM generate_series WHERE start IN (1,7) AND stop=20 AND step=10 ORDER BY +1; } {1 7 11 17} finish_test |
Changes to tool/addopcodes.tcl.
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 | COLUMN AGG_FUNCTION AGG_COLUMN UMINUS UPLUS REGISTER ASTERISK SPACE ILLEGAL } if {[lrange $extras end-1 end]!="SPACE ILLEGAL"} { error "SPACE and ILLEGAL must be the last two token codes and they\ must be in that order" } | > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | COLUMN AGG_FUNCTION AGG_COLUMN UMINUS UPLUS REGISTER ASTERISK SPAN SPACE ILLEGAL } if {[lrange $extras end-1 end]!="SPACE ILLEGAL"} { error "SPACE and ILLEGAL must be the last two token codes and they\ must be in that order" } |
︙ | ︙ |