]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhancements to the DELETE command (CVS 194)
authordrh <drh@noemail.net>
Tue, 20 Mar 2001 22:05:00 +0000 (22:05 +0000)
committerdrh <drh@noemail.net>
Tue, 20 Mar 2001 22:05:00 +0000 (22:05 +0000)
FossilOrigin-Name: daea156e2430762e683ff5460f9f8bb3204ae168

12 files changed:
VERSION
manifest
manifest.uuid
src/dbbe.c
src/dbbe.h
src/dbbegdbm.c
src/dbbemem.c
src/delete.c
src/sqliteInt.h
src/vdbe.c
test/delete.test
www/changes.tcl

diff --git a/VERSION b/VERSION
index 8955a0173eb8468ed27b66207e02b819a3cd7fd6..adb7b04cb2fa210fbe2ce1b09f9926f7bedea01e 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.26
+1.0.27
index e092172dc8b04d2278e19da89c020a6afdf1442b..c4e9b7cd814a852db46dae03f3b1af0653fb378e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,20 +1,20 @@
-C Version\s1.0.26\s(CVS\s477)
-D 2001-03-20T13:00:00
+C Enhancements\sto\sthe\sDELETE\scommand\s(CVS\s194)
+D 2001-03-20T22:05:00
 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
 F Makefile.in 7efa81e2985b45ba73db27d55b70cc927f5abfd7
 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
-F VERSION 900bbde4128ea2f66efdd32cae849187ea790e77
+F VERSION dee81fa1259d8cbb43230e982a9392f11f89859d
 F configure 3dc1edb9dcf60215e31ff72b447935ab62211442 x
 F configure.in d892ca33db7e88a055519ce2f36dcb11020e8fff
 F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
 F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e
 F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
 F src/build.c 7aa5879bf58ea6bbff22c26c59d1130021fa6ca4
-F src/dbbe.c 1b3b8b5ded9e58d10d94d268cd12343b6212dbd1
-F src/dbbe.h 0435a36906a839cce062608f51bd9d3e79878fec
-F src/dbbegdbm.c 5bfcb1b4ee47a98c5eae83041e9716cd3233fd0e
-F src/dbbemem.c e0ffaae47c22dd8d73362a4fae2f2b4f074fd079
-F src/delete.c b83dc815f83220a82df13f1f1f479187d305fe6a
+F src/dbbe.c b178f0959f6bac5ef8a109484c1571053f31abe5
+F src/dbbe.h 57d6debb99f6d7a91364b73cf3f0b129058ebbb3
+F src/dbbegdbm.c 84b2bf31d220f1de1cb0507ea051d30128fd681b
+F src/dbbemem.c d0fb86f1e8a52cdb195dc91d07f43765cf48bb95
+F src/delete.c 7aa9dcb86d5e98c3eb9dee00a459e0ef9b73fbe3
 F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a
 F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7
 F src/ex/db.h 3f2933ee20c147fe494835786e4c6f3a562def4e
@@ -33,20 +33,20 @@ F src/select.c faac634ef0c717bc82ca112a4531a257886f2c7a
 F src/shell.c 441e20913cde0bb71281f4027623c623530241cd
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in 7c1a53f020418d89d13ed2fe9c477ff54540755d
-F src/sqliteInt.h fd513fa6b7ac94919f85ebfa183aaa194284ce16
+F src/sqliteInt.h 9887d207b98362392668410a11c59b3e334f51a1
 F src/table.c 5be76051a8ed6f6bfa641f4adc52529efa34fbf9
 F src/tclsqlite.c 2a925e1835c348f07dd17c87d95ae9a577833407
 F src/test.file 55ca6286e3e4f4fba5d0448333fa99fc5a404a73
 F src/tokenize.c c7ad428f38e56342eb2025320480b5ae9ece1b90
 F src/update.c 8365b3922ea098330d1e20862d6e64911e4e03d0
 F src/util.c f4573201fc2b581dbf601c53787349310b7da150
