DBD-SQLite2
view release on metacpan or search on metacpan
** that extra information.
*/
#define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data))
/*
** Everything we need to know about an open database
*/
struct Btree {
BtOps *pOps; /* Function table */
Pager *pPager; /* The page cache */
BtCursor *pCursor; /* A list of all open cursors */
PageOne *page1; /* First page of the database */
u8 inTrans; /* True if a transaction is in progress */
u8 inCkpt; /* True if there is a checkpoint on the transaction */
u8 readOnly; /* True if the underlying file is readonly */
u8 needSwab; /* Need to byte-swapping */
};
typedef Btree Bt;
/*
** A cursor is a pointer to a particular entry in the BTree.
** The entry is identified by its MemPage and the index in
** MemPage.apCell[] of the entry.
*/
struct BtCursor {
BtCursorOps *pOps; /* Function table */
Btree *pBt; /* The Btree to which this cursor belongs */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
BtCursor *pShared; /* Loop of cursors with the same root page */
Pgno pgnoRoot; /* The root page of this tree */
MemPage *pPage; /* Page that contains the entry */
int idx; /* Index of the entry in pPage->apCell[] */
u8 wrFlag; /* True if writable */
u8 eSkip; /* Determines if next step operation is a no-op */
u8 iMatch; /* compare result from last sqliteBtreeMoveto() */
};
/*
** Legal values for BtCursor.eSkip.
*/
#define SKIP_NONE 0 /* Always step the cursor */
#define SKIP_NEXT 1 /* The next sqliteBtreeNext() is a no-op */
#define SKIP_PREV 2 /* The next sqliteBtreePrevious() is a no-op */
#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */
/* Forward declarations */
static int fileBtreeCloseCursor(BtCursor *pCur);
/*
** Routines for byte swapping.
*/
sqlitepager_set_destructor(pBt->pPager, pageDestructor);
pBt->pCursor = 0;
pBt->page1 = 0;
pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
pBt->pOps = &sqliteBtreeOps;
*ppBtree = pBt;
return SQLITE_OK;
}
/*
** Close an open database and invalidate all cursors.
*/
static int fileBtreeClose(Btree *pBt){
while( pBt->pCursor ){
fileBtreeCloseCursor(pBt->pCursor);
}
sqlitepager_close(pBt->pPager);
sqliteFree(pBt);
return SQLITE_OK;
}
}
return rc;
page1_init_failed:
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
return rc;
}
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there are any outstanding cursors, this routine is a no-op.
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
pBt->inTrans = 0;
pBt->inCkpt = 0;
}
}else{
unlockBtreeIfUnused(pBt);
}
return rc;
}
/*
** Commit the transaction currently in progress.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
static int fileBtreeCommit(Btree *pBt){
int rc;
rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
pBt->inTrans = 0;
pBt->inCkpt = 0;
unlockBtreeIfUnused(pBt);
return rc;
}
/*
** Rollback the transaction in progress. All cursors will be
** invalided by this operation. Any attempt to use a cursor
** that was open at the beginning of this operation will result
** in an error.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
static int fileBtreeRollback(Btree *pBt){
int rc;
BtCursor *pCur;
if( pBt->inTrans==0 ) return SQLITE_OK;
pBt->inTrans = 0;
pBt->inCkpt = 0;
rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage && pCur->pPage->isInit==0 ){
rc = SQLITE_OK;
}
pBt->inCkpt = 0;
return rc;
}
/*
** Rollback the checkpoint to the current transaction. If there
** is no active checkpoint or transaction, this routine is a no-op.
**
** All cursors will be invalided by this operation. Any attempt
** to use a cursor that was open at the beginning of this operation
** will result in an error.
*/
static int fileBtreeRollbackCkpt(Btree *pBt){
int rc;
BtCursor *pCur;
if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
rc = sqlitepager_ckpt_rollback(pBt->pPager);
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage && pCur->pPage->isInit==0 ){
sqlitepager_unref(pCur->pPage);
pCur->pPage = 0;
}
}
pBt->inCkpt = 0;
return rc;
}
/*
** Create a new cursor for the BTree whose root is on the page
** iTable. The act of acquiring a cursor gets a read lock on
** the database file.
**
** If wrFlag==0, then the cursor can only be used for reading.
** If wrFlag==1, then the cursor can be used for reading or for
** writing if other conditions for writing are also met. These
** are the conditions that must be met in order for writing to
** be allowed:
**
** 1: The cursor must have been opened with wrFlag==1
**
** 2: No other cursors may be open with wrFlag==0 on the same table
**
** 3: The database must be writable (not on read-only media)
**
** 4: There must be an active transaction.
**
** Condition 2 warrants further discussion. If any cursor is opened
** on a table with wrFlag==0, that prevents all other cursors from
** writing to that table. This is a kind of "read-lock". When a cursor
** is opened with wrFlag==0 it is guaranteed that the table will not
** change as long as the cursor is open. This allows the cursor to
** do a sequential scan of the table without having to worry about
** entries being inserted or deleted during the scan. Cursors should
** be opened with wrFlag==0 only if this read-lock property is needed.
** That is to say, cursors should be opened with wrFlag==0 only if they
** intend to use the sqliteBtreeNext() system call. All other cursors
** should be opened with wrFlag==1 even if they never really intend
** to write.
**
** No checking is done to make sure that page iTable really is the
** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly.
*/
static
int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
int rc;
BtCursor *pCur, *pRing;
if( pBt->readOnly && wrFlag ){
*ppCur = 0;
return SQLITE_READONLY;
if( pBt->page1==0 ){
rc = lockBtree(pBt);
if( rc!=SQLITE_OK ){
*ppCur = 0;
return rc;
}
}
pCur = sqliteMalloc( sizeof(*pCur) );
if( pCur==0 ){
rc = SQLITE_NOMEM;
goto create_cursor_exception;
}
pCur->pgnoRoot = (Pgno)iTable;
rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
pCur->pOps = &sqliteBtreeCursorOps;
pCur->pBt = pBt;
pCur->wrFlag = wrFlag;
pCur->idx = 0;
pCur->eSkip = SKIP_INVALID;
pCur->pNext = pBt->pCursor;
if( pCur->pNext ){
pCur->pNext->pPrev = pCur;
}
if( pRing ){
pCur->pShared = pRing->pShared;
pRing->pShared = pCur;
}else{
pCur->pShared = pCur;
}
pBt->pCursor = pCur;
*ppCur = pCur;
return SQLITE_OK;
create_cursor_exception:
*ppCur = 0;
if( pCur ){
if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
sqliteFree(pCur);
}
unlockBtreeIfUnused(pBt);
return rc;
}
/*
** Close a cursor. The read lock on the database file is released
** when the last cursor is closed.
*/
static int fileBtreeCloseCursor(BtCursor *pCur){
Btree *pBt = pCur->pBt;
if( pCur->pPrev ){
pCur->pPrev->pNext = pCur->pNext;
}else{
pBt->pCursor = pCur->pNext;
}
if( pCur->pNext ){
pCur->pNext->pPrev = pCur->pPrev;
BtCursor *pRing = pCur->pShared;
while( pRing->pShared!=pCur ){ pRing = pRing->pShared; }
pRing->pShared = pCur->pShared;
}
unlockBtreeIfUnused(pBt);
sqliteFree(pCur);
return SQLITE_OK;
}
/*
** Make a temporary cursor by filling in the fields of pTempCur.
** The temporary cursor is not on the cursor list for the Btree.
*/
static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
memcpy(pTempCur, pCur, sizeof(*pCur));
pTempCur->pNext = 0;
pTempCur->pPrev = 0;
if( pTempCur->pPage ){
sqlitepager_ref(pTempCur->pPage);
}
}
/*
** Delete a temporary cursor such as was made by the CreateTemporaryCursor()
** function above.
*/
static void releaseTempCursor(BtCursor *pCur){
if( pCur->pPage ){
sqlitepager_unref(pCur->pPage);
}
}
/*
** Set *pSize to the number of bytes of key in the entry the
** cursor currently points to. Always return SQLITE_OK.
** Failure is not possible. If the cursor is not currently
** pointing to an entry (which can happen, for example, if
** the database is empty) then *pSize is set to 0.
*/
static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
Cell *pCell;
MemPage *pPage;
pPage = pCur->pPage;
assert( pPage!=0 );
if( pCur->idx >= pPage->nCell ){
*pSize = 0;
}else{
pCell = pPage->apCell[pCur->idx];
*pSize = NKEY(pCur->pBt, pCell->h);
}
return SQLITE_OK;
}
/*
** Read payload information from the entry that the pCur cursor is
** pointing to. Begin reading the payload at "offset" and read
** a total of "amt" bytes. Put the result in zBuf.
**
** This routine does not make a distinction between key and data.
** It just reads bytes from the payload area.
*/
static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
char *aPayload;
Pgno nextPage;
int rc;
}
sqlitepager_unref(pOvfl);
}
if( amt>0 ){
return SQLITE_CORRUPT;
}
return SQLITE_OK;
}
/*
** Read part of the key associated with cursor pCur. A maximum
** of "amt" bytes will be transfered into zBuf[]. The transfer
** begins at "offset". The number of bytes actually read is
** returned.
**
** Change: It used to be that the amount returned will be smaller
** than the amount requested if there are not enough bytes in the key
** to satisfy the request. But now, it must be the case that there
** is enough data available to satisfy the request. If not, an exception
** is raised. The change was made in an effort to boost performance
** by eliminating unneeded tests.
if( pCur->idx >= pPage->nCell ){
return 0;
}
assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) );
getPayload(pCur, offset, amt, zBuf);
return amt;
}
/*
** Set *pSize to the number of bytes of data in the entry the
** cursor currently points to. Always return SQLITE_OK.
** Failure is not possible. If the cursor is not currently
** pointing to an entry (which can happen, for example, if
** the database is empty) then *pSize is set to 0.
*/
static int fileBtreeDataSize(BtCursor *pCur, int *pSize){
Cell *pCell;
MemPage *pPage;
pPage = pCur->pPage;
assert( pPage!=0 );
if( pCur->idx >= pPage->nCell ){
*pSize = 0;
}else{
pCell = pPage->apCell[pCur->idx];
*pSize = NDATA(pCur->pBt, pCell->h);
}
return SQLITE_OK;
}
/*
** Read part of the data associated with cursor pCur. A maximum
** of "amt" bytes will be transfered into zBuf[]. The transfer
** begins at "offset". The number of bytes actually read is
** returned. The amount returned will be smaller than the
** amount requested if there are not enough bytes in the data
** to satisfy the request.
*/
static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
Cell *pCell;
MemPage *pPage;
zKey += n;
}
if( c==0 ){
c = nLocal - nKey;
}
*pResult = c;
return SQLITE_OK;
}
/*
** Move the cursor down to a new child page. The newPgno argument is the
** page number of the child page in the byte order of the disk image.
*/
static int moveToChild(BtCursor *pCur, int newPgno){
int rc;
MemPage *pNewPage;
Btree *pBt = pCur->pBt;
newPgno = SWAB32(pBt, newPgno);
rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
if( rc ) return rc;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNewPage;
pCur->idx = 0;
if( pNewPage->nCell<1 ){
return SQLITE_CORRUPT;
}
return SQLITE_OK;
}
/*
** Move the cursor up to the parent page.
**
** pCur->idx is set to the cell index that contains the pointer
** to the page we are coming from. If we are coming from the
** right-most child page then pCur->idx is set to one more than
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
Pgno oldPgno;
MemPage *pParent;
MemPage *pPage;
for(i=0; i<pParent->nCell; i++){
if( pParent->apCell[i]->h.leftChild==oldPgno ){
pCur->idx = i;
break;
}
}
}
}
/*
** Move the cursor to the root page
*/
static int moveToRoot(BtCursor *pCur){
MemPage *pNew;
int rc;
Btree *pBt = pCur->pBt;
rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
if( rc ) return rc;
rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
if( rc ) return rc;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNew;
pCur->idx = 0;
return SQLITE_OK;
}
/*
** Move the cursor down to the left-most leaf entry beneath the
** entry to which it is currently pointing.
*/
static int moveToLeftmost(BtCursor *pCur){
Pgno pgno;
int rc;
while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
return SQLITE_OK;
}
/*
** Move the cursor down to the right-most leaf entry beneath the
** page to which it is currently pointing. Notice the difference
** between moveToLeftmost() and moveToRightmost(). moveToLeftmost()
** finds the left-most entry beneath the *entry* whereas moveToRightmost()
** finds the right-most entry beneath the *page*.
*/
static int moveToRightmost(BtCursor *pCur){
Pgno pgno;
int rc;
while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
pCur->idx = pCur->pPage->nCell;
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
pCur->idx = pCur->pPage->nCell - 1;
return SQLITE_OK;
}
/* Move the cursor to the first entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
static int fileBtreeFirst(BtCursor *pCur, int *pRes){
int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT;
rc = moveToRoot(pCur);
if( rc ) return rc;
if( pCur->pPage->nCell==0 ){
*pRes = 1;
return SQLITE_OK;
}
*pRes = 0;
rc = moveToLeftmost(pCur);
pCur->eSkip = SKIP_NONE;
return rc;
}
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
static int fileBtreeLast(BtCursor *pCur, int *pRes){
int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT;
rc = moveToRoot(pCur);
if( rc ) return rc;
assert( pCur->pPage->isInit );
if( pCur->pPage->nCell==0 ){
*pRes = 1;
return SQLITE_OK;
}
*pRes = 0;
rc = moveToRightmost(pCur);
pCur->eSkip = SKIP_NONE;
return rc;
}
/* Move the cursor so that it points to an entry near pKey.
** Return a success code.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
** were present. The cursor might point to an entry that comes
** before or after the key.
**
** The result of comparing the key with the entry to which the
** cursor is left pointing is stored in pCur->iMatch. The same
** value is also written to *pRes if pRes!=NULL. The meaning of
** this value is as follows:
**
** *pRes<0 The cursor is left pointing at an entry that
** is smaller than pKey or if the table is empty
** and the cursor is therefore left point to nothing.
**
** *pRes==0 The cursor is left pointing at an entry that
** exactly matches pKey.
**
** *pRes>0 The cursor is left pointing at an entry that
** is larger than pKey.
*/
static
int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT;
pCur->eSkip = SKIP_NONE;
rc = moveToRoot(pCur);
if( rc ) return rc;
for(;;){
return SQLITE_OK;
}
pCur->idx = lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) return rc;
}
/* NOT REACHED */
}
/*
** Advance the cursor to the next entry in the database. If
** successful then set *pRes=0. If the cursor
** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1.
*/
static int fileBtreeNext(BtCursor *pCur, int *pRes){
int rc;
MemPage *pPage = pCur->pPage;
assert( pRes!=0 );
if( pPage==0 ){
*pRes = 1;
return SQLITE_ABORT;
}
*pRes = 0;
if( pPage->u.hdr.rightChild==0 ){
return SQLITE_OK;
}
rc = moveToLeftmost(pCur);
return rc;
}
/*
** Step the cursor to the back to the previous entry in the database. If
** successful then set *pRes=0. If the cursor
** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1.
*/
static int fileBtreePrevious(BtCursor *pCur, int *pRes){
int rc;
Pgno pgno;
MemPage *pPage;
pPage = pCur->pPage;
if( pPage==0 ){
*pRes = 1;
static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
MemPage *pParent; /* The parent of pPage */
int nCell; /* Number of cells in apCell[] */
int nOld; /* Number of pages in apOld[] */
int nNew; /* Number of pages in apNew[] */
int nDiv; /* Number of cells in apDiv[] */
int i, j, k; /* Loop counters */
int idx; /* Index of pPage in pParent->apCell[] */
int nxDiv; /* Next divider slot in pParent->apCell[] */
int rc; /* The return code */
int iCur; /* apCell[iCur] is the cell of the cursor */
MemPage *pOldCurPage; /* The cursor originally points to this page */
int subtotal; /* Subtotal of bytes in cells on one page */
MemPage *extraUnref = 0; /* A page that needs to be unref-ed */
MemPage *apOld[NB]; /* pPage and up to two siblings */
Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
MemPage *apNew[NB+1]; /* pPage and up to NB siblings after balancing */
Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */
int idxDiv[NB]; /* Indices of divider cells in pParent */
Cell *apDiv[NB]; /* Divider cells in pParent */
Cell aTemp[NB]; /* Temporary holding area for apDiv[] */
int cntNew[NB+1]; /* Index in apCell[] of cell after i-th page */
}
rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
if( rc ) goto balance_cleanup;
rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
if( rc ) goto balance_cleanup;
apOld[i]->idxParent = k;
nOld++;
}
/*
** Set iCur to be the index in apCell[] of the cell that the cursor
** is pointing to. We will need this later on in order to keep the
** cursor pointing at the same cell. If pCur points to a page that
** has no involvement with this rebalancing, then set iCur to a large
** number so that the iCur==j tests always fail in the main cell
** distribution loop below.
*/
if( pCur ){
iCur = 0;
for(i=0; i<nOld; i++){
if( pCur->pPage==apOld[i] ){
iCur += pCur->idx;
break;
if( pCur && pCur->pPage==0 ){
pCur->pPage = pParent;
pCur->idx = 0;
}else{
sqlitepager_unref(pParent);
}
return rc;
}
/*
** This routine checks all cursors that point to the same table
** as pCur points to. If any of those cursors were opened with
** wrFlag==0 then this routine returns SQLITE_LOCKED. If all
** cursors point to the same table were opened with wrFlag==1
** then this routine returns SQLITE_OK.
**
** In addition to checking for read-locks (where a read-lock
** means a cursor opened with wrFlag==0) this routine also moves
** all cursors other than pCur so that they are pointing to the
** first Cell on root page. This is necessary because an insert
** or delete might change the number of cells on a page or delete
** a page entirely and we do not want to leave any cursors
** pointing to non-existant pages or cells.
*/
static int checkReadLocks(BtCursor *pCur){
BtCursor *p;
assert( pCur->wrFlag );
for(p=pCur->pShared; p!=pCur; p=p->pShared){
assert( p );
assert( p->pgnoRoot==pCur->pgnoRoot );
if( p->wrFlag==0 ) return SQLITE_LOCKED;
if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){
moveToRoot(p);
}
}
return SQLITE_OK;
}
/*
** Insert a new record into the BTree. The key is given by (pKey,nKey)
** and the data is given by (pData,nData). The cursor is used only to
** define what database the record should be inserted into. The cursor
** is left pointing at the new record.
*/
static int fileBtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const void *pKey, int nKey, /* The key of the new record */
const void *pData, int nData /* The data of the new record */
){
Cell newCell;
int rc;
int loc;
int szNew;
MemPage *pPage;
Btree *pBt = pCur->pBt;
if( pCur->pPage==0 ){
return SQLITE_ABORT; /* A rollback destroyed this cursor */
}
if( !pBt->inTrans || nKey+nData==0 ){
/* Must start a transaction before doing an insert */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( !pBt->readOnly );
if( !pCur->wrFlag ){
return SQLITE_PERM; /* Cursor not open for writing */
}
if( checkReadLocks(pCur) ){
}
insertCell(pBt, pPage, pCur->idx, &newCell, szNew);
rc = balance(pCur->pBt, pPage, pCur);
/* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
/* fflush(stdout); */
pCur->eSkip = SKIP_INVALID;
return rc;
}
/*
** Delete the entry that the cursor is pointing to.
**
** The cursor is left pointing at either the next or the previous
** entry. If the cursor is left pointing to the next entry, then
** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to
** sqliteBtreeNext() to be a no-op. That way, you can always call
** sqliteBtreeNext() after a delete and the cursor will be left
** pointing to the first entry after the deleted entry. Similarly,
** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
** the entry prior to the deleted entry so that a subsequent call to
** sqliteBtreePrevious() will always leave the cursor pointing at the
** entry immediately before the one that was deleted.
*/
static int fileBtreeDelete(BtCursor *pCur){
MemPage *pPage = pCur->pPage;
Cell *pCell;
int rc;
Pgno pgnoChild;
Btree *pBt = pCur->pBt;
assert( pPage->isInit );
if( pCur->pPage==0 ){
return SQLITE_ABORT; /* A rollback destroyed this cursor */
}
if( !pBt->inTrans ){
/* Must start a transaction before doing a delete */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( !pBt->readOnly );
if( pCur->idx >= pPage->nCell ){
return SQLITE_ERROR; /* The cursor is not pointing to anything */
}
if( !pCur->wrFlag ){
return SQLITE_PERM; /* Did not open this cursor for writing */
}
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
rc = sqlitepager_write(pPage);
if( rc ) return rc;
pCell = pPage->apCell[pCur->idx];
pgnoChild = SWAB32(pBt, pCell->h.leftChild);
clearCell(pBt, pCell);
if( pgnoChild ){
*/
static int fileBtreeDropTable(Btree *pBt, int iTable){
int rc;
MemPage *pPage;
BtCursor *pCur;
if( !pBt->inTrans ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pgnoRoot==(Pgno)iTable ){
return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */
}
}
rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
if( rc ) return rc;
rc = fileBtreeClearTable(pBt, iTable);
if( rc ) return rc;
if( iTable>2 ){
rc = freePage(pBt, pPage, iTable);
}else{
zeroPage(pBt, pPage);
fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
}
sqlitepager_unref(pPage);
return SQLITE_OK;
}
#endif
#ifdef SQLITE_TEST
/*
** Fill aResult[] with information about the entry and page that the
** cursor is pointing to.
**
** aResult[0] = The page number
** aResult[1] = The entry number
** aResult[2] = Total number of entries on this page
** aResult[3] = Size of this entry
** aResult[4] = Number of free bytes on this page
** aResult[5] = Number of free blocks on the page
** aResult[6] = Page number of the left child of this entry
** aResult[7] = Page number of the right child for the whole page
**
const char *(*GetFilename)(Btree*);
int (*Copyfile)(Btree*,Btree*);
struct Pager *(*Pager)(Btree*);
#ifdef SQLITE_TEST
int (*PageDump)(Btree*, int, int);
#endif
};
/*
** An instance of this structure defines all of the methods that can
** be executed against a cursor.
*/
struct BtCursorOps {
int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
int (*Delete)(BtCursor*);
int (*Insert)(BtCursor*, const void *pKey, int nKey,
const void *pData, int nData);
int (*First)(BtCursor*, int *pRes);
int (*Last)(BtCursor*, int *pRes);
int (*Next)(BtCursor*, int *pRes);
int (*Previous)(BtCursor*, int *pRes);
#define TRANS_INCHECKPOINT 2 /* A checkpoint is in progress */
#define TRANS_ROLLBACK 3 /* We are currently rolling back a checkpoint or
* transaction. */
struct RbtCursor {
BtCursorOps *pOps; /* Function table */
Rbtree *pRbtree;
BtRbTree *pTree;
int iTree; /* Index of pTree in pRbtree */
BtRbNode *pNode;
RbtCursor *pShared; /* List of all cursors on the same Rbtree */
u8 eSkip; /* Determines if next step operation is a no-op */
u8 wrFlag; /* True if this cursor is open for writing */
};
/*
** Legal values for RbtCursor.eSkip.
*/
#define SKIP_NONE 0 /* Always step the cursor */
#define SKIP_NEXT 1 /* The next sqliteRbtreeNext() is a no-op */
#define SKIP_PREV 2 /* The next sqliteRbtreePrevious() is a no-op */
#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */
struct BtRbTree {
RbtCursor *pCursors; /* All cursors pointing to this tree */
BtRbNode *pHead; /* Head of the tree, or NULL */
};
struct BtRbNode {
int nKey;
void *pKey;
int nData;
void *pData;
u8 isBlack; /* true for a black node, 0 for a red node */
BtRbNode *pParent; /* Nodes parent node, NULL for the tree head */
int nKey,
int *pRes
);
static int memRbtreeClearTable(Rbtree* tree, int n);
static int memRbtreeNext(RbtCursor* pCur, int *pRes);
static int memRbtreeLast(RbtCursor* pCur, int *pRes);
static int memRbtreePrevious(RbtCursor* pCur, int *pRes);
/*
** This routine checks all cursors that point to the same table
** as pCur points to. If any of those cursors were opened with
** wrFlag==0 then this routine returns SQLITE_LOCKED. If all
** cursors point to the same table were opened with wrFlag==1
** then this routine returns SQLITE_OK.
**
** In addition to checking for read-locks (where a read-lock
** means a cursor opened with wrFlag==0) this routine also NULLs
** out the pNode field of all other cursors.
** This is necessary because an insert
** or delete might change erase the node out from under
** another cursor.
*/
static int checkReadLocks(RbtCursor *pCur){
RbtCursor *p;
assert( pCur->wrFlag );
for(p=pCur->pTree->pCursors; p; p=p->pShared){
if( p!=pCur ){
if( p->wrFlag==0 ) return SQLITE_LOCKED;
p->pNode = 0;
}
}
*pRes = -1;
}else{
*pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore,
pKey, nKey);
}
}
return SQLITE_OK;
}
/*
* Get a new cursor for table iTable of the supplied Rbtree. The wrFlag
* parameter indicates that the cursor is open for writing.
*
* Note that RbtCursor.eSkip and RbtCursor.pNode both initialize to 0.
*/
static int memRbtreeCursor(
Rbtree* tree,
int iTable,
int wrFlag,
RbtCursor **ppCur
){
RbtCursor *pCur;
pCur->wrFlag = wrFlag;
pCur->pShared = pCur->pTree->pCursors;
pCur->pTree->pCursors = pCur;
assert( (*ppCur)->pTree );
return SQLITE_OK;
}
/*
* Insert a new record into the Rbtree. The key is given by (pKey,nKey)
* and the data is given by (pData,nData). The cursor is used only to
* define what database the record should be inserted into. The cursor
* is left pointing at the new record.
*
* If the key exists already in the tree, just replace the data.
*/
static int memRbtreeInsert(
RbtCursor* pCur,
const void *pKey,
int nKey,
const void *pDataInput,
int nData
){
void * pData;
int match;
/* It is illegal to call sqliteRbtreeInsert() if we are
** not in a transaction */
assert( pCur->pRbtree->eTransState != TRANS_NONE );
/* Make sure some other cursor isn't trying to read this same table */
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
/* Take a copy of the input data now, in case we need it for the
* replace case */
pData = sqliteMallocRaw(nData);
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
memcpy(pData, pDataInput, nData);
/* Move the cursor to a node near the key to be inserted. If the key already
* exists in the table, then (match == 0). In this case we can just replace
* the data associated with the entry, we don't need to manipulate the tree.
*
* If there is no exact match, then the cursor points at what would be either
* the predecessor (match == -1) or successor (match == 1) of the
* searched-for key, were it to be inserted. The new node becomes a child of
* this node.
*
* The new node is initially red.
*/
memRbtreeMoveto( pCur, pKey, nKey, &match);
if( match ){
BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode));
if( pNode==0 ) return SQLITE_NOMEM;
pNode->pParent = pCur->pNode;
pCur->pNode->pLeft = pNode;
break;
default:
assert(0);
}
}else{
pCur->pTree->pHead = pNode;
}
/* Point the cursor at the node just inserted, as per SQLite requirements */
pCur->pNode = pNode;
/* A new node has just been inserted, so run the balancing code */
do_insert_balancing(pCur->pTree, pNode);
/* Set up a rollback-op in case we have to roll this operation back */
if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
if( pOp==0 ) return SQLITE_NOMEM;
pOp->eOp = ROLLBACK_DELETE;
}
/* Actually clobber the nodes data */
pCur->pNode->pData = pData;
pCur->pNode->nData = nData;
}
return SQLITE_OK;
}
/* Move the cursor so that it points to an entry near pKey.
** Return a success code.
**
** *pRes<0 The cursor is left pointing at an entry that
** is smaller than pKey or if the table is empty
** and the cursor is therefore left point to nothing.
**
** *pRes==0 The cursor is left pointing at an entry that
** exactly matches pKey.
**
** *pRes>0 The cursor is left pointing at an entry that
** is larger than pKey.
*/
static int memRbtreeMoveto(
RbtCursor* pCur,
const void *pKey,
int nKey,
int *pRes
){
BtRbNode *pTmp = 0;
pCur->pNode = pCur->pTree->pHead;
*pRes = -1;
while( pCur->pNode && *pRes ) {
*pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey);
pTmp = pCur->pNode;
switch( *pRes ){
case 1: /* cursor > key */
pCur->pNode = pCur->pNode->pLeft;
break;
case -1: /* cursor < key */
pCur->pNode = pCur->pNode->pRight;
break;
}
}
/* If (pCur->pNode == NULL), then we have failed to find a match. Set
* pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the
* last node traversed in the search. In either case the relation ship
* between pTmp and the searched for key is already stored in *pRes. pTmp is
* either the successor or predecessor of the key we tried to move to. */
if( !pCur->pNode ) pCur->pNode = pTmp;
pCur->eSkip = SKIP_NONE;
return SQLITE_OK;
}
/*
** Delete the entry that the cursor is pointing to.
**
** The cursor is left pointing at either the next or the previous
** entry. If the cursor is left pointing to the next entry, then
** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to
** sqliteRbtreeNext() to be a no-op. That way, you can always call
** sqliteRbtreeNext() after a delete and the cursor will be left
** pointing to the first entry after the deleted entry. Similarly,
** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
** the entry prior to the deleted entry so that a subsequent call to
** sqliteRbtreePrevious() will always leave the cursor pointing at the
** entry immediately before the one that was deleted.
*/
static int memRbtreeDelete(RbtCursor* pCur)
{
BtRbNode *pZ; /* The one being deleted */
BtRbNode *pChild; /* The child of the spliced out node */
/* It is illegal to call sqliteRbtreeDelete() if we are
** not in a transaction */
assert( pCur->pRbtree->eTransState != TRANS_NONE );
/* Make sure some other cursor isn't trying to read this same table */
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
pZ = pCur->pNode;
if( !pZ ){
return SQLITE_OK;
}
/* If we are not currently doing a rollback, set up a rollback op for this
if( pCur->pNode ){
*pRes = 0;
}else{
*pRes = 1;
}
pCur->eSkip = SKIP_NONE;
return SQLITE_OK;
}
/*
** Advance the cursor to the next entry in the database. If
** successful then set *pRes=0. If the cursor
** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1.
*/
static int memRbtreeNext(RbtCursor* pCur, int *pRes)
{
if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){
if( pCur->pNode->pRight ){
pCur->pNode = pCur->pNode->pRight;
while( pCur->pNode->pLeft )
pCur->pNode = pCur->pNode->pLeft;
char *sqliteTableNameFromToken(Token *pName){
char *zName = sqliteStrNDup(pName->z, pName->n);
sqliteDequote(zName);
return zName;
}
/*
** Generate code to open the appropriate master table. The table
** opened will be SQLITE_MASTER for persistent tables and
** SQLITE_TEMP_MASTER for temporary tables. The table is opened
** on cursor 0.
*/
void sqliteOpenMasterTable(Vdbe *v, int isTemp){
sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
}
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement. In particular, this routine is called
}else{
sqliteDequote(*pz);
}
}
pList->a[pList->nSrc].iCursor = -1;
pList->nSrc++;
return pList;
}
/*
** Assign cursors to all tables in a SrcList
*/
void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
for(i=0; i<pList->nSrc; i++){
if( pList->a[i].iCursor<0 ){
pList->a[i].iCursor = pParse->nTab++;
}
}
}
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto delete_from_cleanup;
}
/* If pTab is really a view, make sure it has been initialized.
*/
if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
goto delete_from_cleanup;
}
/* Allocate a cursor used to store the old.* data for a trigger.
*/
if( row_triggers_exist ){
oldIdx = pParse->nTab++;
}
/* Resolve the column names in all the expressions.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
if( pWhere ){
if( !isView ){
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
}
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_ListRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
pParse->nTab = iCur + 1;
sqliteOpenTableAndIndices(pParse, pTab, iCur);
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !row_triggers_exist ){
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
}
/* Delete the row */
sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
}
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
*/
if( row_triggers_exist ){
if( !isView ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
}
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
/* End of the delete loop */
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
/* Close the cursors after the loop if there are no row triggers */
if( !row_triggers_exist ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
}
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
sqliteEndWriteOperation(pParse);
return;
}
/*
** This routine generates VDBE code that causes a single row of a
** single table to be deleted.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
** 1. A read/write cursor pointing to pTab, the table containing the row
** to be deleted, must be opened as cursor number "base".
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number base+i for the i-th index.
**
** 3. The record number of the row to be deleted must be on the top
** of the stack.
**
** This routine pops the top of the stack to remove the record number
** and then generates code to remove both the table record and all index
** entries that point to that record.
*/
void sqliteGenerateRowDelete(
sqlite *db, /* The database containing the index */
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
}
/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
** 1. A read/write cursor pointing to pTab, the table containing the row
** to be deleted, must be opened as cursor number "iCur".
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number iCur+i for the i-th index.
**
** 3. The "iCur" cursor must be pointing to the row that is to be
** deleted.
*/
void sqliteGenerateRowIndexDelete(
sqlite *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
){
int i;
}
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
** are made to pExpr:
**
** pExpr->iDb Set the index in db->aDb[] of the database holding
** the table.
** pExpr->iTable Set to the cursor number for the table obtained
** from pSrcList.
** pExpr->iColumn Set to the column number within the table.
** pExpr->dataType Set to the appropriate data type for the column.
** pExpr->op Set to TK_COLUMN.
** pExpr->pLeft Any expression this points to is deleted
** pExpr->pRight Any expression this points to is deleted.
**
** The pDbToken is the name of the database (the "X"). This value may be
** NULL meaning that name is of the form Y.Z or Z. Any available database
** can be used. The pTableToken is the name of the table (the "Y"). This
return cnt!=1;
}
/*
** This routine walks an expression tree and resolves references to
** table columns. Nodes of the form ID.ID or ID resolve into an
** index to the table in the table list and a column offset. The
** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
** value is changed to the index of the referenced table in pTabList
** plus the "base" value. The base value will ultimately become the
** VDBE cursor number for a cursor that is pointing into the referenced
** table. The Expr.iColumn value is changed to the index of the column
** of the referenced table. The Expr.iColumn value for the special
** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
** alias for ROWID.
**
** We also check for instances of the IN operator. IN comes in two
** forms:
**
** expr IN (exprlist)
** and
case TK_IN: {
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return 1;
if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pSelect ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into a temporary
** table. The cursor number of the temporary table has already
** been put in iTable by sqliteExprResolveInSelect().
*/
pExpr->iTable = pParse->nTab++;
sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0);
}else if( pExpr->pList ){
/* Case 2: expr IN (exprlist)
**
** Create a set to put the exprlist values in. The Set id is stored
** in iTable.
**
** The pList parameter holds EXPRLIST in the first form of the INSERT
** statement above, and pSelect is NULL. For the second form, pList is
** NULL and pSelect is a pointer to the select statement used to generate
** data for the insert.
**
** The code generated follows one of three templates. For a simple
** select with data coming from a VALUES clause, the code executes
** once straight down through. The template looks like this:
**
** open write cursor to <table> and its indices
** puts VALUES clause expressions onto the stack
** write the resulting record into <table>
** cleanup
**
** If the statement is of the form
**
** INSERT INTO <table> SELECT ...
**
** And the SELECT clause does not read from <table> at any time, then
** the generated code follows this template:
**
** goto B
** A: setup for the SELECT
** loop over the tables in the SELECT
** gosub C
** end loop
** cleanup after the SELECT
** goto D
** B: open write cursor to <table> and its indices
** goto A
** C: insert the select result into <table>
** return
** D: cleanup
**
** The third template is used if the insert statement takes its
** values from a SELECT but the data is being inserted into a table
** that is also read as part of the SELECT. In the third form,
** we have to use a intermediate table to store the results of
** the select. The template is like this:
**
** goto B
** A: setup for the SELECT
** loop over the tables in the SELECT
** gosub C
** end loop
** cleanup after the SELECT
** goto D
** C: insert the select result into the intermediate table
** return
** B: open a cursor to an intermediate table
** goto A
** D: open write cursor to <table> and its indices
** loop over the intermediate table
** transfer values form intermediate table into <table>
** end the loop
** cleanup
*/
void sqliteInsert(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */
ExprList *pList, /* List of values to be inserted */
Select *pSelect, /* A SELECT statement to use as the data source */
int i, j, idx; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */
int base; /* VDBE Cursor number for pTab */
int iCont, iBreak; /* Beginning and end of the loop over srcTab */
sqlite *db; /* The main database structure */
int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */
int useTempTable; /* Store SELECT results in intermediate table */
int srcTab; /* Data comes from this temporary cursor if >=0 */
int iSelectLoop; /* Address of code that implements the SELECT */
int iCleanup; /* Address of the cleanup code */
int iInsertBlock; /* Address of the subroutine used to insert data */
int iCntMem; /* Memory cell used for the row counter */
int isView; /* True if attempting to insert into a view */
int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
int before_triggers; /* True if there are BEFORE triggers */
int after_triggers; /* True if there are AFTER triggers */
int newIdx = -1; /* Cursor for the NEW table */
** UNIQUE REPLACE The other row that conflicts with the row
** being inserted is removed.
**
** CHECK REPLACE Illegal. The results in an exception.
**
** Which action to take is determined by the overrideError parameter.
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used. Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
**
** The calling routine must open a read/write cursor for pTab with
** cursor number "base". All indices of pTab must also have open
** read/write cursors with cursor number base+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
** cursors do not need to be open for indices where aIdxUsed[i]==0.
**
** If the isUpdate flag is true, it means that the "base" cursor is
** initially pointing to an entry that is being updated. The isUpdate
** flag causes extra code to be generated so that the "base" cursor
** is still pointing at the same entry after the routine returns.
** Without the isUpdate flag, the "base" cursor might be moved.
*/
void sqliteGenerateConstraintChecks(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
int base, /* Index of a read/write cursor pointing at pTab */
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int recnoChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int overrideError, /* Override onError to this if not OE_Default */
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
){
int i;
Vdbe *v;
int nCol;
int onError;
** The stack must contain keys for all active indices followed by data
** and the recno for the new entry. This routine creates the new
** entries in all indices and in the main table.
**
** The arguments to this routine should be the same as the first six
** arguments to sqliteGenerateConstraintChecks.
*/
void sqliteCompleteInsertion(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
int base, /* Index of a read/write cursor pointing at pTab */
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int recnoChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int newIdx /* Index of NEW table for triggers. -1 if none */
){
int i;
Vdbe *v;
int nIdx;
Index *pIdx;
}
sqliteVdbeAddOp(v, OP_PutIntKey, base,
(pParse->trigStack?0:OPFLAG_NCHANGE) |
(isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);
if( isUpdate && recnoChng ){
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
}
}
/*
** Generate code that will open write cursors for a table and for all
** indices of that table. The "base" parameter is the cursor number used
** for the table. Indices are opened on subsequent cursors.
**
** Return the total number of cursors opened. This is always at least
** 1 (for the main table) plus more for each cursor.
*/
int sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base){
int i;
Index *pIdx;
Vdbe *v = sqliteGetVdbe(pParse);
assert( v!=0 );
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeOp3(v, OP_OpenWrite, base, pTab->tnum, pTab->zName, P3_STATIC);
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
initData.pzErrMsg = pzErrMsg;
sqliteInitCallback(&initData, 5, (char **)azArg, 0);
pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
}else{
return SQLITE_NOMEM;
}
sqliteSafetyOn(db);
/* Create a cursor to hold the database open
*/
if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
if( rc ){
sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
return rc;
}
/* Get the database meta information
*/
}
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
** entry in pEList. (But leave references to the ROWID column
** unchanged.)
**
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
** FORM clause entry is iTable. This routine make the necessary
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
Parse *pParse, /* The parsing context */
Select *p, /* The parent or outer SELECT statement */
int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
int isAgg, /* True if outer SELECT uses aggregate functions */
int subqueryIsAgg /* True if the subquery uses aggregate functions */
){
Select *pSub; /* The inner query or "subquery" */
SrcList *pSrc; /* The FROM clause of the outer query */
SrcList *pSubSrc; /* The FROM clause of the subquery */
ExprList *pList; /* The result set of the outer query */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int i;
Expr *pWhere;
/* Check to see if flattening is permitted. Return 0 if not.
*/
if( p==0 ) return 0;
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSub = pSrc->a[iFrom].pSelect;
assert( pSub!=0 );
&& pSub->pWhere!=0 ){
return 0;
}
/* If we reach this point, it means flattening is permitted for the
** iFrom-th entry of the FROM clause in the outer query.
*/
/* Move all of the FROM elements of the subquery into the
** the FROM clause of the outer query. Before doing this, remember
** the cursor number for the original outer query FROM element in
** iParent. The iParent cursor will never be used. Subsequent code
** will scan expressions looking for iParent references and replace
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
iParent = pSrc->a[iFrom].iCursor;
{
int nSubSrc = pSubSrc->nSrc;
int jointype = pSrc->a[iFrom].jointype;
if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){
**
** The results are distributed in various ways depending on the
** value of eDest and iParm.
**
** eDest Value Result
** ------------ -------------------------------------------
** SRT_Callback Invoke the callback for each row of the result.
**
** SRT_Mem Store first result in memory cell iParm
**
** SRT_Set Store results as keys of a table with cursor iParm
**
** SRT_Union Store results as a key in a temporary table iParm
**
** SRT_Except Remove results from the temporary table iParm.
**
** SRT_Table Store results in temporary table iParm
**
** The table above is incomplete. Additional eDist value have be added
** since this comment was written. See the selectInnerLoop() function for
** a complete listing of the allowed values of eDest and their meanings.
/* Make local copies of the parameters for this query.
*/
pTabList = p->pSrc;
pWhere = p->pWhere;
pOrderBy = p->pOrderBy;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
isDistinct = p->isDistinct;
/* Allocate VDBE cursors for each table in the FROM clause
*/
sqliteSrcListAssignCursors(pParse, pTabList);
/*
** Do not even attempt to generate any code if we have already seen
** errors before this routine starts.
*/
if( pParse->nErr>0 ) goto select_end;
/* Expand any "*" terms in the result set. (For example the "*" in
switch( eDest ){
case SRT_Union:
case SRT_Except:
case SRT_Discard:
pOrderBy = 0;
break;
default:
break;
}
/* At this point, we should have allocated all the cursors that we
** need to handle subquerys and temporary tables.
**
** Resolve the column names and do a semantics check on all the expressions.
*/
for(i=0; i<pEList->nExpr; i++){
if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
goto select_end;
sqliteInt.h view on Meta::CPAN
** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
** is generated for each row of the table. Table.hasPrimKey is true if
** the table has any PRIMARY KEY, INTEGER or otherwise.
**
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
** holds temporary tables and indices. If Table.isTransient
** is true, then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause
** of a SELECT statement.
*/
struct Table {
char *zName; /* Name of the table */
int nCol; /* Number of columns in this table */
Column *aCol; /* Information about each column */
int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */
Index *pIndex; /* List of SQL indexes on this table. */
sqliteInt.h view on Meta::CPAN
** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list
** of argument if the expression is a function.
**
** Expr.token is the operator token for this node. For some expressions
** that have subexpressions, Expr.token can be the complete text that gave
** rise to the Expr. In the latter case, the token is marked as being
** a compound token.
**
** An expression of the form ID or ID.ID refers to a column in a table.
** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
** the integer cursor number of a VDBE cursor pointing to that table and
** Expr.iColumn is the column number for the specific column. If the
** expression is used as a result in an aggregate SELECT, then the
** value is also stored in the Expr.iAgg column in the aggregate so that
** it can be accessed after all aggregates are computed.
**
** If the expression is a function, the Expr.iTable is an integer code
** representing which function. If the expression is an unbound variable
** marker (a question mark character '?' in the original SQL) then the
** Expr.iTable holds the index number for that variable.
**
sqliteInt.h view on Meta::CPAN
struct SrcList {
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
i16 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
int jointype; /* Type of join between this table and the next */
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
} a[1]; /* One entry for each identifier on the list */
};
/*
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER 0x0001 /* Any kind of inner or cross join */
#define JT_NATURAL 0x0002 /* True for a "natural" join */
sqliteInt.h view on Meta::CPAN
Token sLastToken; /* The last token parsed */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
Vdbe *pVdbe; /* An engine for executing database bytecode */
u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
u8 explain; /* True if the EXPLAIN flag is found on the query */
u8 nameClash; /* A permanent table name clashes with temp table name */
u8 useAgg; /* If true, extract field values from the aggregator
** while generating expressions. Normally false */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
int nAgg; /* Number of aggregate expressions */
int nVar; /* Number of '?' variables seen in the SQL so far */
AggExpr *aAgg; /* An array of aggregate expressions */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
TriggerStack *trigStack; /* Trigger actions being coded */
};
sqliteInt.h view on Meta::CPAN
TriggerStep * pNext; /* Next in the link-list */
};
/*
* An instance of struct TriggerStack stores information required during code
* generation of a single trigger program. While the trigger program is being
* coded, its associated TriggerStack instance is pointed to by the
* "pTriggerStack" member of the Parse structure.
*
* The pTab member points to the table that triggers are being coded on. The
* newIdx member contains the index of the vdbe cursor that points at the temp
* table that stores the new.* references. If new.* references are not valid
* for the trigger being coded (for example an ON DELETE trigger), then newIdx
* is set to -1. The oldIdx member is analogous to newIdx, for old.* references.
*
* The ON CONFLICT policy to be used for the trigger program steps is stored
* as the orconf member. If this is OE_Default, then the ON CONFLICT clause
* specified for individual triggers steps is used.
*
* struct TriggerStack has a "pNext" member, to allow linked lists to be
* constructed. When coding nested triggers (triggers fired by other triggers)
sqliteInt.h view on Meta::CPAN
* pointer. Once the nested trigger has been coded, the pNext value is restored
* to the pTriggerStack member of the Parse stucture and coding of the parent
* trigger continues.
*
* Before a nested trigger is coded, the linked list pointed to by the
* pTriggerStack is scanned to ensure that the trigger is not about to be coded
* recursively. If this condition is detected, the nested trigger is not coded.
*/
struct TriggerStack {
Table *pTab; /* Table that triggers are currently being coded on */
int newIdx; /* Index of vdbe cursor to "new" temp table */
int oldIdx; /* Index of vdbe cursor to "old" temp table */
int orconf; /* Current orconf policy */
int ignoreJump; /* where to jump to for a RAISE(IGNORE) */
Trigger *pTrigger; /* The trigger currently being coded */
TriggerStack *pNext; /* Next trigger down on the trigger stack */
};
/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
t/30insertfetch.t view on Meta::CPAN
# Insert a row into the test table.......
#
Test($state or $dbh->do("INSERT INTO $table"
. " VALUES(1, 'Alligator Descartes', 1111,"
. " 'Some Text')"), 'insert')
or DbiError($dbh->err, $dbh->errstr);
#
# Now, try SELECT'ing the row out.
#
Test($state or $cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE id = 1"),
'prepare select')
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute, 'execute select')
or DbiError($cursor->err, $cursor->errstr);
my ($row, $errstr);
Test($state or (defined($row = $cursor->fetchrow_arrayref) &&
!($cursor->errstr)), 'fetch select')
or DbiError($cursor->err, $cursor->errstr);
Test($state or ($row->[0] == 1 &&
$row->[1] eq 'Alligator Descartes' &&
$row->[2] == 1111 &&
$row->[3] eq 'Some Text'), 'compare select')
or DbiError($cursor->err, $cursor->errstr);
Test($state or $cursor->finish, 'finish select')
or DbiError($cursor->err, $cursor->errstr);
Test($state or undef $cursor || 1, 'undef select');
#
# ...and delete it........
#
Test($state or $dbh->do("DELETE FROM $table WHERE id = 1"), 'delete')
or DbiError($dbh->err, $dbh->errstr);
#
# Now, try SELECT'ing the row out. This should fail.
#
Test($state or $cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE id = 1"),
'prepare select deleted')
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute, 'execute select deleted')
or DbiError($cursor->err, $cursor->errstr);
Test($state or (!defined($row = $cursor->fetchrow_arrayref) &&
(!defined($errstr = $cursor->errstr) ||
$cursor->errstr eq '')), 'fetch select deleted')
or DbiError($cursor->err, $cursor->errstr);
Test($state or $cursor->finish, 'finish select deleted')
or DbiError($cursor->err, $cursor->errstr);
Test($state or undef $cursor || 1, 'undef select deleted');
#
# Finally drop the test table.
#
Test($state or $dbh->do("DROP TABLE $table"), 'drop')
or DbiError($dbh->err, $dbh->errstr);
}
t/40bindparam.t view on Meta::CPAN
#
# Create a new table; EDIT THIS!
#
Test($state or ($def = TableDefinition($table,
["id", "INTEGER", 4, 0],
["name", "CHAR", 64, $COL_NULLABLE]) and
$dbh->do($def)), 'create', $def)
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor = $dbh->prepare("INSERT INTO $table"
. " VALUES (?, ?)"), 'prepare')
or DbiError($dbh->err, $dbh->errstr);
#
# Insert some rows
#
my $konig = "Andreas K\xf6nig";
# warn("Konig: $konig\n");
# Automatic type detection
my $numericVal = 1;
my $charVal = "Alligator Descartes";
Test($state or $cursor->execute($numericVal, $charVal), 'execute insert 1')
or DbiError($dbh->err, $dbh->errstr);
# Does the driver remember the automatically detected type?
Test($state or $cursor->execute("3", "Jochen Wiedmann"),
'execute insert num as string')
or DbiError($dbh->err, $dbh->errstr);
$numericVal = 2;
$charVal = "Tim Bunce";
Test($state or $cursor->execute($numericVal, $charVal), 'execute insert 2')
or DbiError($dbh->err, $dbh->errstr);
# Now try the explicit type settings
Test($state or $cursor->bind_param(1, " 4", SQL_INTEGER()), 'bind 1')
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->bind_param(2, $konig), 'bind 2')
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute, 'execute binds')
or DbiError($dbh->err, $dbh->errstr);
# Works undef -> NULL?
Test($state or $cursor->bind_param(1, 5, SQL_INTEGER()))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->bind_param(2, undef))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor -> finish, 'finish');
Test($state or undef $cursor || 1, 'undef cursor');
Test($state or $dbh -> disconnect, 'disconnect');
Test($state or undef $dbh || 1, 'undef dbh');
#
# And now retreive the rows using bind_columns
#
#
# Connect to the database
#
Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password),
'connect for read')
or ServerError();
# $dbh->{NoUTF8Flag} = 1 if $] > 5.007;
Test($state or $cursor = $dbh->prepare("SELECT * FROM $table"
. " ORDER BY id"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->bind_columns(undef, \$id, \$name))
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($ref = $cursor->fetch) && $id == 1 &&
$name eq 'Alligator Descartes')
or printf("Query returned id = %s, name = %s, ref = %s, %d\n",
$id, $name, $ref, scalar(@$ref));
Test($state or (($ref = $cursor->fetch) && $id == 2 &&
$name eq 'Tim Bunce'))
or printf("Query returned id = %s, name = %s, ref = %s, %d\n",
$id, $name, $ref, scalar(@$ref));
Test($state or (($ref = $cursor->fetch) && $id == 3 &&
$name eq 'Jochen Wiedmann'))
or printf("Query returned id = %s, name = %s, ref = %s, %d\n",
$id, $name, $ref, scalar(@$ref));
# warn("Konig: $konig\n");
Test($state or (($ref = $cursor->fetch) && $id == 4 &&
$name eq $konig))
or printf("Query returned id = %s, name = %s, ref = %s, %d\n",
$id, $name, $ref, scalar(@$ref));
# warn("$konig == $name ?\n");
Test($state or (($ref = $cursor->fetch) && $id == 5 &&
!defined($name)))
or printf("Query returned id = %s, name = %s, ref = %s, %d\n",
$id, $name, $ref, scalar(@$ref));
Test($state or undef $cursor or 1);
#
# Finally drop the test table.
#
Test($state or $dbh->do("DROP TABLE $table"))
or DbiError($dbh->err, $dbh->errstr);
}
t/40blobs.t view on Meta::CPAN
print OUT $query, "\n";
close(OUT);
}
}
Test($state or $dbh->do($query,undef,$blob))
or DbiError($dbh->err, $dbh->errstr);
#
# Now, try SELECT'ing the row out.
#
Test($state or $cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE id = 1"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or (defined($row = $cursor->fetchrow_arrayref)))
or DbiError($cursor->err, $cursor->errstr);
Test($state or (@$row == 2 && $$row[0] == 1 && $$row[1] eq $blob))
or (ShowBlob($blob),
ShowBlob(defined($$row[1]) ? $$row[1] : ""));
Test($state or $cursor->finish)
or DbiError($cursor->err, $cursor->errstr);
Test($state or undef $cursor || 1)
or DbiError($cursor->err, $cursor->errstr);
#
# Finally drop the test table.
#
Test($state or $dbh->do("DROP TABLE $table"))
or DbiError($dbh->err, $dbh->errstr);
}
}
t/40listfields.t view on Meta::CPAN
or DbiError($dbh->err, $dbh->errstr);
#
# Create a new table
#
Test($state or ($def = TableDefinition($table, @table_def),
$dbh->do($def)))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor = $dbh->prepare("SELECT * FROM $table"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($cursor->err, $cursor->errstr);
my $res;
Test($state or (($res = $cursor->{'NUM_OF_FIELDS'}) == @table_def))
or DbiError($cursor->err, $cursor->errstr);
if (!$state && $verbose) {
printf("Number of fields: %s\n", defined($res) ? $res : "undef");
}
Test($state or ($ref = $cursor->{'NAME'}) && @$ref == @table_def
&& (lc $$ref[0]) eq $table_def[0][0]
&& (lc $$ref[1]) eq $table_def[1][0])
or DbiError($cursor->err, $cursor->errstr);
if (!$state && $verbose) {
print "Names:\n";
for ($i = 0; $i < @$ref; $i++) {
print " ", $$ref[$i], "\n";
}
}
Test($state or ($dbdriver eq 'CSV') or ($dbdriver eq 'ConfFile')
or ($dbdriver eq 'SQLite2')
or ($ref = $cursor->{'NULLABLE'}) && @$ref == @table_def
&& !($$ref[0] xor ($table_def[0][3] & $COL_NULLABLE))
&& !($$ref[1] xor ($table_def[1][3] & $COL_NULLABLE)))
or DbiError($cursor->err, $cursor->errstr);
if (!$state && $verbose) {
print "Nullable:\n";
for ($i = 0; $i < @$ref; $i++) {
print " ", ($$ref[$i] & $COL_NULLABLE) ? "yes" : "no", "\n";
}
}
Test($state or undef $cursor || 1);
#
# Drop the test table
#
Test($state or ($cursor = $dbh->prepare("DROP TABLE $table")))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($cursor->err, $cursor->errstr);
# NUM_OF_FIELDS should be zero (Non-Select)
Test($state or ($cursor->{'NUM_OF_FIELDS'} == 0))
or !$verbose or printf("NUM_OF_FIELDS is %s, not zero.\n",
$cursor->{'NUM_OF_FIELDS'});
Test($state or (undef $cursor) or 1);
}
t/40nulls.t view on Meta::CPAN
#
# Test whether or not a field containing a NULL is returned correctly
# as undef, or something much more bizarre
#
Test($state or $dbh->do("INSERT INTO $table VALUES"
. " ( NULL, 'NULL-valued id' )"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE " . IsNull("id")))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($rv = $cursor->fetchrow_arrayref) or $dbdriver eq 'CSV'
or $dbdriver eq 'ConfFile')
or DbiError($dbh->err, $dbh->errstr);
Test($state or (!defined($$rv[0]) and defined($$rv[1])) or
$dbdriver eq 'CSV' or $dbdriver eq 'ConfFile')
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->finish)
or DbiError($dbh->err, $dbh->errstr);
Test($state or undef $cursor || 1);
#
# Finally drop the test table.
#
Test($state or $dbh->do("DROP TABLE $table"))
or DbiError($dbh->err, $dbh->errstr);
}
t/40numrows.t view on Meta::CPAN
# This section should exercise the sth->rows
# method by preparing a statement, then finding the
# number of rows within it.
# Prior to execution, this should fail. After execution, the
# number of rows affected by the statement will be returned.
#
Test($state or $dbh->do("INSERT INTO $table"
. " VALUES( 1, 'Alligator Descartes' )"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE id = 1")))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($numrows = TrueRows($cursor)) == 1)
or ErrMsgF("Expected to fetch 1 rows, got %s.\n", $numrows);
Test($state or $cursor->finish)
or DbiError($dbh->err, $dbh->errstr);
Test($state or undef $cursor or 1);
Test($state or $dbh->do("INSERT INTO $table"
. " VALUES( 2, 'Jochen Wiedmann' )"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE id >= 1")))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($numrows = TrueRows($cursor)) == 2)
or ErrMsgF("Expected to fetch 2 rows, got %s.\n", $numrows);
Test($state or $cursor->finish)
or DbiError($dbh->err, $dbh->errstr);
Test($state or undef $cursor or 1);
Test($state or $dbh->do("INSERT INTO $table"
. " VALUES(3, 'Tim Bunce')"))
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($cursor = $dbh->prepare("SELECT * FROM $table"
. " WHERE id >= 2")))
or DbiError($dbh->err, $dbh->errstr);
Test($state or $cursor->execute)
or DbiError($dbh->err, $dbh->errstr);
Test($state or ($numrows = TrueRows($cursor)) == 2)
or ErrMsgF("Expected to fetch 2 rows, got %s.\n", $numrows);
# RT #16451 fetchrow() is called again after it has returned an
# empty list
Test($state or !TrueRows($cursor))
or ErrMsgF("Expected to fetch 0 rows\n");
Test($state or $cursor->finish)
or DbiError($dbh->err, $dbh->errstr);
Test($state or undef $cursor or 1);
#
# Finally drop the test table.
#
Test($state or $dbh->do("DROP TABLE $table"))
or DbiError($dbh->err, $dbh->errstr);
}
return 0;
}
/*
** This is called to code FOR EACH ROW triggers.
**
** When the code that this function generates is executed, the following
** must be true:
**
** 1. No cursors may be open in the main database. (But newIdx and oldIdx
** can be indices of cursors in temporary tables. See below.)
**
** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
** a temporary vdbe cursor (index newIdx) must be open and pointing at
** a row containing values to be substituted for new.* expressions in the
** trigger program(s).
**
** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
** a temporary vdbe cursor (index oldIdx) must be open and pointing at
** a row containing values to be substituted for old.* expressions in the
** trigger program(s).
**
*/
int sqliteCodeRowTrigger(
Parse *pParse, /* Parse context */
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
int tr_tm, /* One of TK_BEFORE, TK_AFTER */
Table *pTab, /* The table to code triggers from */
}
if( isView ){
if( sqliteViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
}
aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* If there are FOR EACH ROW triggers, allocate cursors for the
** special OLD and NEW tables
*/
if( row_triggers_exist ){
newIdx = pParse->nTab++;
oldIdx = pParse->nTab++;
}
/* Allocate a cursors for the main database table and for all indices.
** The index cursors might not be used, but if they are used they
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
pTabList->a[0].iCursor = iCur = pParse->nTab++;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
pParse->nTab++;
}
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
/* The top of the update loop for when there are triggers.
*/
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
}
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
/* Generate the OLD table
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum);
assert( pParse->nTab>iCur+i+1 );
}
}
/* Loop over every record that needs updating. We have to load
** the old data for each record to be updated because some columns
** might not change and we will need to copy the old value.
** Also, the old data is needed to delete the old index entires.
** So make the cursor point at the old record.
*/
if( !row_triggers_exist ){
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
}
sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
/* If the record number will change, push the record number as it
** will be after the update. (The old record number is currently
*/
sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
}
/* Increment the row counter
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
}
/* If there are triggers, close all the cursors after each iteration
** through the loop. The fire the after triggers.
*/
if( row_triggers_exist ){
if( !isView ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] )
sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"
/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode. The test
** procedures use this information to make sure that indices are
** working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
int sqlite_search_count = 0;
/*
** When this global variable is positive, it gets decremented once before
** each instruction in the VDBE. When reaches zero, the SQLITE_Interrupt
i++;
break;
}
}
zBuf[i] = 0;
return i>0 ? zBuf : 0;
}
/*
** Make sure there is space in the Vdbe structure to hold at least
** mxCursor cursors. If there is not currently enough space, then
** allocate more.
**
** If a memory allocation error occurs, return 1. Return 0 if
** everything works.
*/
static int expandCursorArraySize(Vdbe *p, int mxCursor){
if( mxCursor>=p->nCursor ){
Cursor *aCsr = sqliteRealloc( p->aCsr, (mxCursor+1)*sizeof(Cursor) );
if( aCsr==0 ) return 1;
p->aCsr = aCsr;
p->rc = SQLITE_INTERNAL;
return SQLITE_ERROR;
}
p->returnDepth--;
pc = p->returnStack[p->returnDepth] - 1;
break;
}
/* Opcode: Halt P1 P2 *
**
** Exit immediately. All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite_exec(). For a normal
** halt, this should be SQLITE_OK (0). For errors, it can be some
** other value. If P1!=0 then P2 will determine whether or not to
** rollback the current transaction. Do not rollback if P2==OE_Fail.
** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back
** out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
p->undoTransOnError = 1;
break;
}
/* Opcode: Commit * * *
**
** Cause all modifications to the database that have been made since the
** last Transaction to actually take effect. No additional modifications
** are allowed until another transaction is started. The Commit instruction
** deletes the journal file and releases the write lock on the database.
** A read lock continues to be held if there are still cursors open.
*/
case OP_Commit: {
int i;
if( db->xCommitCallback!=0 ){
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
if( db->xCommitCallback(db->pCommitArg)!=0 ){
rc = SQLITE_CONSTRAINT;
}
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
}
**
** Cause all modifications to the database that have been made since the
** last Transaction to be undone. The database is restored to its state
** before the Transaction opcode was executed. No additional modifications
** are allowed until another transaction is started.
**
** P1 is the index of the database file that is committed. An index of 0
** is used for the main database and an index of 1 is used for the file used
** to hold temporary tables.
**
** This instruction automatically closes all cursors and releases both
** the read and write locks on the indicated database.
*/
case OP_Rollback: {
sqliteRollbackAll(db);
break;
}
/* Opcode: ReadCookie P1 P2 *
**
** Read cookie number P2 from database P1 and push it onto the stack.
** P2==0 is the schema version. P2==1 is the database format.
** P2==2 is the recommended pager cache size, and so forth. P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be an open cursor) before
** executing this instruction.
*/
case OP_ReadCookie: {
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
pTos++;
pTos->i = aMeta[1+pOp->p2];
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK && aMeta[1]!=pOp->p2 ){
sqliteSetString(&p->zErrMsg, "database schema has changed", (char*)0);
rc = SQLITE_SCHEMA;
}
break;
}
/* Opcode: OpenRead P1 P2 P3
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file. The database file is determined by an
** integer from the top of the stack. 0 means the main database and
** 1 means the database used for temporary tables. Give the new
** cursor an identifier of P1. The P1 values need not be contiguous
** but all P1 values should be small integers. It is an error for
** P1 to be negative.
**
** If P2==0 then take the root page number from the next of the stack.
**
** There will be a read lock on the database whenever there is an
** open cursor. If the database was unlocked prior to this instruction
** then a read lock is acquired as part of this instruction. A read
** lock allows other processes to read the database but prohibits
** any other process from modifying the database. The read lock is
** released when all cursors are closed. If this instruction attempts
** to get a read lock but fails, the script terminates with an
** SQLITE_BUSY error code.
**
** The P3 value is the name of the table or index being opened.
** The P3 value is not actually used by this opcode and may be
** omitted. But the code generator usually inserts the index or
** table name into P3 to make the code easier to read.
**
** See also OpenWrite.
*/
/* Opcode: OpenWrite P1 P2 P3
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2. If P2==0 then take the root page number from the stack.
**
** The P3 value is the name of the table or index being opened.
** The P3 value is not actually used by this opcode and may be
** omitted. But the code generator usually inserts the index or
** table name into P3 to make the code easier to read.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode. For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
**
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
int busy = 0;
int i = pOp->p1;
int p2 = pOp->p2;
int wrFlag;
Btree *pX;
default: {
goto abort_due_to_error;
}
}
}while( busy );
break;
}
/* Opcode: OpenTemp P1 P2 *
**
** Open a new cursor to a transient table.
** The transient cursor is always opened read/write even if
** the main database is read-only. The transient table is deleted
** automatically when the cursor is closed.
**
** The cursor points to a BTree table if P2==0 and to a BTree index
** if P2==1. A BTree table must have an integer key and can have arbitrary
** data. A BTree index has no data but can have an arbitrary key.
**
** This opcode is used for tables that exist for the duration of a single
** SQL statement only. Tables created using CREATE TEMPORARY TABLE
** are opened using OP_OpenRead or OP_OpenWrite. "Temporary" in the
** context of this opcode means for the duration of a single SQL statement
** whereas "Temporary" in the context of CREATE TABLE means for the duration
** of the connection to the database. Same word; different meanings.
*/
}
}else{
rc = sqliteBtreeCursor(pCx->pBt, 2, 1, &pCx->pCursor);
}
}
break;
}
/* Opcode: OpenPseudo P1 * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data. Any attempt to write a second row of data causes the
** first row to be deleted. All data is deleted when the cursor is
** closed.
**
** A pseudo-table created by this opcode is useful for holding the
** NEW or OLD tables in a trigger.
*/
case OP_OpenPseudo: {
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
pCx->nullRow = 1;
pCx->pseudoTable = 1;
break;
}
/* Opcode: Close P1 * *
**
** Close a cursor previously opened as P1. If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
int i = pOp->p1;
if( i>=0 && i<p->nCursor ){
sqliteVdbeCleanupCursor(&p->aCsr[i]);
}
break;
}
/* Opcode: MoveTo P1 P2 *
**
** Pop the top of the stack and use its value as a key. Reposition
** cursor P1 so that it points to an entry with a matching key. If
** the table contains no record with a matching key, then the cursor
** is left pointing at the first record that is greater than the key.
** If there are no records greater than the key and P2 is not zero,
** then an immediate jump to P2 is made.
**
** See also: Found, NotFound, Distinct, MoveLt
*/
/* Opcode: MoveLt P1 P2 *
**
** Pop the top of the stack and use its value as a key. Reposition
** cursor P1 so that it points to the entry with the largest key that is
** less than the key popped from the stack.
** If there are no records less than than the key and P2
** is not zero then an immediate jump to P2 is made.
**
** See also: MoveTo
*/
case OP_MoveLt:
case OP_MoveTo: {
int i = pOp->p1;
Cursor *pC;
}
}
Release(pTos);
pTos--;
break;
}
/* Opcode: Distinct P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key does
** not exist in the table of cursor P1, then jump to P2. If the record
** does already exist, then fall thru. The cursor is left pointing
** at the record if it exists. The key is not popped from the stack.
**
** This operation is similar to NotFound except that this operation
** does not pop the key from the stack.
**
** See also: Found, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: Found P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does exist in table of P1, then jump to P2. If the record
** does not exist, then fall thru. The cursor is left pointing
** to the record if it exists. The key is popped from the stack.
**
** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The key is popped from the stack.
**
** The difference between this operation and Distinct is that
** Distinct does not pop the key from the stack.
**
** See also: Distinct, Found, MoveTo, NotExists, IsUnique
*/
case OP_Distinct:
case OP_NotFound:
case OP_Found: {
pTos->i = v;
pTos->flags = MEM_Int;
}
break;
}
/* Opcode: NotExists P1 P2 *
**
** Use the top of the stack as a integer key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The integer key is popped from the stack.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and NotFound assumes it
** is a string.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {
int i = pOp->p1;
}
Release(pTos);
pTos--;
break;
}
/* Opcode: NewRecno P1 * *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is pushed
** onto the stack.
*/
case OP_NewRecno: {
int i = pOp->p1;
int v = 0;
Cursor *pC;
assert( i>=0 && i<p->nCursor );
if( (pC = &p->aCsr[i])->pCursor==0 ){
v = 0;
}else{
pC->deferredMoveto = 0;
}
pTos++;
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: PutIntKey P1 P2 *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** stack. The key is the next value down on the stack. The key must
** be an integer. The stack is popped twice by this instruction.
**
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set,
** then the current statement change count is incremented (otherwise not).
** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is
** stored for subsequent return by the sqlite_last_insert_rowid() function
** (otherwise it's unmodified).
*/
/* Opcode: PutStrKey P1 * *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** stack. The key is the next value down on the stack. The key must
** be a string. The stack is popped twice by this instruction.
**
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
*/
case OP_PutIntKey:
case OP_PutStrKey: {
Mem *pNos = &pTos[-1];
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
popStack(&pTos, 2);
break;
}
/* Opcode: Delete P1 P2 *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op. Hence it is OK to delete
** a record from within an Next loop.
**
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set,
** then the current statement change count is incremented (otherwise not).
**
** If P1 is a pseudo-table, then this instruction is a no-op.
*/
** and resets csChange (current statement change count) to 0.
*/
case OP_SetCounts: {
db->lsChange=db->csChange;
db->csChange=0;
break;
}
/* Opcode: KeyAsData P1 P2 *
**
** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
** data off of the key rather than the data. This is used for
** processing compound selects.
*/
case OP_KeyAsData: {
int i = pOp->p1;
assert( i>=0 && i<p->nCursor );
p->aCsr[i].keyAsData = pOp->p2;
break;
}
/* Opcode: RowData P1 * *
**
** Push onto the stack the complete row data for cursor P1.
** There is no interpretation of the data. It is just copied
** onto the stack exactly as it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
/* Opcode: RowKey P1 * *
**
** Push onto the stack the complete row key for cursor P1.
** There is no interpretation of the key. It is just copied
** onto the stack exactly as it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
Cursor *pC;
int n;
pTos++;
assert( i>=0 && i<p->nCursor );
pTos->z = pC->pData;
pTos->flags = MEM_Str|MEM_Ephem;
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as
** a structure built using the MakeRecord instruction.
** (See the MakeRecord opcode for additional information about
** the format of the data.)
** Push onto the stack the value of the P2-th column contained
** in the data.
**
** If the KeyAsData opcode has previously executed on this cursor,
** then the field might be extracted from the key rather than the
** data.
**
** If P1 is negative, then the record is stored on the stack rather
** than in a table. For P1==-1, the top of the stack is used.
** For P1==-2, the next on the stack is used. And so forth. The
** value pushed is always just a pointer into the record which is
** stored further down on the stack. The column value is not copied.
*/
case OP_Column: {
sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v);
v = keyToInt(v);
}
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: FullKey P1 * *
**
** Extract the complete key from the record that cursor P1 is currently
** pointing to and push the key onto the stack as a string.
**
** Compare this opcode to Recno. The Recno opcode extracts the first
** 4 bytes of the key and pushes those bytes onto the stack as an
** integer. This instruction pushes the entire key as a string.
**
** This opcode may not be used on a pseudo-table.
*/
case OP_FullKey: {
int i = pOp->p1;
}
sqliteBtreeKey(pCrsr, 0, amt, z);
pTos->z = z;
pTos->n = amt;
}
break;
}
/* Opcode: NullRow P1 * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always push
** a NULL onto the stack.
*/
case OP_NullRow: {
int i = pOp->p1;
assert( i>=0 && i<p->nCursor );
p->aCsr[i].nullRow = 1;
p->aCsr[i].recnoIsValid = 0;
break;
}
pc = pOp->p2 - 1;
}
}else{
pC->nullRow = 0;
}
break;
}
/* Opcode: Next P1 P2 *
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
** to the following instruction. But if the cursor advance was successful,
** jump immediately to P2.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 *
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
** to the following instruction. But if the cursor backup was successful,
** jump immediately to P2.
*/
case OP_Prev:
case OP_Next: {
Cursor *pC;
BtCursor *pCrsr;
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = &p->aCsr[pOp->p1];
}
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: IdxGT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is greater than the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
/* Opcode: IdxGE P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is greater than or equal to
** the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
/* Opcode: IdxLT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is less than the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
int i= pOp->p1;
BtCursor *pCrsr;
** of the following structure.
*/
typedef struct VdbeOp Op;
/*
** Boolean values
*/
typedef unsigned char Bool;
/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
** loop over all entries of the Btree. You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
**
** If the Cursor.isTriggerRow flag is set it means that this cursor is
** really a single row that represents the NEW or OLD pseudo-table of
** a row trigger. The data for the row is stored in Cursor.pData and
** the rowid is in Cursor.iKey.
*/
struct Cursor {
BtCursor *pCursor; /* The cursor structure of the backend */
int lastRecno; /* Last recno from a Next or NextIdx operation */
int nextRowid; /* Next rowid returned by OP_NewRowid */
Bool recnoIsValid; /* True if lastRecno is valid */
Bool keyAsData; /* The OP_Column command works on key instead of data */
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 deferredMoveto; /* A call to sqliteBtreeMoveto() is needed */
int nOpAlloc; /* Number of slots allocated for aOp[] */
Op *aOp; /* Space to hold the virtual machine's program */
int nLabel; /* Number of labels used */
int nLabelAlloc; /* Number of slots allocated in aLabel[] */
int *aLabel; /* Space to hold the labels */
Mem *aStack; /* The operand stack, except string values */
Mem *pTos; /* Top entry in the operand stack */
char **zArgv; /* Text values used by the callback */
char **azColName; /* Becomes the 4th parameter to callbacks */
int nCursor; /* Number of slots in aCsr[] */
Cursor *aCsr; /* One element of this array for each open cursor */
Sorter *pSort; /* A linked list of objects to be sorted */
FILE *pFile; /* At most one open file handler */
int nField; /* Number of file fields */
char **azField; /* Data for each file field */
int nVar; /* Number of entries in azVariable[] */
char **azVar; /* Values for the OP_Variable opcode */
int *anVar; /* Length of each value in azVariable[] */
u8 *abVar; /* TRUE if azVariable[i] needs to be sqliteFree()ed */
char *zLine; /* A single line from the input file */
int nLineAlloc; /* Number of spaces allocated for zLine */
*/
void sqliteVdbeKeylistFree(Keylist *p){
while( p ){
Keylist *pNext = p->pNext;
sqliteFree(p);
p = pNext;
}
}
/*
** Close a cursor and release all the resources that cursor happens
** to hold.
*/
void sqliteVdbeCleanupCursor(Cursor *pCx){
if( pCx->pCursor ){
sqliteBtreeCloseCursor(pCx->pCursor);
}
if( pCx->pBt ){
sqliteBtreeClose(pCx->pBt);
}
sqliteFree(pCx->pData);
memset(pCx, 0, sizeof(Cursor));
}
/*
** Close all cursors
*/
static void closeAllCursors(Vdbe *p){
int i;
for(i=0; i<p->nCursor; i++){
sqliteVdbeCleanupCursor(&p->aCsr[i]);
}
sqliteFree(p->aCsr);
p->aCsr = 0;
p->nCursor = 0;
}
/*
** Clean up the VM after execution.
**
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open. It also deletes the values of
** variables in the azVariable[] array.
*/
static void Cleanup(Vdbe *p){
int i;
if( p->aStack ){
Mem *pTos = p->pTos;
while( pTos>=p->aStack ){
if( pTos->flags & MEM_Dyn ){
sqliteFree(pTos->z);
int i;
} ux;
ux.zBuf[3] = x&0xff;
ux.zBuf[2] = (x>>8)&0xff;
ux.zBuf[1] = (x>>16)&0xff;
ux.zBuf[0] = (x>>24)&0xff;
return ux.i;
}
/*
** If a MoveTo operation is pending on the given cursor, then do that
** MoveTo now. Return an error code. If no MoveTo is pending, this
** routine does nothing and returns SQLITE_OK.
*/
int sqliteVdbeCursorMoveto(Cursor *p){
if( p->deferredMoveto ){
int res;
extern int sqlite_search_count;
sqliteBtreeMoveto(p->pCursor, (char*)&p->movetoTarget, sizeof(int), &res);
p->lastRecno = keyToInt(p->movetoTarget);
p->recnoIsValid = res==0;
** p->pLeft is not the column of any table */
short int idxRight; /* p->pRight is a column in this table number. -1 if
** p->pRight is not the column of any table */
unsigned prereqLeft; /* Bitmask of tables referenced by p->pLeft */
unsigned prereqRight; /* Bitmask of tables referenced by p->pRight */
unsigned prereqAll; /* Bitmask of tables referenced by p */
};
/*
** An instance of the following structure keeps track of a mapping
** between VDBE cursor numbers and bitmasks. The VDBE cursor numbers
** are small integers contained in SrcList_item.iCursor and Expr.iTable
** fields. For any given WHERE clause, we want to track which cursors
** are being used, so we assign a single bit in a 32-bit word to track
** that cursor. Then a 32-bit integer is able to show the set of all
** cursors being used.
*/
typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
int n; /* Number of assigned cursor values */
int ix[31]; /* Cursor assigned to each bit */
};
/*
** Determine the number of elements in an array.
*/
#define ARRAYSIZE(X) (sizeof(X)/sizeof(X[0]))
/*
** This routine is used to divide the WHERE expression into subexpressions
}
return cnt;
}
/*
** Initialize an expression mask set
*/
#define initMaskSet(P) memset(P, 0, sizeof(*P))
/*
** Return the bitmask for the given cursor. Assign a new bitmask
** if this is the first time the cursor has been seen.
*/
static int getMask(ExprMaskSet *pMaskSet, int iCursor){
int i;
for(i=0; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ) return 1<<i;
}
if( i==pMaskSet->n && i<ARRAYSIZE(pMaskSet->ix) ){
pMaskSet->n++;
pMaskSet->ix[i] = iCursor;
return 1<<i;
/*
** This routine walks (recursively) an expression tree and generates
** a bitmask indicating which tables are used in that expression
** tree.
**
** In order for this routine to work, the calling function must have
** previously invoked sqliteExprResolveIds() on the expression. See
** the header comment on that routine for additional information.
** The sqliteExprResolveIds() routines looks for column names and
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table.
*/
static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
unsigned int mask = 0;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
mask = getMask(pMaskSet, p->iTable);
if( mask==0 ) mask = -1;
return mask;
}
if( p->pRight ){
if( pExpr->pLeft->op==TK_COLUMN ){
pInfo->idxLeft = pExpr->pLeft->iTable;
pInfo->indexable = 1;
}
}
}
/*
** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the
** left-most table in the FROM clause of that same SELECT statement and
** the table has a cursor number of "base".
**
** This routine attempts to find an index for pTab that generates the
** correct record sequence for the given ORDER BY clause. The return value
** is a pointer to an index that does the job. NULL is returned if the
** table has no index that will generate the correct sort order.
**
** If there are two or more indices that generate the correct sort order
** and pPreferredIdx is one of those indices, then return pPreferredIdx.
**
** nEqCol is the number of columns of pPreferredIdx that are used as
** Then the code generated is conceptually like the following:
**
** foreach row1 in t1 do \ Code generated
** foreach row2 in t2 do |-- by sqliteWhereBegin()
** foreach row3 in t3 do /
** ...
** end \ Code generated
** end |-- by sqliteWhereEnd()
** end /
**
** There are Btree cursors associated with each table. t1 uses cursor
** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor.
** And so forth. This routine generates code to open those VDBE cursors
** and sqliteWhereEnd() generates the code to close them.
**
** If the WHERE clause is empty, the foreach loops must each scan their
** entire tables. Thus a three-way join is an O(N^3) operation. But if
** the tables have indices and there are terms in the WHERE clause that
** refer to those indices, a complete table scan can be avoided and the
** code will run much faster. Most of the work of this routine is checking
** to see if there are indices that can be used to speed up the loop.
**
** Terms of the WHERE clause are also used to limit which rows actually
** An outer join of tables t1 and t2 is conceptally coded as follows:
**
** foreach row1 in t1 do
** flag = 0
** foreach row2 in t2 do
** start:
** ...
** flag = 1
** end
** if flag==0 then
** move the row2 cursor to a null row
** goto start
** fi
** end
**
** ORDER BY CLAUSE PROCESSING
**
** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
** if there is one. If there is no ORDER BY clause or if this routine
** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
**
** index which requires reading an index first to get the rowid then
** doing a second read of the actual database table.
**
** Actually, if there are more than 32 tables in the join, only the
** first 32 tables are candidates for indices. This is (again) due
** to the limit of 32 bits in an integer bitmask.
*/
loopMask = 0;
for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++){
int j;
int iCur = pTabList->a[i].iCursor; /* The cursor for this table */
int mask = getMask(&maskSet, iCur); /* Cursor mask for this table */
Table *pTab = pTabList->a[i].pTab;
Index *pIdx;
Index *pBestIdx = 0;
int bestScore = 0;
/* Check to see if there is an expression that uses only the
** ROWID field of this table. For terms of the form ROWID==expr
** set iDirectEq[i] to the index of the term. For terms of the
** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index.
for(i=0; i<pTabList->nSrc; i++){
Table *pTab = pTabList->a[i].pTab;
assert( pTab!=0 );
if( pTab->isTransient || pTab->pSelect ) continue;
pLevel = &pWInfo->a[i];
sqliteVdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);
if( pLevel->pIdx!=0 ){
sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0);
}
}
#if 0 /* Never reuse a cursor */
if( pWInfo->pParse->nTab==pWInfo->peakNTab ){
pWInfo->pParse->nTab = pWInfo->savedNTab;
}
#endif
sqliteFree(pWInfo);
return;
}
( run in 0.444 second using v1.01-cache-2.11-cpan-4d50c553e7e )