Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add experimental sqlite_kvstore table. Currently read-only. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c13692183a5ea0526e6e1b0f5aa6b481 |
User & Date: | dan 2013-07-30 20:01:49.913 |
Context
2013-07-30
| ||
20:27 | Combine the OP_MakeIdxKey and OP_MakeKey opcodes into a single OP_MakeKey that does the work of both. Standardize the parameter meanings on OP_MakeRecord and OP_MakeKey. Remove the unused OP_Seek opcode. Other related code simplifications and cleanup. check-in: ed5d6992cd user: drh tags: trunk | |
20:01 | Add experimental sqlite_kvstore table. Currently read-only. check-in: c13692183a user: dan tags: trunk | |
16:57 | Remove an unnecessary function call in lsm_sorted.c slowing down xNext() operations. check-in: 48d0585fff user: dan tags: trunk | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
143 144 145 146 147 148 149 | Schema *pSchema; HashElem *p; int maxTab = 1; pSchema = pParse->db->aDb[iDb].pSchema; for(p=sqliteHashFirst(&pSchema->idxHash); p;p=sqliteHashNext(p)){ Index *pIdx = (Index*)sqliteHashData(p); | | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | Schema *pSchema; HashElem *p; int maxTab = 1; pSchema = pParse->db->aDb[iDb].pSchema; for(p=sqliteHashFirst(&pSchema->idxHash); p;p=sqliteHashNext(p)){ Index *pIdx = (Index*)sqliteHashData(p); if( pIdx->tnum!=KVSTORE_ROOT && pIdx->tnum > maxTab ) maxTab = pIdx->tnum; } pParse->iNewidxReg = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Integer, maxTab, pParse->iNewidxReg); } sqlite4VdbeAddOp2(v, OP_NewIdxid, pParse->iNewidxReg, iDb); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 | Table *pTab, /* The table containing the value */ int iTabCur, /* The cursor for this table */ int iCol, /* Index of the column to extract */ int regOut /* Extract the valud into this register */ ){ if( iCol<0 ){ sqlite4VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); }else{ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; sqlite4VdbeAddOp3(v, op, iTabCur, iCol, regOut); } if( iCol>=0 ){ sqlite4ColumnDefault(v, pTab, iCol, regOut); } | > > > > | 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 | Table *pTab, /* The table containing the value */ int iTabCur, /* The cursor for this table */ int iCol, /* Index of the column to extract */ int regOut /* Extract the valud into this register */ ){ if( iCol<0 ){ sqlite4VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); }else if( IsKvstore(pTab) ){ int aOp[2] = { OP_RowKey, OP_RowData }; assert( iCol==0 || iCol==1 ); sqlite4VdbeAddOp2(v, aOp[iCol], iTabCur, regOut); }else{ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; sqlite4VdbeAddOp3(v, op, iTabCur, iCol, regOut); } if( iCol>=0 ){ sqlite4ColumnDefault(v, pTab, iCol, regOut); } |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
713 714 715 716 717 718 719 | Table *pTab = (Table *)sqliteHashData(x); int addrRewind; int nIdx = 0; int iPkCsr; Index *pPk; int iCsr; | | | | 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | Table *pTab = (Table *)sqliteHashData(x); int addrRewind; int nIdx = 0; int iPkCsr; Index *pPk; int iCsr; /* Do nothing for views or sqlite_kvstore */ if( IsView(pTab) || IsKvstore(pTab) ) continue; /* Open all indexes for table pTab. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ pPk = pIdx; iPkCsr = nIdx+baseCsr; } |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
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 | sqlite4_value_text(apVal[2], 0) /* Text of CREATE statement */ ); } } return 0; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE4_ error codes to ** indicate success or failure. */ static int sqlite4InitOne(sqlite4 *db, int iDb, char **pzErrMsg){ int rc; Table *pTab; Db *pDb; InitData initData; char const *zMasterSchema; char const *zMasterName; int openedTransaction = 0; | > > > > > > > > > > > > > > > > < < < | | < < < | > > > > > > > > > > | > > < < | < < < < < < > | > | < < < < | 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 | sqlite4_value_text(apVal[2], 0) /* Text of CREATE statement */ ); } } return 0; } static int createSchemaTable( InitData *pInit, const char *zName, i64 iRoot, const char *zSchema ){ Table *pTab; initCallback(pInit, zName, iRoot, zSchema); if( pInit->rc ) return 1; pTab = sqlite4FindTable(pInit->db, zName, pInit->db->aDb[pInit->iDb].zName); if( ALWAYS(pTab) ) pTab->tabFlags |= TF_Readonly; return 0; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE4_ error codes to ** indicate success or failure. */ static int sqlite4InitOne(sqlite4 *db, int iDb, char **pzErrMsg){ int rc; Table *pTab; Db *pDb; InitData initData; char const *zMasterSchema; char const *zMasterName; char const *zKvstoreName; int openedTransaction = 0; static const char *aMaster[] = { "CREATE TABLE sqlite_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")", #ifndef SQLITE4_OMIT_TEMPDB "CREATE TEMP TABLE sqlite_temp_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" #endif }; static const char *aKvstore[] = { "CREATE TABLE sqlite_kvstore(key BLOB PRIMARY KEY, value BLOB)", #ifndef SQLITE4_OMIT_TEMPDB "CREATE TABLE sqlite_temp_kvstore(key BLOB PRIMARY KEY, value BLOB)" #endif }; static const char *aKvstoreName[] = { "sqlite_kvstore", #ifndef SQLITE4_OMIT_TEMPDB "sqlite_temp_kvstore" #endif }; assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite4_mutex_held(db->mutex) ); /* zMasterName is the name of the master table. */ zMasterName = SCHEMA_TABLE(iDb); zKvstoreName = aKvstoreName[iDb==1]; /* Construct the schema tables. */ initData.db = db; initData.iDb = iDb; initData.rc = SQLITE4_OK; initData.pzErrMsg = pzErrMsg; if( createSchemaTable(&initData, zMasterName, 1, aMaster[iDb==1]) || createSchemaTable(&initData, zKvstoreName, KVSTORE_ROOT, aKvstore[iDb==1]) ){ rc = initData.rc; goto error_out; } /* Create a cursor to hold the database open */ pDb = &db->aDb[iDb]; if( pDb->pKV==0 ){ if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ DbSetProperty(db, 1, DB_SchemaLoaded); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
521 522 523 524 525 526 527 528 529 530 531 532 533 534 | #define MASTER_NAME "sqlite_master" #define TEMP_MASTER_NAME "sqlite_temp_master" /* ** The root-page of the master database table. */ #define MASTER_ROOT 1 /* ** The name of the schema table. */ #define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) /* | > > > | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | #define MASTER_NAME "sqlite_master" #define TEMP_MASTER_NAME "sqlite_temp_master" /* ** The root-page of the master database table. */ #define MASTER_ROOT 1 #define KVSTORE_ROOT 0x7fffffff #define IsKvstore(pTab) ((pTab)->pIndex && (pTab)->pIndex->tnum==KVSTORE_ROOT) /* ** The name of the schema table. */ #define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) /* |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 | p1 = pOp->p1; assert( p1<p->nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); pC = p->apCsr[p1]; assert( pC!=0 ); #ifndef SQLITE4_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 ); #endif if( pC->pDecoder==0 ){ mxField = pC->nField; if( pC->pKeyInfo && pC->pKeyInfo->nData ) mxField = pC->pKeyInfo->nData; rc = sqlite4VdbeDecoderCreate(db, pC, 0, mxField, &pC->pDecoder); | > | 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 | p1 = pOp->p1; assert( p1<p->nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); pC = p->apCsr[p1]; assert( pC!=0 ); assert( pC->iRoot!=KVSTORE_ROOT ); #ifndef SQLITE4_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 ); #endif if( pC->pDecoder==0 ){ mxField = pC->nField; if( pC->pKeyInfo && pC->pKeyInfo->nData ) mxField = pC->pKeyInfo->nData; rc = sqlite4VdbeDecoderCreate(db, pC, 0, mxField, &pC->pDecoder); |
︙ | ︙ | |||
2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p2!=0 ); assert( pC!=0 ); assert( OP_SeekLe == OP_SeekLt+1 ); assert( OP_SeekGe == OP_SeekLt+2 ); assert( OP_SeekGt == OP_SeekLt+3 ); /* Encode a database key consisting of the contents of the P4 registers ** starting at register P3. Have the vdbecodec module allocate an extra ** free byte at the end of the database key (see below). */ | > > > > < > | | | | | | | | | | | < < | | | > > > > > > > | | | | | | | | | | | | > > > > | 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p2!=0 ); assert( pC!=0 ); assert( OP_SeekLe == OP_SeekLt+1 ); assert( OP_SeekGe == OP_SeekLt+2 ); assert( OP_SeekGt == OP_SeekLt+3 ); dir = +1; op = pOp->opcode; if( op==OP_SeekLe || op==OP_SeekLt ) dir = -1; /* Encode a database key consisting of the contents of the P4 registers ** starting at register P3. Have the vdbecodec module allocate an extra ** free byte at the end of the database key (see below). */ nField = pOp->p4.i; pIn3 = &aMem[pOp->p3]; if( pC->iRoot!=KVSTORE_ROOT ){ rc = sqlite4VdbeEncodeKey( db, pIn3, nField, nField+(pOp->p5 & OPFLAG_PARTIALKEY), pC->iRoot, pC->pKeyInfo, &aProbe, &nProbe, 1 ); /* Opcode search-dir increment-key ** -------------------------------------- ** SeekLt -1 no ** SeekLe -1 yes ** SeekGe +1 no ** SeekGt +1 yes */ if( op==OP_SeekLe || op==OP_SeekGt ) aProbe[nProbe++] = 0xFF; if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorSeek(pC->pKVCur, aProbe, nProbe, dir); } }else{ Stringify(pIn3, encoding); rc = sqlite4KVCursorSeek( pC->pKVCur, (const KVByteArray *)pIn3->z, pIn3->n, dir ); } if( rc==SQLITE4_OK ){ if( op==OP_SeekLt ){ rc = sqlite4KVCursorPrev(pC->pKVCur); }else if( op==OP_SeekGt ){ rc = sqlite4KVCursorNext(pC->pKVCur); } } if( pC->iRoot!=KVSTORE_ROOT ){ /* Check that the KV cursor currently points to an entry belonging ** to index pC->iRoot (and not an entry that is part of some other ** index). */ if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){ rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey); if( rc==SQLITE4_OK && memcmp(aKey, aProbe, sqlite4VarintLen(pC->iRoot)) ){ rc = SQLITE4_NOTFOUND; } } /* Free the key allocated above. If no error has occurred but the cursor ** does not currently point to a valid entry, jump to instruction P2. */ sqlite4DbFree(db, aProbe); }else if( rc==SQLITE4_INEXACT ){ rc = SQLITE4_OK; } if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_OK; pc = pOp->p2 - 1; } break; } |
︙ | ︙ |
Changes to src/vdbecursor.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 | ** first element is sought if iEnd==+1 and the last element if iEnd==-1. ** ** Return SQLITE4_OK on success. Return SQLITE4_NOTFOUND if the table is empty. * Other error codes are also possible for various kinds of errors. */ int sqlite4VdbeSeekEnd(VdbeCursor *pC, int iEnd){ KVCursor *pCur = pC->pKVCur; | | < < > > > > > > > > > > > > | | | | | | | | | | | | > | | 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 | ** first element is sought if iEnd==+1 and the last element if iEnd==-1. ** ** Return SQLITE4_OK on success. Return SQLITE4_NOTFOUND if the table is empty. * Other error codes are also possible for various kinds of errors. */ int sqlite4VdbeSeekEnd(VdbeCursor *pC, int iEnd){ KVCursor *pCur = pC->pKVCur; int rc; KVSize nProbe; KVByteArray aProbe[16]; assert( iEnd==(+1) || iEnd==(-1) || iEnd==(-2) ); if( pC->iRoot==KVSTORE_ROOT ){ if( iEnd>0 ){ rc = sqlite4KVCursorSeek(pCur, (const KVByteArray *)"\00", 1, iEnd); }else{ nProbe = sqlite4PutVarint64(aProbe, LARGEST_INT64); rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe, iEnd); } if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK; }else{ const KVByteArray *aKey; KVSize nKey; nProbe = sqlite4PutVarint64(aProbe, pC->iRoot); aProbe[nProbe] = 0xFF; rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe+(iEnd<0), iEnd); if( rc==SQLITE4_OK ){ rc = SQLITE4_CORRUPT_BKPT; }else if( rc==SQLITE4_INEXACT ){ rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); if( rc==SQLITE4_OK && (nKey<nProbe || memcmp(aKey, aProbe, nProbe)!=0) ){ rc = SQLITE4_NOTFOUND; } } pC->rowChnged = 1; } return rc; } /* ** Move a VDBE cursor to the next element in its table. ** Return SQLITE4_NOTFOUND if the seek falls of the end of the table. */ int sqlite4VdbeNext(VdbeCursor *pC){ KVCursor *pCur = pC->pKVCur; const KVByteArray *aKey; KVSize nKey; int rc; sqlite4_uint64 iTabno; rc = sqlite4KVCursorNext(pCur); if( rc==SQLITE4_OK && pC->iRoot!=KVSTORE_ROOT ){ rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ iTabno = 0; sqlite4GetVarint64(aKey, nKey, &iTabno); if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND; } } |
︙ | ︙ | |||
89 90 91 92 93 94 95 | KVCursor *pCur = pC->pKVCur; const KVByteArray *aKey; KVSize nKey; int rc; sqlite4_uint64 iTabno; rc = sqlite4KVCursorPrev(pCur); | | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | KVCursor *pCur = pC->pKVCur; const KVByteArray *aKey; KVSize nKey; int rc; sqlite4_uint64 iTabno; rc = sqlite4KVCursorPrev(pCur); if( rc==SQLITE4_OK && pC->iRoot!=KVSTORE_ROOT ){ rc = sqlite4KVCursorKey(pCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ iTabno = 0; sqlite4GetVarint64(aKey, nKey, &iTabno); if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND; } } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
3668 3669 3670 3671 3672 3673 3674 | codeApplyAffinity(pParse, regBase, nEq+1, zEndAff); nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ } /* Now compute an end-key using OP_MakeIdxKey */ regEndKey = ++pParse->nMem; | > > > > | | | > | 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 | codeApplyAffinity(pParse, regBase, nEq+1, zEndAff); nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ } /* Now compute an end-key using OP_MakeIdxKey */ regEndKey = ++pParse->nMem; if( pIdx->tnum==KVSTORE_ROOT ){ sqlite4VdbeAddOp2(v, OP_Copy, regBase, regEndKey); sqlite4VdbeAddOp1(v, OP_ToBlob, regEndKey); }else{ sqlite4VdbeAddOp4Int( v, OP_MakeIdxKey, iIdxCur, regBase, regEndKey, nConstraint ); } } sqlite4DbFree(pParse->db, zStartAff); sqlite4DbFree(pParse->db, zEndAff); /* Top of the loop body */ |
︙ | ︙ |
Added test/kvstore.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 | # 2013 Jul 31 # # 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. The # focus of this file is testing the SELECT statement. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix kvstore do_execsql_test 1.1 { SELECT * FROM sqlite_kvstore ; CREATE TABLE t1(x); } {} do_execsql_test 1.2 { SELECT quote(key), quote(value) FROM sqlite_kvstore ; } [list \ x'011802' \ x'052a1e1e035e7461626c657431743102435245415445205441424c45207431287829' ] do_execsql_test 1.3 { SELECT quote(key), quote(value) FROM sqlite_temp_kvstore ; } {} do_execsql_test 2.1 { CREATE TABLE t2(x PRIMARY KEY, y UNIQUE); INSERT INTO t2 VALUES(1, 2); INSERT INTO t2 VALUES(3, 4); CREATE INDEX i1 ON t2(y DESC, x DESC); } array unset ::data db eval { SELECT quote(key) AS k, quote(value) AS v FROM sqlite_kvstore } { set ::data($k) $v } do_execsql_test 2.2 { SELECT quote(key) FROM sqlite_kvstore ORDER BY key DESC; } [lsort -decreasing [array names ::data]] do_execsql_test 2.3 { SELECT quote(key) FROM sqlite_kvstore ORDER BY key ASC; } [lsort -incr [array names ::data]] set i 0 foreach k [array names ::data] { do_execsql_test 2.4.$i " SELECT quote(value) FROM sqlite_kvstore WHERE key = $k " $::data($k) incr i } proc key_range {a b} { set res [list] foreach k [lsort [array names ::data]] { if {[string compare $k $a]>=0 && [string compare $k $b]<=0} { lappend res $k } } set res } set sorted_keys [lsort [array names ::data]] set nKey [llength $sorted_keys] for {set i 0} {$i < $nKey} {incr i} { for {set i2 $i} {$i2 < $nKey} {incr i2} { set k1 [lindex $sorted_keys $i] set k2 [lindex $sorted_keys $i2] set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>=$k1 AND key<=$k2" set s1 [lsort [key_range $k1 $k2]] set s2 [lsort -decr [key_range $k1 $k2]] do_execsql_test 2.4.1.$i.$i2.asc " $sql ORDER BY key ASC " $s1 do_execsql_test 2.4.1.$i.$i2.desc " $sql ORDER BY key DESC " $s2 set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>$k1 AND key<=$k2" set s1 [lrange [lsort [key_range $k1 $k2]] 1 end] set s2 [lsort -decr $s1] do_execsql_test 2.4.2.$i.$i2.asc " $sql ORDER BY key ASC " $s1 do_execsql_test 2.4.2.$i.$i2.desc " $sql ORDER BY key DESC " $s2 set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>=$k1 AND key<$k2" set s1 [lrange [lsort [key_range $k1 $k2]] 0 end-1] set s2 [lsort -decr $s1] do_execsql_test 2.4.3.$i.$i2.asc " $sql ORDER BY key ASC " $s1 do_execsql_test 2.4.3.$i.$i2.desc " $sql ORDER BY key DESC " $s2 set sql "SELECT quote(key) FROM sqlite_kvstore WHERE key>$k1 AND key<$k2" set s1 [lrange [lsort [key_range $k1 $k2]] 1 end-1] set s2 [lsort -decr $s1] do_execsql_test 2.4.4.$i.$i2.asc " $sql ORDER BY key ASC " $s1 do_execsql_test 2.4.4.$i.$i2.desc " $sql ORDER BY key DESC " $s2 do_execsql_test 2.4.4.$i.$i2.asc " $sql ORDER BY key ASC " $s1 do_execsql_test 2.4.4.$i.$i2.desc " $sql ORDER BY key DESC " $s2 } } finish_test |
Changes to test/permutations.test.
︙ | ︙ | |||
184 185 186 187 188 189 190 191 192 193 194 195 196 197 | func.test func2.test func3.test fuzz.test fuzz2.test in.test in2.test in3.test in4.test index.test index2.test index3.test index4.test insert.test insert2.test insert3.test insert5.test join.test join2.test join3.test join4.test join5.test join6.test keyword1.test laststmtchanges.test limit.test like.test like2.test main.test manydb.test misc5.test misc6.test misuse.test | > | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | func.test func2.test func3.test fuzz.test fuzz2.test in.test in2.test in3.test in4.test index.test index2.test index3.test index4.test insert.test insert2.test insert3.test insert5.test join.test join2.test join3.test join4.test join5.test join6.test keyword1.test kvstore.test laststmtchanges.test limit.test like.test like2.test main.test manydb.test misc5.test misc6.test misuse.test |
︙ | ︙ |