-F src/vdbe.c e8254ae39d2f42a3f85b168b67a493ae206f4bf4
+F src/vdbe.c aa14a8aef0229fd5cfa32c3957dc627555f42be8
 F src/vdbe.h 031b7dd7d6f94c51dc37cdf26efe43d1619bb672
 F src/where.c 478fde7c930969ca428de2d80b137959d25ee2fb
 F test/all.test 15cac2f6b2d4c55bf896212aff3cc9d6597b0490
 F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
 F test/dbbe.test 03a6940807f8a1e7538897b4c802a7937677e053
-F test/delete.test e3e082a9dc764e3c259a8d175b31cd648e7c58f7
+F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
 F test/expr.test 48273bf48a15d226c35829f702af4254c0ff6795
 F test/func.test 02aed8845b98bde1043dda97455de1d37238ebb3
 F test/in.test 2c560c0f55fb777029fd9bb5378f2997582aa603
@@ -80,7 +80,7 @@ F www/arch.fig 4f246003b7da23bd63b8b0af0618afb4ee3055c8
 F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6
 F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be
 F www/c_interface.tcl 11be2d5826eb7d6efd629751d3b483c1ed78ba14
-F www/changes.tcl 6216d3a09f4cde137e635ab9aedda63adef086c0
+F www/changes.tcl e01a5257038fafe0302b629d1b278789409029d2
 F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
 F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
@@ -91,7 +91,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
 F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
 F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
 F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
-P 126fbcb7a8f52a0cc01c8346150a187dbabe96d5
-R daa25a3d54c3808b11e465e636487674
+P 99f9ea412f87cfb518cfb34f0e187fd1baf56761
+R e053fcd301655951022cbe2ddba947b1
 U drh
-Z a8bc1022041cda3a4a5da0367e128d28
+Z 61cc14fc5b8ff57148f02f9ffc944cce
index 97f6034d99a68747ce4ca13973c537904e50d30c..167435563a44a20046f59707d54cf46235985137 100644 (file)
@@ -1 +1 @@
-99f9ea412f87cfb518cfb34f0e187fd1baf56761
\ No newline at end of file
+daea156e2430762e683ff5460f9f8bb3204ae168
\ No newline at end of file
index da99eb9e5ad283983442c090a291ae5123b98ee1..f637f5388c431727614fd400589d7a0c084f3241 100644 (file)
@@ -30,7 +30,7 @@
 ** relatively simple to convert to a different database such
 ** as NDBM, SDBM, or BerkeleyDB.
 **
-** $Id: dbbe.c,v 1.24 2001/03/20 12:55:14 drh Exp $
+** $Id: dbbe.c,v 1.25 2001/03/20 22:05:00 drh Exp $
 */
 #include "sqliteInt.h"
 #include <unistd.h>
@@ -64,92 +64,6 @@ Dbbe *sqliteDbbeOpen(
   return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg);
 }
 
