Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch btree-fordelete-flag Excluding Merge-Ins
This is equivalent to a diff from a3d7b8ac to 46080b04
2016-01-30
| ||
13:32 | Add the BTREE_FORDELETE and BTREE_AUXDELETE flags to the b-tree layer interface and use them. Add assert() statement to verify that they are correct. (check-in: 85c46704 user: drh tags: trunk) | |
2016-01-29
| ||
19:04 | Improvements to FORDELETE processing, including bug fixes and adding assert() statements to help verify correct operation. (Closed-Leaf check-in: 46080b04 user: drh tags: btree-fordelete-flag) | |
18:48 | Remove a stray "exit" in a test script. (Closed-Leaf check-in: 10c88bf9 user: drh tags: fordelete-assert) | |
2016-01-27
| ||
07:28 | Support building for Windows 10 desktop using 'MinCore.lib'. (check-in: 4bf89891 user: mistachkin tags: trunk) | |
2016-01-26
| ||
23:32 | Merge all recent trunk enhancements. (check-in: 9a71d56d user: drh tags: btree-fordelete-flag) | |
20:19 | Performance improvements for fts5, particularly detail=col mode. (check-in: a3d7b8ac user: dan tags: trunk) | |
20:08 | Further minor performance improvements and code-size reductions related to fts5 column filters on detail=col tables. (Leaf check-in: b4ac61ae user: dan tags: fts5-perf) | |
14:48 | Fix issues on unix with opening database files via symlinks that are not in the current working directory. And with nested symlinks. (check-in: 4003db4a user: dan tags: trunk) | |
Changes to src/btree.c.
︙ | |||
4045 4046 4047 4048 4049 4050 4051 | 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 | - - - - - + + + + + - + + + + + + + + + + + | /* ** Create a new cursor for the BTree whose root is on the page ** iTable. If a read-only cursor is requested, it is assumed that ** the caller already has at least a read-only transaction open ** on the database already. If a write-cursor is requested, then ** the caller is assumed to have an open write transaction. ** |
︙ | |||
8078 8079 8080 8081 8082 8083 8084 | 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 | - - - - - + + + + + + + + + + + + + - + + + | end_insert: return rc; } /* ** Delete the entry that the cursor is pointing to. ** |
︙ |
Changes to src/btree.h.
︙ | |||
241 242 243 244 245 246 247 | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | - + + + + + + | UnpackedRecord *pUnKey, i64 intKey, int bias, int *pRes ); int sqlite3BtreeCursorHasMoved(BtCursor*); int sqlite3BtreeCursorRestore(BtCursor*, int*); |
︙ |
Changes to src/delete.c.
︙ | |||
475 476 477 478 479 480 481 | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | - - - + + | /* Unless this is a view, open cursors for the table we are ** deleting from and all its indices. If this is a view, then the ** only effect this statement has is to fire the INSTEAD OF ** triggers. */ if( !isView ){ int iAddrOnce = 0; |
︙ | |||
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | + + + + + - + | sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); } /* Delete the index and table entries. Skip this step if pTab is really ** a view (in which case the only effect of the DELETE statement is to ** fire the INSTEAD OF triggers). */ if( pTab->pSelect==0 ){ u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); if( count ){ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); } if( eMode!=ONEPASS_OFF ){ sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); } if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; |
︙ |
Changes to src/insert.c.
︙ | |||
1643 1644 1645 1646 1647 1648 1649 | 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 | - + | ** If pTab is a virtual table, then this routine is a no-op and the ** *piDataCur and *piIdxCur values are left uninitialized. */ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int op, /* OP_OpenRead or OP_OpenWrite */ |
︙ | |||
1678 1679 1680 1681 1682 1683 1684 | 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | - - - - + + + + + | }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); } if( piIdxCur ) *piIdxCur = iBase; for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); |
︙ |
Changes to src/sqliteInt.h.
︙ | |||
2843 2844 2845 2846 2847 2848 2849 | 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 | - + + + + | const char *zAuthContext; /* Put saved Parse.zAuthContext here */ Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P5 value in various opcodes. */ |
︙ |
Changes to src/vdbe.c.
︙ | |||
548 549 550 551 552 553 554 555 556 557 558 559 560 561 | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | + + + | Vdbe *p /* The VDBE */ ){ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp = aOp; /* Current operation */ #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) Op *pOrigOp; /* Value of pOp at the top of the loop */ #endif #ifdef SQLITE_DEBUG int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ #endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ int iCompare = 0; /* Result of last OP_Compare operation */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
︙ | |||
3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 | 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 | + + + | assert( nField>=0 ); testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; pCur->isOrdered = 1; pCur->pgnoRoot = p2; #ifdef SQLITE_DEBUG pCur->wrFlag = wrFlag; #endif rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); pCur->pKeyInfo = pKeyInfo; /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; |
︙ | |||
4337 4338 4339 4340 4341 4342 4343 | 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 | + - - - - - + + + + + + + + + + + + - - + + | break; } /* Opcode: Delete P1 P2 * P4 P5 ** ** Delete the record at which the P1 cursor is currently pointing. ** ** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then |
︙ | |||
4380 4381 4382 4383 4384 4385 4386 | 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 | - + + + + + + + + + + + + + + + + + + + + | ** is being deleted */ if( pOp->p4.z && pC->isTable && pOp->p5==0 ){ i64 iKey = 0; sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); assert( pC->movetoTarget==iKey ); } #endif |
︙ | |||
4925 4926 4927 4928 4929 4930 4931 | 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 | - - - - + | pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); assert( pOp->p5==0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p3; r.default_rc = 0; r.aMem = &aMem[pOp->p2]; |
︙ | |||
6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 | 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 | + + + | ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: db->lastRowid = lastRowid; testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); assert( rc!=SQLITE_OK || nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH ** is encountered. */ too_big: sqlite3VdbeError(p, "string or blob too big"); |
︙ |
Changes to src/vdbeInt.h.
︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | + | u8 eCurType; /* One of the CURTYPE_* values above */ i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ u8 nullRow; /* True if pointing to a row with no data */ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ u8 isTable; /* True for rowid tables. False for indexes */ #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ Pgno pgnoRoot; /* Root page of the open btree cursor */ i16 nField; /* Number of fields in the header */ u16 nHdrParsed; /* Number of header fields parsed so far */ |
︙ |
Changes to test/fordelete.test.
︙ | |||
26 27 28 29 30 31 32 | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 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 | - - - + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + | proc analyze_delete_program {sql} { # Build a map from root page to table/index name. db eval { SELECT name, rootpage FROM sqlite_master } { set T($rootpage) $name } |
︙ | |||
121 122 123 124 125 126 127 128 129 130 | 153 154 155 156 157 158 159 160 161 162 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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | btree_close_cursor $csr db eval { COMMIT } db eval { SELECT * FROM x2; } } {6 {} {} {}} #------------------------------------------------------------------------- # reset_db do_execsql_test 4.0 { CREATE TABLE log(x); CREATE TABLE p1(one PRIMARY KEY, two); CREATE TRIGGER tr_bd BEFORE DELETE ON p1 BEGIN INSERT INTO log VALUES('delete'); END; INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C'); DELETE FROM p1 WHERE one = 'a'; } reset_db do_execsql_test 4.1 { BEGIN TRANSACTION; CREATE TABLE tbl(a PRIMARY KEY, b, c); CREATE TABLE log(a, b, c); INSERT INTO "tbl" VALUES(1,2,3); CREATE TRIGGER the_trigger BEFORE DELETE ON tbl BEGIN INSERT INTO log VALUES(1, 2,3); END; COMMIT; DELETE FROM tbl WHERE a=1; } reset_db do_execsql_test 5.1 { PRAGMA foreign_keys = 1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b); CREATE TABLE t2( c INTEGER PRIMARY KEY, d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT ); } {} do_execsql_test 5.2 { INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t2 VALUES(1, 2); SELECT * FROM t2; } {1 2} do_execsql_test 5.3 { DELETE FROM t1 WHERE a = 2; } {} finish_test |