mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
Cleanup and simplification of constraint processing. Simplifications
to the VM for better test coverage. (CVS 4729) FossilOrigin-Name: d9ebe9d78c558af050c44ac4437ce0ef8193a4a8
This commit is contained in:
20
manifest
20
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\stest\sinstrumentation\sproblems\son\sshared_err.test.\s(CVS\s4728)
|
C Cleanup\sand\ssimplification\sof\sconstraint\sprocessing.\s\sSimplifications\nto\sthe\sVM\sfor\sbetter\stest\scoverage.\s(CVS\s4729)
|
||||||
D 2008-01-18T17:03:33
|
D 2008-01-19T03:35:59
|
||||||
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
|
||||||
@@ -96,7 +96,7 @@ F src/expr.c 9ac9177466b17b57e814f0beabc9e7bba88f8e38
|
|||||||
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 ed16eaf9391929e29fdbfa589db09b7224b31905
|
F src/insert.c 969b543eedaeb3ec4cd52cd6931db94da67388c3
|
||||||
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
|
||||||
@@ -131,7 +131,7 @@ F src/pragma.c 155315ee3e6a861a0060ba4d184dfffd08ebbc03
|
|||||||
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
||||||
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
||||||
F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
|
F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
|
||||||
F src/select.c d9a394a2566849f9f7b03e2da3fd3ed4a91611eb
|
F src/select.c 9fb094cc0c8acdcbf3581fdfc4490e997b5d1d1e
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c 0691a3d52dc37cf6ac2f74838e5ff8ae1055ac9b
|
F src/shell.c 0691a3d52dc37cf6ac2f74838e5ff8ae1055ac9b
|
||||||
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
||||||
@@ -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 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
|
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
|
||||||
F src/update.c 2513c6120f9510ae782446a2b839931e994b75dd
|
F src/update.c 31edd9c9764e80753930bd5f9b43e0edb404636f
|
||||||
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
||||||
F src/util.c deda8c5a400530e1c27c03619cc4cd1a06fc5281
|
F src/util.c deda8c5a400530e1c27c03619cc4cd1a06fc5281
|
||||||
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
||||||
F src/vdbe.c 3734b4b4fc34e46be4542593f9907a8a4d31c3d4
|
F src/vdbe.c 986d1b4034e271c67f8cab0e03a5e459cb288ad7
|
||||||
F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9
|
F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9
|
||||||
F src/vdbeInt.h 835e6f0337ce89d705ef9a162338788808adc4b7
|
F src/vdbeInt.h 835e6f0337ce89d705ef9a162338788808adc4b7
|
||||||
F src/vdbeapi.c cb8c427a3ab646490c83204a98e94eff03ee2e89
|
F src/vdbeapi.c cb8c427a3ab646490c83204a98e94eff03ee2e89
|
||||||
F src/vdbeaux.c 0d2a9730195d40f7d1156731bc69f240927255c5
|
F src/vdbeaux.c 0d2a9730195d40f7d1156731bc69f240927255c5
|
||||||
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
|
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
|
||||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||||
F src/vdbemem.c 666a1d7b9d48ce6b1f6eb5e454693e0da08f6187
|
F src/vdbemem.c e15122efe8868e400c2aba8ea101588944e83317
|
||||||
F src/vtab.c 9924e37cf7f5c527aeabb5da025874af505fb91d
|
F src/vtab.c 9924e37cf7f5c527aeabb5da025874af505fb91d
|
||||||
F src/where.c 0cc6052f73aef0d2ce59505d7ae06d6fbf696025
|
F src/where.c 0cc6052f73aef0d2ce59505d7ae06d6fbf696025
|
||||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||||
@@ -607,7 +607,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 42d8a377551baef01fb4e80f35fc12f9454a3cd4
|
P 5aef5b0dd8e44a56f84fbc6f843016bca5101987
|
||||||
R 53a68cbdb5a0c09e7f3102caf81464df
|
R 07faac02e9ea2890001493a3c96130c4
|
||||||
U drh
|
U drh
|
||||||
Z f8720638d058f6048f391f0665e9a25c
|
Z 11b35796b0f55998b3b3bad35c703ebb
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
5aef5b0dd8e44a56f84fbc6f843016bca5101987
|
d9ebe9d78c558af050c44ac4437ce0ef8193a4a8
|
||||||
82
src/insert.c
82
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.225 2008/01/17 16:22:15 drh Exp $
|
** $Id: insert.c,v 1.226 2008/01/19 03:35:59 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -943,7 +943,7 @@ insert_cleanup:
|
|||||||
**
|
**
|
||||||
** 1. The rowid of the row to be updated before the update. This
|
** 1. The rowid of the row to be updated before the update. This
|
||||||
** value is omitted unless we are doing an UPDATE that involves a
|
** value is omitted unless we are doing an UPDATE that involves a
|
||||||
** change to the record number. (Or writing to a virtual table.)
|
** change to the record number or writing to a virtual table.
|
||||||
**
|
**
|
||||||
** 2. The rowid of the row after the update.
|
** 2. The rowid of the row after the update.
|
||||||
**
|
**
|
||||||
@@ -957,7 +957,10 @@ insert_cleanup:
|
|||||||
**
|
**
|
||||||
** The old rowid shown as entry (1) above is omitted unless both isUpdate
|
** The old rowid shown as entry (1) above is omitted unless both isUpdate
|
||||||
** 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. RowidChng means that the new rowid is explicitly specified by
|
||||||
|
** the update or insert statement. If rowidChng is false, it means that
|
||||||
|
** the rowid is computed automatically in an insert or that the rowid value
|
||||||
|
** is not modified by the update.
|
||||||
**
|
**
|
||||||
** The code generated by this routine store new index entries into
|
** The code generated by this routine store new index entries into
|
||||||
** registers identified by aRegIdx[]. No index entry is created for
|
** registers identified by aRegIdx[]. No index entry is created for
|
||||||
@@ -1009,12 +1012,6 @@ insert_cleanup:
|
|||||||
** read/write cursors with cursor number baseCur+i for the i-th cursor.
|
** read/write cursors with cursor number baseCur+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 aRegIdx[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 "baseCur" cursor is
|
|
||||||
** initially pointing to an entry that is being updated. The isUpdate
|
|
||||||
** flag causes extra code to be generated so that the "baseCur" cursor
|
|
||||||
** is still pointing at the same entry after the routine returns.
|
|
||||||
** Without the isUpdate flag, the "baseCur" cursor might be moved.
|
|
||||||
*/
|
*/
|
||||||
void sqlite3GenerateConstraintChecks(
|
void sqlite3GenerateConstraintChecks(
|
||||||
Parse *pParse, /* The parser context */
|
Parse *pParse, /* The parser context */
|
||||||
@@ -1022,7 +1019,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
int baseCur, /* Index of a read/write cursor pointing at pTab */
|
int baseCur, /* Index of a read/write cursor pointing at pTab */
|
||||||
int regRowid, /* Index of the range of input registers */
|
int regRowid, /* Index of the range of input registers */
|
||||||
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
||||||
int rowidChng, /* True if the rowid will change */
|
int rowidChng, /* True if the rowid might collide with existing entry */
|
||||||
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 */
|
||||||
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
|
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
|
||||||
@@ -1031,7 +1028,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
Vdbe *v;
|
Vdbe *v;
|
||||||
int nCol;
|
int nCol;
|
||||||
int onError;
|
int onError;
|
||||||
int j1, j2, j3; /* Address of jump instructions */
|
int j1, j2, j3; /* Addresses of jump instructions */
|
||||||
int regData; /* Register containing first data column */
|
int regData; /* Register containing first data column */
|
||||||
int iCur;
|
int iCur;
|
||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
@@ -1116,41 +1113,41 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
onError = OE_Abort;
|
onError = OE_Abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isUpdate ){
|
if( onError==OE_Replace && pTab->pIndex==0 ){
|
||||||
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
|
seenReplace = 1;
|
||||||
}
|
}else{
|
||||||
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
if( isUpdate ){
|
||||||
switch( onError ){
|
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
|
||||||
default: {
|
|
||||||
onError = OE_Abort;
|
|
||||||
/* Fall thru into the next case */
|
|
||||||
}
|
}
|
||||||
case OE_Rollback:
|
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
||||||
case OE_Abort:
|
switch( onError ){
|
||||||
case OE_Fail: {
|
default: {
|
||||||
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
|
onError = OE_Abort;
|
||||||
"PRIMARY KEY must be unique", P4_STATIC);
|
/* Fall thru into the next case */
|
||||||
break;
|
}
|
||||||
}
|
case OE_Rollback:
|
||||||
case OE_Replace: {
|
case OE_Abort:
|
||||||
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
|
case OE_Fail: {
|
||||||
if( isUpdate ){
|
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
|
||||||
sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
|
"PRIMARY KEY must be unique", P4_STATIC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OE_Replace: {
|
||||||
|
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
|
||||||
|
seenReplace = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OE_Ignore: {
|
||||||
|
assert( seenReplace==0 );
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
seenReplace = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case OE_Ignore: {
|
sqlite3VdbeJumpHere(v, j3);
|
||||||
assert( seenReplace==0 );
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
|
sqlite3VdbeJumpHere(v, j2);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeJumpHere(v, j3);
|
|
||||||
if( isUpdate ){
|
|
||||||
sqlite3VdbeJumpHere(v, j2);
|
|
||||||
sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test all UNIQUE constraints by creating entries for each UNIQUE
|
/* Test all UNIQUE constraints by creating entries for each UNIQUE
|
||||||
@@ -1239,9 +1236,6 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
case OE_Replace: {
|
case OE_Replace: {
|
||||||
sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0);
|
sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0);
|
||||||
if( isUpdate ){
|
|
||||||
sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
|
|
||||||
}
|
|
||||||
seenReplace = 1;
|
seenReplace = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.405 2008/01/17 17:15:56 drh Exp $
|
** $Id: select.c,v 1.406 2008/01/19 03:35:59 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -602,12 +602,11 @@ static int selectInnerLoop(
|
|||||||
** the temporary table iParm.
|
** the temporary table iParm.
|
||||||
*/
|
*/
|
||||||
case SRT_Except: {
|
case SRT_Except: {
|
||||||
int addr, r1;
|
int r1;
|
||||||
r1 = sqlite3GetTempReg(pParse);
|
r1 = sqlite3GetTempReg(pParse);
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
||||||
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
||||||
sqlite3VdbeAddOp3(v, OP_NotFound, iParm, addr+3, r1);
|
sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1);
|
||||||
sqlite3VdbeAddOp1(v, OP_Delete, iParm);
|
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
sqlite3ReleaseTempReg(pParse, r1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.169 2008/01/17 16:22:15 drh Exp $
|
** $Id: update.c,v 1.170 2008/01/19 03:35:59 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ void sqlite3Update(
|
|||||||
AuthContext sContext; /* The authorization context */
|
AuthContext sContext; /* The authorization context */
|
||||||
NameContext sNC; /* The name-context to resolve expressions in */
|
NameContext sNC; /* The name-context to resolve expressions in */
|
||||||
int iDb; /* Database containing the table being updated */
|
int iDb; /* Database containing the table being updated */
|
||||||
|
int j1; /* Addresses of jump instructions */
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
int isView; /* Trying to update a view */
|
int isView; /* Trying to update a view */
|
||||||
@@ -504,6 +505,7 @@ void sqlite3Update(
|
|||||||
|
|
||||||
/* Delete the old indices for the current record.
|
/* Delete the old indices for the current record.
|
||||||
*/
|
*/
|
||||||
|
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
|
||||||
sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
|
sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
|
||||||
|
|
||||||
/* If changing the record number, delete the old record.
|
/* If changing the record number, delete the old record.
|
||||||
@@ -511,6 +513,7 @@ void sqlite3Update(
|
|||||||
if( chngRowid ){
|
if( chngRowid ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
|
sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
|
||||||
}
|
}
|
||||||
|
sqlite3VdbeJumpHere(v, j1);
|
||||||
|
|
||||||
/* Create the new index entries and the new record.
|
/* Create the new index entries and the new record.
|
||||||
*/
|
*/
|
||||||
|
|||||||
265
src/vdbe.c
265
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.699 2008/01/18 14:08:25 drh Exp $
|
** $Id: vdbe.c,v 1.700 2008/01/19 03:35:59 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -595,7 +595,7 @@ int sqlite3VdbeExec(
|
|||||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||||
if( prc!=0 ){
|
if( prc!=0 ){
|
||||||
rc = SQLITE_INTERRUPT;
|
rc = SQLITE_INTERRUPT;
|
||||||
goto vdbe_halt;
|
goto vdbe_error_halt;
|
||||||
}
|
}
|
||||||
nProgressOps = 0;
|
nProgressOps = 0;
|
||||||
}
|
}
|
||||||
@@ -950,7 +950,6 @@ case OP_SCopy: {
|
|||||||
if( pOp->opcode==OP_Move ){
|
if( pOp->opcode==OP_Move ){
|
||||||
rc = sqlite3VdbeMemMove(pOut, pIn1);
|
rc = sqlite3VdbeMemMove(pOut, pIn1);
|
||||||
}else{
|
}else{
|
||||||
Release(pOut);
|
|
||||||
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
|
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
|
||||||
if( pOp->opcode==OP_Copy ){
|
if( pOp->opcode==OP_Copy ){
|
||||||
Deephemeralize(pOut);
|
Deephemeralize(pOut);
|
||||||
@@ -1074,10 +1073,8 @@ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
|
|||||||
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
||||||
int flags;
|
int flags;
|
||||||
flags = pIn1->flags | pIn2->flags;
|
flags = pIn1->flags | pIn2->flags;
|
||||||
if( (flags & MEM_Null)!=0 ){
|
if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
|
||||||
Release(pOut);
|
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
|
||||||
pOut->flags = MEM_Null;
|
|
||||||
}else if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
|
|
||||||
i64 a, b;
|
i64 a, b;
|
||||||
a = pIn1->u.i;
|
a = pIn1->u.i;
|
||||||
b = pIn2->u.i;
|
b = pIn2->u.i;
|
||||||
@@ -1086,7 +1083,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
|||||||
case OP_Subtract: b -= a; break;
|
case OP_Subtract: b -= a; break;
|
||||||
case OP_Multiply: b *= a; break;
|
case OP_Multiply: b *= a; break;
|
||||||
case OP_Divide: {
|
case OP_Divide: {
|
||||||
if( a==0 ) goto divide_by_zero;
|
if( a==0 ) goto arithmetic_result_is_null;
|
||||||
/* Dividing the largest possible negative 64-bit integer (1<<63) by
|
/* Dividing the largest possible negative 64-bit integer (1<<63) by
|
||||||
** -1 returns an integer to large to store in a 64-bit data-type. On
|
** -1 returns an integer to large to store in a 64-bit data-type. On
|
||||||
** some architectures, the value overflows to (1<<63). On others,
|
** some architectures, the value overflows to (1<<63). On others,
|
||||||
@@ -1099,7 +1096,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if( a==0 ) goto divide_by_zero;
|
if( a==0 ) goto arithmetic_result_is_null;
|
||||||
if( a==-1 ) a = 1;
|
if( a==-1 ) a = 1;
|
||||||
b %= a;
|
b %= a;
|
||||||
break;
|
break;
|
||||||
@@ -1117,21 +1114,21 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
|||||||
case OP_Subtract: b -= a; break;
|
case OP_Subtract: b -= a; break;
|
||||||
case OP_Multiply: b *= a; break;
|
case OP_Multiply: b *= a; break;
|
||||||
case OP_Divide: {
|
case OP_Divide: {
|
||||||
if( a==0.0 ) goto divide_by_zero;
|
if( a==0.0 ) goto arithmetic_result_is_null;
|
||||||
b /= a;
|
b /= a;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
i64 ia = (i64)a;
|
i64 ia = (i64)a;
|
||||||
i64 ib = (i64)b;
|
i64 ib = (i64)b;
|
||||||
if( ia==0 ) goto divide_by_zero;
|
if( ia==0 ) goto arithmetic_result_is_null;
|
||||||
if( ia==-1 ) ia = 1;
|
if( ia==-1 ) ia = 1;
|
||||||
b = ib % ia;
|
b = ib % ia;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( sqlite3_isnan(b) ){
|
if( sqlite3_isnan(b) ){
|
||||||
goto divide_by_zero;
|
goto arithmetic_result_is_null;
|
||||||
}
|
}
|
||||||
Release(pOut);
|
Release(pOut);
|
||||||
pOut->r = b;
|
pOut->r = b;
|
||||||
@@ -1142,9 +1139,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
divide_by_zero:
|
arithmetic_result_is_null:
|
||||||
Release(pOut);
|
sqlite3VdbeMemSetNull(pOut);
|
||||||
pOut->flags = MEM_Null;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,8 +1291,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
|
|||||||
i64 a, b;
|
i64 a, b;
|
||||||
|
|
||||||
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
|
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
|
||||||
Release(pOut);
|
sqlite3VdbeMemSetNull(pOut);
|
||||||
pOut->flags = MEM_Null;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
a = sqlite3VdbeIntValue(pIn2);
|
a = sqlite3VdbeIntValue(pIn2);
|
||||||
@@ -1305,8 +1300,8 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
|
|||||||
case OP_BitAnd: a &= b; break;
|
case OP_BitAnd: a &= b; break;
|
||||||
case OP_BitOr: a |= b; break;
|
case OP_BitOr: a |= b; break;
|
||||||
case OP_ShiftLeft: a <<= b; break;
|
case OP_ShiftLeft: a <<= b; break;
|
||||||
case OP_ShiftRight: a >>= b; break;
|
default: assert( pOp->opcode==OP_ShiftRight );
|
||||||
default: /* CANT HAPPEN */ break;
|
a >>= b; break;
|
||||||
}
|
}
|
||||||
Release(pOut);
|
Release(pOut);
|
||||||
pOut->u.i = a;
|
pOut->u.i = a;
|
||||||
@@ -1880,7 +1875,8 @@ case OP_Column: {
|
|||||||
sqlite3BtreeDataSize(pCrsr, &payloadSize);
|
sqlite3BtreeDataSize(pCrsr, &payloadSize);
|
||||||
}
|
}
|
||||||
nField = pC->nField;
|
nField = pC->nField;
|
||||||
}else if( pC->pseudoTable ){
|
}else{
|
||||||
|
assert( pC->pseudoTable );
|
||||||
/* The record is the sole entry of a pseudo-table */
|
/* The record is the sole entry of a pseudo-table */
|
||||||
payloadSize = pC->nData;
|
payloadSize = pC->nData;
|
||||||
zRec = pC->pData;
|
zRec = pC->pData;
|
||||||
@@ -1888,11 +1884,6 @@ case OP_Column: {
|
|||||||
assert( payloadSize==0 || zRec!=0 );
|
assert( payloadSize==0 || zRec!=0 );
|
||||||
nField = pC->nField;
|
nField = pC->nField;
|
||||||
pCrsr = 0;
|
pCrsr = 0;
|
||||||
}else{
|
|
||||||
zRec = 0;
|
|
||||||
payloadSize = 0;
|
|
||||||
pCrsr = 0;
|
|
||||||
nField = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If payloadSize is 0, then just store a NULL */
|
/* If payloadSize is 0, then just store a NULL */
|
||||||
@@ -1909,7 +1900,7 @@ case OP_Column: {
|
|||||||
/* Read and parse the table header. Store the results of the parse
|
/* Read and parse the table header. Store the results of the parse
|
||||||
** into the record header cache fields of the cursor.
|
** into the record header cache fields of the cursor.
|
||||||
*/
|
*/
|
||||||
if( pC && pC->cacheStatus==p->cacheCtr ){
|
if( pC->cacheStatus==p->cacheCtr ){
|
||||||
aType = pC->aType;
|
aType = pC->aType;
|
||||||
aOffset = pC->aOffset;
|
aOffset = pC->aOffset;
|
||||||
}else{
|
}else{
|
||||||
@@ -2125,7 +2116,7 @@ case OP_MakeRecord: {
|
|||||||
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
||||||
}
|
}
|
||||||
if( pRec->flags&MEM_Zero && pRec->n>0 ){
|
if( pRec->flags&MEM_Zero && pRec->n>0 ){
|
||||||
ExpandBlob(pRec);
|
sqlite3VdbeMemExpandBlob(pRec);
|
||||||
}
|
}
|
||||||
serial_type = sqlite3VdbeSerialType(pRec, file_format);
|
serial_type = sqlite3VdbeSerialType(pRec, file_format);
|
||||||
len = sqlite3VdbeSerialTypeLen(serial_type);
|
len = sqlite3VdbeSerialTypeLen(serial_type);
|
||||||
@@ -2209,10 +2200,12 @@ case OP_MakeRecord: {
|
|||||||
** has an index of 1.
|
** has an index of 1.
|
||||||
*/
|
*/
|
||||||
case OP_Statement: {
|
case OP_Statement: {
|
||||||
int i = pOp->p1;
|
if( db->autoCommit==0 || db->activeVdbeCnt>1 ){
|
||||||
Btree *pBt;
|
int i = pOp->p1;
|
||||||
if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0
|
Btree *pBt;
|
||||||
&& (db->autoCommit==0 || db->activeVdbeCnt>1) ){
|
assert( i>=0 && i<db->nDb );
|
||||||
|
assert( db->aDb[i].pBt!=0 );
|
||||||
|
pBt = db->aDb[i].pBt;
|
||||||
assert( sqlite3BtreeIsInTrans(pBt) );
|
assert( sqlite3BtreeIsInTrans(pBt) );
|
||||||
assert( (p->btreeMask & (1<<i))!=0 );
|
assert( (p->btreeMask & (1<<i))!=0 );
|
||||||
if( !sqlite3BtreeIsInStmt(pBt) ){
|
if( !sqlite3BtreeIsInStmt(pBt) ){
|
||||||
@@ -2533,7 +2526,6 @@ case OP_OpenWrite: {
|
|||||||
pCur = allocateCursor(p, i, iDb);
|
pCur = allocateCursor(p, i, iDb);
|
||||||
if( pCur==0 ) goto no_mem;
|
if( pCur==0 ) goto no_mem;
|
||||||
pCur->nullRow = 1;
|
pCur->nullRow = 1;
|
||||||
if( pX==0 ) break;
|
|
||||||
/* We always provide a key comparison function. If the table being
|
/* We always provide a key comparison function. If the table being
|
||||||
** opened is of type INTKEY, the comparision function will be ignored. */
|
** opened is of type INTKEY, the comparision function will be ignored. */
|
||||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag,
|
rc = sqlite3BtreeCursor(pX, p2, wrFlag,
|
||||||
@@ -2691,10 +2683,9 @@ case OP_OpenPseudo: {
|
|||||||
*/
|
*/
|
||||||
case OP_Close: {
|
case OP_Close: {
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
if( i>=0 && i<p->nCursor ){
|
assert( i>=0 && i<p->nCursor );
|
||||||
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
|
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
|
||||||
p->apCsr[i] = 0;
|
p->apCsr[i] = 0;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3223,73 +3214,71 @@ case OP_Insert: {
|
|||||||
Mem *pData = &p->aMem[pOp->p2];
|
Mem *pData = &p->aMem[pOp->p2];
|
||||||
Mem *pKey = &p->aMem[pOp->p3];
|
Mem *pKey = &p->aMem[pOp->p3];
|
||||||
|
|
||||||
|
i64 iKey; /* The integer ROWID or key for the record to be inserted */
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
assert( i>=0 && i<p->nCursor );
|
assert( i>=0 && i<p->nCursor );
|
||||||
assert( p->apCsr[i]!=0 );
|
pC = p->apCsr[i];
|
||||||
|
assert( pC!=0 );
|
||||||
|
assert( pC->pCursor!=0 || pC->pseudoTable );
|
||||||
|
assert( pKey->flags & MEM_Int );
|
||||||
|
assert( pC->isTable );
|
||||||
REGISTER_TRACE(pOp->p2, pData);
|
REGISTER_TRACE(pOp->p2, pData);
|
||||||
REGISTER_TRACE(pOp->p3, pKey);
|
REGISTER_TRACE(pOp->p3, pKey);
|
||||||
if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){
|
|
||||||
i64 iKey; /* The integer ROWID or key for the record to be inserted */
|
|
||||||
|
|
||||||
assert( pKey->flags & MEM_Int );
|
iKey = intToKey(pKey->u.i);
|
||||||
assert( pC->isTable );
|
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
||||||
iKey = intToKey(pKey->u.i);
|
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i;
|
||||||
|
if( pC->nextRowidValid && pKey->u.i>=pC->nextRowid ){
|
||||||
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
pC->nextRowidValid = 0;
|
||||||
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i;
|
|
||||||
if( pC->nextRowidValid && pKey->u.i>=pC->nextRowid ){
|
|
||||||
pC->nextRowidValid = 0;
|
|
||||||
}
|
|
||||||
if( pData->flags & MEM_Null ){
|
|
||||||
pData->z = 0;
|
|
||||||
pData->n = 0;
|
|
||||||
}else{
|
|
||||||
assert( pData->flags & (MEM_Blob|MEM_Str) );
|
|
||||||
}
|
|
||||||
if( pC->pseudoTable ){
|
|
||||||
sqlite3_free(pC->pData);
|
|
||||||
pC->iKey = iKey;
|
|
||||||
pC->nData = pData->n;
|
|
||||||
if( pData->flags & MEM_Dyn ){
|
|
||||||
pC->pData = pData->z;
|
|
||||||
pData->flags &= ~MEM_Dyn;
|
|
||||||
pData->flags |= MEM_Ephem;
|
|
||||||
}else{
|
|
||||||
pC->pData = sqlite3_malloc( pC->nData+2 );
|
|
||||||
if( !pC->pData ) goto no_mem;
|
|
||||||
memcpy(pC->pData, pData->z, pC->nData);
|
|
||||||
pC->pData[pC->nData] = 0;
|
|
||||||
pC->pData[pC->nData+1] = 0;
|
|
||||||
}
|
|
||||||
pC->nullRow = 0;
|
|
||||||
}else{
|
|
||||||
int nZero;
|
|
||||||
if( pData->flags & MEM_Zero ){
|
|
||||||
nZero = pData->u.i;
|
|
||||||
}else{
|
|
||||||
nZero = 0;
|
|
||||||
}
|
|
||||||
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
|
|
||||||
pData->z, pData->n, nZero,
|
|
||||||
pOp->p5 & OPFLAG_APPEND);
|
|
||||||
}
|
|
||||||
|
|
||||||
pC->rowidIsValid = 0;
|
|
||||||
pC->deferredMoveto = 0;
|
|
||||||
pC->cacheStatus = CACHE_STALE;
|
|
||||||
|
|
||||||
/* Invoke the update-hook if required. */
|
|
||||||
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
|
|
||||||
const char *zDb = db->aDb[pC->iDb].zName;
|
|
||||||
const char *zTbl = pOp->p4.z;
|
|
||||||
int op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
|
|
||||||
assert( pC->isTable );
|
|
||||||
db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
|
|
||||||
assert( pC->iDb>=0 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if( pData->flags & MEM_Null ){
|
||||||
|
pData->z = 0;
|
||||||
|
pData->n = 0;
|
||||||
|
}else{
|
||||||
|
assert( pData->flags & (MEM_Blob|MEM_Str) );
|
||||||
|
}
|
||||||
|
if( pC->pseudoTable ){
|
||||||
|
sqlite3_free(pC->pData);
|
||||||
|
pC->iKey = iKey;
|
||||||
|
pC->nData = pData->n;
|
||||||
|
if( pData->flags & MEM_Dyn ){
|
||||||
|
pC->pData = pData->z;
|
||||||
|
pData->flags &= ~MEM_Dyn;
|
||||||
|
pData->flags |= MEM_Ephem;
|
||||||
|
}else{
|
||||||
|
pC->pData = sqlite3_malloc( pC->nData+2 );
|
||||||
|
if( !pC->pData ) goto no_mem;
|
||||||
|
memcpy(pC->pData, pData->z, pC->nData);
|
||||||
|
pC->pData[pC->nData] = 0;
|
||||||
|
pC->pData[pC->nData+1] = 0;
|
||||||
|
}
|
||||||
|
pC->nullRow = 0;
|
||||||
|
}else{
|
||||||
|
int nZero;
|
||||||
|
if( pData->flags & MEM_Zero ){
|
||||||
|
nZero = pData->u.i;
|
||||||
|
}else{
|
||||||
|
nZero = 0;
|
||||||
|
}
|
||||||
|
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
|
||||||
|
pData->z, pData->n, nZero,
|
||||||
|
pOp->p5 & OPFLAG_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
pC->rowidIsValid = 0;
|
||||||
|
pC->deferredMoveto = 0;
|
||||||
|
pC->cacheStatus = CACHE_STALE;
|
||||||
|
|
||||||
|
/* Invoke the update-hook if required. */
|
||||||
|
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
|
||||||
|
const char *zDb = db->aDb[pC->iDb].zName;
|
||||||
|
const char *zTbl = pOp->p4.z;
|
||||||
|
int op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
|
||||||
|
assert( pC->isTable );
|
||||||
|
db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
|
||||||
|
assert( pC->iDb>=0 );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3403,10 +3392,7 @@ case OP_RowData: { /* out2-prerelease */
|
|||||||
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->isIndex ){
|
||||||
pOut->flags = MEM_Null;
|
|
||||||
break;
|
|
||||||
}else if( pC->isIndex ){
|
|
||||||
i64 n64;
|
i64 n64;
|
||||||
assert( !pC->isTable );
|
assert( !pC->isTable );
|
||||||
sqlite3BtreeKeySize(pCrsr, &n64);
|
sqlite3BtreeKeySize(pCrsr, &n64);
|
||||||
@@ -3436,13 +3422,12 @@ case OP_RowData: { /* out2-prerelease */
|
|||||||
}else{
|
}else{
|
||||||
rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
|
rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
|
||||||
}
|
}
|
||||||
}else if( pC->pseudoTable ){
|
}else{
|
||||||
|
assert( pC->pseudoTable );
|
||||||
pOut->n = pC->nData;
|
pOut->n = pC->nData;
|
||||||
assert( pC->nData<=SQLITE_MAX_LENGTH );
|
assert( pC->nData<=SQLITE_MAX_LENGTH );
|
||||||
pOut->z = pC->pData;
|
pOut->z = pC->pData;
|
||||||
pOut->flags = MEM_Blob|MEM_Ephem;
|
pOut->flags = MEM_Blob|MEM_Ephem;
|
||||||
}else{
|
|
||||||
pOut->flags = MEM_Null;
|
|
||||||
}
|
}
|
||||||
pOut->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 */
|
||||||
UPDATE_MAX_BLOBSIZE(pOut);
|
UPDATE_MAX_BLOBSIZE(pOut);
|
||||||
@@ -3468,7 +3453,7 @@ case OP_Rowid: { /* out2-prerelease */
|
|||||||
v = pC->lastRowid;
|
v = pC->lastRowid;
|
||||||
}else if( pC->pseudoTable ){
|
}else if( pC->pseudoTable ){
|
||||||
v = keyToInt(pC->iKey);
|
v = keyToInt(pC->iKey);
|
||||||
}else if( pC->nullRow || pC->pCursor==0 ){
|
}else if( pC->nullRow ){
|
||||||
/* Leave the rowid set to a NULL */
|
/* Leave the rowid set to a NULL */
|
||||||
break;
|
break;
|
||||||
}else{
|
}else{
|
||||||
@@ -3511,21 +3496,19 @@ case OP_Last: { /* jump */
|
|||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
BtCursor *pCrsr;
|
BtCursor *pCrsr;
|
||||||
|
int res;
|
||||||
|
|
||||||
assert( i>=0 && i<p->nCursor );
|
assert( i>=0 && i<p->nCursor );
|
||||||
pC = p->apCsr[i];
|
pC = p->apCsr[i];
|
||||||
assert( pC!=0 );
|
assert( pC!=0 );
|
||||||
if( (pCrsr = pC->pCursor)!=0 ){
|
pCrsr = pC->pCursor;
|
||||||
int res;
|
assert( pCrsr!=0 );
|
||||||
rc = sqlite3BtreeLast(pCrsr, &res);
|
rc = sqlite3BtreeLast(pCrsr, &res);
|
||||||
pC->nullRow = res;
|
pC->nullRow = res;
|
||||||
pC->deferredMoveto = 0;
|
pC->deferredMoveto = 0;
|
||||||
pC->cacheStatus = CACHE_STALE;
|
pC->cacheStatus = CACHE_STALE;
|
||||||
if( res && pOp->p2>0 ){
|
if( res && pOp->p2>0 ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
}
|
|
||||||
}else{
|
|
||||||
pC->nullRow = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3576,7 +3559,8 @@ case OP_Rewind: { /* jump */
|
|||||||
res = 1;
|
res = 1;
|
||||||
}
|
}
|
||||||
pC->nullRow = res;
|
pC->nullRow = res;
|
||||||
if( res && pOp->p2>0 ){
|
assert( pOp->p2>0 && pOp->p2<p->nOp );
|
||||||
|
if( res ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3722,17 +3706,6 @@ case OP_IdxRowid: { /* out2-prerelease */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: IdxGT P1 P2 P3 * *
|
|
||||||
**
|
|
||||||
** The value in register P3 is an index entry that omits the ROWID. Compare
|
|
||||||
** the value in register P3 against the index that P1 is currently pointing to.
|
|
||||||
** Ignore the ROWID on the P1 index.
|
|
||||||
**
|
|
||||||
** The P3 value might have fewer columns that P1 index.
|
|
||||||
**
|
|
||||||
** If the P1 index entry is greater than the value in register P3
|
|
||||||
** then jump to P2. Otherwise fall through to the next instruction.
|
|
||||||
*/
|
|
||||||
/* Opcode: IdxGE P1 P2 P3 * P5
|
/* Opcode: IdxGE P1 P2 P3 * P5
|
||||||
**
|
**
|
||||||
** The value in register P3 is an index entry that omits the ROWID. Compare
|
** The value in register P3 is an index entry that omits the ROWID. Compare
|
||||||
@@ -3764,7 +3737,6 @@ case OP_IdxRowid: { /* out2-prerelease */
|
|||||||
** like IdxLE.
|
** like IdxLE.
|
||||||
*/
|
*/
|
||||||
case OP_IdxLT: /* jump, in3 */
|
case OP_IdxLT: /* jump, in3 */
|
||||||
case OP_IdxGT: /* jump, in3 */
|
|
||||||
case OP_IdxGE: { /* jump, in3 */
|
case OP_IdxGE: { /* jump, in3 */
|
||||||
int i= pOp->p1;
|
int i= pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
@@ -3777,8 +3749,8 @@ case OP_IdxGE: { /* jump, in3 */
|
|||||||
assert( pIn3->flags & MEM_Blob ); /* Created using OP_MakeRecord */
|
assert( pIn3->flags & MEM_Blob ); /* Created using OP_MakeRecord */
|
||||||
assert( pC->deferredMoveto==0 );
|
assert( pC->deferredMoveto==0 );
|
||||||
ExpandBlob(pIn3);
|
ExpandBlob(pIn3);
|
||||||
*pC->pIncrKey = pOp->p5!=0;
|
assert( pOp->p5==0 || pOp->p5==1 );
|
||||||
assert( pOp->opcode!=OP_IdxGT || pOp->p5==0 );
|
*pC->pIncrKey = pOp->p5;
|
||||||
rc = sqlite3VdbeIdxKeyCompare(pC, pIn3->n, (u8*)pIn3->z, &res);
|
rc = sqlite3VdbeIdxKeyCompare(pC, pIn3->n, (u8*)pIn3->z, &res);
|
||||||
*pC->pIncrKey = 0;
|
*pC->pIncrKey = 0;
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
@@ -3786,7 +3758,8 @@ case OP_IdxGE: { /* jump, in3 */
|
|||||||
}
|
}
|
||||||
if( pOp->opcode==OP_IdxLT ){
|
if( pOp->opcode==OP_IdxLT ){
|
||||||
res = -res;
|
res = -res;
|
||||||
}else if( pOp->opcode==OP_IdxGE ){
|
}else{
|
||||||
|
assert( pOp->opcode==OP_IdxGE );
|
||||||
res++;
|
res++;
|
||||||
}
|
}
|
||||||
if( res>0 ){
|
if( res>0 ){
|
||||||
@@ -4056,10 +4029,9 @@ case OP_IntegrityCk: {
|
|||||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
|
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
|
||||||
pnErr->u.i, &nErr);
|
pnErr->u.i, &nErr);
|
||||||
pnErr->u.i -= nErr;
|
pnErr->u.i -= nErr;
|
||||||
Release(pIn1);
|
sqlite3VdbeMemSetNull(pIn1);
|
||||||
if( nErr==0 ){
|
if( nErr==0 ){
|
||||||
assert( z==0 );
|
assert( z==0 );
|
||||||
pIn1->flags = MEM_Null;
|
|
||||||
}else{
|
}else{
|
||||||
pIn1->z = z;
|
pIn1->z = z;
|
||||||
pIn1->n = strlen(z);
|
pIn1->n = strlen(z);
|
||||||
@@ -4790,15 +4762,13 @@ default: {
|
|||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
} /* The end of the for(;;) loop the loops through opcodes */
|
} /* The end of the for(;;) loop the loops through opcodes */
|
||||||
|
|
||||||
/* If we reach this point, it means that execution is finished.
|
/* If we reach this point, it means that execution is finished with
|
||||||
|
** an error of some kind.
|
||||||
*/
|
*/
|
||||||
vdbe_halt:
|
vdbe_error_halt:
|
||||||
if( rc ){
|
assert( rc );
|
||||||
p->rc = rc;
|
p->rc = rc;
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}else{
|
|
||||||
rc = SQLITE_DONE;
|
|
||||||
}
|
|
||||||
sqlite3VdbeHalt(p);
|
sqlite3VdbeHalt(p);
|
||||||
|
|
||||||
/* This is the only way out of this procedure. We have to
|
/* This is the only way out of this procedure. We have to
|
||||||
@@ -4814,7 +4784,7 @@ vdbe_return:
|
|||||||
too_big:
|
too_big:
|
||||||
sqlite3SetString(&p->zErrMsg, "string or blob too big", (char*)0);
|
sqlite3SetString(&p->zErrMsg, "string or blob too big", (char*)0);
|
||||||
rc = SQLITE_TOOBIG;
|
rc = SQLITE_TOOBIG;
|
||||||
goto vdbe_halt;
|
goto vdbe_error_halt;
|
||||||
|
|
||||||
/* Jump to here if a malloc() fails.
|
/* Jump to here if a malloc() fails.
|
||||||
*/
|
*/
|
||||||
@@ -4822,7 +4792,7 @@ no_mem:
|
|||||||
db->mallocFailed = 1;
|
db->mallocFailed = 1;
|
||||||
sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0);
|
sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0);
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
goto vdbe_halt;
|
goto vdbe_error_halt;
|
||||||
|
|
||||||
/* Jump to here for an SQLITE_MISUSE error.
|
/* Jump to here for an SQLITE_MISUSE error.
|
||||||
*/
|
*/
|
||||||
@@ -4834,11 +4804,10 @@ abort_due_to_misuse:
|
|||||||
** should hold the error number.
|
** should hold the error number.
|
||||||
*/
|
*/
|
||||||
abort_due_to_error:
|
abort_due_to_error:
|
||||||
if( p->zErrMsg==0 ){
|
assert( p->zErrMsg==0 );
|
||||||
if( db->mallocFailed ) rc = SQLITE_NOMEM;
|
if( db->mallocFailed ) rc = SQLITE_NOMEM;
|
||||||
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
|
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
|
||||||
}
|
goto vdbe_error_halt;
|
||||||
goto vdbe_halt;
|
|
||||||
|
|
||||||
/* Jump to here if the sqlite3_interrupt() API sets the interrupt
|
/* Jump to here if the sqlite3_interrupt() API sets the interrupt
|
||||||
** flag.
|
** flag.
|
||||||
@@ -4852,5 +4821,5 @@ abort_due_to_interrupt:
|
|||||||
}
|
}
|
||||||
p->rc = rc;
|
p->rc = rc;
|
||||||
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
|
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
|
||||||
goto vdbe_halt;
|
goto vdbe_error_halt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -508,11 +508,12 @@ int sqlite3VdbeMemTooBig(Mem *p){
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Make an shallow copy of pFrom into pTo. Prior contents of
|
** Make an shallow copy of pFrom into pTo. Prior contents of
|
||||||
** pTo are overwritten. The pFrom->z field is not duplicated. If
|
** pTo are freed. The pFrom->z field is not duplicated. If
|
||||||
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
|
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
|
||||||
** and flags gets srcType (either MEM_Ephem or MEM_Static).
|
** and flags gets srcType (either MEM_Ephem or MEM_Static).
|
||||||
*/
|
*/
|
||||||
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
|
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
|
||||||
|
sqlite3VdbeMemRelease(pTo);
|
||||||
memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
|
memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
|
||||||
pTo->xDel = 0;
|
pTo->xDel = 0;
|
||||||
if( pTo->flags & (MEM_Str|MEM_Blob) ){
|
if( pTo->flags & (MEM_Str|MEM_Blob) ){
|
||||||
@@ -528,9 +529,6 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
|
|||||||
*/
|
*/
|
||||||
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
||||||
int rc;
|
int rc;
|
||||||
if( pTo->flags & MEM_Dyn ){
|
|
||||||
sqlite3VdbeMemRelease(pTo);
|
|
||||||
}
|
|
||||||
sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
|
sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
|
||||||
if( pTo->flags & MEM_Ephem ){
|
if( pTo->flags & MEM_Ephem ){
|
||||||
rc = sqlite3VdbeMemMakeWriteable(pTo);
|
rc = sqlite3VdbeMemMakeWriteable(pTo);
|
||||||
|
|||||||
Reference in New Issue
Block a user