-/*
-** Open a temporary file.  The file should be deleted when closed.
-**
-** Note that we can't use the old Unix trick of opening the file
-** and then immediately unlinking the file.  That works great
-** under Unix, but fails when we try to port to Windows.
-*/
-int sqliteDbbeOpenTempFile(const char *zDir, Dbbe *pBe, FILE **ppFile){
-  char *zFile;         /* Full name of the temporary file */
-  char zBuf[50];       /* Base name of the temporary file */
-  int i;               /* Loop counter */
-  int limit;           /* Prevent an infinite loop */
-  int rc = SQLITE_OK;  /* Value returned by this function */
-
-  for(i=0; i<pBe->nTemp; i++){
-    if( pBe->apTemp[i]==0 ) break;
-  }
-  if( i>=pBe->nTemp ){
-    pBe->nTemp++;
-    pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) );
-    pBe->azTemp = sqliteRealloc(pBe->azTemp, pBe->nTemp*sizeof(char*) );
-  }
-  if( pBe->apTemp==0 ){
-    *ppFile = 0;
-    return SQLITE_NOMEM;
-  }
-  limit = 4;
-  zFile = 0;
-  do{
-    sqliteRandomName(zBuf, "/_temp_file_");
-    sqliteFree(zFile);
-    zFile = 0;
-    sqliteSetString(&zFile, zDir, zBuf, 0);
-  }while( access(zFile,0)==0 && limit-- >= 0 );
-#if OS_WIN
-  *ppFile = pBe->apTemp[i] = fopen(zFile, "w+b");
-#else
-  *ppFile = pBe->apTemp[i] = fopen(zFile, "w+");
-#endif
-  if( pBe->apTemp[i]==0 ){
-    rc = SQLITE_ERROR;
-    sqliteFree(zFile);
-    pBe->azTemp[i] = 0;
-  }else{
-    pBe->azTemp[i] = zFile;
-  }
-  return rc;
-}
-
-/*
-** Close a temporary file opened using sqliteGdbmOpenTempFile()
-*/
-void sqliteDbbeCloseTempFile(Dbbe *pBe, FILE *f){
-  int i;
-  for(i=0; i<pBe->nTemp; i++){
-    if( pBe->apTemp[i]==f ){
-      unlink(pBe->azTemp[i]);
-      sqliteFree(pBe->azTemp[i]);
-      pBe->apTemp[i] = 0;
-      pBe->azTemp[i] = 0;
-      break;
-    }
-  }
-  fclose(f);
-}
-
-/*
-** Close all temporary files that happen to still be open.
-** This routine is called when the database is being closed.
-*/
-void sqliteDbbeCloseAllTempFiles(Dbbe *pBe){
-  int i;
-  for(i=0; i<pBe->nTemp; i++){
-    if( pBe->apTemp[i]!=0 ){
-      unlink(pBe->azTemp[i]);
-      fclose(pBe->apTemp[i]);
-      sqliteFree(pBe->azTemp[i]);
-      pBe->apTemp[i] = 0;
-      pBe->azTemp[i] = 0;
-      break;
-    }
-  }
-  sqliteFree(pBe->azTemp);
-  sqliteFree(pBe->apTemp);
-}
-
 /*
 ** Translate the name of an SQL table (or index) into the name 
 ** of a file that holds the key/data pairs for that table or
index 09166469d5125f9013da4e162995d5744aab18aa..6a386adf9af656ca838e9707acf81befb23bc3f6 100644 (file)
@@ -28,7 +28,7 @@
 ** This library was originally designed to support the following
 ** backends: GDBM, NDBM, SDBM, Berkeley DB.
 **
-** $Id: dbbe.h,v 1.10 2001/01/15 22:51:10 drh Exp $
+** $Id: dbbe.h,v 1.11 2001/03/20 22:05:00 drh Exp $
 */
 #ifndef _SQLITE_DBBE_H_
 #define _SQLITE_DBBE_H_
@@ -150,12 +150,6 @@ struct DbbeMethods {
 
   /* Remove an entry from the table */
   int (*Delete)(DbbeCursor*, int nKey, char *pKey);
-
-  /* Open a file suitable for temporary storage */
-  int (*OpenTempFile)(Dbbe*, FILE**);
-
-  /* Close a temporary file */
-  void (*CloseTempFile)(Dbbe *, FILE *);
 };
 
 /*
@@ -170,9 +164,8 @@ struct DbbeMethods {
 */
 struct Dbbe {
   struct DbbeMethods *x; /* Backend-specific methods for database access */
-  int nTemp;             /* Number of temporary files created */
-  FILE **apTemp;         /* Space to hold temporary file pointers */
-  char **azTemp;         /* Names of the temporary files */
+  /* There used to be other information here, but it has since
+  ** been removed.  */
 };
 
 #endif /* defined(_SQLITE_DBBE_H_) */
index eb4d482e7f24fb62b08dd7235352acaf44adfc59..777c7dacef4c43539946bc6ec5e82163b474b932 100644 (file)
@@ -30,7 +30,7 @@
 ** relatively simple to convert to a different database such
 ** as NDBM, SDBM, or BerkeleyDB.
 **
-** $Id: dbbegdbm.c,v 1.3 2001/01/15 22:51:10 drh Exp $
+** $Id: dbbegdbm.c,v 1.4 2001/03/20 22:05:00 drh Exp $
 */
 #include "sqliteInt.h"
 #include <gdbm.h>
@@ -110,7 +110,6 @@ static void sqliteGdbmClose(Dbbe *pDbbe){
     memset(pFile, 0, sizeof(*pFile));   
     sqliteFree(pFile);
   }
