mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Incremental update. We are in the middle of modifying the index system
to support range queries without doing a complete table scan. (CVS 303) FossilOrigin-Name: e6ca23fa4569bc33065bf57ce7ce6132cd6a9de0
This commit is contained in:
28
manifest
28
manifest
@ -1,5 +1,5 @@
|
||||
C Added\ssupport\sfor\sLIMIT.\s(CVS\s302)
|
||||
D 2001-11-06T14:10:42
|
||||
C Incremental\supdate.\s\sWe\sare\sin\sthe\smiddle\sof\smodifying\sthe\sindex\ssystem\nto\ssupport\srange\squeries\swithout\sdoing\sa\scomplete\stable\sscan.\s(CVS\s303)
|
||||
D 2001-11-07T14:22:00
|
||||
F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd
|
||||
F Makefile.template 1fdb891f14083ee0b63cf7282f91529634438e7a
|
||||
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
||||
@ -19,14 +19,14 @@ F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6
|
||||
F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
|
||||
F publish.sh 33cbe6798969f637698044023c139080e5d772a6
|
||||
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
|
||||
F src/btree.c 2789f704777d29b1b38e62e4798381ce602dc0fb
|
||||
F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7
|
||||
F src/build.c 65438f92919d92c7974e995f2d654b6cb3280a50
|
||||
F src/delete.c a4c13c444544f315703d5fbed6419c8786f66581
|
||||
F src/btree.c add522fad1b18c0face24e6f9f7468a6c696c5cc
|
||||
F src/btree.h 0250a0a577a98cc64ddf1582d50c08b8d2451650
|
||||
F src/build.c b459cbe33ee617f46b1975f96ae605d3519583d9
|
||||
F src/delete.c 9cb0b1470e50881d3404f78af353df3ebb6399e5
|
||||
F src/expr.c 2dd0252ced345c1e64db015b94dc6b5d7a57eef3
|
||||
F src/hash.c d0110e6da70a5962e21575fccf8206f7d9d75e00
|
||||
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
|
||||
F src/insert.c b65c1d4b848e45d41e9dcccd2b226ca335de67b6
|
||||
F src/insert.c 962f277340adc265fbde4dd952055df7ede4e67b
|
||||
F src/main.c e2ae5e14a3f936d5fa7e3d9d9477610b5f16e7eb
|
||||
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
|
||||
F src/os.c 66b677479eae37e30bdfbe32deb0fe6a2efca983
|
||||
@ -36,7 +36,7 @@ F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
|
||||
F src/parse.y 5295f393f41ea89958287e5738e6c12c7cd67482
|
||||
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
|
||||
F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
|
||||
F src/select.c da60dfdd449ef6a71225878aca130b86f298c76e
|
||||
F src/select.c a97d3d27c544dc9a4849bfbad1cfa3e7c673bda9
|
||||
F src/shell.c 71597951753b56a97fea1c7a30908f31e635c00c
|
||||
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
||||
F src/sqlite.h.in 934de9112747ad8d8e7d5fec44876246b24ca5a3
|
||||
@ -47,10 +47,10 @@ F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49
|
||||
F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
|
||||
F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96
|
||||
F src/tokenize.c 830e9ef684334070a26583d94770bb869e2727bf
|
||||
F src/update.c 4eeb154a2da8a934d180e2d9e4211ac0a7a4ce8b
|
||||
F src/update.c b1e315e20b98a013d30fd9ff3b7d9dc4f29b39b3
|
||||
F src/util.c ac83973ecc647d3d3c58708f148442365abf9b94
|
||||
F src/vdbe.c 9f6ff3444a38d9bba27497be56e4ad386b316cbb
|
||||
F src/vdbe.h ea71a2c29d43c03283dee30237a01f4726900b29
|
||||
F src/vdbe.c 24306643bed5e19406735152ad68e98d598dcab0
|
||||
F src/vdbe.h a1170446638ce5b7f078279e640dcf91ec50de01
|
||||
F src/where.c 601f096f2a37ca688a775ca36d33534b13b876cb
|
||||
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
|
||||
F test/bigrow.test 9458134d67f81559845f934fdd6802fe19a68ad1
|
||||
@ -115,7 +115,7 @@ F www/speed.tcl 212a91d555384e01873160d6a189f1490c791bc2
|
||||
F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e
|
||||
F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
|
||||
F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44
|
||||
P eb07768ae93f14bf6c150c1c4329948857a9d01c
|
||||
R 69771165b17aa31e07d926b8467701a7
|
||||
P 177012249ae93dbea4a11fb50faaae7912848bd0
|
||||
R 28881ea0807c6135a3c8ce43fbf768db
|
||||
U drh
|
||||
Z 0d18c20a2f39388100a44f2bc527ed6b
|
||||
Z bdd4c0f13b513e97b71388c7bea5ec3a
|
||||
|
@ -1 +1 @@
|
||||
177012249ae93dbea4a11fb50faaae7912848bd0
|
||||
e6ca23fa4569bc33065bf57ce7ce6132cd6a9de0
|
87
src/btree.c
87
src/btree.c
@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.37 2001/11/04 18:32:47 drh Exp $
|
||||
** $Id: btree.c,v 1.38 2001/11/07 14:22:00 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@ -1085,9 +1085,14 @@ int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the first nKey bytes of the key of the entry that pCur
|
||||
** points to against the first nKey bytes of pKey. Set *pRes to
|
||||
** show the comparison results:
|
||||
** Compare an external key against the key on the entry that pCur points to.
|
||||
**
|
||||
** The external key is pKey and is nKey bytes long. The last nIgnore bytes
|
||||
** of the key associated with pCur are ignored, as if they do not exist.
|
||||
** (The normal case is for nIgnore to be zero in which case the entire
|
||||
** internal key is used in the comparison.)
|
||||
**
|
||||
** The comparison result is written to *pRes as follows:
|
||||
**
|
||||
** *pRes<0 This means pCur<pKey
|
||||
**
|
||||
@ -1095,33 +1100,29 @@ int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
|
||||
**
|
||||
** *pRes>0 This means pCur>pKey
|
||||
**
|
||||
** If pCur contains N bytes where N<nKey and the N bytes of pCur
|
||||
** match the first N bytes of pKey, then *pRes<0 is returned.
|
||||
** If pCur differs from pKey in the first N bytes, then *pRes<0
|
||||
** or *pRes>0 depending on the difference.
|
||||
**
|
||||
** If pCur contains M bytes where M>nKey then only the first nKey
|
||||
** bytes of pCur are used in the comparison. The result is the same
|
||||
** as it would be if pCur were truncated to nKey bytes.
|
||||
** When one key is an exact prefix of the other, the shorter key is
|
||||
** considered less than the longer one. In order to be equal the
|
||||
** keys must be exactly the same length. (The length of the pCur key
|
||||
** is the actual key length minus nIgnore bytes.)
|
||||
*/
|
||||
int sqliteBtreeKeyCompare(
|
||||
BtCursor *pCur,
|
||||
const void *pKey,
|
||||
int nKey,
|
||||
int *pResult
|
||||
BtCursor *pCur, /* Pointer to entry to compare against */
|
||||
const void *pKey, /* Key to compare against entry that pCur points to */
|
||||
int nKey, /* Number of bytes in pKey */
|
||||
int nIgnore, /* Ignore this many bytes at the end of pCur */
|
||||
int *pResult /* Write the result here */
|
||||
){
|
||||
Pgno nextPage;
|
||||
int n, c, rc;
|
||||
int n, c, rc, nLocal;
|
||||
Cell *pCell;
|
||||
const char *zKey = (const char*)pKey;
|
||||
|
||||
assert( pCur->pPage );
|
||||
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
|
||||
pCell = pCur->pPage->apCell[pCur->idx];
|
||||
if( nKey > NKEY(pCell->h) ){
|
||||
nKey = NKEY(pCell->h);
|
||||
}
|
||||
n = nKey;
|
||||
nLocal = NKEY(pCell->h) - nIgnore;
|
||||
if( nLocal<0 ) nLocal = 0;
|
||||
n = nKey<nLocal ? nKey : nLocal;
|
||||
if( n>MX_LOCAL_PAYLOAD ){
|
||||
n = MX_LOCAL_PAYLOAD;
|
||||
}
|
||||
@ -1132,8 +1133,9 @@ int sqliteBtreeKeyCompare(
|
||||
}
|
||||
zKey += n;
|
||||
nKey -= n;
|
||||
nLocal -= n;
|
||||
nextPage = pCell->ovfl;
|
||||
while( nKey>0 ){
|
||||
while( nKey>0 && nLocal>0 ){
|
||||
OverflowPage *pOvfl;
|
||||
if( nextPage==0 ){
|
||||
return SQLITE_CORRUPT;
|
||||
@ -1143,7 +1145,7 @@ int sqliteBtreeKeyCompare(
|
||||
return rc;
|
||||
}
|
||||
nextPage = pOvfl->iNext;
|
||||
n = nKey;
|
||||
n = nKey<nLocal ? nKey : nLocal;
|
||||
if( n>OVERFLOW_SIZE ){
|
||||
n = OVERFLOW_SIZE;
|
||||
}
|
||||
@ -1154,44 +1156,11 @@ int sqliteBtreeKeyCompare(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
nKey -= n;
|
||||
nLocal -= n;
|
||||
zKey += n;
|
||||
}
|
||||
*pResult = c;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the key for the entry that pCur points to against the
|
||||
** given key (pKey,nKeyOrig). Put the comparison result in *pResult.
|
||||
** The result is negative if pCur<pKey, zero if they are equal and
|
||||
** positive if pCur>pKey.
|
||||
**
|
||||
** Shorter strings are considered less than longer strings if they
|
||||
** are otherwise equal. All bytes of both pCur and pKey are considered
|
||||
** in this comparison. This is different from sqliteBtreeKeyCompare()
|
||||
** which only considers the first nKeyOrig bytes of pCur.
|
||||
**
|
||||
** SQLITE_OK is returned on success. If part of the cursor key
|
||||
** is on overflow pages and we are unable to access those overflow
|
||||
** pages, then some other value might be returned to indicate the
|
||||
** reason for the error.
|
||||
*/
|
||||
static int compareKey(
|
||||
BtCursor *pCur, /* Points to the entry against which we are comparing */
|
||||
const char *pKey, /* The comparison key */
|
||||
int nKeyOrig, /* Number of bytes in the comparison key */
|
||||
int *pResult /* Write the comparison results here */
|
||||
){
|
||||
int rc, c;
|
||||
|
||||
rc = sqliteBtreeKeyCompare(pCur, pKey, nKeyOrig, &c);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( c==0 ){
|
||||
Cell *pCell;
|
||||
assert( pCur->pPage );
|
||||
assert( pCur->pPage->nCell>pCur->idx && pCur->idx>=0 );
|
||||
pCell = pCur->pPage->apCell[pCur->idx];
|
||||
c = NKEY(pCell->h) - nKeyOrig;
|
||||
c = nLocal - nKey;
|
||||
}
|
||||
*pResult = c;
|
||||
return SQLITE_OK;
|
||||
@ -1329,7 +1298,7 @@ int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
|
||||
upr = pPage->nCell-1;
|
||||
while( lwr<=upr ){
|
||||
pCur->idx = (lwr+upr)/2;
|
||||
rc = compareKey(pCur, pKey, nKey, &c);
|
||||
rc = sqliteBtreeKeyCompare(pCur, pKey, nKey, 0, &c);
|
||||
if( rc ) return rc;
|
||||
if( c==0 ){
|
||||
pCur->iMatch = c;
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the sqlite B-Tree file
|
||||
** subsystem.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.16 2001/09/27 03:22:33 drh Exp $
|
||||
** @(#) $Id: btree.h,v 1.17 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
@ -41,7 +41,8 @@ int sqliteBtreeFirst(BtCursor*, int *pRes);
|
||||
int sqliteBtreeNext(BtCursor*, int *pRes);
|
||||
int sqliteBtreeKeySize(BtCursor*, int *pSize);
|
||||
int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int sqliteBtreeKeyCompare(BtCursor*, const void *pKey, int nKey, int *pRes);
|
||||
int sqliteBtreeKeyCompare(BtCursor*, const void *pKey, int nKey,
|
||||
int nIgnore, int *pRes);
|
||||
int sqliteBtreeDataSize(BtCursor*, int *pSize);
|
||||
int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int sqliteBtreeCloseCursor(BtCursor*);
|
||||
|
@ -25,7 +25,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.53 2001/11/06 14:10:42 drh Exp $
|
||||
** $Id: build.c,v 1.54 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -991,7 +991,7 @@ void sqliteCreateIndex(
|
||||
sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
|
||||
sqliteVdbeAddOp(v, OP_PutIdx, 1, pIndex->isUnique);
|
||||
sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->isUnique);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, lbl1);
|
||||
sqliteVdbeResolveLabel(v, lbl2);
|
||||
sqliteVdbeAddOp(v, OP_Noop, 0, 0);
|
||||
@ -1282,7 +1282,7 @@ void sqliteCopy(
|
||||
sqliteVdbeAddOp(v, OP_FileColumn, pIdx->aiColumn[j], 0);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqliteVdbeAddOp(v, OP_PutIdx, i, pIdx->isUnique);
|
||||
sqliteVdbeAddOp(v, OP_IdxPut, i, pIdx->isUnique);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
|
||||
sqliteVdbeResolveLabel(v, end);
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.19 2001/11/01 14:41:34 drh Exp $
|
||||
** $Id: delete.c,v 1.20 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -161,7 +161,7 @@ void sqliteDeleteFrom(
|
||||
sqliteVdbeAddOp(v, OP_Column, base, pIdx->aiColumn[j]);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqliteVdbeAddOp(v, OP_DeleteIdx, base+i, 0);
|
||||
sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0);
|
||||
}
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_Delete, base, 0);
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.24 2001/10/15 00:44:36 drh Exp $
|
||||
** $Id: insert.c,v 1.25 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -231,7 +231,7 @@ void sqliteInsert(
|
||||
}
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqliteVdbeAddOp(v, OP_PutIdx, idx+base, pIdx->isUnique);
|
||||
sqliteVdbeAddOp(v, OP_IdxPut, idx+base, pIdx->isUnique);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.47 2001/11/06 14:10:42 drh Exp $
|
||||
** $Id: select.c,v 1.48 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -200,7 +200,7 @@ static int selectInnerLoop(
|
||||
*/
|
||||
if( eDest==SRT_Mem ){
|
||||
assert( nColumn==1 );
|
||||
sqliteVdbeAddOp(v, OP_MemStore, iParm, 0);
|
||||
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, iBreak);
|
||||
}else
|
||||
|
||||
@ -907,7 +907,7 @@ int sqliteSelect(
|
||||
*/
|
||||
if( eDest==SRT_Mem ){
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_MemStore, iParm, 0);
|
||||
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
|
||||
}
|
||||
|
||||
/* Begin the database scan
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle UPDATE statements.
|
||||
**
|
||||
** $Id: update.c,v 1.20 2001/11/01 14:41:34 drh Exp $
|
||||
** $Id: update.c,v 1.21 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -190,7 +190,7 @@ void sqliteUpdate(
|
||||
sqliteVdbeAddOp(v, OP_Column, base, pIdx->aiColumn[j]);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqliteVdbeAddOp(v, OP_DeleteIdx, base+i+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_IdxDelete, base+i+1, 0);
|
||||
}
|
||||
|
||||
/* Compute a completely new data for this record.
|
||||
@ -213,7 +213,7 @@ void sqliteUpdate(
|
||||
sqliteVdbeAddOp(v, OP_Dup, j+pTab->nCol-pIdx->aiColumn[j], 0);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqliteVdbeAddOp(v, OP_PutIdx, base+i+1, pIdx->isUnique);
|
||||
sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, pIdx->isUnique);
|
||||
}
|
||||
|
||||
/* Write the new data back into the database.
|
||||
|
238
src/vdbe.c
238
src/vdbe.c
@ -30,7 +30,7 @@
|
||||
** But other routines are also provided to help in building up
|
||||
** a program instruction by instruction.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.93 2001/11/06 04:00:19 drh Exp $
|
||||
** $Id: vdbe.c,v 1.94 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -843,28 +843,29 @@ static char *zOpName[] = { 0,
|
||||
"MoveTo", "Fcnt", "NewRecno", "Put",
|
||||
"Distinct", "Found", "NotFound", "Delete",
|
||||
"Column", "KeyAsData", "Recno", "FullKey",
|
||||
"Rewind", "Next", "Destroy", "Clear",
|
||||
"CreateIndex", "CreateTable", "Reorganize", "BeginIdx",
|
||||
"NextIdx", "PutIdx", "DeleteIdx", "MemLoad",
|
||||
"Rewind", "Next", "NextN", "Destroy",
|
||||
"Clear", "CreateIndex", "CreateTable", "Reorganize",
|
||||
"BeginIdx", "NextIdx", "IdxPut", "IdxDelete",
|
||||
"IdxRecno", "IdxGT", "IdxGE", "MemLoad",
|
||||
"MemStore", "ListWrite", "ListRewind", "ListRead",
|
||||
"ListReset", "SortPut", "SortMakeRec", "SortMakeKey",
|
||||
"Sort", "SortNext", "SortCallback", "SortReset",
|
||||
"FileOpen", "FileRead", "FileColumn", "AggReset",
|
||||
"AggFocus", "AggIncr", "AggNext", "AggSet",
|
||||
"AggGet", "SetInsert", "SetFound", "SetNotFound",
|
||||
"MakeRecord", "MakeKey", "MakeIdxKey", "Goto",
|
||||
"If", "Halt", "ColumnCount", "ColumnName",
|
||||
"Callback", "NullCallback", "Integer", "String",
|
||||
"Pop", "Dup", "Pull", "Add",
|
||||
"AddImm", "Subtract", "Multiply", "Divide",
|
||||
"Remainder", "BitAnd", "BitOr", "BitNot",
|
||||
"ShiftLeft", "ShiftRight", "AbsValue", "Precision",
|
||||
"Min", "Max", "Like", "Glob",
|
||||
"Eq", "Ne", "Lt", "Le",
|
||||
"Gt", "Ge", "IsNull", "NotNull",
|
||||
"Negative", "And", "Or", "Not",
|
||||
"Concat", "Noop", "Strlen", "Substr",
|
||||
"Limit",
|
||||
"MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey",
|
||||
"Goto", "If", "Halt", "ColumnCount",
|
||||
"ColumnName", "Callback", "NullCallback", "Integer",
|
||||
"String", "Pop", "Dup", "Pull",
|
||||
"Add", "AddImm", "Subtract", "Multiply",
|
||||
"Divide", "Remainder", "BitAnd", "BitOr",
|
||||
"BitNot", "ShiftLeft", "ShiftRight", "AbsValue",
|
||||
"Precision", "Min", "Max", "Like",
|
||||
"Glob", "Eq", "Ne", "Lt",
|
||||
"Le", "Gt", "Ge", "IsNull",
|
||||
"NotNull", "Negative", "And", "Or",
|
||||
"Not", "Concat", "Noop", "Strlen",
|
||||
"Substr", "Limit",
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2156,6 +2157,29 @@ case OP_MakeKey: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IncrKey * * *
|
||||
**
|
||||
** The top of the stack should contain an index key generated by
|
||||
** The MakeKey opcode. This routine increases the least significant
|
||||
** byte of that key by one. This is used so that the MoveTo opcode
|
||||
** will move to the first entry greater than the key rather than to
|
||||
** the key itself.
|
||||
*/
|
||||
case OP_IncrKey: {
|
||||
int tos = p->tos;
|
||||
|
||||
VERIFY( if( tos<0 ) goto bad_instruction );
|
||||
if( Stringify(p, tos) ) goto no_mem;
|
||||
if( aStack[tos].flags & STK_Static ){
|
||||
char *zNew = sqliteMalloc( aStack[tos].n );
|
||||
memcpy(zNew, zStack[tos], aStack[tos].n);
|
||||
zStack[tos] = zNew;
|
||||
aStack[tos].flags = STK_Str | STK_Dyn;
|
||||
}
|
||||
zStack[tos][aStack[tos].n-1]++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Transaction * * *
|
||||
**
|
||||
** Begin a transaction. The transaction ends when a Commit or Rollback
|
||||
@ -2473,12 +2497,14 @@ case OP_Close: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: MoveTo P1 * *
|
||||
/* Opcode: MoveTo P1 P2 *
|
||||
**
|
||||
** Pop the top of the stack and use its value as a key. Reposition
|
||||
** cursor P1 so that it points to an entry with a matching key. If
|
||||
** the table contains no record with a matching key, then the cursor
|
||||
** is left pointing at a nearby record.
|
||||
** is left pointing at the first record that is greater than the key.
|
||||
** If there are no records greater than the key and P2 is not zero,
|
||||
** then an immediate jump to P2 is made.
|
||||
**
|
||||
** See also: Found, NotFound, Distinct
|
||||
*/
|
||||
@ -2501,6 +2527,13 @@ case OP_MoveTo: {
|
||||
pC->recnoIsValid = 0;
|
||||
}
|
||||
p->nFetch++;
|
||||
if( res<0 ){
|
||||
sqliteBtreeNext(pC->pCursor, &res);
|
||||
pC->recnoIsValid = 0;
|
||||
if( res && pOp->p2>0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
POPSTACK;
|
||||
break;
|
||||
@ -2870,10 +2903,13 @@ case OP_FullKey: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Rewind P1 * *
|
||||
/* Opcode: Rewind P1 P2 *
|
||||
**
|
||||
** The next use of the Recno or Column or Next instruction for P1
|
||||
** will refer to the first entry in the database file.
|
||||
** will refer to the first entry in the database table or index.
|
||||
** If the table or index is empty and P2>0, then jump immediately to P2.
|
||||
** If P2 is 0 or if the table or index is not empty, fall through
|
||||
** to the following instruction.
|
||||
*/
|
||||
case OP_Rewind: {
|
||||
int i = pOp->p1;
|
||||
@ -2883,6 +2919,9 @@ case OP_Rewind: {
|
||||
int res;
|
||||
sqliteBtreeFirst(pCrsr, &res);
|
||||
p->aCsr[i].atFirst = res==0;
|
||||
if( res && pOp->p2>0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2912,6 +2951,29 @@ case OP_Next: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: NextN P1 P2 *
|
||||
**
|
||||
** Advance cursor P1 so that it points to the next key/data pair in its
|
||||
** table or index. If there are no more key/value pairs then fall through
|
||||
** to the following instruction. But if the cursor advance was successful,
|
||||
** jump immediately to P2.
|
||||
*/
|
||||
case OP_NextN: {
|
||||
int i = pOp->p1;
|
||||
BtCursor *pCrsr;
|
||||
|
||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||
int res;
|
||||
rc = sqliteBtreeNext(pCrsr, &res);
|
||||
if( res==0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
p->nFetch++;
|
||||
}
|
||||
p->aCsr[i].recnoIsValid = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: BeginIdx P1 * *
|
||||
**
|
||||
** Begin searching an index for records with the key found on the
|
||||
@ -2981,8 +3043,8 @@ case OP_NextIdx: {
|
||||
}
|
||||
sqliteBtreeKeySize(pCur, &size);
|
||||
if( res>0 || size!=pCrsr->nKey+sizeof(u32) ||
|
||||
sqliteBtreeKeyCompare(pCur, pCrsr->zKey, pCrsr->nKey, &res)!=SQLITE_OK ||
|
||||
res!=0
|
||||
sqliteBtreeKeyCompare(pCur, pCrsr->zKey, pCrsr->nKey, 4, &res)!=SQLITE_OK
|
||||
|| res!=0
|
||||
){
|
||||
pc = pOp->p2 - 1;
|
||||
POPSTACK;
|
||||
@ -2998,7 +3060,7 @@ case OP_NextIdx: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: PutIdx P1 P2 P3
|
||||
/* Opcode: IdxPut P1 P2 P3
|
||||
**
|
||||
** The top of the stack hold an SQL index key made using the
|
||||
** MakeIdxKey instruction. This opcode writes that key into the
|
||||
@ -3009,7 +3071,7 @@ case OP_NextIdx: {
|
||||
** is rolled back. If P3 is not null, then it because part of the
|
||||
** error message returned with the SQLITE_CONSTRAINT.
|
||||
*/
|
||||
case OP_PutIdx: {
|
||||
case OP_IdxPut: {
|
||||
int i = pOp->p1;
|
||||
int tos = p->tos;
|
||||
BtCursor *pCrsr;
|
||||
@ -3026,7 +3088,7 @@ case OP_PutIdx: {
|
||||
int c;
|
||||
sqliteBtreeKeySize(pCrsr, &n);
|
||||
if( n==nKey
|
||||
&& sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, &c)==SQLITE_OK
|
||||
&& sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &c)==SQLITE_OK
|
||||
&& c==0
|
||||
){
|
||||
rc = SQLITE_CONSTRAINT;
|
||||
@ -3049,12 +3111,12 @@ case OP_PutIdx: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: DeleteIdx P1 * *
|
||||
/* Opcode: IdxDelete P1 * *
|
||||
**
|
||||
** The top of the stack is an index key built using the MakeIdxKey opcode.
|
||||
** This opcode removes that entry from the index.
|
||||
*/
|
||||
case OP_DeleteIdx: {
|
||||
case OP_IdxDelete: {
|
||||
int i = pOp->p1;
|
||||
int tos = p->tos;
|
||||
BtCursor *pCrsr;
|
||||
@ -3070,6 +3132,74 @@ case OP_DeleteIdx: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxRecno P1 * *
|
||||
**
|
||||
** Push onto the stack an integer which is the last 4 bytes of the
|
||||
** the key to the current entry in index P1. These 4 bytes should
|
||||
** be the record number of the table entry to which this index entry
|
||||
** points.
|
||||
**
|
||||
** See also: Recno, MakeIdxKey.
|
||||
*/
|
||||
case OP_IdxRecno: {
|
||||
int i = pOp->p1;
|
||||
int tos = ++p->tos;
|
||||
BtCursor *pCrsr;
|
||||
|
||||
VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
|
||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||
int v;
|
||||
int sz;
|
||||
sqliteBtreeKeySize(pCrsr, &sz);
|
||||
sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v);
|
||||
v = bigEndian(v);
|
||||
aStack[tos].i = v;
|
||||
aStack[tos].flags = STK_Int;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxGT P1 P2 *
|
||||
**
|
||||
** Compare the top of the stack against the key on the index entry that
|
||||
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
|
||||
** index entry. If the index entry is greater than the top of the stack
|
||||
** then jump to P2. Otherwise fall through to the next instruction.
|
||||
** In either case, the stack is popped once.
|
||||
*/
|
||||
/* Opcode: IdxGE P1 P2 *
|
||||
**
|
||||
** Compare the top of the stack against the key on the index entry that
|
||||
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
|
||||
** index entry. If the index entry is greater than or equal to
|
||||
** the top of the stack
|
||||
** then jump to P2. Otherwise fall through to the next instruction.
|
||||
** In either case, the stack is popped once.
|
||||
*/
|
||||
case OP_IdxGT:
|
||||
case OP_IdxGE: {
|
||||
int i= pOp->p1;
|
||||
int tos = p->tos;
|
||||
BtCursor *pCrsr;
|
||||
|
||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||
int res, rc;
|
||||
|
||||
if( Stringify(p, tos) ) goto no_mem;
|
||||
rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
break;
|
||||
}
|
||||
if( pOp->opcode==OP_IdxGE ){
|
||||
res++;
|
||||
}
|
||||
if( res>0 ){
|
||||
pc = pOp->p2 - 1 ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Destroy P1 P2 *
|
||||
**
|
||||
** Delete an entire database table or index whose root page in the database
|
||||
@ -3613,11 +3743,15 @@ case OP_FileColumn: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: MemStore P1 * *
|
||||
/* Opcode: MemStore P1 P2 *
|
||||
**
|
||||
** Pop a single value of the stack and store that value into memory
|
||||
** location P1. P1 should be a small integer since space is allocated
|
||||
** Write the top of the stack into memory location P1.
|
||||
** P1 should be a small integer since space is allocated
|
||||
** for all memory locations between 0 and P1 inclusive.
|
||||
**
|
||||
** After the data is stored in the memory location, the
|
||||
** stack is popped once if P2 is 1. If P2 is zero, then
|
||||
** the original data remains on the stack.
|
||||
*/
|
||||
case OP_MemStore: {
|
||||
int i = pOp->p1;
|
||||
@ -3644,41 +3778,43 @@ case OP_MemStore: {
|
||||
}
|
||||
pMem->s = aStack[tos];
|
||||
if( pMem->s.flags & (STK_Static|STK_Dyn) ){
|
||||
pMem->z = zStack[tos];
|
||||
if( pOp->p2==0 && (pMem->s.flags & STK_Dyn)!=0 ){
|
||||
pMem->z = sqliteMalloc( pMem->s.n );
|
||||
if( pMem->z ) goto no_mem;
|
||||
memcpy(pMem->z, zStack[tos], pMem->s.n);
|
||||
}else{
|
||||
pMem->z = zStack[tos];
|
||||
}
|
||||
}else{
|
||||
pMem->z = pMem->s.z;
|
||||
}
|
||||
if( zOld ) sqliteFree(zOld);
|
||||
zStack[tos] = 0;
|
||||
aStack[tos].flags = 0;
|
||||
POPSTACK;
|
||||
if( pOp->p2 ){
|
||||
zStack[tos] = 0;
|
||||
aStack[tos].flags = 0;
|
||||
POPSTACK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: MemLoad P1 * *
|
||||
**
|
||||
** Push a copy of the value in memory location P1 onto the stack.
|
||||
**
|
||||
** If the value is a string, then the value pushed is a pointer to
|
||||
** the string that is stored in the memory location. If the memory
|
||||
** location is subsequently changed (using OP_MemStore) then the
|
||||
** value pushed onto the stack will change too.
|
||||
*/
|
||||
case OP_MemLoad: {
|
||||
int tos = ++p->tos;
|
||||
int i = pOp->p1;
|
||||
VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
|
||||
if( i<0 || i>=p->nMem ){
|
||||
aStack[tos].flags = STK_Null;
|
||||
zStack[tos] = 0;
|
||||
}else{
|
||||
aStack[tos] = p->aMem[i].s;
|
||||
if( aStack[tos].flags & STK_Dyn ){
|
||||
char *z = sqliteMalloc(aStack[tos].n);
|
||||
if( z==0 ) goto no_mem;
|
||||
memcpy(z, p->aMem[i].z, aStack[tos].n);
|
||||
zStack[tos] = z;
|
||||
aStack[tos].flags |= STK_Dyn;
|
||||
}else if( aStack[tos].flags & STK_Static ){
|
||||
zStack[tos] = p->aMem[i].z;
|
||||
}else if( aStack[tos].flags & STK_Str ){
|
||||
zStack[tos] = aStack[tos].z;
|
||||
}
|
||||
VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
|
||||
memcpy(&aStack[tos], &p->aMem[i].s, sizeof(aStack[tos])-NBFS);;
|
||||
if( aStack[tos].flags & STK_Str ){
|
||||
zStack[tos] = p->aMem[i].z;
|
||||
aStack[tos].flags = STK_Str | STK_Static;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
175
src/vdbe.h
175
src/vdbe.h
@ -15,7 +15,7 @@
|
||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||
** simple program to access and modify the underlying database.
|
||||
**
|
||||
** $Id: vdbe.h,v 1.33 2001/11/06 04:00:19 drh Exp $
|
||||
** $Id: vdbe.h,v 1.34 2001/11/07 14:22:00 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_VDBE_H_
|
||||
#define _SQLITE_VDBE_H_
|
||||
@ -96,106 +96,111 @@ typedef struct VdbeOp VdbeOp;
|
||||
#define OP_FullKey 24
|
||||
#define OP_Rewind 25
|
||||
#define OP_Next 26
|
||||
#define OP_NextN 27
|
||||
|
||||
#define OP_Destroy 27
|
||||
#define OP_Clear 28
|
||||
#define OP_CreateIndex 29
|
||||
#define OP_CreateTable 30
|
||||
#define OP_Reorganize 31
|
||||
#define OP_Destroy 28
|
||||
#define OP_Clear 29
|
||||
#define OP_CreateIndex 30
|
||||
#define OP_CreateTable 31
|
||||
#define OP_Reorganize 32
|
||||
|
||||
#define OP_BeginIdx 32
|
||||
#define OP_NextIdx 33
|
||||
#define OP_PutIdx 34
|
||||
#define OP_DeleteIdx 35
|
||||
#define OP_BeginIdx 33
|
||||
#define OP_NextIdx 34
|
||||
#define OP_IdxPut 35
|
||||
#define OP_IdxDelete 36
|
||||
#define OP_IdxRecno 37
|
||||
#define OP_IdxGT 38
|
||||
#define OP_IdxGE 39
|
||||
|
||||
#define OP_MemLoad 36
|
||||
#define OP_MemStore 37
|
||||
#define OP_MemLoad 40
|
||||
#define OP_MemStore 41
|
||||
|
||||
#define OP_ListWrite 38
|
||||
#define OP_ListRewind 39
|
||||
#define OP_ListRead 40
|
||||
#define OP_ListReset 41
|
||||
#define OP_ListWrite 42
|
||||
#define OP_ListRewind 43
|
||||
#define OP_ListRead 44
|
||||
#define OP_ListReset 45
|
||||
|
||||
#define OP_SortPut 42
|
||||
#define OP_SortMakeRec 43
|
||||
#define OP_SortMakeKey 44
|
||||
#define OP_Sort 45
|
||||
#define OP_SortNext 46
|
||||
#define OP_SortCallback 47
|
||||
#define OP_SortReset 48
|
||||
#define OP_SortPut 46
|
||||
#define OP_SortMakeRec 47
|
||||
#define OP_SortMakeKey 48
|
||||
#define OP_Sort 49
|
||||
#define OP_SortNext 50
|
||||
#define OP_SortCallback 51
|
||||
#define OP_SortReset 52
|
||||
|
||||
#define OP_FileOpen 49
|
||||
#define OP_FileRead 50
|
||||
#define OP_FileColumn 51
|
||||
#define OP_FileOpen 53
|
||||
#define OP_FileRead 54
|
||||
#define OP_FileColumn 55
|
||||
|
||||
#define OP_AggReset 52
|
||||
#define OP_AggFocus 53
|
||||
#define OP_AggIncr 54
|
||||
#define OP_AggNext 55
|
||||
#define OP_AggSet 56
|
||||
#define OP_AggGet 57
|
||||
#define OP_AggReset 56
|
||||
#define OP_AggFocus 57
|
||||
#define OP_AggIncr 58
|
||||
#define OP_AggNext 59
|
||||
#define OP_AggSet 60
|
||||
#define OP_AggGet 61
|
||||
|
||||
#define OP_SetInsert 58
|
||||
#define OP_SetFound 59
|
||||
#define OP_SetNotFound 60
|
||||
#define OP_SetInsert 62
|
||||
#define OP_SetFound 63
|
||||
#define OP_SetNotFound 64
|
||||
|
||||
#define OP_MakeRecord 61
|
||||
#define OP_MakeKey 62
|
||||
#define OP_MakeIdxKey 63
|
||||
#define OP_MakeRecord 65
|
||||
#define OP_MakeKey 66
|
||||
#define OP_MakeIdxKey 67
|
||||
#define OP_IncrKey 68
|
||||
|
||||
#define OP_Goto 64
|
||||
#define OP_If 65
|
||||
#define OP_Halt 66
|
||||
#define OP_Goto 69
|
||||
#define OP_If 70
|
||||
#define OP_Halt 71
|
||||
|
||||
#define OP_ColumnCount 67
|
||||
#define OP_ColumnName 68
|
||||
#define OP_Callback 69
|
||||
#define OP_NullCallback 70
|
||||
#define OP_ColumnCount 72
|
||||
#define OP_ColumnName 73
|
||||
#define OP_Callback 74
|
||||
#define OP_NullCallback 75
|
||||
|
||||
#define OP_Integer 71
|
||||
#define OP_String 72
|
||||
#define OP_Pop 73
|
||||
#define OP_Dup 74
|
||||
#define OP_Pull 75
|
||||
#define OP_Integer 76
|
||||
#define OP_String 77
|
||||
#define OP_Pop 78
|
||||
#define OP_Dup 79
|
||||
#define OP_Pull 80
|
||||
|
||||
#define OP_Add 76
|
||||
#define OP_AddImm 77
|
||||
#define OP_Subtract 78
|
||||
#define OP_Multiply 79
|
||||
#define OP_Divide 80
|
||||
#define OP_Remainder 81
|
||||
#define OP_BitAnd 82
|
||||
#define OP_BitOr 83
|
||||
#define OP_BitNot 84
|
||||
#define OP_ShiftLeft 85
|
||||
#define OP_ShiftRight 86
|
||||
#define OP_AbsValue 87
|
||||
#define OP_Precision 88
|
||||
#define OP_Min 89
|
||||
#define OP_Max 90
|
||||
#define OP_Like 91
|
||||
#define OP_Glob 92
|
||||
#define OP_Eq 93
|
||||
#define OP_Ne 94
|
||||
#define OP_Lt 95
|
||||
#define OP_Le 96
|
||||
#define OP_Gt 97
|
||||
#define OP_Ge 98
|
||||
#define OP_IsNull 99
|
||||
#define OP_NotNull 100
|
||||
#define OP_Negative 101
|
||||
#define OP_And 102
|
||||
#define OP_Or 103
|
||||
#define OP_Not 104
|
||||
#define OP_Concat 105
|
||||
#define OP_Noop 106
|
||||
#define OP_Add 81
|
||||
#define OP_AddImm 82
|
||||
#define OP_Subtract 83
|
||||
#define OP_Multiply 84
|
||||
#define OP_Divide 85
|
||||
#define OP_Remainder 86
|
||||
#define OP_BitAnd 87
|
||||
#define OP_BitOr 88
|
||||
#define OP_BitNot 89
|
||||
#define OP_ShiftLeft 90
|
||||
#define OP_ShiftRight 91
|
||||
#define OP_AbsValue 92
|
||||
#define OP_Precision 93
|
||||
#define OP_Min 94
|
||||
#define OP_Max 95
|
||||
#define OP_Like 96
|
||||
#define OP_Glob 97
|
||||
#define OP_Eq 98
|
||||
#define OP_Ne 99
|
||||
#define OP_Lt 100
|
||||
#define OP_Le 101
|
||||
#define OP_Gt 102
|
||||
#define OP_Ge 103
|
||||
#define OP_IsNull 104
|
||||
#define OP_NotNull 105
|
||||
#define OP_Negative 106
|
||||
#define OP_And 107
|
||||
#define OP_Or 108
|
||||
#define OP_Not 109
|
||||
#define OP_Concat 110
|
||||
#define OP_Noop 111
|
||||
|
||||
#define OP_Strlen 107
|
||||
#define OP_Substr 108
|
||||
#define OP_Strlen 112
|
||||
#define OP_Substr 113
|
||||
|
||||
#define OP_Limit 109
|
||||
#define OP_Limit 114
|
||||
|
||||
#define OP_MAX 111
|
||||
#define OP_MAX 114
|
||||
|
||||
/*
|
||||
** Prototypes for the VDBE interface. See comments on the implementation
|
||||
|
Reference in New Issue
Block a user