mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add index access methods to the DBBE in preparation for adding a new
DBBE for the btree.c module. (CVS 236) FossilOrigin-Name: c15f6ffc4d41f30a06d750c8015226713ae0126b
This commit is contained in:
30
manifest
30
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Version\s1.0.32\s(CVS\s471)
|
C Add\sindex\saccess\smethods\sto\sthe\sDBBE\sin\spreparation\sfor\sadding\sa\snew\nDBBE\sfor\sthe\sbtree.c\smodule.\s(CVS\s236)
|
||||||
D 2001-07-23T14:35:00
|
D 2001-08-19T18:19:46
|
||||||
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
||||||
F Makefile.in a4595a83d56549b527dace5415729d20995f717b
|
F Makefile.in a4595a83d56549b527dace5415729d20995f717b
|
||||||
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
|
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
|
||||||
@@ -17,9 +17,9 @@ F src/btree.c d6bbe3152ce3eb47ffd0c797897bf75c5ca784fc
|
|||||||
F src/btree.h 5fb5799bcb39900386ce6cae61fa33e357851ffe
|
F src/btree.h 5fb5799bcb39900386ce6cae61fa33e357851ffe
|
||||||
F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651
|
F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651
|
||||||
F src/dbbe.c b18259f99d87240cbe751021cf14dd3aa83a48af
|
F src/dbbe.c b18259f99d87240cbe751021cf14dd3aa83a48af
|
||||||
F src/dbbe.h 7235b15c6c5d8be0c4da469cef9620cee70b1cc8
|
F src/dbbe.h bbb53eafcd1e3186597f6ee4a17ef2501f1b0628
|
||||||
F src/dbbegdbm.c d75c45d39f15970c6e2881e955b799643649ebb1
|
F src/dbbegdbm.c cbb6ebc79a7100324f07b67d4e867faca9f9efa9
|
||||||
F src/dbbemem.c f76343d1ad1f92f1367536973e2c1d17c2f7686f
|
F src/dbbemem.c f4534a524e956b1db9af070b896040fc1b9cb80e
|
||||||
F src/delete.c 40ddb169ee98013d976b2dadd140d98f7876f54f
|
F src/delete.c 40ddb169ee98013d976b2dadd140d98f7876f54f
|
||||||
F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a
|
F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a
|
||||||
F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7
|
F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7
|
||||||
@@ -49,9 +49,9 @@ F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4
|
|||||||
F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf
|
F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf
|
||||||
F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6
|
F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6
|
||||||
F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc
|
F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc
|
||||||
F src/vdbe.c f93be4414ba892df9c5589815d2a57c1fb12c820
|
F src/vdbe.c b019394ebe0de12917a93ec06d787d8d909726cc
|
||||||
F src/vdbe.h dc1205da434c6a9da03b5d6b089270bbc8e6d437
|
F src/vdbe.h 5331b9a3963d13af01a9cf749f57ac46727bdbe6
|
||||||
F src/where.c 0c542fc44bd85152dfb8507862cfe2e60c629e9f
|
F src/where.c a49083e59358bac83c80cf0d19626d09bab629bd
|
||||||
F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048
|
F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048
|
||||||
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
|
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
|
||||||
F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
|
F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
|
||||||
@@ -59,7 +59,7 @@ F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
|
|||||||
F test/expr.test 80bf8f0e9aa6b9c35bf97ce5d603a28381168d8a
|
F test/expr.test 80bf8f0e9aa6b9c35bf97ce5d603a28381168d8a
|
||||||
F test/func.test ac3def2a673d1042750ae1a4ad1768bb7c7ae90b
|
F test/func.test ac3def2a673d1042750ae1a4ad1768bb7c7ae90b
|
||||||
F test/in.test ea48016c4fcc479d315932ae2b8568146686ffaf
|
F test/in.test ea48016c4fcc479d315932ae2b8568146686ffaf
|
||||||
F test/index.test b189ac11bf8d4fbcf87402f4028c25c8a6d91bb5
|
F test/index.test 266474cd101d7ed3703a0fc0428145cedacc92e0
|
||||||
F test/insert.test dbd3bd189edb61fddbe66c236694ef23352429f1
|
F test/insert.test dbd3bd189edb61fddbe66c236694ef23352429f1
|
||||||
F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
|
F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
|
||||||
F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
|
F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
|
||||||
@@ -67,9 +67,9 @@ F test/main.test da635f9e078cd21ddf074e727381a715064489ff
|
|||||||
F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861
|
F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861
|
||||||
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
|
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
|
||||||
F test/quote.test 40a3164af8456933a81312803fa8cdb21b205c12
|
F test/quote.test 40a3164af8456933a81312803fa8cdb21b205c12
|
||||||
F test/rowid.test 128453599def7435e988216f7fe89c7450b8a9a3
|
F test/rowid.test b01e6dec09780c93f55db6cfe7ad097323954f23
|
||||||
F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f
|
F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f
|
||||||
F test/select2.test 04ac3bd69298f58c7d0883159bab42ab9ad6021c
|
F test/select2.test 4cee2d9d4d7d4657b086569064a0c454e1795afe
|
||||||
F test/select3.test a9234b8424b6c6d71de534f43b91ade9be68e9cc
|
F test/select3.test a9234b8424b6c6d71de534f43b91ade9be68e9cc
|
||||||
F test/select4.test cb5374d7c87680e294ac749307459a5cc547609d
|
F test/select4.test cb5374d7c87680e294ac749307459a5cc547609d
|
||||||
F test/select5.test e2b9d51d88cbd6c307c2c05b0ef55fe7ba811ac2
|
F test/select5.test e2b9d51d88cbd6c307c2c05b0ef55fe7ba811ac2
|
||||||
@@ -82,7 +82,7 @@ F test/tester.tcl 39a707dac2b6048d9c9e07a98d3256d50069fe47
|
|||||||
F test/trans.test 51e50e8273da6845b31a2095e9d3b221fb60d8d0
|
F test/trans.test 51e50e8273da6845b31a2095e9d3b221fb60d8d0
|
||||||
F test/update.test 72c0c93310483b86dc904a992220c5b84c7ce100
|
F test/update.test 72c0c93310483b86dc904a992220c5b84c7ce100
|
||||||
F test/vacuum.test b95d8119a0a83dc6c4ac63888f8872f06199e065
|
F test/vacuum.test b95d8119a0a83dc6c4ac63888f8872f06199e065
|
||||||
F test/where.test bbab5a308055fb6087dc23d600b4ad2b72797397
|
F test/where.test 755957829c493b1b7ad1ecb27d6c782131a6b3d5
|
||||||
F tool/gdbmdump.c 529e67c78d920606ba196326ea55b57b75fcc82b
|
F tool/gdbmdump.c 529e67c78d920606ba196326ea55b57b75fcc82b
|
||||||
F tool/gdbmstat.c 56a9033531e5f5a48413f6ec436d5fb0341632c1
|
F tool/gdbmstat.c 56a9033531e5f5a48413f6ec436d5fb0341632c1
|
||||||
F tool/lemon.c e007bfdbc79a51a4cd7c8a5f81f517cebd121150
|
F tool/lemon.c e007bfdbc79a51a4cd7c8a5f81f517cebd121150
|
||||||
@@ -107,7 +107,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
|
|||||||
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
|
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
|
||||||
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
|
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
|
||||||
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
|
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
|
||||||
P 770e983628d873039857c889ba302cf6926d19d9
|
P cfc86dc48afb6b7e052e418db1c596b665d5cc66
|
||||||
R eec7e6db07d9a5655c1c80f7d8ed8318
|
R 79a41eb08d305d22b658e8f00e7f0110
|
||||||
U drh
|
U drh
|
||||||
Z 72bd26de798d42ee72d6abb10f413593
|
Z 385160b9b18c8b4f775dcbb82eee9159
|
||||||
|
@@ -1 +1 @@
|
|||||||
cfc86dc48afb6b7e052e418db1c596b665d5cc66
|
c15f6ffc4d41f30a06d750c8015226713ae0126b
|
17
src/dbbe.h
17
src/dbbe.h
@@ -28,7 +28,7 @@
|
|||||||
** This library was originally designed to support the following
|
** This library was originally designed to support the following
|
||||||
** backends: GDBM, NDBM, SDBM, Berkeley DB.
|
** backends: GDBM, NDBM, SDBM, Berkeley DB.
|
||||||
**
|
**
|
||||||
** $Id: dbbe.h,v 1.13 2001/04/04 11:48:57 drh Exp $
|
** $Id: dbbe.h,v 1.14 2001/08/19 18:19:46 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_DBBE_H_
|
#ifndef _SQLITE_DBBE_H_
|
||||||
#define _SQLITE_DBBE_H_
|
#define _SQLITE_DBBE_H_
|
||||||
@@ -160,6 +160,21 @@ struct DbbeMethods {
|
|||||||
|
|
||||||
/* Rollback a transaction. */
|
/* Rollback a transaction. */
|
||||||
int (*Rollback)(Dbbe*);
|
int (*Rollback)(Dbbe*);
|
||||||
|
|
||||||
|
/* Begin searching an index where the key is given. */
|
||||||
|
int (*BeginIndex)(DbbeCursor*, int nKey, char *pKey);
|
||||||
|
|
||||||
|
/* Return the integer key for the next index entry, or return 0 if
|
||||||
|
** there are no more index entries. */
|
||||||
|
int (*NextIndex)(DbbeCursor*);
|
||||||
|
|
||||||
|
/* Add a new index entry to the file. The key and record number are
|
||||||
|
** given. */
|
||||||
|
int (*PutIndex)(DbbeCursor*, int nKey, char *pKey, int recno);
|
||||||
|
|
||||||
|
/* Delete an index entry from the file. The key and record number are
|
||||||
|
** given. */
|
||||||
|
int (*DeleteIndex)(DbbeCursor*, int nKey, char *pKey, int recno);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
128
src/dbbegdbm.c
128
src/dbbegdbm.c
@@ -30,7 +30,7 @@
|
|||||||
** relatively simple to convert to a different database such
|
** relatively simple to convert to a different database such
|
||||||
** as NDBM, SDBM, or BerkeleyDB.
|
** as NDBM, SDBM, or BerkeleyDB.
|
||||||
**
|
**
|
||||||
** $Id: dbbegdbm.c,v 1.8 2001/04/28 16:52:41 drh Exp $
|
** $Id: dbbegdbm.c,v 1.9 2001/08/19 18:19:46 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef DISABLE_GDBM
|
#ifndef DISABLE_GDBM
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@@ -87,6 +87,7 @@ struct DbbeCursor {
|
|||||||
BeFile *pFile; /* The database file for this table */
|
BeFile *pFile; /* The database file for this table */
|
||||||
datum key; /* Most recently used key */
|
datum key; /* Most recently used key */
|
||||||
datum data; /* Most recent data */
|
datum data; /* Most recent data */
|
||||||
|
int nextIndex; /* Next index entry to search */
|
||||||
int needRewind; /* Next key should be the first */
|
int needRewind; /* Next key should be the first */
|
||||||
int readPending; /* The fetch hasn't actually been done yet */
|
int readPending; /* The fetch hasn't actually been done yet */
|
||||||
};
|
};
|
||||||
@@ -334,18 +335,18 @@ static void sqliteGdbmCloseCursor(DbbeCursor *pCursr){
|
|||||||
** Reorganize a table to reduce search times and disk usage.
|
** Reorganize a table to reduce search times and disk usage.
|
||||||
*/
|
*/
|
||||||
static int sqliteGdbmReorganizeTable(Dbbe *pBe, const char *zTable){
|
static int sqliteGdbmReorganizeTable(Dbbe *pBe, const char *zTable){
|
||||||
DbbeCursor *pCrsr;
|
DbbeCursor *pCursr;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = sqliteGdbmOpenCursor(pBe, zTable, 1, 0, &pCrsr);
|
rc = sqliteGdbmOpenCursor(pBe, zTable, 1, 0, &pCursr);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if( pCrsr && pCrsr->pFile && pCrsr->pFile->dbf ){
|
if( pCursr && pCursr->pFile && pCursr->pFile->dbf ){
|
||||||
gdbm_reorganize(pCrsr->pFile->dbf);
|
gdbm_reorganize(pCursr->pFile->dbf);
|
||||||
}
|
}
|
||||||
if( pCrsr ){
|
if( pCursr ){
|
||||||
sqliteGdbmCloseCursor(pCrsr);
|
sqliteGdbmCloseCursor(pCursr);
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -586,7 +587,116 @@ static int sqliteGdbmEndTrans(Dbbe *pDbbe){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Begin scanning an index for the given key. Return 1 on success and
|
||||||
|
** 0 on failure.
|
||||||
|
*/
|
||||||
|
static int sqliteGdbmBeginIndex(DbbeCursor *pCursr, int nKey, char *pKey){
|
||||||
|
if( !sqliteGdbmFetch(pCursr, nKey, pKey) ) return 0;
|
||||||
|
pCursr->nextIndex = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return an integer key which is the next record number in the index search
|
||||||
|
** that was started by a prior call to BeginIndex. Return 0 if all records
|
||||||
|
** have already been searched.
|
||||||
|
*/
|
||||||
|
static int sqliteGdbmNextIndex(DbbeCursor *pCursr){
|
||||||
|
int *aIdx;
|
||||||
|
int nIdx;
|
||||||
|
int k;
|
||||||
|
nIdx = pCursr->data.dsize/sizeof(int);
|
||||||
|
aIdx = (int*)pCursr->data.dptr;
|
||||||
|
if( nIdx>1 ){
|
||||||
|
k = *(aIdx++);
|
||||||
|
if( k>nIdx-1 ) k = nIdx-1;
|
||||||
|
}else{
|
||||||
|
k = nIdx;
|
||||||
|
}
|
||||||
|
while( pCursr->nextIndex < k ){
|
||||||
|
int recno = aIdx[pCursr->nextIndex++];
|
||||||
|
if( recno!=0 ) return recno;
|
||||||
|
}
|
||||||
|
pCursr->nextIndex = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write a new record number and key into an index table. Return a status
|
||||||
|
** code.
|
||||||
|
*/
|
||||||
|
static int sqliteGdbmPutIndex(DbbeCursor *pCursr, int nKey, char *pKey, int N){
|
||||||
|
int r = sqliteGdbmFetch(pCursr, nKey, pKey);
|
||||||
|
if( r==0 ){
|
||||||
|
/* Create a new record for this index */
|
||||||
|
sqliteGdbmPut(pCursr, nKey, pKey, sizeof(int), (char*)&N);
|
||||||
|
}else{
|
||||||
|
/* Extend the existing record */
|
||||||
|
int nIdx;
|
||||||
|
int *aIdx;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
nIdx = pCursr->data.dsize/sizeof(int);
|
||||||
|
if( nIdx==1 ){
|
||||||
|
aIdx = sqliteMalloc( sizeof(int)*4 );
|
||||||
|
if( aIdx==0 ) return SQLITE_NOMEM;
|
||||||
|
aIdx[0] = 2;
|
||||||
|
sqliteGdbmCopyData(pCursr, 0, sizeof(int), (char*)&aIdx[1]);
|
||||||
|
aIdx[2] = N;
|
||||||
|
sqliteGdbmPut(pCursr, nKey, pKey, sizeof(int)*4, (char*)aIdx);
|
||||||
|
sqliteFree(aIdx);
|
||||||
|
}else{
|
||||||
|
aIdx = (int*)sqliteGdbmReadData(pCursr, 0);
|
||||||
|
k = aIdx[0];
|
||||||
|
if( k<nIdx-1 ){
|
||||||
|
aIdx[k+1] = N;
|
||||||
|
aIdx[0]++;
|
||||||
|
sqliteGdbmPut(pCursr, nKey, pKey, sizeof(int)*nIdx, (char*)aIdx);
|
||||||
|
}else{
|
||||||
|
nIdx *= 2;
|
||||||
|
aIdx = sqliteMalloc( sizeof(int)*nIdx );
|
||||||
|
if( aIdx==0 ) return SQLITE_NOMEM;
|
||||||
|
sqliteGdbmCopyData(pCursr, 0, sizeof(int)*(k+1), (char*)aIdx);
|
||||||
|
aIdx[k+1] = N;
|
||||||
|
aIdx[0]++;
|
||||||
|
sqliteGdbmPut(pCursr, nKey, pKey, sizeof(int)*nIdx, (char*)aIdx);
|
||||||
|
sqliteFree(aIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Delete an index entry. Return a status code.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int sqliteGdbmDeleteIndex(DbbeCursor *pCursr, int nKey, char *pKey, int N){
|
||||||
|
int *aIdx;
|
||||||
|
int nIdx;
|
||||||
|
int j, k;
|
||||||
|
int rc;
|
||||||
|
rc = sqliteGdbmFetch(pCursr, nKey, pKey);
|
||||||
|
if( !rc ) return SQLITE_OK;
|
||||||
|
nIdx = pCursr->data.dsize/sizeof(int);
|
||||||
|
aIdx = (int*)sqliteGdbmReadData(pCursr, 0);
|
||||||
|
if( (nIdx==1 && aIdx[0]==N) || (aIdx[0]==1 && aIdx[1]==N) ){
|
||||||
|
sqliteGdbmDelete(pCursr, nKey, pKey);
|
||||||
|
}else{
|
||||||
|
k = aIdx[0];
|
||||||
|
for(j=1; j<=k && aIdx[j]!=N; j++){}
|
||||||
|
if( j>k ) return SQLITE_OK;
|
||||||
|
aIdx[j] = aIdx[k];
|
||||||
|
aIdx[k] = 0;
|
||||||
|
aIdx[0]--;
|
||||||
|
if( aIdx[0]*3 + 1 < nIdx ){
|
||||||
|
nIdx /= 2;
|
||||||
|
}
|
||||||
|
sqliteGdbmPut(pCursr, nKey, pKey, sizeof(int)*nIdx, (char*)aIdx);
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This variable contains pointers to all of the access methods
|
** This variable contains pointers to all of the access methods
|
||||||
@@ -614,6 +724,10 @@ static struct DbbeMethods gdbmMethods = {
|
|||||||
/* BeginTrans */ sqliteGdbmBeginTrans,
|
/* BeginTrans */ sqliteGdbmBeginTrans,
|
||||||
/* Commit */ sqliteGdbmEndTrans,
|
/* Commit */ sqliteGdbmEndTrans,
|
||||||
/* Rollback */ sqliteGdbmEndTrans,
|
/* Rollback */ sqliteGdbmEndTrans,
|
||||||
|
/* BeginIndex */ sqliteGdbmBeginIndex,
|
||||||
|
/* NextIndex */ sqliteGdbmNextIndex,
|
||||||
|
/* PutIndex */ sqliteGdbmPutIndex,
|
||||||
|
/* DeleteIndex */ sqliteGdbmDeleteIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
121
src/dbbemem.c
121
src/dbbemem.c
@@ -30,7 +30,7 @@
|
|||||||
** Nothing is ever written to disk using this backend. All information
|
** Nothing is ever written to disk using this backend. All information
|
||||||
** is forgotten when the program exits.
|
** is forgotten when the program exits.
|
||||||
**
|
**
|
||||||
** $Id: dbbemem.c,v 1.15 2001/04/28 16:52:42 drh Exp $
|
** $Id: dbbemem.c,v 1.16 2001/08/19 18:19:46 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -371,6 +371,7 @@ struct DbbeCursor {
|
|||||||
MTable *pTble; /* The database file for this table */
|
MTable *pTble; /* The database file for this table */
|
||||||
ArrayElem *elem; /* Most recently accessed record */
|
ArrayElem *elem; /* Most recently accessed record */
|
||||||
int needRewind; /* Next key should be the first */
|
int needRewind; /* Next key should be the first */
|
||||||
|
int nextIndex; /* Next recno in an index entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -722,6 +723,117 @@ static int sqliteMemDelete(DbbeCursor *pCursr, int nKey, char *pKey){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Begin scanning an index for the given key. Return 1 on success and
|
||||||
|
** 0 on failure.
|
||||||
|
*/
|
||||||
|
static int sqliteMemBeginIndex(DbbeCursor *pCursr, int nKey, char *pKey){
|
||||||
|
if( !sqliteMemFetch(pCursr, nKey, pKey) ) return 0;
|
||||||
|
pCursr->nextIndex = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return an integer key which is the next record number in the index search
|
||||||
|
** that was started by a prior call to BeginIndex. Return 0 if all records
|
||||||
|
** have already been searched.
|
||||||
|
*/
|
||||||
|
static int sqliteMemNextIndex(DbbeCursor *pCursr){
|
||||||
|
int *aIdx;
|
||||||
|
int nIdx;
|
||||||
|
int k;
|
||||||
|
nIdx = sqliteMemDataLength(pCursr)/sizeof(int);
|
||||||
|
aIdx = (int*)sqliteMemReadData(pCursr, 0);
|
||||||
|
if( nIdx>1 ){
|
||||||
|
k = *(aIdx++);
|
||||||
|
if( k>nIdx-1 ) k = nIdx-1;
|
||||||
|
}else{
|
||||||
|
k = nIdx;
|
||||||
|
}
|
||||||
|
while( pCursr->nextIndex < k ){
|
||||||
|
int recno = aIdx[pCursr->nextIndex++];
|
||||||
|
if( recno!=0 ) return recno;
|
||||||
|
}
|
||||||
|
pCursr->nextIndex = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write a new record number and key into an index table. Return a status
|
||||||
|
** code.
|
||||||
|
*/
|
||||||
|
static int sqliteMemPutIndex(DbbeCursor *pCursr, int nKey, char *pKey, int N){
|
||||||
|
int r = sqliteMemFetch(pCursr, nKey, pKey);
|
||||||
|
if( r==0 ){
|
||||||
|
/* Create a new record for this index */
|
||||||
|
sqliteMemPut(pCursr, nKey, pKey, sizeof(int), (char*)&N);
|
||||||
|
}else{
|
||||||
|
/* Extend the existing record */
|
||||||
|
int nIdx;
|
||||||
|
int *aIdx;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
nIdx = sqliteMemDataLength(pCursr)/sizeof(int);
|
||||||
|
if( nIdx==1 ){
|
||||||
|
aIdx = sqliteMalloc( sizeof(int)*4 );
|
||||||
|
if( aIdx==0 ) return SQLITE_NOMEM;
|
||||||
|
aIdx[0] = 2;
|
||||||
|
sqliteMemCopyData(pCursr, 0, sizeof(int), (char*)&aIdx[1]);
|
||||||
|
aIdx[2] = N;
|
||||||
|
sqliteMemPut(pCursr, nKey, pKey, sizeof(int)*4, (char*)aIdx);
|
||||||
|
sqliteFree(aIdx);
|
||||||
|
}else{
|
||||||
|
aIdx = (int*)sqliteMemReadData(pCursr, 0);
|
||||||
|
k = aIdx[0];
|
||||||
|
if( k<nIdx-1 ){
|
||||||
|
aIdx[k+1] = N;
|
||||||
|
aIdx[0]++;
|
||||||
|
sqliteMemPut(pCursr, nKey, pKey, sizeof(int)*nIdx, (char*)aIdx);
|
||||||
|
}else{
|
||||||
|
nIdx *= 2;
|
||||||
|
aIdx = sqliteMalloc( sizeof(int)*nIdx );
|
||||||
|
if( aIdx==0 ) return SQLITE_NOMEM;
|
||||||
|
sqliteMemCopyData(pCursr, 0, sizeof(int)*(k+1), (char*)aIdx);
|
||||||
|
aIdx[k+1] = N;
|
||||||
|
aIdx[0]++;
|
||||||
|
sqliteMemPut(pCursr, nKey, pKey, sizeof(int)*nIdx, (char*)aIdx);
|
||||||
|
sqliteFree(aIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Delete an index entry. Return a status code.
|
||||||
|
*/
|
||||||
|
static int sqliteMemDeleteIndex(DbbeCursor *pCursr,int nKey,char *pKey, int N){
|
||||||
|
int *aIdx;
|
||||||
|
int nIdx;
|
||||||
|
int j, k;
|
||||||
|
int rc;
|
||||||
|
rc = sqliteMemFetch(pCursr, nKey, pKey);
|
||||||
|
if( !rc ) return SQLITE_OK;
|
||||||
|
nIdx = sqliteMemDataLength(pCursr)/sizeof(int);
|
||||||
|
if( nIdx==0 ) return SQLITE_OK;
|
||||||
|
aIdx = (int*)sqliteMemReadData(pCursr, 0);
|
||||||
|
if( (nIdx==1 && aIdx[0]==N) || (aIdx[0]==1 && aIdx[1]==N) ){
|
||||||
|
sqliteMemDelete(pCursr, nKey, pKey);
|
||||||
|
}else{
|
||||||
|
k = aIdx[0];
|
||||||
|
for(j=1; j<=k && aIdx[j]!=N; j++){}
|
||||||
|
if( j>k ) return SQLITE_OK;
|
||||||
|
aIdx[j] = aIdx[k];
|
||||||
|
aIdx[k] = 0;
|
||||||
|
aIdx[0]--;
|
||||||
|
if( aIdx[0]*3 + 1 < nIdx ){
|
||||||
|
nIdx /= 2;
|
||||||
|
}
|
||||||
|
sqliteMemPut(pCursr, nKey, pKey, sizeof(int)*nIdx, (char*)aIdx);
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This variable contains pointers to all of the access methods
|
** This variable contains pointers to all of the access methods
|
||||||
** used to implement the MEMORY backend.
|
** used to implement the MEMORY backend.
|
||||||
@@ -745,6 +857,13 @@ static struct DbbeMethods memoryMethods = {
|
|||||||
/* New */ sqliteMemNew,
|
/* New */ sqliteMemNew,
|
||||||
/* Put */ sqliteMemPut,
|
/* Put */ sqliteMemPut,
|
||||||
/* Delete */ sqliteMemDelete,
|
/* Delete */ sqliteMemDelete,
|
||||||
|
/* BeginTrans */ 0,
|
||||||
|
/* Commit */ 0,
|
||||||
|
/* Rollback */ 0,
|
||||||
|
/* BeginIndex */ sqliteMemBeginIndex,
|
||||||
|
/* NextIndex */ sqliteMemNextIndex,
|
||||||
|
/* PutIndex */ sqliteMemPutIndex,
|
||||||
|
/* DeleteIndex */ sqliteMemDeleteIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
160
src/vdbe.c
160
src/vdbe.c
@@ -41,7 +41,7 @@
|
|||||||
** But other routines are also provided to help in building up
|
** But other routines are also provided to help in building up
|
||||||
** a program instruction by instruction.
|
** a program instruction by instruction.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.58 2001/04/28 16:52:42 drh Exp $
|
** $Id: vdbe.c,v 1.59 2001/08/19 18:19:46 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -822,7 +822,7 @@ static char *zOpName[] = { 0,
|
|||||||
"Fcnt", "New", "Put", "Distinct",
|
"Fcnt", "New", "Put", "Distinct",
|
||||||
"Found", "NotFound", "Delete", "Field",
|
"Found", "NotFound", "Delete", "Field",
|
||||||
"KeyAsData", "Key", "FullKey", "Rewind",
|
"KeyAsData", "Key", "FullKey", "Rewind",
|
||||||
"Next", "Destroy", "Reorganize", "ResetIdx",
|
"Next", "Destroy", "Reorganize", "BeginIdx",
|
||||||
"NextIdx", "PutIdx", "DeleteIdx", "MemLoad",
|
"NextIdx", "PutIdx", "DeleteIdx", "MemLoad",
|
||||||
"MemStore", "ListOpen", "ListWrite", "ListRewind",
|
"MemStore", "ListOpen", "ListWrite", "ListRewind",
|
||||||
"ListRead", "ListClose", "SortOpen", "SortPut",
|
"ListRead", "ListClose", "SortOpen", "SortPut",
|
||||||
@@ -2245,35 +2245,33 @@ int sqliteVdbeExec(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: ResetIdx P1 * *
|
/* Opcode: BeginIdx P1 * *
|
||||||
**
|
**
|
||||||
** Begin treating the current data in cursor P1 as a bunch of integer
|
** Begin searching an index for records with the key found on the
|
||||||
** keys to records of a (separate) SQL table file. This instruction
|
** top of the stack. The stack is popped once. Subsequent calls
|
||||||
** causes the new NextIdx instruction push the first integer table
|
** to NextIdx will push record numbers onto the stack until all
|
||||||
** key in the data.
|
** records with the same key have been returned.
|
||||||
*/
|
*/
|
||||||
case OP_ResetIdx: {
|
case OP_BeginIdx: {
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
if( i>=0 && i<p->nCursor ){
|
int tos = p->tos;
|
||||||
p->aCsr[i].index = 0;
|
VERIFY( if( tos<0 ) goto not_enough_stack; )
|
||||||
|
if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
|
||||||
|
if( Stringify(p, tos) ) goto no_mem;
|
||||||
|
pBex->BeginIndex(p->aCsr[i].pCursor, aStack[tos].n, zStack[tos]);
|
||||||
|
p->aCsr[i].keyIsValid = 0;
|
||||||
}
|
}
|
||||||
|
POPSTACK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: NextIdx P1 P2 *
|
/* Opcode: NextIdx P1 P2 *
|
||||||
**
|
**
|
||||||
** The P1 cursor points to an SQL index. The data from the most
|
** The P1 cursor points to an SQL index for which a BeginIdx operation
|
||||||
** recent fetch on that cursor consists of a bunch of integers where
|
** has been issued. This operation retrieves the next record number and
|
||||||
** each integer is the key to a record in an SQL table file.
|
** pushes that record number onto the stack. Or, if there are no more
|
||||||
** This instruction grabs the next integer table key from the data
|
** record numbers for the given key, this opcode pushes nothing onto the
|
||||||
** of P1 and pushes that integer onto the stack. The first time
|
** stack but instead jumps to instruction P2.
|
||||||
** this instruction is executed after a fetch, the first integer
|
|
||||||
** table key is pushed. Subsequent integer table keys are pushed
|
|
||||||
** in each subsequent execution of this instruction.
|
|
||||||
**
|
|
||||||
** If there are no more integer table keys in the data of P1
|
|
||||||
** when this instruction is executed, then nothing gets pushed and
|
|
||||||
** there is an immediate jump to instruction P2.
|
|
||||||
*/
|
*/
|
||||||
case OP_NextIdx: {
|
case OP_NextIdx: {
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
@@ -2283,32 +2281,15 @@ int sqliteVdbeExec(
|
|||||||
VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
|
VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
|
||||||
zStack[tos] = 0;
|
zStack[tos] = 0;
|
||||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||||
int *aIdx;
|
int recno = pBex->NextIndex(pCrsr);
|
||||||
int nIdx;
|
if( recno!=0 ){
|
||||||
int j, k;
|
p->aCsr[i].lastKey = aStack[tos].i = recno;
|
||||||
nIdx = pBex->DataLength(pCrsr)/sizeof(int);
|
p->aCsr[i].keyIsValid = 1;
|
||||||
aIdx = (int*)pBex->ReadData(pCrsr, 0);
|
aStack[tos].flags = STK_Int;
|
||||||
if( nIdx>1 ){
|
|
||||||
k = *(aIdx++);
|
|
||||||
if( k>nIdx-1 ) k = nIdx-1;
|
|
||||||
}else{
|
}else{
|
||||||
k = nIdx;
|
|
||||||
}
|
|
||||||
p->aCsr[i].keyIsValid = 0;
|
|
||||||
for(j=p->aCsr[i].index; j<k; j++){
|
|
||||||
if( aIdx[j]!=0 ){
|
|
||||||
aStack[tos].i = p->aCsr[i].lastKey = aIdx[j];
|
|
||||||
p->aCsr[i].keyIsValid = 1;
|
|
||||||
aStack[tos].flags = STK_Int;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( j>=k ){
|
|
||||||
j = -1;
|
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
}
|
}
|
||||||
p->aCsr[i].index = j+1;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2317,10 +2298,9 @@ int sqliteVdbeExec(
|
|||||||
**
|
**
|
||||||
** The top of the stack hold an SQL index key (probably made using the
|
** The top of the stack hold an SQL index key (probably made using the
|
||||||
** MakeKey instruction) and next on stack holds an integer which
|
** MakeKey instruction) and next on stack holds an integer which
|
||||||
** the key to an SQL table entry. Locate the record in cursor P1
|
** the record number for an SQL table entry. This opcode makes an entry
|
||||||
** that has the same key as on the TOS. Create a new record if
|
** in the index table P1 that associates the key with the record number.
|
||||||
** necessary. Then append the integer table key to the data for that
|
** But the record number and the key are popped from the stack.
|
||||||
** record and write it back to the P1 file.
|
|
||||||
*/
|
*/
|
||||||
case OP_PutIdx: {
|
case OP_PutIdx: {
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
@@ -2329,53 +2309,9 @@ int sqliteVdbeExec(
|
|||||||
DbbeCursor *pCrsr;
|
DbbeCursor *pCrsr;
|
||||||
VERIFY( if( nos<0 ) goto not_enough_stack; )
|
VERIFY( if( nos<0 ) goto not_enough_stack; )
|
||||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||||
int r;
|
|
||||||
int newVal;
|
|
||||||
Integerify(p, nos);
|
Integerify(p, nos);
|
||||||
newVal = aStack[nos].i;
|
|
||||||
if( Stringify(p, tos) ) goto no_mem;
|
if( Stringify(p, tos) ) goto no_mem;
|
||||||
r = pBex->Fetch(pCrsr, aStack[tos].n, zStack[tos]);
|
pBex->PutIndex(pCrsr, aStack[tos].n, zStack[tos], aStack[nos].i);
|
||||||
if( r==0 ){
|
|
||||||
/* Create a new record for this index */
|
|
||||||
pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
|
|
||||||
sizeof(int), (char*)&newVal);
|
|
||||||
}else{
|
|
||||||
/* Extend the existing record */
|
|
||||||
int nIdx;
|
|
||||||
int *aIdx;
|
|
||||||
int k;
|
|
||||||
|
|
||||||
nIdx = pBex->DataLength(pCrsr)/sizeof(int);
|
|
||||||
if( nIdx==1 ){
|
|
||||||
aIdx = sqliteMalloc( sizeof(int)*4 );
|
|
||||||
if( aIdx==0 ) goto no_mem;
|
|
||||||
aIdx[0] = 2;
|
|
||||||
pBex->CopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]);
|
|
||||||
aIdx[2] = newVal;
|
|
||||||
pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
|
|
||||||
sizeof(int)*4, (char*)aIdx);
|
|
||||||
sqliteFree(aIdx);
|
|
||||||
}else{
|
|
||||||
aIdx = (int*)pBex->ReadData(pCrsr, 0);
|
|
||||||
k = aIdx[0];
|
|
||||||
if( k<nIdx-1 ){
|
|
||||||
aIdx[k+1] = newVal;
|
|
||||||
aIdx[0]++;
|
|
||||||
pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
|
|
||||||
sizeof(int)*nIdx, (char*)aIdx);
|
|
||||||
}else{
|
|
||||||
nIdx *= 2;
|
|
||||||
aIdx = sqliteMalloc( sizeof(int)*nIdx );
|
|
||||||
if( aIdx==0 ) goto no_mem;
|
|
||||||
pBex->CopyData(pCrsr, 0, sizeof(int)*(k+1), (char*)aIdx);
|
|
||||||
aIdx[k+1] = newVal;
|
|
||||||
aIdx[0]++;
|
|
||||||
pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
|
|
||||||
sizeof(int)*nIdx, (char*)aIdx);
|
|
||||||
sqliteFree(aIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
@@ -2385,15 +2321,9 @@ int sqliteVdbeExec(
|
|||||||
/* Opcode: DeleteIdx P1 * *
|
/* Opcode: DeleteIdx P1 * *
|
||||||
**
|
**
|
||||||
** The top of the stack is a key and next on stack is integer
|
** The top of the stack is a key and next on stack is integer
|
||||||
** which is the key to a record in an SQL table.
|
** which is a record number for an SQL table. The operation removes
|
||||||
** Locate the record in the cursor P1 (P1 represents an SQL index)
|
** any entry to the index table P1 that associates the key with the
|
||||||
** that has the same key as the top of stack. Then look through
|
** record number.
|
||||||
** the integer table-keys contained in the data of the P1 record.
|
|
||||||
** Remove the integer table-key that matches the NOS and write the
|
|
||||||
** revised data back to P1 with the same key.
|
|
||||||
**
|
|
||||||
** If this routine removes the very last integer table-key from
|
|
||||||
** the P1 data, then the corresponding P1 record is deleted.
|
|
||||||
*/
|
*/
|
||||||
case OP_DeleteIdx: {
|
case OP_DeleteIdx: {
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
@@ -2402,33 +2332,9 @@ int sqliteVdbeExec(
|
|||||||
DbbeCursor *pCrsr;
|
DbbeCursor *pCrsr;
|
||||||
VERIFY( if( nos<0 ) goto not_enough_stack; )
|
VERIFY( if( nos<0 ) goto not_enough_stack; )
|
||||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||||
int *aIdx;
|
|
||||||
int nIdx;
|
|
||||||
int j, k;
|
|
||||||
int r;
|
|
||||||
int oldVal;
|
|
||||||
Integerify(p, nos);
|
Integerify(p, nos);
|
||||||
oldVal = aStack[nos].i;
|
|
||||||
if( Stringify(p, tos) ) goto no_mem;
|
if( Stringify(p, tos) ) goto no_mem;
|
||||||
r = pBex->Fetch(pCrsr, aStack[tos].n, zStack[tos]);
|
pBex->DeleteIndex(pCrsr, aStack[tos].n, zStack[tos], aStack[nos].i);
|
||||||
if( r==0 ) break;
|
|
||||||
nIdx = pBex->DataLength(pCrsr)/sizeof(int);
|
|
||||||
aIdx = (int*)pBex->ReadData(pCrsr, 0);
|
|
||||||
if( (nIdx==1 && aIdx[0]==oldVal) || (aIdx[0]==1 && aIdx[1]==oldVal) ){
|
|
||||||
pBex->Delete(pCrsr, aStack[tos].n, zStack[tos]);
|
|
||||||
}else{
|
|
||||||
k = aIdx[0];
|
|
||||||
for(j=1; j<=k && aIdx[j]!=oldVal; j++){}
|
|
||||||
if( j>k ) break;
|
|
||||||
aIdx[j] = aIdx[k];
|
|
||||||
aIdx[k] = 0;
|
|
||||||
aIdx[0]--;
|
|
||||||
if( aIdx[0]*3 + 1 < nIdx ){
|
|
||||||
nIdx /= 2;
|
|
||||||
}
|
|
||||||
pBex->Put(pCrsr, aStack[tos].n, zStack[tos],
|
|
||||||
sizeof(int)*nIdx, (char*)aIdx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||||
** simple program to access and modify the underlying database.
|
** simple program to access and modify the underlying database.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.h,v 1.17 2001/04/04 11:48:58 drh Exp $
|
** $Id: vdbe.h,v 1.18 2001/08/19 18:19:46 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_VDBE_H_
|
#ifndef _SQLITE_VDBE_H_
|
||||||
#define _SQLITE_VDBE_H_
|
#define _SQLITE_VDBE_H_
|
||||||
@@ -92,7 +92,7 @@ typedef struct VdbeOp VdbeOp;
|
|||||||
#define OP_Destroy 18
|
#define OP_Destroy 18
|
||||||
#define OP_Reorganize 19
|
#define OP_Reorganize 19
|
||||||
|
|
||||||
#define OP_ResetIdx 20
|
#define OP_BeginIdx 20
|
||||||
#define OP_NextIdx 21
|
#define OP_NextIdx 21
|
||||||
#define OP_PutIdx 22
|
#define OP_PutIdx 22
|
||||||
#define OP_DeleteIdx 23
|
#define OP_DeleteIdx 23
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
** the WHERE clause of SQL statements. Also found here are subroutines
|
** the WHERE clause of SQL statements. Also found here are subroutines
|
||||||
** to generate VDBE code to evaluate expressions.
|
** to generate VDBE code to evaluate expressions.
|
||||||
**
|
**
|
||||||
** $Id: where.c,v 1.14 2001/04/11 14:28:43 drh Exp $
|
** $Id: where.c,v 1.15 2001/08/19 18:19:46 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -385,7 +385,7 @@ WhereInfo *sqliteWhereBegin(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nColumn, 0, 0, 0);
|
sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nColumn, 0, 0, 0);
|
||||||
sqliteVdbeAddOp(v, OP_Fetch, base+pTabList->nId+i, 0, 0, 0);
|
sqliteVdbeAddOp(v, OP_BeginIdx, base+pTabList->nId+i, 0, 0, 0);
|
||||||
sqliteVdbeAddOp(v, OP_NextIdx, base+pTabList->nId+i, brk, 0, cont);
|
sqliteVdbeAddOp(v, OP_NextIdx, base+pTabList->nId+i, brk, 0, cont);
|
||||||
if( i==pTabList->nId-1 && pushKey ){
|
if( i==pTabList->nId-1 && pushKey ){
|
||||||
haveKey = 1;
|
haveKey = 1;
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the CREATE INDEX statement.
|
# focus of this file is testing the CREATE INDEX statement.
|
||||||
#
|
#
|
||||||
# $Id: index.test,v 1.9 2001/04/04 11:48:58 drh Exp $
|
# $Id: index.test,v 1.10 2001/08/19 18:19:46 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -349,6 +349,6 @@ do_test index-11.1 {
|
|||||||
execsql "INSERT INTO t3 VALUES('x${i}x',$i,0.$i)"
|
execsql "INSERT INTO t3 VALUES('x${i}x',$i,0.$i)"
|
||||||
}
|
}
|
||||||
execsql {SELECT c, fcnt() FROM t3 WHERE b==10}
|
execsql {SELECT c, fcnt() FROM t3 WHERE b==10}
|
||||||
} {0.10 2}
|
} {0.10 1}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
# focus of this file is testing the magic ROWID column that is
|
# focus of this file is testing the magic ROWID column that is
|
||||||
# found on all tables.
|
# found on all tables.
|
||||||
#
|
#
|
||||||
# $Id: rowid.test,v 1.1 2001/04/04 11:48:58 drh Exp $
|
# $Id: rowid.test,v 1.2 2001/08/19 18:19:46 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -247,13 +247,13 @@ do_test rowid-4.5 {
|
|||||||
SELECT t1.x, fcnt() FROM t2, t1
|
SELECT t1.x, fcnt() FROM t2, t1
|
||||||
WHERE t2.y==256 AND t1.rowid==t2.rowid
|
WHERE t2.y==256 AND t1.rowid==t2.rowid
|
||||||
}
|
}
|
||||||
} {4 3}
|
} {4 2}
|
||||||
do_test rowid-4.5.1 {
|
do_test rowid-4.5.1 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT t1.x, fcnt() FROM t2, t1
|
SELECT t1.x, fcnt() FROM t2, t1
|
||||||
WHERE t1.OID==t2.rowid AND t2.y==81
|
WHERE t1.OID==t2.rowid AND t2.y==81
|
||||||
}
|
}
|
||||||
} {3 3}
|
} {3 2}
|
||||||
do_test rowid-4.6 {
|
do_test rowid-4.6 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT t1.x FROM t1, t2
|
SELECT t1.x FROM t1, t2
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the SELECT statement.
|
# focus of this file is testing the SELECT statement.
|
||||||
#
|
#
|
||||||
# $Id: select2.test,v 1.10 2001/03/15 18:21:22 drh Exp $
|
# $Id: select2.test,v 1.11 2001/08/19 18:19:46 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -105,10 +105,10 @@ do_test select2-3.2c {
|
|||||||
} {500}
|
} {500}
|
||||||
do_test select2-3.2d {
|
do_test select2-3.2d {
|
||||||
execsql {SELECT fcnt() FROM tbl2 WHERE 1000=f2}
|
execsql {SELECT fcnt() FROM tbl2 WHERE 1000=f2}
|
||||||
} {2}
|
} {1}
|
||||||
do_test select2-3.2e {
|
do_test select2-3.2e {
|
||||||
execsql {SELECT fcnt() FROM tbl2 WHERE f2=1000}
|
execsql {SELECT fcnt() FROM tbl2 WHERE f2=1000}
|
||||||
} {2}
|
} {1}
|
||||||
|
|
||||||
# omit the time-dependent tests
|
# omit the time-dependent tests
|
||||||
#
|
#
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the use of indices in WHERE clases.
|
# focus of this file is testing the use of indices in WHERE clases.
|
||||||
#
|
#
|
||||||
# $Id: where.test,v 1.1 2000/06/12 12:20:49 drh Exp $
|
# $Id: where.test,v 1.2 2001/08/19 18:19:46 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -59,37 +59,37 @@ do_test where-1.0 {
|
|||||||
#
|
#
|
||||||
do_test where-1.1 {
|
do_test where-1.1 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w=10}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w=10}
|
||||||
} {3 121 2}
|
} {3 121 1}
|
||||||
do_test where-1.2 {
|
do_test where-1.2 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w=11}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w=11}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.3 {
|
do_test where-1.3 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE 11=w}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE 11=w}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.4 {
|
do_test where-1.4 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE 11=w AND x>2}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE 11=w AND x>2}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.5 {
|
do_test where-1.5 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE y<200 AND w=11 AND x>2}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE y<200 AND w=11 AND x>2}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.6 {
|
do_test where-1.6 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE y<200 AND x>2 AND w=11}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE y<200 AND x>2 AND w=11}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.7 {
|
do_test where-1.7 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w=11 AND y<200 AND x>2}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w=11 AND y<200 AND x>2}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.8 {
|
do_test where-1.8 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w>10 AND y=144 AND x=3}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE w>10 AND y=144 AND x=3}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.9 {
|
do_test where-1.9 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE y=144 AND w>10 AND x=3}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE y=144 AND w>10 AND x=3}
|
||||||
} {3 144 2}
|
} {3 144 1}
|
||||||
do_test where-1.10 {
|
do_test where-1.10 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE x=3 AND w>=10 AND y=121}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE x=3 AND w>=10 AND y=121}
|
||||||
} {3 121 2}
|
} {3 121 1}
|
||||||
do_test where-1.11 {
|
do_test where-1.11 {
|
||||||
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE x=3 AND y=100 AND w<10}
|
execsql {SELECT x, y, fcnt(*) FROM t1 WHERE x=3 AND y=100 AND w<10}
|
||||||
} {3 100 2}
|
} {3 100 1}
|
||||||
|
|
||||||
# Do the same kind of thing except use a join as the data source.
|
# Do the same kind of thing except use a join as the data source.
|
||||||
#
|
#
|
||||||
@@ -98,43 +98,43 @@ do_test where-2.1 {
|
|||||||
SELECT w, p, fcnt(*) FROM t2, t1
|
SELECT w, p, fcnt(*) FROM t2, t1
|
||||||
WHERE x=q AND y=s AND r=8977
|
WHERE x=q AND y=s AND r=8977
|
||||||
}
|
}
|
||||||
} {34 67 4}
|
} {34 67 2}
|
||||||
do_test where-2.2 {
|
do_test where-2.2 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT w, p, fcnt(*) FROM t2, t1
|
SELECT w, p, fcnt(*) FROM t2, t1
|
||||||
WHERE x=q AND s=y AND r=8977
|
WHERE x=q AND s=y AND r=8977
|
||||||
}
|
}
|
||||||
} {34 67 4}
|
} {34 67 2}
|
||||||
do_test where-2.3 {
|
do_test where-2.3 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT w, p, fcnt(*) FROM t2, t1
|
SELECT w, p, fcnt(*) FROM t2, t1
|
||||||
WHERE x=q AND s=y AND r=8977 AND w>10
|
WHERE x=q AND s=y AND r=8977 AND w>10
|
||||||
}
|
}
|
||||||
} {34 67 4}
|
} {34 67 2}
|
||||||
do_test where-2.4 {
|
do_test where-2.4 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT w, p, fcnt(*) FROM t2, t1
|
SELECT w, p, fcnt(*) FROM t2, t1
|
||||||
WHERE p<80 AND x=q AND s=y AND r=8977 AND w>10
|
WHERE p<80 AND x=q AND s=y AND r=8977 AND w>10
|
||||||
}
|
}
|
||||||
} {34 67 4}
|
} {34 67 2}
|
||||||
do_test where-2.5 {
|
do_test where-2.5 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT w, p, fcnt(*) FROM t2, t1
|
SELECT w, p, fcnt(*) FROM t2, t1
|
||||||
WHERE p<80 AND x=q AND 8977=r AND s=y AND w>10
|
WHERE p<80 AND x=q AND 8977=r AND s=y AND w>10
|
||||||
}
|
}
|
||||||
} {34 67 4}
|
} {34 67 2}
|
||||||
do_test where-2.6 {
|
do_test where-2.6 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT w, p, fcnt(*) FROM t2, t1
|
SELECT w, p, fcnt(*) FROM t2, t1
|
||||||
WHERE x=q AND p=77 AND s=y AND w>5
|
WHERE x=q AND p=77 AND s=y AND w>5
|
||||||
}
|
}
|
||||||
} {24 77 4}
|
} {24 77 2}
|
||||||
do_test where-2.7 {
|
do_test where-2.7 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT w, p, fcnt(*) FROM t1, t2
|
SELECT w, p, fcnt(*) FROM t1, t2
|
||||||
WHERE x=q AND p>77 AND s=y AND w=5
|
WHERE x=q AND p>77 AND s=y AND w=5
|
||||||
}
|
}
|
||||||
} {5 96 4}
|
} {5 96 2}
|
||||||
|
|
||||||
# Lets do a 3-way join.
|
# Lets do a 3-way join.
|
||||||
#
|
#
|
||||||
@@ -143,18 +143,18 @@ do_test where-3.1 {
|
|||||||
SELECT A.w, B.p, C.w, fcnt(*) FROM t1 as A, t2 as B, t1 as C
|
SELECT A.w, B.p, C.w, fcnt(*) FROM t1 as A, t2 as B, t1 as C
|
||||||
WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=11
|
WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=11
|
||||||
}
|
}
|
||||||
} {11 90 11 6}
|
} {11 90 11 3}
|
||||||
do_test where-3.2 {
|
do_test where-3.2 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT A.w, B.p, C.w, fcnt(*) FROM t1 as A, t2 as B, t1 as C
|
SELECT A.w, B.p, C.w, fcnt(*) FROM t1 as A, t2 as B, t1 as C
|
||||||
WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=12
|
WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=12
|
||||||
}
|
}
|
||||||
} {12 89 12 6}
|
} {12 89 12 3}
|
||||||
do_test where-3.3 {
|
do_test where-3.3 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT A.w, B.p, C.w, fcnt(*) FROM t1 as A, t2 as B, t1 as C
|
SELECT A.w, B.p, C.w, fcnt(*) FROM t1 as A, t2 as B, t1 as C
|
||||||
WHERE A.w=15 AND B.p=C.w AND B.r=10202-A.y
|
WHERE A.w=15 AND B.p=C.w AND B.r=10202-A.y
|
||||||
}
|
}
|
||||||
} {15 86 86 6}
|
} {15 86 86 3}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
Reference in New Issue
Block a user