mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
Progress toward registerification of the constraint checking logic for
INSERT and UPDATE. (CVS 4693) FossilOrigin-Name: b9bf509e39f5ac38c2149d2a648f68e5df5ae9e3
This commit is contained in:
26
manifest
26
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Registerify\sthe\sAUTOINCREMENT\sprocessing\sand\sthe\sOP_IsNull\sand\sOP_NotNull\noperators.\s(CVS\s4692)
|
C Progress\stoward\sregisterification\sof\sthe\sconstraint\schecking\slogic\sfor\nINSERT\sand\sUPDATE.\s(CVS\s4693)
|
||||||
D 2008-01-07T19:20:25
|
D 2008-01-08T02:57:56
|
||||||
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 22b50a462d7b2be82e29071069d1c3daf29e953f
|
|||||||
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 09c7b312a061d08df8a95b1f75cb10c6af14114a
|
F src/delete.c d78e46b259a94a5f98a1bceee206c5fd21276ae7
|
||||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||||
F src/expr.c f84b4901dff3bacd08ece3f0de09318a5a298121
|
F src/expr.c 6f2a852227ba2abd5ad0916f539c1f2159da28b4
|
||||||
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 9c1a6501d79c9c4e674e0e2c3bc4a5207f9b3b95
|
F src/insert.c 3a45102002b611aa1707bb6c6c5c148547d2630a
|
||||||
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 95cdddce11ee871fad1d91d6b6e405969dcc405f
|
F src/sqliteInt.h 964754dcd508ddf0dd0b326072ad80678452e5c2
|
||||||
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
|
||||||
@@ -164,18 +164,18 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
|
|||||||
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
|
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
|
||||||
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
|
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
|
||||||
F src/trigger.c 33071215111825634b85567bfc36c14094eebe54
|
F src/trigger.c 33071215111825634b85567bfc36c14094eebe54
|
||||||
F src/update.c 38e9e4c27896df2d189927e3b483cadf5641f47c
|
F src/update.c acd1c38dbbf253183fe2a8e5be0b3f3fee59be15
|
||||||
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 3d849013558e52b2c85134fc6ed655d6dc00ace7
|
F src/vdbe.c e71595acce83c585c31ac0551cee1c8cf9540fd2
|
||||||
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
|
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
|
||||||
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
|
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
|
||||||
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
|
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
|
||||||
F src/vdbeaux.c 75b7d3e42c94310f28f6f7d3e08b69797fbe8a78
|
F src/vdbeaux.c b6241be0277795ecd902743366434704f03b7636
|
||||||
F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
|
F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
|
||||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||||
F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
|
F src/vdbemem.c a94f3e9e85578ba457133ad3446fc6114a03ec5a
|
||||||
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
|
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
|
||||||
F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb
|
F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb
|
||||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||||
@@ -604,7 +604,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 38020592f15c072e0d221ae2e0df13508ac4bd49
|
P aa48867cfa04da265b906e5b583bc7ac6b6a1157
|
||||||
R dde2d5dbca593f8bc201758cd5d40a3d
|
R af4f73c6bffdbedd3861a3c5eb6d920e
|
||||||
U drh
|
U drh
|
||||||
Z 07f47472df3751ae71471b817e3e70f7
|
Z 313f66697e8ae592eab31fdd061363d6
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
aa48867cfa04da265b906e5b583bc7ac6b6a1157
|
b9bf509e39f5ac38c2149d2a648f68e5df5ae9e3
|
||||||
@@ -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.152 2008/01/06 00:25:22 drh Exp $
|
** $Id: delete.c,v 1.153 2008/01/08 02:57:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -492,13 +492,13 @@ void sqlite3GenerateRowIndexDelete(
|
|||||||
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 */
|
||||||
char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
|
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
|
||||||
){
|
){
|
||||||
int i;
|
int i;
|
||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
|
|
||||||
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||||
if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
|
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
|
||||||
sqlite3GenerateIndexKey(v, pIdx, iCur);
|
sqlite3GenerateIndexKey(v, pIdx, iCur);
|
||||||
sqlite3VdbeAddOp1(v, OP_IdxDelete, iCur+i);
|
sqlite3VdbeAddOp1(v, OP_IdxDelete, iCur+i);
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/expr.c
35
src/expr.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains routines used for analyzing expressions and
|
** This file contains routines used for analyzing expressions and
|
||||||
** for generating VDBE code that evaluates expressions in SQLite.
|
** for generating VDBE code that evaluates expressions in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: expr.c,v 1.336 2008/01/07 19:20:25 drh Exp $
|
** $Id: expr.c,v 1.337 2008/01/08 02:57:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1944,15 +1944,12 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
int op;
|
int op;
|
||||||
int inReg = 0;
|
int inReg = 0;
|
||||||
int stackChng = 0;
|
|
||||||
int origTarget = target;
|
int origTarget = target;
|
||||||
|
|
||||||
assert( v!=0 || pParse->db->mallocFailed );
|
assert( v!=0 || pParse->db->mallocFailed );
|
||||||
if( v==0 ) return 0;
|
if( v==0 ) return 0;
|
||||||
if( target<0 ){
|
if( target<0 ){
|
||||||
target = ++pParse->nMem;
|
target = ++pParse->nMem;
|
||||||
}else if( target==0 ){
|
|
||||||
stackChng = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pExpr==0 ){
|
if( pExpr==0 ){
|
||||||
@@ -1979,9 +1976,8 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_COLUMN: {
|
case TK_COLUMN: {
|
||||||
if( pExpr->iTable<0 ){
|
if( pExpr->iTable<0 ){
|
||||||
/* This only happens when coding check constraints */
|
/* This only happens when coding check constraints */
|
||||||
assert( pParse->ckOffset>0 );
|
assert( pParse->ckBase>0 );
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(pParse->ckOffset-pExpr->iColumn-1));
|
inReg = pExpr->iColumn + pParse->ckBase;
|
||||||
/* inReg = -(pParse->ckOffset-pExpr->iColumn-1); */
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3ExprCodeGetColumn(v, pExpr->pTab,
|
sqlite3ExprCodeGetColumn(v, pExpr->pTab,
|
||||||
pExpr->iColumn, pExpr->iTable, target);
|
pExpr->iColumn, pExpr->iTable, target);
|
||||||
@@ -2052,7 +2048,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
|
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
|
||||||
assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
|
assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
|
||||||
sqlite3VdbeAddOp1(v, to_op, target);
|
sqlite3VdbeAddOp1(v, to_op, target);
|
||||||
stackChng = 0;
|
|
||||||
inReg = target;
|
inReg = target;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2072,7 +2067,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
|
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
|
||||||
sqlite3ExprCode(pParse, pExpr->pRight, 0);
|
sqlite3ExprCode(pParse, pExpr->pRight, 0);
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0);
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0);
|
||||||
stackChng = -1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_AND:
|
case TK_AND:
|
||||||
@@ -2099,12 +2093,9 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
assert( TK_LSHIFT==OP_ShiftLeft );
|
assert( TK_LSHIFT==OP_ShiftLeft );
|
||||||
assert( TK_RSHIFT==OP_ShiftRight );
|
assert( TK_RSHIFT==OP_ShiftRight );
|
||||||
assert( TK_CONCAT==OP_Concat );
|
assert( TK_CONCAT==OP_Concat );
|
||||||
r1 = sqlite3ExprCode(pParse, pExpr->pLeft, 0);
|
r1 = sqlite3ExprCode(pParse, pExpr->pLeft, -1);
|
||||||
r2 = sqlite3ExprCode(pParse, pExpr->pRight, 0);
|
r2 = sqlite3ExprCode(pParse, pExpr->pRight, -1);
|
||||||
sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
||||||
if( r1==0 ) stackChng--;
|
|
||||||
if( r2==0 ) stackChng--;
|
|
||||||
if( target==0 ) stackChng++;
|
|
||||||
inReg = target;
|
inReg = target;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2129,7 +2120,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
assert( TK_NOT==OP_Not );
|
assert( TK_NOT==OP_Not );
|
||||||
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
|
sqlite3ExprCode(pParse, pExpr->pLeft, 0);
|
||||||
sqlite3VdbeAddOp0(v, op);
|
sqlite3VdbeAddOp0(v, op);
|
||||||
stackChng = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_ISNULL:
|
case TK_ISNULL:
|
||||||
@@ -2142,7 +2132,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
addr = sqlite3VdbeAddOp0(v, op);
|
addr = sqlite3VdbeAddOp0(v, op);
|
||||||
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
|
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, addr);
|
||||||
stackChng = 0;
|
|
||||||
inReg = target;
|
inReg = target;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2207,7 +2196,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
}
|
}
|
||||||
sqlite3VdbeAddOp4(v, OP_Function, constMask, nExpr, 0,
|
sqlite3VdbeAddOp4(v, OP_Function, constMask, nExpr, 0,
|
||||||
(char*)pDef, P4_FUNCDEF);
|
(char*)pDef, P4_FUNCDEF);
|
||||||
stackChng = 1-nExpr;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_SUBQUERY
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
@@ -2224,7 +2212,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_IN: {
|
case TK_IN: {
|
||||||
int j1, j2, j3, j4, j5;
|
int j1, j2, j3, j4, j5;
|
||||||
char affinity;
|
char affinity;
|
||||||
int ckOffset = pParse->ckOffset;
|
|
||||||
int eType;
|
int eType;
|
||||||
|
|
||||||
eType = sqlite3FindInIndex(pParse, pExpr, 0);
|
eType = sqlite3FindInIndex(pParse, pExpr, 0);
|
||||||
@@ -2236,7 +2223,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
affinity = comparisonAffinity(pExpr);
|
affinity = comparisonAffinity(pExpr);
|
||||||
|
|
||||||
sqlite3VdbeAddOp1(v, OP_Integer, 1);
|
sqlite3VdbeAddOp1(v, OP_Integer, 1);
|
||||||
pParse->ckOffset = (ckOffset ? (ckOffset+1) : 0);
|
|
||||||
|
|
||||||
/* Code the <expr> from "<expr> IN (...)". The temporary table
|
/* Code the <expr> from "<expr> IN (...)". The temporary table
|
||||||
** pExpr->iTable contains the values that make up the (...) set.
|
** pExpr->iTable contains the values that make up the (...) set.
|
||||||
@@ -2282,7 +2268,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
}
|
}
|
||||||
case TK_UPLUS: {
|
case TK_UPLUS: {
|
||||||
inReg = sqlite3ExprCode(pParse, pExpr->pLeft, origTarget);
|
inReg = sqlite3ExprCode(pParse, pExpr->pLeft, origTarget);
|
||||||
stackChng = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_CASE: {
|
case TK_CASE: {
|
||||||
@@ -2349,7 +2334,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
|
||||||
VdbeComment((v, "raise(IGNORE)"));
|
VdbeComment((v, "raise(IGNORE)"));
|
||||||
}
|
}
|
||||||
stackChng = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2360,11 +2344,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
}else{
|
}else{
|
||||||
target = inReg;
|
target = inReg;
|
||||||
}
|
}
|
||||||
stackChng = 0;
|
|
||||||
}
|
|
||||||
if( pParse->ckOffset ){
|
|
||||||
pParse->ckOffset += stackChng;
|
|
||||||
assert( pParse->ckOffset );
|
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
@@ -2443,7 +2422,6 @@ int sqlite3ExprCodeExprList(
|
|||||||
void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
int op = 0;
|
int op = 0;
|
||||||
int ckOffset = pParse->ckOffset;
|
|
||||||
if( v==0 || pExpr==0 ) return;
|
if( v==0 || pExpr==0 ) return;
|
||||||
op = pExpr->op;
|
op = pExpr->op;
|
||||||
switch( op ){
|
switch( op ){
|
||||||
@@ -2518,7 +2496,6 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pParse->ckOffset = ckOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2532,7 +2509,6 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
int op = 0;
|
int op = 0;
|
||||||
int ckOffset = pParse->ckOffset;
|
|
||||||
if( v==0 || pExpr==0 ) return;
|
if( v==0 || pExpr==0 ) return;
|
||||||
|
|
||||||
/* The value of pExpr->op and op are related as follows:
|
/* The value of pExpr->op and op are related as follows:
|
||||||
@@ -2629,7 +2605,6 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pParse->ckOffset = ckOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
116
src/insert.c
116
src/insert.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
|
||||||
** to handle INSERT statements in SQLite.
|
** to handle INSERT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: insert.c,v 1.215 2008/01/07 19:20:25 drh Exp $
|
** $Id: insert.c,v 1.216 2008/01/08 02:57:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -373,6 +373,7 @@ void sqlite3Insert(
|
|||||||
int regRowid; /* registers holding insert rowid */
|
int regRowid; /* registers holding insert rowid */
|
||||||
int regData; /* register holding first column to insert */
|
int regData; /* register holding first column to insert */
|
||||||
int regRecord; /* Holds the assemblied row record */
|
int regRecord; /* Holds the assemblied row record */
|
||||||
|
int *aRegIdx = 0; /* One register allocated to each index */
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
@@ -631,8 +632,18 @@ void sqlite3Insert(
|
|||||||
|
|
||||||
/* If this is not a view, open the table and and all indices */
|
/* If this is not a view, open the table and and all indices */
|
||||||
if( !isView ){
|
if( !isView ){
|
||||||
|
int nIdx;
|
||||||
|
int i;
|
||||||
|
|
||||||
base = pParse->nTab;
|
base = pParse->nTab;
|
||||||
sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
|
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
|
||||||
|
aRegIdx = sqlite3DbMallocZero(db, sizeof(int)*(nIdx+1));
|
||||||
|
if( aRegIdx==0 ){
|
||||||
|
goto insert_cleanup;
|
||||||
|
}
|
||||||
|
for(i=0; i<nIdx; i++){
|
||||||
|
aRegIdx[i] = ++pParse->nMem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the data source is a temporary table, then we have to create
|
/* If the data source is a temporary table, then we have to create
|
||||||
@@ -830,9 +841,9 @@ void sqlite3Insert(
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
sqlite3RegToStack(pParse, regIns, pTab->nCol+1);
|
sqlite3RegToStack(pParse, regIns, pTab->nCol+1);
|
||||||
sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
|
sqlite3GenerateConstraintChecks(pParse, pTab, base, aRegIdx, keyColumn>=0,
|
||||||
0, onError, endOfLoop);
|
0, onError, endOfLoop);
|
||||||
sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
|
sqlite3CompleteInsertion(pParse, pTab, base, aRegIdx,0,0,
|
||||||
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
|
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
|
||||||
appendFlag);
|
appendFlag);
|
||||||
}
|
}
|
||||||
@@ -895,6 +906,7 @@ insert_cleanup:
|
|||||||
sqlite3ExprListDelete(pList);
|
sqlite3ExprListDelete(pList);
|
||||||
sqlite3SelectDelete(pSelect);
|
sqlite3SelectDelete(pSelect);
|
||||||
sqlite3IdListDelete(pColumn);
|
sqlite3IdListDelete(pColumn);
|
||||||
|
sqlite3_free(aRegIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -919,11 +931,11 @@ insert_cleanup:
|
|||||||
** and rowidChng are 1. isUpdate is true for UPDATEs and false for
|
** and rowidChng are 1. isUpdate is true for UPDATEs and false for
|
||||||
** INSERTs and rowidChng is true if the record number is being changed.
|
** INSERTs and rowidChng is true if the record number is being changed.
|
||||||
**
|
**
|
||||||
** The code generated by this routine pushes additional entries onto
|
** The code generated by this routine store new index entries into
|
||||||
** the stack which are the keys for new index entries for the new record.
|
** registers identified by aRegIdx[]. No index entry is created for
|
||||||
** The order of index keys is the same as the order of the indices on
|
** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
|
||||||
** the pTable->pIndex list. A key is only created for index i if
|
** the same as the order of indices on the linked list of indices
|
||||||
** aIdxUsed!=0 and aIdxUsed[i]!=0.
|
** attached to the table.
|
||||||
**
|
**
|
||||||
** This routine also generates code to check constraints. NOT NULL,
|
** This routine also generates code to check constraints. NOT NULL,
|
||||||
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
|
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
|
||||||
@@ -968,7 +980,7 @@ insert_cleanup:
|
|||||||
** cursor number "base". All indices of pTab must also have open
|
** cursor number "base". All indices of pTab must also have open
|
||||||
** read/write cursors with cursor number base+i for the i-th cursor.
|
** read/write cursors with cursor number base+i for the i-th cursor.
|
||||||
** Except, if there is no possibility of a REPLACE action then
|
** Except, if there is no possibility of a REPLACE action then
|
||||||
** cursors do not need to be open for indices where aIdxUsed[i]==0.
|
** cursors do not need to be open for indices where aRegIdx[i]==0.
|
||||||
**
|
**
|
||||||
** If the isUpdate flag is true, it means that the "base" cursor is
|
** If the isUpdate flag is true, it means that the "base" cursor is
|
||||||
** initially pointing to an entry that is being updated. The isUpdate
|
** initially pointing to an entry that is being updated. The isUpdate
|
||||||
@@ -980,7 +992,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
Parse *pParse, /* The parser context */
|
Parse *pParse, /* The parser context */
|
||||||
Table *pTab, /* the table into which we are inserting */
|
Table *pTab, /* the table into which we are inserting */
|
||||||
int base, /* Index of a read/write cursor pointing at pTab */
|
int base, /* Index of a read/write cursor pointing at pTab */
|
||||||
char *aIdxUsed, /* Which indices are used. NULL means all are used */
|
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
||||||
int rowidChng, /* True if the record number will change */
|
int rowidChng, /* True if the record number will change */
|
||||||
int isUpdate, /* True for UPDATE, False for INSERT */
|
int isUpdate, /* True for UPDATE, False for INSERT */
|
||||||
int overrideError, /* Override onError to this if not OE_Default */
|
int overrideError, /* Override onError to this if not OE_Default */
|
||||||
@@ -990,19 +1002,26 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
Vdbe *v;
|
Vdbe *v;
|
||||||
int nCol;
|
int nCol;
|
||||||
int onError;
|
int onError;
|
||||||
int addr;
|
int j1, j2, j3; /* Address of jump instructions */
|
||||||
int extra;
|
|
||||||
int iCur;
|
int iCur;
|
||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
int seenReplace = 0;
|
int seenReplace = 0;
|
||||||
int jumpInst1=0, jumpInst2;
|
|
||||||
int hasTwoRowids = (isUpdate && rowidChng);
|
int hasTwoRowids = (isUpdate && rowidChng);
|
||||||
|
|
||||||
|
int regRowid, regData;
|
||||||
|
|
||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
||||||
nCol = pTab->nCol;
|
nCol = pTab->nCol;
|
||||||
|
|
||||||
|
/* Copy rowids and data into registers
|
||||||
|
*/
|
||||||
|
regRowid = sqlite3StackToReg(pParse, nCol+1+hasTwoRowids);
|
||||||
|
sqlite3RegToStack(pParse, regRowid, nCol+1+hasTwoRowids);
|
||||||
|
if( hasTwoRowids ) regRowid++;
|
||||||
|
regData = regRowid+1;
|
||||||
|
|
||||||
/* Test all NOT NULL constraints.
|
/* Test all NOT NULL constraints.
|
||||||
*/
|
*/
|
||||||
for(i=0; i<nCol; i++){
|
for(i=0; i<nCol; i++){
|
||||||
@@ -1019,8 +1038,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
|
if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
|
||||||
onError = OE_Abort;
|
onError = OE_Abort;
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i));
|
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
|
||||||
addr = sqlite3VdbeAddOp0(v, OP_NotNull);
|
|
||||||
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
||||||
|| onError==OE_Ignore || onError==OE_Replace );
|
|| onError==OE_Ignore || onError==OE_Replace );
|
||||||
switch( onError ){
|
switch( onError ){
|
||||||
@@ -1041,11 +1059,12 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
case OE_Replace: {
|
case OE_Replace: {
|
||||||
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0);
|
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Copy, 0, regData+i);
|
||||||
sqlite3VdbeAddOp1(v, OP_Push, nCol-i);
|
sqlite3VdbeAddOp1(v, OP_Push, nCol-i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, j1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test all CHECK constraints
|
/* Test all CHECK constraints
|
||||||
@@ -1053,11 +1072,8 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
#ifndef SQLITE_OMIT_CHECK
|
#ifndef SQLITE_OMIT_CHECK
|
||||||
if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
|
if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
|
||||||
int allOk = sqlite3VdbeMakeLabel(v);
|
int allOk = sqlite3VdbeMakeLabel(v);
|
||||||
assert( pParse->ckOffset==0 );
|
pParse->ckBase = regData;
|
||||||
pParse->ckOffset = nCol;
|
|
||||||
sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);
|
sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);
|
||||||
assert( pParse->ckOffset==nCol );
|
|
||||||
pParse->ckOffset = 0;
|
|
||||||
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
|
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
|
||||||
if( onError==OE_Ignore ){
|
if( onError==OE_Ignore ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Pop, nCol+1+hasTwoRowids, 0);
|
sqlite3VdbeAddOp2(v, OP_Pop, nCol+1+hasTwoRowids, 0);
|
||||||
@@ -1082,12 +1098,11 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
|
||||||
jumpInst1 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
|
j2 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -nCol);
|
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, base, 0, regRowid);
|
||||||
jumpInst2 = sqlite3VdbeAddOp2(v, OP_NotExists, base, 0);
|
|
||||||
switch( onError ){
|
switch( onError ){
|
||||||
default: {
|
default: {
|
||||||
onError = OE_Abort;
|
onError = OE_Abort;
|
||||||
@@ -1103,7 +1118,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
case OE_Replace: {
|
case OE_Replace: {
|
||||||
sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
|
sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+hasTwoRowids));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
|
||||||
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
||||||
}
|
}
|
||||||
seenReplace = 1;
|
seenReplace = 1;
|
||||||
@@ -1116,10 +1131,10 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeJumpHere(v, jumpInst2);
|
sqlite3VdbeJumpHere(v, j3);
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeJumpHere(v, jumpInst1);
|
sqlite3VdbeJumpHere(v, j2);
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
|
||||||
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1128,22 +1143,20 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
** index and making sure that duplicate entries do not already exist.
|
** index and making sure that duplicate entries do not already exist.
|
||||||
** Add the new records to the indices as we go.
|
** Add the new records to the indices as we go.
|
||||||
*/
|
*/
|
||||||
extra = -1;
|
|
||||||
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
|
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
|
||||||
if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; /* Skip unused indices */
|
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
|
||||||
extra++;
|
|
||||||
|
|
||||||
/* Create a key for accessing the index entry */
|
/* Create a key for accessing the index entry */
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
|
||||||
for(i=0; i<pIdx->nColumn; i++){
|
for(i=0; i<pIdx->nColumn; i++){
|
||||||
int idx = pIdx->aiColumn[i];
|
int idx = pIdx->aiColumn[i];
|
||||||
if( idx==pTab->iPKey ){
|
if( idx==pTab->iPKey ){
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol+1));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol-idx));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regData+idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jumpInst1 = sqlite3VdbeAddOp2(v, OP_MakeIdxRec, pIdx->nColumn, 0);
|
j2 = sqlite3VdbeAddOp3(v, OP_MakeIdxRec, pIdx->nColumn, 0, aRegIdx[iCur]);
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
sqlite3IndexAffinityStr(v, pIdx);
|
||||||
|
|
||||||
/* Find out what action to take in case there is an indexing conflict */
|
/* Find out what action to take in case there is an indexing conflict */
|
||||||
@@ -1161,8 +1174,9 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
|
|
||||||
|
|
||||||
/* Check to see if the new index entry will be unique */
|
/* Check to see if the new index entry will be unique */
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(extra+nCol+1+hasTwoRowids));
|
sqlite3VdbeAddOp1(v, OP_SCopy, aRegIdx[iCur]);
|
||||||
jumpInst2 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
|
||||||
|
j3 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);
|
||||||
|
|
||||||
/* Generate code that executes if the new index entry is not unique */
|
/* Generate code that executes if the new index entry is not unique */
|
||||||
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
||||||
@@ -1199,7 +1213,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
case OE_Ignore: {
|
case OE_Ignore: {
|
||||||
assert( seenReplace==0 );
|
assert( seenReplace==0 );
|
||||||
sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
|
sqlite3VdbeAddOp2(v, OP_Pop, nCol+3+hasTwoRowids, 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1207,17 +1221,18 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
int iRowid = sqlite3StackToReg(pParse, 1);
|
int iRowid = sqlite3StackToReg(pParse, 1);
|
||||||
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
|
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra+1+hasTwoRowids));
|
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
|
||||||
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
|
||||||
}
|
}
|
||||||
seenReplace = 1;
|
seenReplace = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sqlite3VdbeJumpHere(v, j3);
|
||||||
|
sqlite3VdbeAddOp1(v, OP_Pop, 1);
|
||||||
#if NULL_DISTINCT_FOR_UNIQUE
|
#if NULL_DISTINCT_FOR_UNIQUE
|
||||||
sqlite3VdbeJumpHere(v, jumpInst1);
|
sqlite3VdbeJumpHere(v, j2);
|
||||||
#endif
|
#endif
|
||||||
sqlite3VdbeJumpHere(v, jumpInst2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,7 +1250,7 @@ void sqlite3CompleteInsertion(
|
|||||||
Parse *pParse, /* The parser context */
|
Parse *pParse, /* The parser context */
|
||||||
Table *pTab, /* the table into which we are inserting */
|
Table *pTab, /* the table into which we are inserting */
|
||||||
int base, /* Index of a read/write cursor pointing at pTab */
|
int base, /* Index of a read/write cursor pointing at pTab */
|
||||||
char *aIdxUsed, /* Which indices are used. NULL means all are used */
|
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
||||||
int rowidChng, /* True if the record number will change */
|
int rowidChng, /* True if the record number will change */
|
||||||
int isUpdate, /* True for UPDATE, False for INSERT */
|
int isUpdate, /* True for UPDATE, False for INSERT */
|
||||||
int newIdx, /* Index of NEW table for triggers. -1 if none */
|
int newIdx, /* Index of NEW table for triggers. -1 if none */
|
||||||
@@ -1252,8 +1267,8 @@ void sqlite3CompleteInsertion(
|
|||||||
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
||||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
|
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
|
||||||
for(i=nIdx-1; i>=0; i--){
|
for(i=nIdx-1; i>=0; i--){
|
||||||
if( aIdxUsed && aIdxUsed[i]==0 ) continue;
|
if( aRegIdx[i]==0 ) continue;
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, 0);
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, aRegIdx[i]);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_MakeRecord, pTab->nCol, 0);
|
sqlite3VdbeAddOp2(v, OP_MakeRecord, pTab->nCol, 0);
|
||||||
sqlite3TableAffinityStr(v, pTab);
|
sqlite3TableAffinityStr(v, pTab);
|
||||||
@@ -1287,8 +1302,10 @@ void sqlite3CompleteInsertion(
|
|||||||
** Generate code that will open cursors for a table and for all
|
** Generate code that will open cursors for a table and for all
|
||||||
** indices of that table. The "base" parameter is the cursor number used
|
** indices of that table. The "base" parameter is the cursor number used
|
||||||
** for the table. Indices are opened on subsequent cursors.
|
** for the table. Indices are opened on subsequent cursors.
|
||||||
|
**
|
||||||
|
** Return the number of indices on the table.
|
||||||
*/
|
*/
|
||||||
void sqlite3OpenTableAndIndices(
|
int sqlite3OpenTableAndIndices(
|
||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
Table *pTab, /* Table to be opened */
|
Table *pTab, /* Table to be opened */
|
||||||
int base, /* Cursor number assigned to the table */
|
int base, /* Cursor number assigned to the table */
|
||||||
@@ -1299,7 +1316,7 @@ void sqlite3OpenTableAndIndices(
|
|||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
Vdbe *v;
|
Vdbe *v;
|
||||||
|
|
||||||
if( IsVirtual(pTab) ) return;
|
if( IsVirtual(pTab) ) return 0;
|
||||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
@@ -1314,6 +1331,7 @@ void sqlite3OpenTableAndIndices(
|
|||||||
if( pParse->nTab<=base+i ){
|
if( pParse->nTab<=base+i ){
|
||||||
pParse->nTab = base+i;
|
pParse->nTab = base+i;
|
||||||
}
|
}
|
||||||
|
return i-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1614,7 +1632,7 @@ static int xferOptimization(
|
|||||||
VdbeComment((v, "%s", pDestIdx->zName));
|
VdbeComment((v, "%s", pDestIdx->zName));
|
||||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
|
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, 0);
|
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, 1);
|
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, 0, 1);
|
||||||
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
|
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
|
||||||
sqlite3VdbeJumpHere(v, addr1);
|
sqlite3VdbeJumpHere(v, addr1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.641 2008/01/06 00:25:22 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.642 2008/01/08 02:57:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -1389,7 +1389,7 @@ struct Parse {
|
|||||||
int nTab; /* Number of previously allocated VDBE cursors */
|
int nTab; /* Number of previously allocated VDBE cursors */
|
||||||
int nMem; /* Number of memory cells used so far */
|
int nMem; /* Number of memory cells used so far */
|
||||||
int nSet; /* Number of sets used so far */
|
int nSet; /* Number of sets used so far */
|
||||||
int ckOffset; /* Stack offset to data used by CHECK constraints */
|
int ckBase; /* Base register of data during check constraints */
|
||||||
u32 writeMask; /* Start a write transaction on these databases */
|
u32 writeMask; /* Start a write transaction on these databases */
|
||||||
u32 cookieMask; /* Bitmask of schema verified databases */
|
u32 cookieMask; /* Bitmask of schema verified databases */
|
||||||
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
|
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
|
||||||
@@ -1774,11 +1774,11 @@ 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, int);
|
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int, int);
|
||||||
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
|
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, int*);
|
||||||
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,int*,int,int,int,int);
|
||||||
void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
|
void sqlite3CompleteInsertion(Parse*, Table*, int, int*, int, int, int, int);
|
||||||
void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
|
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
|
||||||
void sqlite3BeginWriteOperation(Parse*, int, int);
|
void sqlite3BeginWriteOperation(Parse*, int, int);
|
||||||
Expr *sqlite3ExprDup(sqlite3*,Expr*);
|
Expr *sqlite3ExprDup(sqlite3*,Expr*);
|
||||||
void sqlite3TokenCopy(sqlite3*,Token*, Token*);
|
void sqlite3TokenCopy(sqlite3*,Token*, Token*);
|
||||||
|
|||||||
66
src/update.c
66
src/update.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
|
||||||
** to handle UPDATE statements.
|
** to handle UPDATE statements.
|
||||||
**
|
**
|
||||||
** $Id: update.c,v 1.162 2008/01/06 00:25:22 drh Exp $
|
** $Id: update.c,v 1.163 2008/01/08 02:57:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -90,11 +90,9 @@ void sqlite3Update(
|
|||||||
Vdbe *v; /* The virtual database engine */
|
Vdbe *v; /* The virtual database engine */
|
||||||
Index *pIdx; /* For looping over indices */
|
Index *pIdx; /* For looping over indices */
|
||||||
int nIdx; /* Number of indices that need updating */
|
int nIdx; /* Number of indices that need updating */
|
||||||
int nIdxTotal; /* Total number of indices */
|
|
||||||
int iCur; /* VDBE Cursor number of pTab */
|
int iCur; /* VDBE Cursor number of pTab */
|
||||||
sqlite3 *db; /* The database structure */
|
sqlite3 *db; /* The database structure */
|
||||||
Index **apIdx = 0; /* An array of indices that need updating too */
|
int *aRegIdx = 0; /* One register assigned to each index to be updated */
|
||||||
char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
|
|
||||||
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
|
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
|
||||||
** an expression for the i-th column of the table.
|
** an expression for the i-th column of the table.
|
||||||
** aXRef[i]==-1 if the i-th column is not changed. */
|
** aXRef[i]==-1 if the i-th column is not changed. */
|
||||||
@@ -227,40 +225,30 @@ void sqlite3Update(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for the array apIdx[] and fill it with pointers to every
|
/* Allocate memory for the array aRegIdx[]. There is one entry in the
|
||||||
** index that needs to be updated. Indices only need updating if their
|
** array for each index associated with table being updated. Fill in
|
||||||
** key includes one of the columns named in pChanges or if the record
|
** the value with a register number for indices that are to be used
|
||||||
** number of the original table entry is changing.
|
** and with zero for unused indices.
|
||||||
*/
|
*/
|
||||||
for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
|
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
|
||||||
|
if( nIdx>0 ){
|
||||||
|
aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
|
||||||
|
if( aRegIdx==0 ) goto update_cleanup;
|
||||||
|
}
|
||||||
|
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||||
|
int reg;
|
||||||
if( chngRowid ){
|
if( chngRowid ){
|
||||||
i = 0;
|
reg = ++pParse->nMem;
|
||||||
}else {
|
}else{
|
||||||
|
reg = 0;
|
||||||
for(i=0; i<pIdx->nColumn; i++){
|
for(i=0; i<pIdx->nColumn; i++){
|
||||||
if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
|
if( aXRef[pIdx->aiColumn[i]]>=0 ){
|
||||||
|
reg = ++pParse->nMem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( i<pIdx->nColumn ) nIdx++;
|
aRegIdx[j] = reg;
|
||||||
}
|
|
||||||
if( nIdxTotal>0 ){
|
|
||||||
apIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx + nIdxTotal );
|
|
||||||
if( apIdx==0 ) goto update_cleanup;
|
|
||||||
aIdxUsed = (char*)&apIdx[nIdx];
|
|
||||||
}
|
|
||||||
for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
|
||||||
if( chngRowid ){
|
|
||||||
i = 0;
|
|
||||||
}else{
|
|
||||||
for(i=0; i<pIdx->nColumn; i++){
|
|
||||||
if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( i<pIdx->nColumn ){
|
|
||||||
apIdx[nIdx++] = pIdx;
|
|
||||||
aIdxUsed[j] = 1;
|
|
||||||
}else{
|
|
||||||
aIdxUsed[j] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Begin generating code.
|
/* Begin generating code.
|
||||||
@@ -380,7 +368,7 @@ void sqlite3Update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||||
if( openAll || aIdxUsed[i] ){
|
if( openAll || aRegIdx[i]>0 ){
|
||||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||||
sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
|
sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
|
||||||
(char*)pKey, P4_KEYINFO_HANDOFF);
|
(char*)pKey, P4_KEYINFO_HANDOFF);
|
||||||
@@ -486,12 +474,12 @@ void sqlite3Update(
|
|||||||
|
|
||||||
/* Do constraint checks
|
/* Do constraint checks
|
||||||
*/
|
*/
|
||||||
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
|
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aRegIdx, chngRowid, 1,
|
||||||
onError, addr);
|
onError, addr);
|
||||||
|
|
||||||
/* Delete the old indices for the current record.
|
/* Delete the old indices for the current record.
|
||||||
*/
|
*/
|
||||||
sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
|
sqlite3GenerateRowIndexDelete(v, pTab, iCur, aRegIdx);
|
||||||
|
|
||||||
/* If changing the record number, delete the old record.
|
/* If changing the record number, delete the old record.
|
||||||
*/
|
*/
|
||||||
@@ -501,7 +489,7 @@ void sqlite3Update(
|
|||||||
|
|
||||||
/* Create the new index entries and the new record.
|
/* Create the new index entries and the new record.
|
||||||
*/
|
*/
|
||||||
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0);
|
sqlite3CompleteInsertion(pParse, pTab, iCur, aRegIdx, chngRowid, 1, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the row counter
|
/* Increment the row counter
|
||||||
@@ -526,7 +514,7 @@ void sqlite3Update(
|
|||||||
|
|
||||||
/* Close all tables */
|
/* Close all tables */
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||||
if( openAll || aIdxUsed[i] ){
|
if( openAll || aRegIdx[i]>0 ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
|
sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -549,7 +537,7 @@ void sqlite3Update(
|
|||||||
|
|
||||||
update_cleanup:
|
update_cleanup:
|
||||||
sqlite3AuthContextPop(&sContext);
|
sqlite3AuthContextPop(&sContext);
|
||||||
sqlite3_free(apIdx);
|
sqlite3_free(aRegIdx);
|
||||||
sqlite3_free(aXRef);
|
sqlite3_free(aXRef);
|
||||||
sqlite3SrcListDelete(pTabList);
|
sqlite3SrcListDelete(pTabList);
|
||||||
sqlite3ExprListDelete(pChanges);
|
sqlite3ExprListDelete(pChanges);
|
||||||
|
|||||||
61
src/vdbe.c
61
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.687 2008/01/07 19:20:25 drh Exp $
|
** $Id: vdbe.c,v 1.688 2008/01/08 02:57:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -717,6 +717,26 @@ int sqlite3VdbeExec(
|
|||||||
pOut = &p->aMem[pOp->p2];
|
pOut = &p->aMem[pOp->p2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else if( (opProperty & OPFLG_IN2)!=0 ){
|
||||||
|
assert( pOp->p2>=0 );
|
||||||
|
if( pOp->p2==0 ){
|
||||||
|
pIn2 = pTos;
|
||||||
|
nPop = 1;
|
||||||
|
}else{
|
||||||
|
assert( pOp->p2<=p->nMem );
|
||||||
|
pIn2 = &p->aMem[pOp->p2];
|
||||||
|
REGISTER_TRACE(pOp->p2, pIn2);
|
||||||
|
}
|
||||||
|
}else if( (opProperty & OPFLG_IN3)!=0 ){
|
||||||
|
assert( pOp->p3>=0 );
|
||||||
|
if( pOp->p3==0 ){
|
||||||
|
pIn3 = pTos;
|
||||||
|
nPop = 1;
|
||||||
|
}else{
|
||||||
|
assert( pOp->p3<=p->nMem );
|
||||||
|
pIn3 = &p->aMem[pOp->p3];
|
||||||
|
REGISTER_TRACE(pOp->p3, pIn3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( pOp->opcode ){
|
switch( pOp->opcode ){
|
||||||
@@ -4166,67 +4186,60 @@ case OP_Next: { /* no-push, jump */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: IdxInsert P1 P2 *
|
/* Opcode: IdxInsert P1 P2 P3
|
||||||
**
|
**
|
||||||
** The top of the stack holds a SQL index key made using either the
|
** Register P2 holds a SQL index key made using the
|
||||||
** MakeIdxRec or MakeRecord instructions. This opcode writes that key
|
** MakeIdxRec instructions. This opcode writes that key
|
||||||
** into the index P1. Data for the entry is nil.
|
** into the index P1. Data for the entry is nil.
|
||||||
**
|
**
|
||||||
** P2 is a flag that provides a hint to the b-tree layer that this
|
** P3 is a flag that provides a hint to the b-tree layer that this
|
||||||
** insert is likely to be an append.
|
** insert is likely to be an append.
|
||||||
**
|
**
|
||||||
** This instruction only works for indices. The equivalent instruction
|
** This instruction only works for indices. The equivalent instruction
|
||||||
** for tables is OP_Insert.
|
** for tables is OP_Insert.
|
||||||
*/
|
*/
|
||||||
case OP_IdxInsert: { /* no-push */
|
case OP_IdxInsert: { /* no-push, in2 */
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
BtCursor *pCrsr;
|
BtCursor *pCrsr;
|
||||||
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 );
|
||||||
assert( pTos->flags & MEM_Blob );
|
assert( pIn2->flags & MEM_Blob );
|
||||||
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
|
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
|
||||||
assert( pC->isTable==0 );
|
assert( pC->isTable==0 );
|
||||||
rc = ExpandBlob(pTos);
|
rc = ExpandBlob(pIn2);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
int nKey = pTos->n;
|
int nKey = pIn2->n;
|
||||||
const char *zKey = pTos->z;
|
const char *zKey = pIn2->z;
|
||||||
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p2);
|
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3);
|
||||||
assert( pC->deferredMoveto==0 );
|
assert( pC->deferredMoveto==0 );
|
||||||
pC->cacheStatus = CACHE_STALE;
|
pC->cacheStatus = CACHE_STALE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Release(pTos);
|
|
||||||
pTos--;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: IdxDelete P1 * *
|
/* Opcode: IdxDelete P1 P2 *
|
||||||
**
|
**
|
||||||
** The top of the stack is an index key built using the either the
|
** The content of register P2 is an index key built using the either the
|
||||||
** MakeIdxRec or MakeRecord opcodes.
|
** MakeIdxRec opcode. Removes that entry from the index.
|
||||||
** This opcode removes that entry from the index.
|
|
||||||
*/
|
*/
|
||||||
case OP_IdxDelete: { /* no-push */
|
case OP_IdxDelete: { /* no-push, in2 */
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
BtCursor *pCrsr;
|
BtCursor *pCrsr;
|
||||||
assert( pTos>=p->aStack );
|
assert( pIn2->flags & MEM_Blob );
|
||||||
assert( pTos->flags & MEM_Blob );
|
|
||||||
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;
|
||||||
rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, 0, &res);
|
rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res);
|
||||||
if( rc==SQLITE_OK && res==0 ){
|
if( rc==SQLITE_OK && res==0 ){
|
||||||
rc = sqlite3BtreeDelete(pCrsr);
|
rc = sqlite3BtreeDelete(pCrsr);
|
||||||
}
|
}
|
||||||
assert( pC->deferredMoveto==0 );
|
assert( pC->deferredMoveto==0 );
|
||||||
pC->cacheStatus = CACHE_STALE;
|
pC->cacheStatus = CACHE_STALE;
|
||||||
}
|
}
|
||||||
Release(pTos);
|
|
||||||
pTos--;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -821,12 +821,14 @@ int sqlite3VdbeList(
|
|||||||
pMem++;
|
pMem++;
|
||||||
|
|
||||||
pMem->flags = MEM_Null; /* Comment */
|
pMem->flags = MEM_Null; /* Comment */
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
if( pOp->zComment ){
|
if( pOp->zComment ){
|
||||||
pMem->flags = MEM_Str|MEM_Term;
|
pMem->flags = MEM_Str|MEM_Term;
|
||||||
pMem->z = pOp->zComment;
|
pMem->z = pOp->zComment;
|
||||||
pMem->n = strlen(pMem->z);
|
pMem->n = strlen(pMem->z);
|
||||||
pMem->enc = SQLITE_UTF8;
|
pMem->enc = SQLITE_UTF8;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
p->nResColumn = 8 - 5*(p->explain-1);
|
p->nResColumn = 8 - 5*(p->explain-1);
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
|
|||||||
}
|
}
|
||||||
pFrom->flags = MEM_Null;
|
pFrom->flags = MEM_Null;
|
||||||
pFrom->xDel = 0;
|
pFrom->xDel = 0;
|
||||||
if( pTo->flags & MEM_Ephem ){
|
if( 0 /* pTo->flags & MEM_Ephem */ ){
|
||||||
rc = sqlite3VdbeMemMakeWriteable(pTo);
|
rc = sqlite3VdbeMemMakeWriteable(pTo);
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user