Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enhancements to the DELETE command (CVS 194) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
daea156e2430762e683ff5460f9f8bb3 |
User & Date: | drh 2001-03-20 22:05:00.000 |
Context
2001-03-20
| ||
22:15 | Version 1.0.27 (CVS 476) (check-in: 833291c227 user: drh tags: trunk) | |
22:05 | Enhancements to the DELETE command (CVS 194) (check-in: daea156e24 user: drh tags: trunk) | |
13:00 | Version 1.0.26 (CVS 477) (check-in: 99f9ea412f user: drh tags: trunk) | |
Changes
Changes to VERSION.
|
| | | 1 | 1.0.27 |
Changes to src/dbbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** ** $Id: dbbe.c,v 1.25 2001/03/20 22:05:00 drh Exp $ */ #include "sqliteInt.h" #include <unistd.h> /* ** This routine opens a new database. It looks at the first ** few characters of the database name to try to determine what |
︙ | ︙ | |||
60 61 62 63 64 65 66 | if( strncmp(zName, "memory:", 7)==0 ){ extern Dbbe *sqliteMemOpen(const char*,int,int,char**); return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg); } return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | if( strncmp(zName, "memory:", 7)==0 ){ extern Dbbe *sqliteMemOpen(const char*,int,int,char**); return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg); } return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg); } /* ** 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. Space to hold the filename is obtained from ** sqliteMalloc() and must be freed by the calling function. ** ** zDir is the name of the directory in which the file should |
︙ | ︙ |
Changes to src/dbbe.h.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** This file defines the interface to the database backend (Dbbe). ** ** The database backend is designed to be as general as possible ** so that it can easily be replaced by a different backend. ** This library was originally designed to support the following ** backends: GDBM, NDBM, SDBM, Berkeley DB. ** | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** This file defines the interface to the database backend (Dbbe). ** ** The database backend is designed to be as general as possible ** so that it can easily be replaced by a different backend. ** This library was originally designed to support the following ** backends: GDBM, NDBM, SDBM, Berkeley DB. ** ** $Id: dbbe.h,v 1.11 2001/03/20 22:05:00 drh Exp $ */ #ifndef _SQLITE_DBBE_H_ #define _SQLITE_DBBE_H_ #include <stdio.h> /* ** The database backend supports two opaque structures. A Dbbe is |
︙ | ︙ | |||
146 147 148 149 150 151 152 | /* Write an entry into a table. If another entry already exists with ** the same key, the old entry is discarded first. */ int (*Put)(DbbeCursor*, int nKey, char *pKey, int nData, char *pData); /* Remove an entry from the table */ int (*Delete)(DbbeCursor*, int nKey, char *pKey); | < < < < < < | | < | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /* Write an entry into a table. If another entry already exists with ** the same key, the old entry is discarded first. */ int (*Put)(DbbeCursor*, int nKey, char *pKey, int nData, char *pData); /* Remove an entry from the table */ int (*Delete)(DbbeCursor*, int nKey, char *pKey); }; /* ** This is the structure returned by sqliteDbbeOpen(). It contains ** information common to all the different backend drivers. ** ** The information in this structure (with the exception the method ** pointers in the Dbbe.x field) is intended to be visible to ** the backend drivers only. Users should not access or modify ** this structure in any way other than the read the method pointers ** in Dbbe.x. */ struct Dbbe { struct DbbeMethods *x; /* Backend-specific methods for database access */ /* There used to be other information here, but it has since ** been removed. */ }; #endif /* defined(_SQLITE_DBBE_H_) */ |
Changes to src/dbbegdbm.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** ** $Id: dbbegdbm.c,v 1.4 2001/03/20 22:05:00 drh Exp $ */ #include "sqliteInt.h" #include <gdbm.h> #include <sys/stat.h> #include <unistd.h> #include <ctype.h> #include <time.h> |
︙ | ︙ | |||
106 107 108 109 110 111 112 | BeFile *pFile, *pNext; for(pFile=pBe->pOpen; pFile; pFile=pNext){ pNext = pFile->pNext; gdbm_close(pFile->dbf); memset(pFile, 0, sizeof(*pFile)); sqliteFree(pFile); } | < | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | BeFile *pFile, *pNext; for(pFile=pBe->pOpen; pFile; pFile=pNext){ pNext = pFile->pNext; gdbm_close(pFile->dbf); memset(pFile, 0, sizeof(*pFile)); sqliteFree(pFile); } memset(pBe, 0, sizeof(*pBe)); sqliteFree(pBe); } /* ** 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 |
︙ | ︙ | |||
537 538 539 540 541 542 543 | key.dsize = nKey; key.dptr = pKey; rc = gdbm_delete(pCursr->pFile->dbf, key); if( rc ) rc = SQLITE_ERROR; return rc; } | < < < < < < < < < | 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | key.dsize = nKey; key.dptr = pKey; rc = gdbm_delete(pCursr->pFile->dbf, key); if( rc ) rc = SQLITE_ERROR; return rc; } /* ** This variable contains pointers to all of the access methods ** used to implement the GDBM backend. */ static struct DbbeMethods gdbmMethods = { /* n Close */ sqliteGdbmClose, /* OpenCursor */ sqliteGdbmOpenCursor, |
︙ | ︙ | |||
569 570 571 572 573 574 575 | /* KeyLength */ sqliteGdbmKeyLength, /* DataLength */ sqliteGdbmDataLength, /* NextKey */ sqliteGdbmNextKey, /* Rewind */ sqliteGdbmRewind, /* New */ sqliteGdbmNew, /* Put */ sqliteGdbmPut, /* Delete */ sqliteGdbmDelete, | < < | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | /* KeyLength */ sqliteGdbmKeyLength, /* DataLength */ sqliteGdbmDataLength, /* NextKey */ sqliteGdbmNextKey, /* Rewind */ sqliteGdbmRewind, /* New */ sqliteGdbmNew, /* Put */ sqliteGdbmPut, /* Delete */ sqliteGdbmDelete, }; /* ** This routine opens a new database. For the GDBM driver ** implemented here, the database name is the name of the directory ** containing all the files of the database. |
︙ | ︙ |
Changes to src/dbbemem.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** This file contains code to implement the database backend (DBBE) ** for sqlite. The database backend is the interface between ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses an in-memory hash table as the database backend. ** | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** This file contains code to implement the database backend (DBBE) ** for sqlite. The database backend is the interface between ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses an in-memory hash table as the database backend. ** ** $Id: dbbemem.c,v 1.11 2001/03/20 22:05:00 drh Exp $ */ #include "sqliteInt.h" #include <sys/stat.h> #include <unistd.h> #include <ctype.h> #include <time.h> |
︙ | ︙ | |||
395 396 397 398 399 400 401 | MTable *pTble; ArrayElem *j; for(j=ArrayFirst(&pBe->tables); j; j=ArrayNext(j)){ pTble = ArrayData(j); deleteMTable(pTble); } ArrayClear(&pBe->tables); | < | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | MTable *pTble; ArrayElem *j; for(j=ArrayFirst(&pBe->tables); j; j=ArrayNext(j)){ pTble = ArrayData(j); deleteMTable(pTble); } ArrayClear(&pBe->tables); memset(pBe, 0, sizeof(*pBe)); sqliteFree(pBe); } /* ** Translate the name of an SQL table (or index) into its ** canonical name. |
︙ | ︙ | |||
712 713 714 715 716 717 718 | data = ArrayInsert(&pCursr->pTble->data, key, data); if( data.p ){ sqliteFree(data.p); } return SQLITE_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < | 711 712 713 714 715 716 717 718 719 720 721 722 723 724 | data = ArrayInsert(&pCursr->pTble->data, key, data); if( data.p ){ sqliteFree(data.p); } return SQLITE_OK; } /* ** This variable contains pointers to all of the access methods ** used to implement the MEMORY backend. */ static struct DbbeMethods memoryMethods = { /* n Close */ sqliteMemClose, /* OpenCursor */ sqliteMemOpenCursor, |
︙ | ︙ | |||
760 761 762 763 764 765 766 | /* KeyLength */ sqliteMemKeyLength, /* DataLength */ sqliteMemDataLength, /* NextKey */ sqliteMemNextKey, /* Rewind */ sqliteMemRewind, /* New */ sqliteMemNew, /* Put */ sqliteMemPut, /* Delete */ sqliteMemDelete, | < < | 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | /* KeyLength */ sqliteMemKeyLength, /* DataLength */ sqliteMemDataLength, /* NextKey */ sqliteMemNextKey, /* Rewind */ sqliteMemRewind, /* New */ sqliteMemNew, /* Put */ sqliteMemPut, /* Delete */ sqliteMemDelete, }; /* ** This routine opens a new database. For the GDBM driver ** implemented here, the database name is the name of the directory ** containing all the files of the database. ** |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** ** $Id: delete.c,v 1.8 2001/03/20 22:05:00 drh Exp $ */ #include "sqliteInt.h" /* ** Process a DELETE FROM statement. */ void sqliteDeleteFrom( |
︙ | ︙ | |||
81 82 83 84 85 86 87 | } /* Begin generating code. */ v = sqliteGetVdbe(pParse); if( v==0 ) goto delete_from_cleanup; | > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | } /* Begin generating code. */ v = sqliteGetVdbe(pParse); if( v==0 ) goto delete_from_cleanup; /* Special case: A DELETE without a WHERE clause deletes everything. ** It is easier just to deleted the database files directly. */ 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); } } /* The usual case: There is a WHERE clause so we have to scan through ** the table an pick which records to delete. */ 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; /* Remember the key of every item to be deleted. */ sqliteVdbeAddOp(v, OP_ListWrite, 0, 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){ 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); 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_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); sqliteExprDelete(pWhere); return; } |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.37 2001/03/20 22:05:00 drh Exp $ */ #include "sqlite.h" #include "dbbe.h" #include "vdbe.h" #include "parse.h" #include <gdbm.h> #include <stdio.h> |
︙ | ︙ | |||
423 424 425 426 427 428 429 | void sqliteExprResolveInSelect(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); void sqliteParseInfoReset(Parse*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); int sqliteRandomInteger(void); void sqliteRandomName(char*,char*); | < < < | 423 424 425 426 427 428 429 430 | void sqliteExprResolveInSelect(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); void sqliteParseInfoReset(Parse*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); int sqliteRandomInteger(void); void sqliteRandomName(char*,char*); char *sqliteDbbeNameToFile(const char*,const char*,const char*); |
Changes to src/vdbe.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.53 2001/03/20 22:05:00 drh Exp $ */ #include "sqliteInt.h" #include <unistd.h> #include <ctype.h> /* ** SQL is translated into a sequence of instructions to be |
︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 172 173 174 175 176 | }; struct SetElem { SetElem *pHash; /* Next element with the same hash on zKey */ SetElem *pNext; /* Next element in a list of them all */ char zKey[1]; /* Value of this key */ }; /* ** An instance of the virtual machine */ struct Vdbe { sqlite *db; /* The whole database */ Dbbe *pBe; /* Opaque context structure used by DB backend */ FILE *trace; /* Write an execution trace here, if not NULL */ | > > > > > > > > > > > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | }; struct SetElem { SetElem *pHash; /* Next element with the same hash on zKey */ SetElem *pNext; /* Next element in a list of them all */ 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 */ struct Vdbe { sqlite *db; /* The whole database */ Dbbe *pBe; /* Opaque context structure used by DB backend */ FILE *trace; /* Write an execution trace here, if not NULL */ |
︙ | ︙ | |||
184 185 186 187 188 189 190 | int nStackAlloc; /* Size of the stack */ Stack *aStack; /* The operand stack, except string values */ char **zStack; /* Text or binary values of the stack */ char **azColName; /* Becomes the 4th parameter to callbacks */ 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[] */ | | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | int nStackAlloc; /* Size of the stack */ Stack *aStack; /* The operand stack, except string values */ char **zStack; /* Text or binary values of the stack */ char **azColName; /* Becomes the 4th parameter to callbacks */ 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[] */ 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 */ int nField; /* Number of file fields */ char **azField; /* Data for each file field */ char *zLine; /* A single line from the input file */ int nLineAlloc; /* Number of spaces allocated for zLine */ |
︙ | ︙ | |||
680 681 682 683 684 685 686 687 688 689 690 691 692 693 | for(i=oldAlloc; i<p->nStackAlloc; i++){ p->zStack[i] = 0; p->aStack[i].flags = 0; } } return 0; } /* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, list, and/or ** sorters that were left open. */ | > > > > > > > > > > > | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 | for(i=oldAlloc; i<p->nStackAlloc; i++){ p->zStack[i] = 0; p->aStack[i].flags = 0; } } 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. ** ** This routine will automatically close any cursors, list, and/or ** sorters that were left open. */ |
︙ | ︙ | |||
710 711 712 713 714 715 716 | sqliteFree(p->aMem[i].z); } } sqliteFree(p->aMem); p->aMem = 0; p->nMem = 0; for(i=0; i<p->nList; i++){ | | < | < | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | sqliteFree(p->aMem[i].z); } } sqliteFree(p->aMem); p->aMem = 0; p->nMem = 0; for(i=0; i<p->nList; i++){ KeylistFree(p->apList[i]); p->apList[i] = 0; } sqliteFree(p->apList); p->apList = 0; p->nList = 0; for(i=0; i<p->nSort; i++){ Sorter *pSorter; while( (pSorter = p->apSort[i])!=0 ){ |
︙ | ︙ | |||
2427 2428 2429 2430 2431 2432 2433 | case OP_Reorganize: { pBex->ReorganizeTable(pBe, pOp->p3); break; } /* Opcode: ListOpen P1 * * ** | | > | | | | | < | < < | > | | > > > > > > | > > | | | < < | < < > | | | > > > > > | > > > > | | | < | 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 | case OP_Reorganize: { pBex->ReorganizeTable(pBe, pOp->p3); break; } /* Opcode: ListOpen P1 * * ** ** 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: { int i = pOp->p1; VERIFY( if( i<0 ) goto bad_instruction; ) if( i>=p->nList ){ int j; 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] ){ KeylistFree(p->apList[i]); p->apList[i] = 0; } break; } /* Opcode: ListWrite P1 * * ** ** Write the integer on the top of the stack ** into the temporary storage list P1. */ case OP_ListWrite: { int i = pOp->p1; Keylist *pKeylist; VERIFY( if( i<0 || i>=p->nList ) goto bad_instruction; ) VERIFY( if( p->tos<0 ) goto not_enough_stack; ) 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; } /* Opcode: ListRewind P1 * * ** ** Rewind the temporary buffer P1 back to the beginning. */ case OP_ListRewind: { int i = pOp->p1; VERIFY( if( i<0 ) goto bad_instruction; ) /* This is now a no-op */ break; } /* Opcode: ListRead P1 P2 * ** ** Attempt to read an integer from temporary storage buffer P1 ** and push it onto the stack. If the storage buffer is empty, ** push nothing but instead jump to P2. */ case OP_ListRead: { int i = pOp->p1; int val, amt; 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 = 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; } break; } /* Opcode: ListClose P1 * * ** ** Close the temporary storage buffer and discard its contents. */ case OP_ListClose: { int i = pOp->p1; VERIFY( if( i<0 ) goto bad_instruction; ) VERIFY( if( i>=p->nList ) goto bad_instruction; ) KeylistFree(p->apList[i]); p->apList[i] = 0; break; } /* Opcode: SortOpen P1 * * ** ** Create a new sorter with index P1 */ |
︙ | ︙ |
Changes to test/delete.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the DELETE FROM statement. # | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the DELETE FROM statement. # # $Id: delete.test,v 1.8 2001/03/20 22:05:00 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Try to delete from a non-existant table. # do_test delete-1.1 { |
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 | } execsql {SELECT f1 FROM table1 ORDER BY f1} } {42 44 47 48 50} do_test delete-5.7 { execsql "DELETE FROM table1 WHERE f1!=48" execsql {SELECT f1 FROM table1 ORDER BY f1} } {48} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | } execsql {SELECT f1 FROM table1 ORDER BY f1} } {42 44 47 48 50} do_test delete-5.7 { execsql "DELETE FROM table1 WHERE f1!=48" 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 |
Changes to www/changes.tcl.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | } proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2001 Mar 20 (1.0.26)} { <li>A serious bug fixed on Windows. Windows users should upgrade. No impact to Unix.</li> } chng {2001 Mar 15 (1.0.25)} { | > > > > > > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | } proc chng {date desc} { puts "<DT><B>$date</B></DT>" 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> } chng {2001 Mar 15 (1.0.25)} { |
︙ | ︙ |