mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
Modify the code generated for a DELETE to use registers instead of the vdbe stack. (CVS 4675)
FossilOrigin-Name: 173f281334d340290e1978abea5d1ea804141910
This commit is contained in:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sOP_MemSet,\sfor\ssetting\sa\smemory\scell\sto\sa\sstring\svalue.\s(CVS\s4674)
|
C Modify\sthe\scode\sgenerated\sfor\sa\sDELETE\sto\suse\sregisters\sinstead\sof\sthe\svdbe\sstack.\s(CVS\s4675)
|
||||||
D 2008-01-04T11:01:04
|
D 2008-01-04T13:24:29
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -90,13 +90,13 @@ F src/build.c b7874b45716fa56e6fd1291ffb0b97a55e470728
|
|||||||
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
||||||
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
||||||
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
||||||
F src/delete.c b5f77d88cc35367cfafc2e4edcf9327d19428615
|
F src/delete.c 36193a3a10e636d3ee4fe1fdfac57982d5471623
|
||||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||||
F src/expr.c e60ee4f48194469bf7b101fb7a14e56abea3daa4
|
F src/expr.c e60ee4f48194469bf7b101fb7a14e56abea3daa4
|
||||||
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
|
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
|
||||||
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
|
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
|
||||||
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
|
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
|
||||||
F src/insert.c ecffad8ecc5dc69d6dc05d8dc136f872864af84e
|
F src/insert.c 7a8c825953ab6435fef1823e83cbe627860dd6d5
|
||||||
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
|
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
|
||||||
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
|
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
|
||||||
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
||||||
@@ -136,7 +136,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
|||||||
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
|
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
|
||||||
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
||||||
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
|
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
|
||||||
F src/sqliteInt.h 2cae3a7556208c68987752b6d8f9212a8a2327a7
|
F src/sqliteInt.h df036b69e3c5c6a87354a10668f165b22994f264
|
||||||
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
|
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
|
||||||
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
|
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
|
||||||
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
|
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
|
||||||
@@ -168,7 +168,7 @@ F src/update.c a68e11e766376bf0fbec93d70c9389c4c502dd55
|
|||||||
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
||||||
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
|
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
|
||||||
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
||||||
F src/vdbe.c 09caf5753f176603ad4965d92c7ff32786c1cc2b
|
F src/vdbe.c 55e1a0541f87e2c73fa4c4d73649c3d6cd39b9a3
|
||||||
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
|
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
|
||||||
F src/vdbeInt.h 869d0f550354c1364dde1d3611d770bd1c767505
|
F src/vdbeInt.h 869d0f550354c1364dde1d3611d770bd1c767505
|
||||||
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
|
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
|
||||||
@@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P 61bfb77c4267b99ac8a8ef49355bcbc395a1a37b
|
P 8bb9f970dd71cbf19e45774fc822aa1efebc1724
|
||||||
R edd05b654f5ed425ebc77621c6cc523e
|
R 991771337c0268b312b29969927e9c60
|
||||||
U danielk1977
|
U danielk1977
|
||||||
Z 55c192a0d96eb126863103cbe98ffaaa
|
Z 58a58785d108e95cb589bb5d4ad7f5cb
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
8bb9f970dd71cbf19e45774fc822aa1efebc1724
|
173f281334d340290e1978abea5d1ea804141910
|
||||||
44
src/delete.c
44
src/delete.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** in order to generate code for DELETE FROM statements.
|
** in order to generate code for DELETE FROM statements.
|
||||||
**
|
**
|
||||||
** $Id: delete.c,v 1.144 2008/01/03 18:03:09 drh Exp $
|
** $Id: delete.c,v 1.145 2008/01/04 13:24:29 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -299,6 +299,8 @@ void sqlite3DeleteFrom(
|
|||||||
** the table and pick which records to delete.
|
** the table and pick which records to delete.
|
||||||
*/
|
*/
|
||||||
else{
|
else{
|
||||||
|
int iRowid = ++pParse->nMem; /* Used for storing value read from fifo */
|
||||||
|
|
||||||
/* Begin the database scan
|
/* Begin the database scan
|
||||||
*/
|
*/
|
||||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
|
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
|
||||||
@@ -342,44 +344,41 @@ void sqlite3DeleteFrom(
|
|||||||
if( triggers_exist ){
|
if( triggers_exist ){
|
||||||
sqlite3VdbeResolveLabel(v, addr);
|
sqlite3VdbeResolveLabel(v, addr);
|
||||||
}
|
}
|
||||||
addr = sqlite3VdbeAddOp2(v, OP_FifoRead, 0, end);
|
addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end);
|
||||||
sqlite3VdbeAddOp1(v, OP_StackDepth, -1);
|
sqlite3VdbeAddOp1(v, OP_StackDepth, -1);
|
||||||
|
|
||||||
if( triggers_exist ){
|
if( triggers_exist ){
|
||||||
int mem1 = ++pParse->nMem;
|
int iData = ++pParse->nMem; /* For storing row data of OLD table */
|
||||||
if( !isView ){
|
|
||||||
sqlite3VdbeAddOp1(v, OP_MemStore, mem1);
|
/* If the record is no longer present in the table, jump to the
|
||||||
}
|
** next iteration of the loop through the contents of the fifo.
|
||||||
sqlite3VdbeAddOp2(v, OP_NotExists, iCur, addr);
|
*/
|
||||||
sqlite3VdbeAddOp1(v, OP_Rowid, iCur);
|
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);
|
||||||
|
|
||||||
|
/* Populate the OLD.* pseudo-table */
|
||||||
if( old_col_mask ){
|
if( old_col_mask ){
|
||||||
sqlite3VdbeAddOp1(v, OP_RowData, iCur);
|
sqlite3VdbeAddOp3(v, OP_RowData, iCur, 0, iData);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp0(v, OP_Null);
|
sqlite3VdbeAddOp2(v, OP_MemNull, 0, iData);
|
||||||
}
|
}
|
||||||
sqlite3CodeInsert(pParse, oldIdx, 0);
|
sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid);
|
||||||
|
|
||||||
/* Jump back and run the BEFORE triggers */
|
/* Jump back and run the BEFORE triggers */
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
|
||||||
sqlite3VdbeJumpHere(v, iEndBeforeTrigger);
|
sqlite3VdbeJumpHere(v, iEndBeforeTrigger);
|
||||||
|
|
||||||
if( !isView ){
|
|
||||||
sqlite3VdbeAddOp1(v, OP_MemLoad, mem1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isView ){
|
if( !isView ){
|
||||||
/* Delete the row */
|
/* Delete the row */
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
if( IsVirtual(pTab) ){
|
if( IsVirtual(pTab) ){
|
||||||
int iReg = sqlite3StackToReg(pParse, 1);
|
const char *pVtab = (const char *)pTab->pVtab;
|
||||||
pParse->pVirtualLock = pTab;
|
pParse->pVirtualLock = pTab;
|
||||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iReg,
|
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB);
|
||||||
(const char*)pTab->pVtab, P4_VTAB);
|
|
||||||
}else
|
}else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
|
sqlite3GenerateRowDelete(db, v, pTab, iCur, iRowid, pParse->nested==0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,8 +435,8 @@ delete_from_cleanup:
|
|||||||
** 2. Read/write cursors for all indices of pTab must be open as
|
** 2. Read/write cursors for all indices of pTab must be open as
|
||||||
** cursor number base+i for the i-th index.
|
** cursor number base+i for the i-th index.
|
||||||
**
|
**
|
||||||
** 3. The record number of the row to be deleted must be on the top
|
** 3. The record number of the row to be deleted must be stored in
|
||||||
** of the stack.
|
** memory cell iRowid.
|
||||||
**
|
**
|
||||||
** This routine pops the top of the stack to remove the record number
|
** This routine pops the top of the stack to remove the record number
|
||||||
** and then generates code to remove both the table record and all index
|
** and then generates code to remove both the table record and all index
|
||||||
@@ -448,10 +447,11 @@ void sqlite3GenerateRowDelete(
|
|||||||
Vdbe *v, /* Generate code into this VDBE */
|
Vdbe *v, /* Generate code into this VDBE */
|
||||||
Table *pTab, /* Table containing the row to be deleted */
|
Table *pTab, /* Table containing the row to be deleted */
|
||||||
int iCur, /* Cursor number for the table */
|
int iCur, /* Cursor number for the table */
|
||||||
|
int iRowid, /* Memory cell that contains the rowid to delete */
|
||||||
int count /* Increment the row change counter */
|
int count /* Increment the row change counter */
|
||||||
){
|
){
|
||||||
int addr;
|
int addr;
|
||||||
addr = sqlite3VdbeAddOp1(v, OP_NotExists, iCur);
|
addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid);
|
||||||
sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
|
sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
|
sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
|
||||||
if( count ){
|
if( count ){
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle INSERT statements in SQLite.
|
** to handle INSERT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: insert.c,v 1.208 2008/01/03 23:44:53 drh Exp $
|
** $Id: insert.c,v 1.209 2008/01/04 13:24:29 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -1176,7 +1176,8 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OE_Replace: {
|
case OE_Replace: {
|
||||||
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
|
int iRowid = sqlite3StackToReg(pParse, 1);
|
||||||
|
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
|
sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
|
||||||
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.636 2008/01/03 23:44:53 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.637 2008/01/04 13:24:29 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -1768,7 +1768,7 @@ int sqlite3ExprIsConstantNotJoin(Expr*);
|
|||||||
int sqlite3ExprIsConstantOrFunction(Expr*);
|
int sqlite3ExprIsConstantOrFunction(Expr*);
|
||||||
int sqlite3ExprIsInteger(Expr*, int*);
|
int sqlite3ExprIsInteger(Expr*, int*);
|
||||||
int sqlite3IsRowid(const char*);
|
int sqlite3IsRowid(const char*);
|
||||||
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int);
|
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int, int);
|
||||||
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
|
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
|
||||||
void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
|
void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
|
||||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
|
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
|
||||||
|
|||||||
120
src/vdbe.c
120
src/vdbe.c
@@ -43,7 +43,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** commenting and indentation practices when changing or adding code.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.674 2008/01/04 11:01:04 danielk1977 Exp $
|
** $Id: vdbe.c,v 1.675 2008/01/04 13:24:29 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -3344,12 +3344,14 @@ case OP_IsUnique: { /* no-push */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: NotExists P1 P2 *
|
/* Opcode: NotExists P1 P2 P3
|
||||||
**
|
**
|
||||||
** Use the top of the stack as a integer key. If a record with that key
|
** Use the top of the stack as a integer key. Or, if P3 is non-zero,
|
||||||
** does not exist in table of P1, then jump to P2. If the record
|
** use the contents of memory cell P3 as an integer key. If a record
|
||||||
** does exist, then fall thru. The cursor is left pointing to the
|
** with that key does not exist in table of P1, then jump to P2.
|
||||||
** record if it exists. The integer key is popped from the stack.
|
** If the record does exist, then fall thru. The cursor is left
|
||||||
|
** pointing to the record if it exists. The integer key is popped
|
||||||
|
** from the stack (unless it was read from a memory cell).
|
||||||
**
|
**
|
||||||
** The difference between this operation and NotFound is that this
|
** The difference between this operation and NotFound is that this
|
||||||
** operation assumes the key is an integer and that P1 is a table whereas
|
** operation assumes the key is an integer and that P1 is a table whereas
|
||||||
@@ -3362,17 +3364,24 @@ case OP_NotExists: { /* no-push */
|
|||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
BtCursor *pCrsr;
|
BtCursor *pCrsr;
|
||||||
assert( pTos>=p->aStack );
|
Mem *pKey;
|
||||||
|
if( pOp->p3 ){
|
||||||
|
assert( pOp->p3<=p->nMem );
|
||||||
|
pKey = &p->aMem[pOp->p3];
|
||||||
|
}else{
|
||||||
|
pKey = pTos;
|
||||||
|
assert( pTos>=p->aStack );
|
||||||
|
}
|
||||||
assert( i>=0 && i<p->nCursor );
|
assert( i>=0 && i<p->nCursor );
|
||||||
assert( p->apCsr[i]!=0 );
|
assert( p->apCsr[i]!=0 );
|
||||||
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
|
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
|
||||||
int res;
|
int res;
|
||||||
u64 iKey;
|
u64 iKey;
|
||||||
assert( pTos->flags & MEM_Int );
|
assert( pKey->flags & MEM_Int );
|
||||||
assert( p->apCsr[i]->isTable );
|
assert( p->apCsr[i]->isTable );
|
||||||
iKey = intToKey(pTos->u.i);
|
iKey = intToKey(pKey->u.i);
|
||||||
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
|
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
|
||||||
pC->lastRowid = pTos->u.i;
|
pC->lastRowid = pKey->u.i;
|
||||||
pC->rowidIsValid = res==0;
|
pC->rowidIsValid = res==0;
|
||||||
pC->nullRow = 0;
|
pC->nullRow = 0;
|
||||||
pC->cacheStatus = CACHE_STALE;
|
pC->cacheStatus = CACHE_STALE;
|
||||||
@@ -3386,8 +3395,10 @@ case OP_NotExists: { /* no-push */
|
|||||||
pC->rowidIsValid = 0;
|
pC->rowidIsValid = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Release(pTos);
|
if( pOp->p3==0 ){
|
||||||
pTos--;
|
Release(pTos);
|
||||||
|
pTos--;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3727,20 +3738,24 @@ case OP_ResetCount: { /* no-push */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: RowData P1 * *
|
/* Opcode: RowData P1 * P3
|
||||||
**
|
**
|
||||||
** Push onto the stack the complete row data for cursor P1.
|
** Push onto the stack the complete row data for cursor P1. Or if P3
|
||||||
** There is no interpretation of the data. It is just copied
|
** is a positive non-zero integer register number, then the value
|
||||||
** onto the stack exactly as it is found in the database file.
|
** is written into that register. There is no interpretation of the data.
|
||||||
|
** It is just copied onto the stack or into the memory cell exactly as
|
||||||
|
** it is found in the database file.
|
||||||
**
|
**
|
||||||
** If the cursor is not pointing to a valid row, a NULL is pushed
|
** If the cursor is not pointing to a valid row, a NULL value is
|
||||||
** onto the stack.
|
** pushed/inserted instead.
|
||||||
*/
|
*/
|
||||||
/* Opcode: RowKey P1 * *
|
/* Opcode: RowKey P1 * P3
|
||||||
**
|
**
|
||||||
** Push onto the stack the complete row key for cursor P1.
|
** Push onto the stack the complete row key for cursor P1. Or if P3
|
||||||
** There is no interpretation of the key. It is just copied
|
** is a positive non-zero integer register number, then the value
|
||||||
** onto the stack exactly as it is found in the database file.
|
** is written into that register. There is no interpretation of the data.
|
||||||
|
** It is just copied onto the stack or into the memory cell exactly as
|
||||||
|
** it is found in the database file.
|
||||||
**
|
**
|
||||||
** If the cursor is not pointing to a valid row, a NULL is pushed
|
** If the cursor is not pointing to a valid row, a NULL is pushed
|
||||||
** onto the stack.
|
** onto the stack.
|
||||||
@@ -3750,22 +3765,27 @@ case OP_RowData: {
|
|||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
u32 n;
|
u32 n;
|
||||||
|
Mem *pOut;
|
||||||
|
|
||||||
/* Note that RowKey and RowData are really exactly the same instruction */
|
/* Note that RowKey and RowData are really exactly the same instruction */
|
||||||
pTos++;
|
if( pOp->p3 ){
|
||||||
|
pOut = &p->aMem[pOp->p3];
|
||||||
|
}else{
|
||||||
|
pOut = ++pTos;
|
||||||
|
}
|
||||||
assert( i>=0 && i<p->nCursor );
|
assert( i>=0 && i<p->nCursor );
|
||||||
pC = p->apCsr[i];
|
pC = p->apCsr[i];
|
||||||
assert( pC->isTable || pOp->opcode==OP_RowKey );
|
assert( pC->isTable || pOp->opcode==OP_RowKey );
|
||||||
assert( pC->isIndex || pOp->opcode==OP_RowData );
|
assert( pC->isIndex || pOp->opcode==OP_RowData );
|
||||||
assert( pC!=0 );
|
assert( pC!=0 );
|
||||||
if( pC->nullRow ){
|
if( pC->nullRow ){
|
||||||
pTos->flags = MEM_Null;
|
pOut->flags = MEM_Null;
|
||||||
}else if( pC->pCursor!=0 ){
|
}else if( pC->pCursor!=0 ){
|
||||||
BtCursor *pCrsr = pC->pCursor;
|
BtCursor *pCrsr = pC->pCursor;
|
||||||
rc = sqlite3VdbeCursorMoveto(pC);
|
rc = sqlite3VdbeCursorMoveto(pC);
|
||||||
if( rc ) goto abort_due_to_error;
|
if( rc ) goto abort_due_to_error;
|
||||||
if( pC->nullRow ){
|
if( pC->nullRow ){
|
||||||
pTos->flags = MEM_Null;
|
pOut->flags = MEM_Null;
|
||||||
break;
|
break;
|
||||||
}else if( pC->isIndex ){
|
}else if( pC->isIndex ){
|
||||||
i64 n64;
|
i64 n64;
|
||||||
@@ -3781,31 +3801,31 @@ case OP_RowData: {
|
|||||||
if( n>SQLITE_MAX_LENGTH ){
|
if( n>SQLITE_MAX_LENGTH ){
|
||||||
goto too_big;
|
goto too_big;
|
||||||
}
|
}
|
||||||
pTos->n = n;
|
pOut->n = n;
|
||||||
if( n<=NBFS ){
|
if( n<=NBFS ){
|
||||||
pTos->flags = MEM_Blob | MEM_Short;
|
pOut->flags = MEM_Blob | MEM_Short;
|
||||||
pTos->z = pTos->zShort;
|
pOut->z = pOut->zShort;
|
||||||
}else{
|
}else{
|
||||||
char *z = sqlite3_malloc( n );
|
char *z = sqlite3_malloc( n );
|
||||||
if( z==0 ) goto no_mem;
|
if( z==0 ) goto no_mem;
|
||||||
pTos->flags = MEM_Blob | MEM_Dyn;
|
pOut->flags = MEM_Blob | MEM_Dyn;
|
||||||
pTos->xDel = 0;
|
pOut->xDel = 0;
|
||||||
pTos->z = z;
|
pOut->z = z;
|
||||||
}
|
}
|
||||||
if( pC->isIndex ){
|
if( pC->isIndex ){
|
||||||
rc = sqlite3BtreeKey(pCrsr, 0, n, pTos->z);
|
rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3BtreeData(pCrsr, 0, n, pTos->z);
|
rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
|
||||||
}
|
}
|
||||||
}else if( pC->pseudoTable ){
|
}else if( pC->pseudoTable ){
|
||||||
pTos->n = pC->nData;
|
pOut->n = pC->nData;
|
||||||
assert( pC->nData<=SQLITE_MAX_LENGTH );
|
assert( pC->nData<=SQLITE_MAX_LENGTH );
|
||||||
pTos->z = pC->pData;
|
pOut->z = pC->pData;
|
||||||
pTos->flags = MEM_Blob|MEM_Ephem;
|
pOut->flags = MEM_Blob|MEM_Ephem;
|
||||||
}else{
|
}else{
|
||||||
pTos->flags = MEM_Null;
|
pOut->flags = MEM_Null;
|
||||||
}
|
}
|
||||||
pTos->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
|
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4505,8 +4525,7 @@ case OP_IntegrityCk: {
|
|||||||
|
|
||||||
/* Opcode: FifoWrite * * *
|
/* Opcode: FifoWrite * * *
|
||||||
**
|
**
|
||||||
** Write the integer on the top of the stack
|
** Write the integer on the top of the stack into the Fifo.
|
||||||
** into the Fifo.
|
|
||||||
*/
|
*/
|
||||||
case OP_FifoWrite: { /* no-push */
|
case OP_FifoWrite: { /* no-push */
|
||||||
assert( pTos>=p->aStack );
|
assert( pTos>=p->aStack );
|
||||||
@@ -4519,11 +4538,14 @@ case OP_FifoWrite: { /* no-push */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: FifoRead * P2 *
|
/* Opcode: FifoRead P1 P2 *
|
||||||
**
|
**
|
||||||
** Attempt to read a single integer from the Fifo
|
** Attempt to read a single integer from the Fifo. If P1 is zero,
|
||||||
** and push it onto the stack. If the Fifo is empty
|
** push the result onto the stack. Otherwise, store the read integer
|
||||||
** push nothing but instead jump to P2.
|
** in register P1.
|
||||||
|
**
|
||||||
|
** If the Fifo is empty do not push an entry onto the stack or set
|
||||||
|
** a memory register but instead jump to P2.
|
||||||
*/
|
*/
|
||||||
case OP_FifoRead: {
|
case OP_FifoRead: {
|
||||||
i64 v;
|
i64 v;
|
||||||
@@ -4531,9 +4553,13 @@ case OP_FifoRead: {
|
|||||||
if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
|
if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
}else{
|
}else{
|
||||||
pTos++;
|
Mem *pOut;
|
||||||
pTos->u.i = v;
|
if( pOp->p1 ){
|
||||||
pTos->flags = MEM_Int;
|
pOut = &p->aMem[pOp->p1];
|
||||||
|
}else{
|
||||||
|
pOut = ++pTos;
|
||||||
|
}
|
||||||
|
sqlite3VdbeMemSetInt64(pOut, v);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user