-  sqliteDbbeCloseAllTempFiles(pDbbe);
   memset(pBe, 0, sizeof(*pBe));
   sqliteFree(pBe);
 }
@@ -541,15 +540,6 @@ static int sqliteGdbmDelete(DbbeCursor *pCursr, int nKey, char *pKey){
   return rc;
 }
 
-/*
-** Open a temporary file.  The file is located in the same directory
-** as the rest of the database.
-*/
-static int sqliteGdbmOpenTempFile(Dbbe *pDbbe, FILE **ppFile){
-  Dbbex *pBe = (Dbbex*)pDbbe;
-  return sqliteDbbeOpenTempFile(pBe->zDir, pDbbe, ppFile);
-}
-
 /*
 ** This variable contains pointers to all of the access methods
 ** used to implement the GDBM backend.
@@ -573,8 +563,6 @@ static struct DbbeMethods gdbmMethods = {
   /*             New */   sqliteGdbmNew,
   /*             Put */   sqliteGdbmPut,
   /*          Delete */   sqliteGdbmDelete,
-  /*    OpenTempFile */   sqliteGdbmOpenTempFile,
-  /*   CloseTempFile */   sqliteDbbeCloseTempFile
 };
 
 
index 7d03a5faef630b125c045e7482562167d8ea966f..6bf1cc0f2f43504c2725ea098a4aa7f1c8a37ec7 100644 (file)
@@ -28,7 +28,7 @@
 **
 ** This file uses an in-memory hash table as the database backend. 
 **
-** $Id: dbbemem.c,v 1.10 2001/03/20 12:57:57 drh Exp $
+** $Id: dbbemem.c,v 1.11 2001/03/20 22:05:00 drh Exp $
 */
 #include "sqliteInt.h"
 #include <sys/stat.h>
@@ -399,7 +399,6 @@ static void sqliteMemClose(Dbbe *pDbbe){
     deleteMTable(pTble);
   }
   ArrayClear(&pBe->tables);
-  sqliteDbbeCloseAllTempFiles(pDbbe);
   memset(pBe, 0, sizeof(*pBe));
   sqliteFree(pBe);
 }
@@ -716,31 +715,6 @@ static int sqliteMemDelete(DbbeCursor *pCursr, int nKey, char *pKey){
   return SQLITE_OK;
 }
 
-/*
-** Open a temporary file.  The file is located in the current working
-** directory.
-*/
-static int sqliteMemOpenTempFile(Dbbe *pDbbe, FILE **ppFile){
-#if OS_UNIX
-  const char *zTemps[] = { "/usr/tmp", "/var/tmp", "/tmp", "/temp", 0};
-#endif
-#if OS_WIN
-  const char *zTemps[] = { "/temp", "c:/temp", "c:", "d:", "e:", 0};
-#endif
-  const char *zDir;
-  int i;
-  struct stat statbuf;
-  for(i=0; zTemps[i]; i++){
-    zDir = zTemps[i];
-    if( stat(zDir, &statbuf)==0 && S_ISDIR(statbuf.st_mode) 
-      && access(zDir, W_OK|X_OK)==0 ){
-        break;
-    }
-  }
-  if( zDir==0 ) zDir = ".";
-  return sqliteDbbeOpenTempFile(zDir, pDbbe, ppFile);
-}
-
 /*
 ** This variable contains pointers to all of the access methods
 ** used to implement the MEMORY backend.
@@ -764,8 +738,6 @@ static struct DbbeMethods memoryMethods = {
   /*             New */   sqliteMemNew,
   /*             Put */   sqliteMemPut,
   /*          Delete */   sqliteMemDelete,
-  /*    OpenTempFile */   sqliteMemOpenTempFile,
-  /*   CloseTempFile */   sqliteDbbeCloseTempFile
 };
 
 /*
index d5e5a3b01e84029f4ff03b7628cec1758b980625..c4da286220144b164189f065ac8cb795e31470df 100644 (file)
@@ -24,7 +24,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle DELETE FROM statements.
 **
-** $Id: delete.c,v 1.7 2001/01/15 22:51:10 drh Exp $
+** $Id: delete.c,v 1.8 2001/03/20 22:05:00 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -85,48 +85,63 @@ void sqliteDeleteFrom(
   v = sqliteGetVdbe(pParse);
   if( v==0 ) goto delete_from_cleanup;
 
-  /* Begin the database scan
+  /* Special case: A DELETE without a WHERE clause deletes everything.
+  ** It is easier just to deleted the database files directly.
   */
