aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanielk1977 <danielk1977@noemail.net>2008-10-27 13:59:33 +0000
committerdanielk1977 <danielk1977@noemail.net>2008-10-27 13:59:33 +0000
commitc7af484b4b0a4f4db7e6f71b7e65cfde012e374e (patch)
tree572f74e759cd856f68f134cdc5e04a61428d4fe9 /src
parent9a02fb444c7c38360f4dafc91433ddeb13381a6f (diff)
downloadsqlite-c7af484b4b0a4f4db7e6f71b7e65cfde012e374e.tar.gz
sqlite-c7af484b4b0a4f4db7e6f71b7e65cfde012e374e.zip
Make sqlite3_count_changes() and total_changes() work with "DELETE FROM <table-name>". (CVS 5844)
FossilOrigin-Name: e68e4282adb9003aa297d033aeb5d9cadee215cd
Diffstat (limited to 'src')
-rw-r--r--src/btree.c22
-rw-r--r--src/btree.h4
-rw-r--r--src/delete.c16
-rw-r--r--src/test3.c4
-rw-r--r--src/vdbe.c21
5 files changed, 40 insertions, 27 deletions
diff --git a/src/btree.c b/src/btree.c
index 538a706d6..d94d9857a 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.525 2008/10/08 17:58:49 danielk1977 Exp $
+** $Id: btree.c,v 1.526 2008/10/27 13:59:34 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -6187,7 +6187,8 @@ static int clearDatabasePage(
BtShared *pBt, /* The BTree that contains the table */
Pgno pgno, /* Page number to clear */
MemPage *pParent, /* Parent page. NULL for the root */
- int freePageFlag /* Deallocate page if true */
+ int freePageFlag, /* Deallocate page if true */
+ int *pnChange
){
MemPage *pPage = 0;
int rc;
@@ -6204,15 +6205,18 @@ static int clearDatabasePage(
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(pCell), pPage, 1);
+ rc = clearDatabasePage(pBt, get4byte(pCell), pPage, 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
rc = clearCell(pPage, pCell);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage, 1);
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage, 1, pnChange);
if( rc ) goto cleardatabasepage_out;
+ }else if( pnChange ){
+ assert( pPage->intKey );
+ *pnChange += pPage->nCell;
}
if( freePageFlag ){
rc = freePage(pPage);
@@ -6233,8 +6237,12 @@ cleardatabasepage_out:
** This routine will fail with SQLITE_LOCKED if there are any open
** read cursors on the table. Open write cursors are moved to the
** root of the table.
+**
+** If pnChange is not NULL, then table iTable must be an intkey table. The
+** integer value pointed to by pnChange is incremented by the number of
+** entries in the table.
*/
-int sqlite3BtreeClearTable(Btree *p, int iTable){
+int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
@@ -6246,7 +6254,7 @@ int sqlite3BtreeClearTable(Btree *p, int iTable){
}else if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){
/* nothing to do */
}else{
- rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0);
+ rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0, pnChange);
}
sqlite3BtreeLeave(p);
return rc;
@@ -6294,7 +6302,7 @@ static int btreeDropTable(Btree *p, int iTable, int *piMoved){
rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
- rc = sqlite3BtreeClearTable(p, iTable);
+ rc = sqlite3BtreeClearTable(p, iTable, 0);
if( rc ){
releasePage(pPage);
return rc;
diff --git a/src/btree.h b/src/btree.h
index 3f8c4ea4b..ba1673086 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -13,7 +13,7 @@
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.104 2008/10/08 17:58:49 danielk1977 Exp $
+** @(#) $Id: btree.h,v 1.105 2008/10/27 13:59:34 danielk1977 Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@@ -117,7 +117,7 @@ int sqlite3BtreeIncrVacuum(Btree *);
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
int sqlite3BtreeDropTable(Btree*, int, int*);
-int sqlite3BtreeClearTable(Btree*, int);
+int sqlite3BtreeClearTable(Btree*, int, int*);
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
void sqlite3BtreeTripAllCursors(Btree*, int);
diff --git a/src/delete.c b/src/delete.c
index ef036cba9..382f1a67f 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.183 2008/10/27 08:24:38 danielk1977 Exp $
+** $Id: delete.c,v 1.184 2008/10/27 13:59:34 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -233,7 +233,7 @@ void sqlite3DeleteFrom(
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
NameContext sNC; /* Name context to resolve expressions in */
int iDb; /* Database number */
- int memCnt = 0; /* Memory cell used for change counting */
+ int memCnt = -1; /* Memory cell used for change counting */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
@@ -372,17 +372,7 @@ void sqlite3DeleteFrom(
*/
if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){
assert( !isView );
- if( db->flags & SQLITE_CountRows ){
- /* If counting rows deleted, just count the total number of
- ** entries in the table. */
- int addr2;
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
- sqlite3VdbeAddOp2(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
- addr2 = sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
- sqlite3VdbeAddOp2(v, OP_Next, iCur, addr2);
- sqlite3VdbeAddOp1(v, OP_Close, iCur);
- }
- sqlite3VdbeAddOp2(v, OP_Clear, pTab->tnum, iDb);
+ sqlite3VdbeAddOp3(v, OP_Clear, pTab->tnum, iDb, memCnt);
if( !pParse->nested ){
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
}
diff --git a/src/test3.c b/src/test3.c
index 4b75690ff..0d915f3cb 100644
--- a/src/test3.c
+++ b/src/test3.c
@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test3.c,v 1.101 2008/08/13 19:11:48 drh Exp $
+** $Id: test3.c,v 1.102 2008/10/27 13:59:34 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
@@ -389,7 +389,7 @@ static int btree_clear_table(
pBt = sqlite3TestTextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
sqlite3BtreeEnter(pBt);
- rc = sqlite3BtreeClearTable(pBt, iTable);
+ rc = sqlite3BtreeClearTable(pBt, iTable, 0);
sqlite3BtreeLeave(pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
diff --git a/src/vdbe.c b/src/vdbe.c
index 6ee22c1b6..a4a62b8bd 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.782 2008/10/08 17:58:49 danielk1977 Exp $
+** $Id: vdbe.c,v 1.783 2008/10/27 13:59:34 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -4042,7 +4042,7 @@ case OP_Destroy: { /* out2-prerelease */
break;
}
-/* Opcode: Clear P1 P2 *
+/* Opcode: Clear P1 P2 P3
**
** Delete all contents of the database table or index whose root page
** in the database file is given by P1. But, unlike Destroy, do not
@@ -4052,11 +4052,26 @@ case OP_Destroy: { /* out2-prerelease */
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
+** If the P3 value is non-zero, then the table refered to must be an
+** intkey table (an SQL table, not an index). In this case the row change
+** count is incremented by the number of rows in the table being cleared.
+** If P3 is greater than zero, then the value stored in register P3 is
+** also incremented by the number of rows in the table being cleared.
+**
** See also: Destroy
*/
case OP_Clear: {
+ int nChange = 0;
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
- rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
+ rc = sqlite3BtreeClearTable(
+ db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
+ );
+ if( pOp->p3 ){
+ p->nChange += nChange;
+ if( pOp->p3>0 ){
+ p->aMem[pOp->p3].u.i += nChange;
+ }
+ }
break;
}