Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Move the rowid cache out of VdbeCursor and into BtCursor. When multiple BtCursors are open on the same table, set their rowid cache all at the same time. Ticket #3731. (CVS 6354) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
189785832a7dc9f4a0a2113d850b92b9 |
User & Date: | drh 2009-03-17 22:33:01 |
Context
2009-03-18
| ||
10:33 | Fix some cases where executing SQL from within a user-function callback could cause problems related to statement-transactions. (CVS 6355) check-in: a60f4191 user: danielk1977 tags: trunk | |
2009-03-17
| ||
22:33 | Move the rowid cache out of VdbeCursor and into BtCursor. When multiple BtCursors are open on the same table, set their rowid cache all at the same time. Ticket #3731. (CVS 6354) check-in: 18978583 user: drh tags: trunk | |
17:49 | Fix a problem that could cause a crash when a shared-cache schema contains column default values. (CVS 6353) check-in: afadddc3 user: danielk1977 tags: trunk | |
Changes
Changes to src/btree.c.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 .... 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 .... 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 .... 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 .... 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 .... 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 |
** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.573 2009/03/16 13:19:36 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" ................................................................................ /* ** Return the currently defined page size */ int sqlite3BtreeGetPageSize(Btree *p){ return p->pBt->pageSize; } int sqlite3BtreeGetReserve(Btree *p){ int n; sqlite3BtreeEnter(p); n = p->pBt->pageSize - p->pBt->usableSize; sqlite3BtreeLeave(p); return n; } ................................................................................ pCur->wrFlag = (u8)wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; return SQLITE_OK; create_cursor_exception: releasePage(pCur->apPage[0]); unlockBtreeIfUnused(pBt); return rc; ................................................................................ int rc; sqlite3BtreeEnter(p); p->pBt->db = p->db; rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); sqlite3BtreeLeave(p); return rc; } int sqlite3BtreeCursorSize(){ return sizeof(BtCursor); } /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ Btree *pBtree = pCur->pBtree; ................................................................................ int i; assert( cursorHoldsMutex(pCur) ); for(i=0; i<=pCur->iPage; i++){ sqlite3PagerUnref(pCur->apPage[i]->pDbPage); } sqlite3_free(pCur->pKey); } /* ** Make sure the BtCursor* given in the argument has a valid ** BtCursor.info structure. If it is not already valid, call ** sqlite3BtreeParseCell() to fill it in. ** ** BtCursor.info is a cache of the information in the current cell. ................................................................................ ** into *pAmt. If *pAmt==0, then the value returned will not be ** a valid pointer. ** ** This routine is an optimization. It is common for the entire key ** and data to fit on the local page and for there to be no overflow ** pages. When that is so, this routine can be used to access the ** key and data without making a copy. If the key and/or data spills ** onto overflow pages, then accessPayload() must be used to reassembly ** the key/data and copy it into a preallocated buffer. ** ** The pointer returned by this routine looks directly into the cached ** page of the database. The data might change or move the next time ** any btree routine is called. */ static const unsigned char *fetchPayload( |
| > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > | |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 .... 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 .... 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 .... 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 .... 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 .... 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 |
** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.574 2009/03/17 22:33:01 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" ................................................................................ /* ** Return the currently defined page size */ int sqlite3BtreeGetPageSize(Btree *p){ return p->pBt->pageSize; } /* ** Return the number of bytes of space at the end of every page that ** are intentually left unused. This is the "reserved" space that is ** sometimes used by extensions. */ int sqlite3BtreeGetReserve(Btree *p){ int n; sqlite3BtreeEnter(p); n = p->pBt->pageSize - p->pBt->usableSize; sqlite3BtreeLeave(p); return n; } ................................................................................ pCur->wrFlag = (u8)wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; pCur->cachedRowid = 0; return SQLITE_OK; create_cursor_exception: releasePage(pCur->apPage[0]); unlockBtreeIfUnused(pBt); return rc; ................................................................................ int rc; sqlite3BtreeEnter(p); p->pBt->db = p->db; rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); sqlite3BtreeLeave(p); return rc; } /* ** Return the size of a BtCursor object in bytes. ** ** This interfaces is needed so that users of cursors can preallocate ** sufficient storage to hold a cursor. The BtCursor object is opaque ** to users so they cannot do the sizeof() themselves - they must call ** this routine. */ int sqlite3BtreeCursorSize(void){ return sizeof(BtCursor); } /* ** Set the cached rowid value of every cursor in the same database file ** as pCur and having the same root page number as pCur. The value is ** set to iRowid. ** ** Only positive rowid values are considered valid for this cache. ** The cache is initialized to zero, indicating an invalid cache. ** A btree will work fine with zero or negative rowids. We just cannot ** cache zero or negative rowids, which means tables that use zero or ** negative rowids might run a little slower. But in practice, zero ** or negative rowids are very uncommon so this should not be a problem. */ void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){ BtCursor *p; for(p=pCur->pBt->pCursor; p; p=p->pNext){ if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid; } assert( pCur->cachedRowid==iRowid ); } /* ** Return the cached rowid for the given cursor. A negative or zero ** return value indicates that the rowid cache is invalid and should be ** ignored. If the rowid cache has never before been set, then a ** zero is returned. */ sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){ return pCur->cachedRowid; } /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ Btree *pBtree = pCur->pBtree; ................................................................................ int i; assert( cursorHoldsMutex(pCur) ); for(i=0; i<=pCur->iPage; i++){ sqlite3PagerUnref(pCur->apPage[i]->pDbPage); } sqlite3_free(pCur->pKey); } /* ** Make sure the BtCursor* given in the argument has a valid ** BtCursor.info structure. If it is not already valid, call ** sqlite3BtreeParseCell() to fill it in. ** ** BtCursor.info is a cache of the information in the current cell. ................................................................................ ** into *pAmt. If *pAmt==0, then the value returned will not be ** a valid pointer. ** ** This routine is an optimization. It is common for the entire key ** and data to fit on the local page and for there to be no overflow ** pages. When that is so, this routine can be used to access the ** key and data without making a copy. If the key and/or data spills ** onto overflow pages, then accessPayload() must be used to reassemble ** the key/data and copy it into a preallocated buffer. ** ** The pointer returned by this routine looks directly into the cached ** page of the database. The data might change or move the next time ** any btree routine is called. */ static const unsigned char *fetchPayload( |
Changes to src/btree.h.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.109 2009/02/24 10:01:52 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ ................................................................................ int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); sqlite3 *sqlite3BtreeCursorDb(const BtCursor*); const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeCacheOverflow(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); |
|
>
>
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.110 2009/03/17 22:33:01 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ ................................................................................ int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); sqlite3 *sqlite3BtreeCursorDb(const BtCursor*); const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeCacheOverflow(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); |
Changes to src/btreeInt.h.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
|
** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btreeInt.h,v 1.43 2009/03/16 13:19:36 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. ................................................................................ */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ Pgno pgnoRoot; /* The root page of this tree */ CellInfo info; /* A parse of the cell we are pointing at */ u8 wrFlag; /* True if writable */ u8 atLast; /* Cursor pointing to the last entry */ u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ void *pKey; /* Saved key that was cursor's last known position */ i64 nKey; /* Size of pKey, or last integer key */ |
|
>
|
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
|
** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btreeInt.h,v 1.44 2009/03/17 22:33:01 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. ................................................................................ */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ Pgno pgnoRoot; /* The root page of this tree */ sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */ CellInfo info; /* A parse of the cell we are pointing at */ u8 wrFlag; /* True if writable */ u8 atLast; /* Cursor pointing to the last entry */ u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ void *pKey; /* Saved key that was cursor's last known position */ i64 nKey; /* Size of pKey, or last integer key */ |
Changes to src/vdbe.c.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 .... 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 .... 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 .... 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 .... 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 .... 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 |
** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.825 2009/03/16 13:19:36 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test ................................................................................ ** Others complain about 0x7ffffffffffffffffLL. The following macro seems ** to provide the constant while making all compilers happy. */ # define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) #endif if( !pC->useRandomRowid ){ if( pC->nextRowidValid ){ v = pC->nextRowid; }else{ rc = sqlite3BtreeLast(pC->pCursor, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res ){ v = 1; }else{ ................................................................................ if( v<pMem->u.i+1 ){ v = pMem->u.i + 1; } pMem->u.i = v; } #endif if( v<MAX_ROWID ){ pC->nextRowidValid = 1; pC->nextRowid = v+1; }else{ pC->nextRowidValid = 0; } } if( pC->useRandomRowid ){ assert( pOp->p3==0 ); /* SQLITE_FULL must have occurred prior to this */ v = db->priorNewRowid; cnt = 0; do{ if( cnt==0 && (v&0xffffff)==v ){ ................................................................................ assert( pC->isTable ); REGISTER_TRACE(pOp->p2, pData); REGISTER_TRACE(pOp->p3, pKey); iKey = intToKey(pKey->u.i); if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; 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 ){ ................................................................................ }else{ int nZero; if( pData->flags & MEM_Zero ){ nZero = pData->u.nZero; }else{ nZero = 0; } rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pData->z, pData->n, nZero, pOp->p5 & OPFLAG_APPEND); } pC->rowidIsValid = 0; pC->deferredMoveto = 0; ................................................................................ assert( pC->isTable ); assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ iKey = pC->lastRowid; } rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; rc = sqlite3BtreeDelete(pC->pCursor); pC->nextRowidValid = 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; db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); |
| | | < | < < < < < < < < > > < |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 .... 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 .... 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 .... 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 .... 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 .... 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 |
** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.826 2009/03/17 22:33:01 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test ................................................................................ ** Others complain about 0x7ffffffffffffffffLL. The following macro seems ** to provide the constant while making all compilers happy. */ # define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) #endif if( !pC->useRandomRowid ){ v = sqlite3BtreeGetCachedRowid(pC->pCursor); if( v==0 ){ rc = sqlite3BtreeLast(pC->pCursor, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res ){ v = 1; }else{ ................................................................................ if( v<pMem->u.i+1 ){ v = pMem->u.i + 1; } pMem->u.i = v; } #endif sqlite3BtreeSetCachedRowid(pC->pCursor, v<MAX_ROWID ? v+1 : 0); } if( pC->useRandomRowid ){ assert( pOp->p3==0 ); /* SQLITE_FULL must have occurred prior to this */ v = db->priorNewRowid; cnt = 0; do{ if( cnt==0 && (v&0xffffff)==v ){ ................................................................................ assert( pC->isTable ); REGISTER_TRACE(pOp->p2, pData); REGISTER_TRACE(pOp->p3, pKey); iKey = intToKey(pKey->u.i); if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i; if( pData->flags & MEM_Null ){ pData->z = 0; pData->n = 0; }else{ assert( pData->flags & (MEM_Blob|MEM_Str) ); } if( pC->pseudoTable ){ ................................................................................ }else{ int nZero; if( pData->flags & MEM_Zero ){ nZero = pData->u.nZero; }else{ nZero = 0; } sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pData->z, pData->n, nZero, pOp->p5 & OPFLAG_APPEND); } pC->rowidIsValid = 0; pC->deferredMoveto = 0; ................................................................................ assert( pC->isTable ); assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ iKey = pC->lastRowid; } rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeDelete(pC->pCursor); 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; db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); |
Changes to src/vdbeInt.h.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
************************************************************************* ** This is the header file for information that is private to the ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. ** ** $Id: vdbeInt.h,v 1.164 2009/02/20 01:28:59 drh Exp $ */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ /* ** intToKey() and keyToInt() used to transform the rowid. But with ** the latest versions of the design they are no-ops. ................................................................................ ** a row trigger. The data for the row is stored in VdbeCursor.pData and ** the rowid is in VdbeCursor.iKey. */ struct VdbeCursor { BtCursor *pCursor; /* The cursor structure of the backend */ int iDb; /* Index of cursor database in db->aDb[] (or -1) */ i64 lastRowid; /* Last rowid from a Next or NextIdx operation */ i64 nextRowid; /* Next rowid returned by OP_NewRowid */ Bool zeroed; /* True if zeroed out and ready for reuse */ Bool rowidIsValid; /* True if lastRowid is valid */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Bool ephemPseudoTable; Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ |
|
<
<
|
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
************************************************************************* ** This is the header file for information that is private to the ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. ** ** $Id: vdbeInt.h,v 1.165 2009/03/17 22:33:01 drh Exp $ */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ /* ** intToKey() and keyToInt() used to transform the rowid. But with ** the latest versions of the design they are no-ops. ................................................................................ ** a row trigger. The data for the row is stored in VdbeCursor.pData and ** the rowid is in VdbeCursor.iKey. */ struct VdbeCursor { BtCursor *pCursor; /* The cursor structure of the backend */ int iDb; /* Index of cursor database in db->aDb[] (or -1) */ i64 lastRowid; /* Last rowid from a Next or NextIdx operation */ Bool zeroed; /* True if zeroed out and ready for reuse */ Bool rowidIsValid; /* True if lastRowid is valid */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Bool ephemPseudoTable; Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ |
Added test/tkt3731.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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 |
# 2009 March 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # $Id: tkt3731.test,v 1.1 2009/03/17 22:33:01 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!trigger} { finish_test return } do_test tkt3731-1.1 { execsql { CREATE TABLE t1(a PRIMARY KEY, b); CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t1 VALUES(new.a || '+', new.b || '+'); END; } } {} do_test tkt3731-1.2 { execsql { INSERT INTO t1 VALUES('a', 'b'); INSERT INTO t1 VALUES('c', 'd'); SELECT * FROM t1; } } {a b a+ b+ c d c+ d+} do_test tkt3731-1.3 { execsql { DELETE FROM t1; CREATE TABLE t2(a, b); INSERT INTO t2 VALUES('e', 'f'); INSERT INTO t2 VALUES('g', 'h'); INSERT INTO t1 SELECT * FROM t2; SELECT * FROM t1; } } {e f e+ f+ g h g+ h+} integrity_check tkt3731-1.4 finish_test |