-  sqliteVdbeAddOp(v, OP_ListOpen, 0, 0, 0, 0);
-  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
-  if( pWInfo==0 ) goto delete_from_cleanup;
+  if( pWhere==0 ){
+    sqliteVdbeAddOp(v, OP_Destroy, 0, 0, pTab->zName, 0);
+    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+      sqliteVdbeAddOp(v, OP_Destroy, 0, 0, pIdx->zName, 0);
+    }
+  }
 
-  /* Remember the key of every item to be deleted.
+  /* The usual case: There is a WHERE clause so we have to scan through
+  ** the table an pick which records to delete.
   */
-  sqliteVdbeAddOp(v, OP_ListWrite, 0, 0, 0, 0);
+  else{
+    /* Begin the database scan
+    */
+    sqliteVdbeAddOp(v, OP_ListOpen, 0, 0, 0, 0);
+    pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
+    if( pWInfo==0 ) goto delete_from_cleanup;
 
-  /* End the database scan loop.
-  */
-  sqliteWhereEnd(pWInfo);
+    /* Remember the key of every item to be deleted.
+    */
+    sqliteVdbeAddOp(v, OP_ListWrite, 0, 0, 0, 0);
 
-  /* Delete every item whose key was written to the list during the
-  ** database scan.  We have to delete items after the scan is complete
-  ** because deleting an item can change the scan order.
-  */
-  base = pParse->nTab;
-  sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0);
-  sqliteVdbeAddOp(v, OP_OpenTbl, base, 1, pTab->zName, 0);
-  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-    sqliteVdbeAddOp(v, OP_OpenIdx, base+i, 1, pIdx->zName, 0);
-  }
-  end = sqliteVdbeMakeLabel(v);
-  addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end, 0, 0);
-  if( pTab->pIndex ){
-    sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
-    sqliteVdbeAddOp(v, OP_Fetch, base, 0, 0, 0);
+    /* End the database scan loop.
+    */
+    sqliteWhereEnd(pWInfo);
+
+    /* Delete every item whose key was written to the list during the
+    ** database scan.  We have to delete items after the scan is complete
+    ** because deleting an item can change the scan order.
+    */
+    base = pParse->nTab;
+    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0);
+    sqliteVdbeAddOp(v, OP_OpenTbl, base, 1, pTab->zName, 0);
     for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-      int j;
+      sqliteVdbeAddOp(v, OP_OpenIdx, base+i, 1, pIdx->zName, 0);
+    }
+    end = sqliteVdbeMakeLabel(v);
+    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end, 0, 0);
+    if( pTab->pIndex ){
       sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
-      for(j=0; j<pIdx->nColumn; j++){
-        sqliteVdbeAddOp(v, OP_Field, base, pIdx->aiColumn[j], 0, 0);
+      sqliteVdbeAddOp(v, OP_Fetch, base, 0, 0, 0);
+      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+        int j;
+        sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
+        for(j=0; j<pIdx->nColumn; j++){
+          sqliteVdbeAddOp(v, OP_Field, base, pIdx->aiColumn[j], 0, 0);
+        }
+        sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nColumn, 0, 0, 0);
+        sqliteVdbeAddOp(v, OP_DeleteIdx, base+i, 0, 0, 0);
       }
-      sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nColumn, 0, 0, 0);
-      sqliteVdbeAddOp(v, OP_DeleteIdx, base+i, 0, 0, 0);
     }
+    sqliteVdbeAddOp(v, OP_Delete, base, 0, 0, 0);
+    sqliteVdbeAddOp(v, OP_Goto, 0, addr, 0, 0);
+    sqliteVdbeAddOp(v, OP_ListClose, 0, 0, 0, end);
   }
-  sqliteVdbeAddOp(v, OP_Delete, base, 0, 0, 0);
-  sqliteVdbeAddOp(v, OP_Goto, 0, addr, 0, 0);
-  sqliteVdbeAddOp(v, OP_ListClose, 0, 0, 0, end);
 
 delete_from_cleanup:
   sqliteIdListDelete(pTabList);
