mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Simplify the BTree interface by shortening names. Added two new methods
for accessing the current filename and for changing the name of the database file. (CVS 900) FossilOrigin-Name: 185d8dc8d0c26cef36aeba6992823e5124af4056
This commit is contained in:
27
src/btree.c
27
src/btree.c
@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.86 2003/04/01 21:16:42 paul Exp $
|
||||
** $Id: btree.c,v 1.87 2003/04/06 20:44:45 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@ -3495,6 +3495,27 @@ char *sqliteBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
|
||||
return sCheck.zErrMsg;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the full pathname of the underlying database file.
|
||||
*/
|
||||
static const char *sqliteBtreeGetFilename(Btree *pBt){
|
||||
assert( pBt->pPager!=0 );
|
||||
return sqlitepager_filename(pBt->pPager);
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the name of the underlying database file.
|
||||
*/
|
||||
static int sqliteBtreeChangeFilename(Btree *pBt, const char *zNew){
|
||||
return sqlitepager_rename(pBt->pPager, zNew);
|
||||
}
|
||||
|
||||
/*
|
||||
** The following tables contain pointers to all of the interface
|
||||
** routines for this implementation of the B*Tree backend. To
|
||||
** substitute a different implemention of the backend, one has merely
|
||||
** to provide pointers to alternative functions in similar tables.
|
||||
*/
|
||||
static BtOps sqliteBtreeOps = {
|
||||
sqliteBtreeClose,
|
||||
sqliteBtreeSetCacheSize,
|
||||
@ -3513,13 +3534,13 @@ static BtOps sqliteBtreeOps = {
|
||||
sqliteBtreeGetMeta,
|
||||
sqliteBtreeUpdateMeta,
|
||||
sqliteBtreeIntegrityCheck,
|
||||
|
||||
sqliteBtreeGetFilename,
|
||||
sqliteBtreeChangeFilename,
|
||||
#ifdef SQLITE_TEST
|
||||
sqliteBtreePageDump,
|
||||
sqliteBtreePager
|
||||
#endif
|
||||
};
|
||||
|
||||
static BtCursorOps sqliteBtreeCursorOps = {
|
||||
sqliteBtreeMoveto,
|
||||
sqliteBtreeDelete,
|
||||
|
216
src/btree.h
216
src/btree.h
@ -13,69 +13,85 @@
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.29 2003/04/01 21:16:43 paul Exp $
|
||||
** @(#) $Id: btree.h,v 1.30 2003/04/06 20:44:45 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
|
||||
/*
|
||||
** Forward declarations of structure
|
||||
*/
|
||||
typedef struct Btree Btree;
|
||||
typedef struct BtCursor BtCursor;
|
||||
|
||||
struct BtOps {
|
||||
int (*sqliteBtreeClose)(Btree*);
|
||||
int (*sqliteBtreeSetCacheSize)(Btree*, int);
|
||||
int (*sqliteBtreeSetSafetyLevel)(Btree*, int);
|
||||
|
||||
int (*sqliteBtreeBeginTrans)(Btree*);
|
||||
int (*sqliteBtreeCommit)(Btree*);
|
||||
int (*sqliteBtreeRollback)(Btree*);
|
||||
int (*sqliteBtreeBeginCkpt)(Btree*);
|
||||
int (*sqliteBtreeCommitCkpt)(Btree*);
|
||||
int (*sqliteBtreeRollbackCkpt)(Btree*);
|
||||
|
||||
int (*sqliteBtreeCreateTable)(Btree*, int*);
|
||||
int (*sqliteBtreeCreateIndex)(Btree*, int*);
|
||||
int (*sqliteBtreeDropTable)(Btree*, int);
|
||||
int (*sqliteBtreeClearTable)(Btree*, int);
|
||||
|
||||
int (*sqliteBtreeCursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
|
||||
|
||||
int (*sqliteBtreeGetMeta)(Btree*, int*);
|
||||
int (*sqliteBtreeUpdateMeta)(Btree*, int*);
|
||||
|
||||
char *(*sqliteBtreeIntegrityCheck)(Btree*, int*, int);
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
int (*sqliteBtreePageDump)(Btree*, int, int);
|
||||
struct Pager * (*sqliteBtreePager)(Btree*);
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct BtOps BtOps;
|
||||
|
||||
struct BtCursorOps {
|
||||
int (*sqliteBtreeMoveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
|
||||
int (*sqliteBtreeDelete)(BtCursor*);
|
||||
int (*sqliteBtreeInsert)(BtCursor*, const void *pKey, int nKey,
|
||||
const void *pData, int nData);
|
||||
int (*sqliteBtreeFirst)(BtCursor*, int *pRes);
|
||||
int (*sqliteBtreeLast)(BtCursor*, int *pRes);
|
||||
int (*sqliteBtreeNext)(BtCursor*, int *pRes);
|
||||
int (*sqliteBtreePrevious)(BtCursor*, int *pRes);
|
||||
int (*sqliteBtreeKeySize)(BtCursor*, int *pSize);
|
||||
int (*sqliteBtreeKey)(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int (*sqliteBtreeKeyCompare)(BtCursor*, const void *pKey, int nKey,
|
||||
int nIgnore, int *pRes);
|
||||
int (*sqliteBtreeDataSize)(BtCursor*, int *pSize);
|
||||
int (*sqliteBtreeData)(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int (*sqliteBtreeCloseCursor)(BtCursor*);
|
||||
#ifdef SQLITE_TEST
|
||||
int (*sqliteBtreeCursorDump)(BtCursor*, int*);
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct BtCursorOps BtCursorOps;
|
||||
|
||||
|
||||
/*
|
||||
** An instance of the following structure contains pointers to all
|
||||
** methods against an open BTree. Alternative BTree implementations
|
||||
** (examples: file based versus in-memory) can be created by substituting
|
||||
** different methods. Users of the BTree cannot tell the difference.
|
||||
**
|
||||
** In C++ we could do this by defining a virtual base class and then
|
||||
** creating subclasses for each different implementation. But this is
|
||||
** C not C++ so we have to be a little more explicit.
|
||||
*/
|
||||
struct BtOps {
|
||||
int (*Close)(Btree*);
|
||||
int (*SetCacheSize)(Btree*, int);
|
||||
int (*SetSafetyLevel)(Btree*, int);
|
||||
int (*BeginTrans)(Btree*);
|
||||
int (*Commit)(Btree*);
|
||||
int (*Rollback)(Btree*);
|
||||
int (*BeginCkpt)(Btree*);
|
||||
int (*CommitCkpt)(Btree*);
|
||||
int (*RollbackCkpt)(Btree*);
|
||||
int (*CreateTable)(Btree*, int*);
|
||||
int (*CreateIndex)(Btree*, int*);
|
||||
int (*DropTable)(Btree*, int);
|
||||
int (*ClearTable)(Btree*, int);
|
||||
int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
|
||||
int (*GetMeta)(Btree*, int*);
|
||||
int (*UpdateMeta)(Btree*, int*);
|
||||
char *(*IntegrityCheck)(Btree*, int*, int);
|
||||
const char *(*GetFilename)(Btree*);
|
||||
int (*ChangeFilename)(Btree*, const char *zNew);
|
||||
#ifdef SQLITE_TEST
|
||||
int (*PageDump)(Btree*, int, int);
|
||||
struct Pager *(*Pager)(Btree*);
|
||||
#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);
|
||||
int (*KeySize)(BtCursor*, int *pSize);
|
||||
int (*Key)(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int (*KeyCompare)(BtCursor*, const void *pKey, int nKey,
|
||||
int nIgnore, int *pRes);
|
||||
int (*DataSize)(BtCursor*, int *pSize);
|
||||
int (*Data)(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int (*CloseCursor)(BtCursor*);
|
||||
#ifdef SQLITE_TEST
|
||||
int (*CursorDump)(BtCursor*, int*);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** The number of 4-byte "meta" values contained on the first page of each
|
||||
** database file.
|
||||
*/
|
||||
#define SQLITE_N_BTREE_META 10
|
||||
|
||||
int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
|
||||
@ -84,76 +100,58 @@ int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
|
||||
#define btOps(pBt) (*((BtOps **)(pBt)))
|
||||
#define btCOps(pCur) (*((BtCursorOps **)(pCur)))
|
||||
|
||||
#define sqliteBtreeClose(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeClose(pBt))
|
||||
#define sqliteBtreeSetCacheSize(pBt, sz)\
|
||||
(btOps(pBt)->sqliteBtreeSetCacheSize(pBt, sz))
|
||||
#define sqliteBtreeSetSafetyLevel(pBt, sl)\
|
||||
(btOps(pBt)->sqliteBtreeSetSafetyLevel(pBt, sl))
|
||||
#define sqliteBtreeBeginTrans(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeBeginTrans(pBt))
|
||||
#define sqliteBtreeCommit(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeCommit(pBt))
|
||||
#define sqliteBtreeRollback(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeRollback(pBt))
|
||||
#define sqliteBtreeBeginCkpt(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeBeginCkpt(pBt))
|
||||
#define sqliteBtreeCommitCkpt(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeCommitCkpt(pBt))
|
||||
#define sqliteBtreeRollbackCkpt(pBt)\
|
||||
(btOps(pBt)->sqliteBtreeRollbackCkpt(pBt))
|
||||
#define sqliteBtreeCreateTable(pBt, piTable)\
|
||||
(btOps(pBt)->sqliteBtreeCreateTable(pBt, piTable))
|
||||
#define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt))
|
||||
#define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz))
|
||||
#define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl))
|
||||
#define sqliteBtreeBeginTrans(pBt) (btOps(pBt)->BeginTrans(pBt))
|
||||
#define sqliteBtreeCommit(pBt) (btOps(pBt)->Commit(pBt))
|
||||
#define sqliteBtreeRollback(pBt) (btOps(pBt)->Rollback(pBt))
|
||||
#define sqliteBtreeBeginCkpt(pBt) (btOps(pBt)->BeginCkpt(pBt))
|
||||
#define sqliteBtreeCommitCkpt(pBt) (btOps(pBt)->CommitCkpt(pBt))
|
||||
#define sqliteBtreeRollbackCkpt(pBt) (btOps(pBt)->RollbackCkpt(pBt))
|
||||
#define sqliteBtreeCreateTable(pBt,piTable)\
|
||||
(btOps(pBt)->CreateTable(pBt,piTable))
|
||||
#define sqliteBtreeCreateIndex(pBt, piIndex)\
|
||||
(btOps(pBt)->sqliteBtreeCreateIndex(pBt, piIndex))
|
||||
#define sqliteBtreeDropTable(pBt, iTable)\
|
||||
(btOps(pBt)->sqliteBtreeDropTable(pBt, iTable))
|
||||
(btOps(pBt)->CreateIndex(pBt, piIndex))
|
||||
#define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable))
|
||||
#define sqliteBtreeClearTable(pBt, iTable)\
|
||||
(btOps(pBt)->sqliteBtreeClearTable(pBt, iTable))
|
||||
(btOps(pBt)->ClearTable(pBt, iTable))
|
||||
#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\
|
||||
(btOps(pBt)->sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur))
|
||||
(btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur))
|
||||
#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\
|
||||
(btCOps(pCur)->sqliteBtreeMoveto(pCur, pKey, nKey, pRes))
|
||||
#define sqliteBtreeDelete(pCur)\
|
||||
(btCOps(pCur)->sqliteBtreeDelete(pCur))
|
||||
(btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes))
|
||||
#define sqliteBtreeDelete(pCur) (btCOps(pCur)->Delete(pCur))
|
||||
#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \
|
||||
(btCOps(pCur)->sqliteBtreeInsert(pCur, pKey, nKey, pData, nData))
|
||||
#define sqliteBtreeFirst(pCur, pRes)\
|
||||
(btCOps(pCur)->sqliteBtreeFirst(pCur, pRes))
|
||||
#define sqliteBtreeLast(pCur, pRes)\
|
||||
(btCOps(pCur)->sqliteBtreeLast(pCur, pRes))
|
||||
#define sqliteBtreeNext(pCur, pRes)\
|
||||
(btCOps(pCur)->sqliteBtreeNext(pCur, pRes))
|
||||
#define sqliteBtreePrevious(pCur, pRes)\
|
||||
(btCOps(pCur)->sqliteBtreePrevious(pCur, pRes))
|
||||
#define sqliteBtreeKeySize(pCur, pSize)\
|
||||
(btCOps(pCur)->sqliteBtreeKeySize(pCur, pSize) )
|
||||
(btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData))
|
||||
#define sqliteBtreeFirst(pCur, pRes) (btCOps(pCur)->First(pCur, pRes))
|
||||
#define sqliteBtreeLast(pCur, pRes) (btCOps(pCur)->Last(pCur, pRes))
|
||||
#define sqliteBtreeNext(pCur, pRes) (btCOps(pCur)->Next(pCur, pRes))
|
||||
#define sqliteBtreePrevious(pCur, pRes) (btCOps(pCur)->Previous(pCur, pRes))
|
||||
#define sqliteBtreeKeySize(pCur, pSize) (btCOps(pCur)->KeySize(pCur, pSize) )
|
||||
#define sqliteBtreeKey(pCur, offset, amt, zBuf)\
|
||||
(btCOps(pCur)->sqliteBtreeKey(pCur, offset, amt, zBuf))
|
||||
(btCOps(pCur)->Key(pCur, offset, amt, zBuf))
|
||||
#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\
|
||||
(btCOps(pCur)->sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes))
|
||||
#define sqliteBtreeDataSize(pCur, pSize)\
|
||||
(btCOps(pCur)->sqliteBtreeDataSize(pCur, pSize))
|
||||
(btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes))
|
||||
#define sqliteBtreeDataSize(pCur, pSize) (btCOps(pCur)->DataSize(pCur, pSize))
|
||||
#define sqliteBtreeData(pCur, offset, amt, zBuf)\
|
||||
(btCOps(pCur)->sqliteBtreeData(pCur, offset, amt, zBuf))
|
||||
#define sqliteBtreeCloseCursor(pCur)\
|
||||
(btCOps(pCur)->sqliteBtreeCloseCursor(pCur))
|
||||
#define sqliteBtreeGetMeta(pBt, aMeta)\
|
||||
(btOps(pBt)->sqliteBtreeGetMeta(pBt, aMeta))
|
||||
#define sqliteBtreeUpdateMeta(pBt, aMeta)\
|
||||
(btOps(pBt)->sqliteBtreeUpdateMeta(pBt, aMeta))
|
||||
(btCOps(pCur)->Data(pCur, offset, amt, zBuf))
|
||||
#define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur))
|
||||
#define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta))
|
||||
#define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta))
|
||||
#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
|
||||
(btOps(pBt)->sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot))
|
||||
(btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
|
||||
#define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt))
|
||||
#define sqliteBtreeChangeFilename(pBt, zNew)\
|
||||
(btOps(pBt)->ChangeFilename(pBt, zNew))
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
#if !defined(SQLITE_NO_BTREE_DEFS)
|
||||
#define sqliteBtreePageDump(pBt, pgno, recursive)\
|
||||
(btOps(pBt)->sqliteBtreePageDump(pBt, pgno, recursive))
|
||||
(btOps(pBt)->PageDump(pBt, pgno, recursive))
|
||||
#define sqliteBtreeCursorDump(pCur, aResult)\
|
||||
(btCOps(pCur)->sqliteBtreeCursorDump(pCur, aResult))
|
||||
#define sqliteBtreePager(pBt)\
|
||||
(btOps(pBt)->sqliteBtreePager(pBt))
|
||||
(btCOps(pCur)->CursorDump(pCur, aResult))
|
||||
#define sqliteBtreePager(pBt) (btOps(pBt)->Pager(pBt))
|
||||
#endif
|
||||
|
||||
int btree_native_byte_order;
|
||||
|
2
src/os.c
2
src/os.c
@ -271,7 +271,7 @@ int sqliteOsFileExists(const char *zFilename){
|
||||
/*
|
||||
** Change the name of an existing file.
|
||||
*/
|
||||
int sqliteOsRename(const char *zOldName, const char *zNewName){
|
||||
int sqliteOsFileRename(const char *zOldName, const char *zNewName){
|
||||
#if OS_UNIX
|
||||
if( link(zOldName, zNewName) ){
|
||||
return SQLITE_ERROR;
|
||||
|
50
src/pager.c
50
src/pager.c
@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.79 2003/03/19 03:14:02 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.80 2003/04/06 20:44:45 drh Exp $
|
||||
*/
|
||||
#include "os.h" /* Must be first to enable large file support */
|
||||
#include "sqliteInt.h"
|
||||
@ -966,6 +966,10 @@ int sqlitepager_close(Pager *pPager){
|
||||
** }
|
||||
*/
|
||||
CLR_PAGER(pPager);
|
||||
if( pPager->zFilename!=(char*)&pPager[1] ){
|
||||
sqliteFree(pPager->zFilename);
|
||||
sqliteFree(pPager->zJournal);
|
||||
}
|
||||
sqliteFree(pPager);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -2026,6 +2030,50 @@ int sqlitepager_ckpt_rollback(Pager *pPager){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the full pathname of the database file.
|
||||
*/
|
||||
const char *sqlitepager_filename(Pager *pPager){
|
||||
return pPager->zFilename;
|
||||
}
|
||||
|
||||
/*
|
||||
** Rename the database file
|
||||
*/
|
||||
int sqlitepager_rename(Pager *pPager, const char *zNewName){
|
||||
char *zNew;
|
||||
char *zJournal;
|
||||
int nName;
|
||||
int rc;
|
||||
|
||||
nName = strlen(zNewName);
|
||||
zNew = sqliteMalloc( nName*2 + 30 );
|
||||
if( zNew==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memcpy(zNew, zNewName, nName+1);
|
||||
zJournal = &zNew[nName+1];
|
||||
memcpy(zJournal, zNew, nName);
|
||||
strcpy(&zJournal[nName], "-journal");
|
||||
if( pPager->journalOpen ){
|
||||
rc = sqliteOsRename(pPager->zJournal, zJournal);
|
||||
if( rc ){
|
||||
sqliteFree(zNew);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
rc = sqliteOsRename(pPager->zFilename, zNew);
|
||||
if( rc ){
|
||||
sqliteFree(zNew);
|
||||
return rc;
|
||||
}
|
||||
if( pPager->zFilename!=(char*)&pPager[1] ){
|
||||
sqliteFree(pPager->zFilename);
|
||||
}
|
||||
pPager->zFilename = zNew;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** Print a listing of all referenced pages and their ref count.
|
||||
|
@ -13,7 +13,7 @@
|
||||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
**
|
||||
** @(#) $Id: pager.h,v 1.21 2003/03/19 03:14:02 drh Exp $
|
||||
** @(#) $Id: pager.h,v 1.22 2003/04/06 20:44:45 drh Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -72,6 +72,8 @@ void sqlitepager_dont_rollback(void*);
|
||||
void sqlitepager_dont_write(Pager*, Pgno);
|
||||
int *sqlitepager_stats(Pager*);
|
||||
void sqlitepager_set_safety_level(Pager*,int);
|
||||
const char *sqlitepager_filename(Pager*);
|
||||
int sqlitepager_rename(Pager*, const char *zNewName);
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
void sqlitepager_refdump(Pager*);
|
||||
|
Reference in New Issue
Block a user