mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Optimize queries of the form "SELECT count(*) FROM <tbl>" by adding a sqlite3BtreeCount() interface to the btree layer. (CVS 6316)
FossilOrigin-Name: d4aa6593183224b6868a322511511c0bbf63b598
This commit is contained in:
71
src/btree.c
71
src/btree.c
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.566 2009/02/18 20:31:18 drh Exp $
|
||||
** $Id: btree.c,v 1.567 2009/02/24 10:01:52 danielk1977 Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
@@ -6751,6 +6751,75 @@ int sqlite3BtreeFlags(BtCursor *pCur){
|
||||
return pPage->aData[pPage->hdrOffset];
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_BTREECOUNT
|
||||
/*
|
||||
** The first argument, pCur, is a cursor opened on some b-tree. Count the
|
||||
** number of entries in the b-tree and write the result to *pnEntry.
|
||||
**
|
||||
** SQLITE_OK is returned if the operation is successfully executed.
|
||||
** Otherwise, if an error is encountered (i.e. an IO error or database
|
||||
** corruption) an SQLite error code is returned.
|
||||
*/
|
||||
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
|
||||
i64 nEntry = 0; /* Value to return in *pnEntry */
|
||||
int rc; /* Return code */
|
||||
rc = moveToRoot(pCur);
|
||||
|
||||
/* Unless an error occurs, the following loop runs one iteration for each
|
||||
** page in the B-Tree structure (not including overflow pages).
|
||||
*/
|
||||
while( rc==SQLITE_OK ){
|
||||
int iIdx; /* Index of child node in parent */
|
||||
MemPage *pPage; /* Current page of the b-tree */
|
||||
|
||||
/* If this is a leaf page or the tree is not an int-key tree, then
|
||||
** this page contains countable entries. Increment the entry counter
|
||||
** accordingly.
|
||||
*/
|
||||
pPage = pCur->apPage[pCur->iPage];
|
||||
if( pPage->leaf || !pPage->intKey ){
|
||||
nEntry += pPage->nCell;
|
||||
}
|
||||
|
||||
/* pPage is a leaf node. This loop navigates the cursor so that it
|
||||
** points to the first interior cell that it points to the parent of
|
||||
** the next page in the tree that has not yet been visited. The
|
||||
** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
|
||||
** of the page, or to the number of cells in the page if the next page
|
||||
** to visit is the right-child of its parent.
|
||||
**
|
||||
** If all pages in the tree have been visited, return SQLITE_OK to the
|
||||
** caller.
|
||||
*/
|
||||
if( pPage->leaf ){
|
||||
do {
|
||||
if( pCur->iPage==0 ){
|
||||
/* All pages of the b-tree have been visited. Return successfully. */
|
||||
*pnEntry = nEntry;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
sqlite3BtreeMoveToParent(pCur);
|
||||
}while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
|
||||
|
||||
pCur->aiIdx[pCur->iPage]++;
|
||||
pPage = pCur->apPage[pCur->iPage];
|
||||
}
|
||||
|
||||
/* Descend to the child node of the cell that the cursor currently
|
||||
** points at. This is the right-child if (iIdx==pPage->nCell).
|
||||
*/
|
||||
iIdx = pCur->aiIdx[pCur->iPage];
|
||||
if( iIdx==pPage->nCell ){
|
||||
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
|
||||
}else{
|
||||
rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
/* An error has occured. Return an error code. */
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the pager associated with a BTree. This routine is used for
|
||||
|
Reference in New Issue
Block a user