index 22f49b405ce480d93faceae8888256d8d1ce961b..371eafabdd622954a305d310dd986c00fd5b8c8a 100644 (file)
@@ -23,7 +23,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.36 2001/01/20 19:52:50 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.37 2001/03/20 22:05:00 drh Exp $
 */
 #include "sqlite.h"
 #include "dbbe.h"
@@ -427,7 +427,4 @@ Vdbe *sqliteGetVdbe(Parse*);
 int sqliteRandomByte(void);
 int sqliteRandomInteger(void);
 void sqliteRandomName(char*,char*);
-int sqliteDbbeOpenTempFile(const char*, Dbbe*, FILE**);
-void sqliteDbbeCloseTempFile(Dbbe*, FILE*);
-void sqliteDbbeCloseAllTempFiles(Dbbe*);
 char *sqliteDbbeNameToFile(const char*,const char*,const char*);
index 324730f701c61dc0519814f512811834ed0b1b3e..1e852f3975a841d96e0fff7d2f19bf6eec7a607d 100644 (file)
@@ -41,7 +41,7 @@
 ** But other routines are also provided to help in building up
 ** a program instruction by instruction.
 **
-** $Id: vdbe.c,v 1.52 2001/02/19 23:23:39 drh Exp $
+** $Id: vdbe.c,v 1.53 2001/03/20 22:05:00 drh Exp $
 */
 #include "sqliteInt.h"
 #include <unistd.h>
@@ -167,6 +167,20 @@ struct SetElem {
   char zKey[1];          /* Value of this key */
 };
 
+/*
+** A Keylist is a bunch of keys into a table.  The keylist can
+** grow without bound.  The keylist stores the keys of database
+** records that need to be deleted.
+*/
+typedef struct Keylist Keylist;
+struct Keylist {
+  int nKey;         /* Number of slots in aKey[] */
+  int nUsed;        /* Next unwritten slot in aKey[] */
+  int nRead;        /* Next unread slot in aKey[] */
+  Keylist *pNext;   /* Next block of keys */
+  int aKey[1];      /* One or more keys.  Extra space allocated as needed */
+};
+
 /*
 ** An instance of the virtual machine
 */
@@ -188,7 +202,7 @@ struct Vdbe {
   int nCursor;        /* Number of slots in aCsr[] */
   Cursor *aCsr;       /* On element of this array for each open cursor */
   int nList;          /* Number of slots in apList[] */
-  FILE **apList;      /* An open file for each list */
+  Keylist **apList;   /* For each Keylist */
   int nSort;          /* Number of slots in apSort[] */
   Sorter **apSort;    /* An open sorter list */
   FILE *pFile;        /* At most one open file handler */
@@ -685,6 +699,17 @@ static int hardNeedStack(Vdbe *p, int N){
   return 0;
 }
 
+/*
+** Delete a keylist
+*/
+static void KeylistFree(Keylist *p){
+  while( p ){
+    Keylist *pNext = p->pNext;
+    sqliteFree(p);
+    p = pNext;
+  }
+}
+
 /*
 ** Clean up the VM after execution.
 **
@@ -714,10 +739,8 @@ static void Cleanup(Vdbe *p){
   p->aMem = 0;
   p->nMem = 0;
   for(i=0; i<p->nList; i++){
-    if( p->apList[i] ){
-      p->pBe->x->CloseTempFile(p->pBe, p->apList[i]);
-      p->apList[i] = 0;
-    }
+    KeylistFree(p->apList[i]);
+    p->apList[i] = 0;
   }
   sqliteFree(p->apList);
   p->apList = 0;
@@ -2431,10 +2454,11 @@ int sqliteVdbeExec(
 
       /* Opcode: ListOpen P1 * *
       **
-      ** Open a file used for temporary storage of integer table keys.  P1
-      ** will server as a handle to this temporary file for future
-      ** interactions.  If another temporary file with the P1 handle is
-      ** already opened, the prior file is closed and a new one opened
+      ** Open a "List" structure used for temporary storage of integer 
+      ** table keys.  P1
+      ** will server as a handle to this list for future
+      ** interactions.  If another list with the P1 handle is
+      ** already opened, the prior list is closed and a new one opened
       ** in its place.
       */
       case OP_ListOpen: {
@@ -2442,16 +2466,13 @@ int sqliteVdbeExec(
         VERIFY( if( i<0 ) goto bad_instruction; )
         if( i>=p->nList ){
           int j;
-          p->apList = sqliteRealloc( p->apList, (i+1)*sizeof(FILE*) );
+          p->apList = sqliteRealloc( p->apList, (i+1)*sizeof(Keylist*) );
           if( p->apList==0 ){ p->nList = 0; goto no_mem; }
           for(j=p->nList; j<=i; j++) p->apList[j] = 0;
           p->nList = i+1;
         }else if( p->apList[i] ){
-          pBex->CloseTempFile(pBe, p->apList[i]);
-        }
-        rc = pBex->OpenTempFile(pBe, &p->apList[i]);
-        if( rc!=SQLITE_OK ){
-          sqliteSetString(pzErrMsg, "unable to open a temporary file", 0);
+          KeylistFree(p->apList[i]);
+          p->apList[i] = 0;
         }
         break;
       }
@@ -2459,19 +2480,26 @@ int sqliteVdbeExec(
       /* Opcode: ListWrite P1 * *
       **
       ** Write the integer on the top of the stack
-      ** into the temporary storage file P1.
+      ** into the temporary storage list P1.
       */
       case OP_ListWrite: {
         int i = pOp->p1;
-        VERIFY( if( i<0 ) goto bad_instruction; )
+        Keylist *pKeylist;
+        VERIFY( if( i<0 || i>=p->nList ) goto bad_instruction; )
         VERIFY( if( p->tos<0 ) goto not_enough_stack; )
-        if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){
-          int val;
-          Integerify(p, p->tos);
-          val = aStack[p->tos].i;
-          POPSTACK;
-          fwrite(&val, sizeof(int), 1, p->apList[i]);
+        pKeylist = p->apList[i];
+        if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
+          pKeylist = sqliteMalloc( sizeof(Keylist)+999*sizeof(int) );
+          if( pKeylist==0 ) goto no_mem;
+          pKeylist->nKey = 1000;
+          pKeylist->nRead = 0;
+          pKeylist->nUsed = 0;
+          pKeylist->pNext = p->apList[i];
+          p->apList[i] = pKeylist;
         }
+        Integerify(p, p->tos);
+        pKeylist->aKey[pKeylist->nUsed++] = aStack[p->tos].i;
+        POPSTACK;
         break;
       }
 
@@ -2482,9 +2510,7 @@ int sqliteVdbeExec(
       case OP_ListRewind: {
         int i = pOp->p1;
         VERIFY( if( i<0 ) goto bad_instruction; )
-        if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){
-          rewind(p->apList[i]);
-        }
+        /* This is now a no-op */
         break;
       }
 
@@ -2497,14 +2523,24 @@ int sqliteVdbeExec(
       case OP_ListRead: {
         int i = pOp->p1;
         int val, amt;
-        VERIFY(if( i<0 || i>=p->nList || p->apList[i]==0 )goto bad_instruction;)
-        amt = fread(&val, sizeof(int), 1, p->apList[i]);
-        if( amt==1 ){
+        Keylist *pKeylist;
+        VERIFY(if( i<0 || i>=p->nList ) goto bad_instruction;)
+        pKeylist = p->apList[i];
+        if( pKeylist!=0 ){
+          VERIFY(
+            if( pKeylist->nRead<0 
+              || pKeylist->nRead>=pKeylist->nUsed
+              || pKeylist->nRead>=pKeylist->nKey ) goto bad_instruction;
+          )
           p->tos++;
           if( NeedStack(p, p->tos) ) goto no_mem;
-          aStack[p->tos].i = val;
+          aStack[p->tos].i = pKeylist->aKey[pKeylist->nRead++];
           aStack[p->tos].flags = STK_Int;
           zStack[p->tos] = 0;
+          if( pKeylist->nRead>=pKeylist->nUsed ){
+            p->apList[i] = pKeylist->pNext;
+            sqliteFree(pKeylist);
+          }
         }else{
           pc = pOp->p2 - 1;
         }
@@ -2518,10 +2554,9 @@ int sqliteVdbeExec(
       case OP_ListClose: {
         int i = pOp->p1;
         VERIFY( if( i<0 ) goto bad_instruction; )
-        if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){
-          pBex->CloseTempFile(pBe, p->apList[i]);
-          p->apList[i] = 0;
-        }
+        VERIFY( if( i>=p->nList ) goto bad_instruction; )
+        KeylistFree(p->apList[i]);
+        p->apList[i] = 0;
         break;
       }
 
index d8c6f561856f2e7c14bd7d3c8eabef349fe00ad5..4587fbf9f7d924ce18ca0d955598bc11cabed592 100644 (file)
@@ -23,7 +23,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the DELETE FROM statement.
 #
-# $Id: delete.test,v 1.7 2001/03/20 12:55:14 drh Exp $
+# $Id: delete.test,v 1.8 2001/03/20 22:05:00 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -118,4 +118,56 @@ do_test delete-5.7 {
   execsql {SELECT f1 FROM table1 ORDER BY f1}
 } {48}
 
+# Delete large quantities of data.  We want to test the List overflow
+# mechanism in the vdbe.
+#
+do_test delete-6.1 {
+  set fd [open data1.txt w]
+  for {set i 1} {$i<=3000} {incr i} {
+    puts $fd "[expr {$i}]\t[expr {$i*$i}]"
+  }
+  close $fd
+  execsql {DELETE FROM table1}
+  execsql {COPY table1 FROM 'data1.txt'}
+  execsql {DELETE FROM table2}
+  execsql {COPY table2 FROM 'data1.txt'}
+  file delete data1.txt
+  execsql {SELECT count(*) FROM table1}
+} {3000}
+do_test delete-6.2 {
+  execsql {SELECT count(*) FROM table2}
+} {3000}
+do_test delete-6.3 {
+  execsql {SELECT f1 FROM table1 WHERE f1<10 ORDER BY f1}
+} {1 2 3 4 5 6 7 8 9}
+do_test delete-6.4 {
+  execsql {SELECT f1 FROM table2 WHERE f1<10 ORDER BY f1}
+} {1 2 3 4 5 6 7 8 9}
+do_test delete-6.5 {
+  execsql {DELETE FROM table1 WHERE f1>7}
+  execsql {SELECT f1 FROM table1 ORDER BY f1}
+} {1 2 3 4 5 6 7}
+do_test delete-6.6 {
+  execsql {DELETE FROM table2 WHERE f1>7}
+  execsql {SELECT f1 FROM table2 ORDER BY f1}
+} {1 2 3 4 5 6 7}
+do_test delete-6.7 {
+  execsql {DELETE FROM table1}
+  execsql {SELECT f1 FROM table1}
+} {}
+do_test delete-6.8 {
+  execsql {INSERT INTO table1 VALUES(2,3)}
+  execsql {SELECT f1 FROM table1}
+} {2}
+do_test delete-6.9 {
+  execsql {DELETE FROM table2}
+  execsql {SELECT f1 FROM table2}
+} {}
+do_test delete-6.10 {
+  execsql {INSERT INTO table2 VALUES(2,3)}
+  execsql {SELECT f1 FROM table2}
+} {2}
+
+
+
 finish_test
index c12e98e825a540979d46f67a15573d8fc23555c8..111276c81a1cbff0eecd933ad5944b6ba5229bea 100644 (file)
@@ -17,6 +17,15 @@ proc chng {date desc} {
   puts "<DD><P><UL>$desc</UL></P></DD>"
 }
 
+chng {2001 Mar 20 (1.0.27)} {
+<li>When doing DELETE and UPDATE, the library used to write the record
+    numbers of records to be deleted or updated into a temporary file.
+    This is changed so that the record numbers are held in memory.</li>
+<li>The DELETE command without a WHILE clause just removes the database
+    files from the disk, rather than going through and deleting record
+    by record.</li>
+}
+
 chng {2001 Mar 20 (1.0.26)} {
 <li>A serious bug fixed on Windows.  Windows users should upgrade.
     No impact to Unix.</li>