1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Restore btree to the main line. (CVS 237)

FossilOrigin-Name: 2e6aff980287825b59d2ebb7005bb08dd601ff1c
This commit is contained in:
drh
2001-08-20 00:33:58 +00:00
parent c87fa69a29
commit 5c4d9703d9
12 changed files with 3057 additions and 30 deletions

View File

@@ -47,13 +47,14 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
# Object files for the SQLite library.
#
LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \
main.o parse.o printf.o random.o select.o table.o \
LIBOBJ = btree.o build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \
main.o pager.o parse.o printf.o random.o select.o table.o \
tokenize.o update.o util.o vdbe.o where.o tclsqlite.o
# All of the source code files.
#
SRC = \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/dbbe.c \
$(TOP)/src/dbbe.h \
@@ -63,6 +64,7 @@ SRC = \
$(TOP)/src/expr.c \
$(TOP)/src/insert.c \
$(TOP)/src/main.c \
$(TOP)/src/pager.c \
$(TOP)/src/parse.y \
$(TOP)/src/printf.c \
$(TOP)/src/random.c \
@@ -82,7 +84,11 @@ SRC = \
# Source code to the test files.
#
TESTSRC = \
$(TOP)/src/btree.c \
$(TOP)/src/pager.c \
$(TOP)/src/test1.c \
$(TOP)/src/test2.c \
$(TOP)/src/test3.c \
$(TOP)/src/md5.c
# This is the default Makefile target. The objects listed here
@@ -120,6 +126,9 @@ HDR = \
$(TOP)/src/vdbe.h \
parse.h
btree.o: $(TOP)/src/btree.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/btree.c
build.o: $(TOP)/src/build.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/build.c
@@ -135,6 +144,9 @@ dbbemem.o: $(TOP)/src/dbbemem.c $(HDR)
main.o: $(TOP)/src/main.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/main.c
pager.o: $(TOP)/src/pager.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/pager.c
parse.o: parse.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c parse.c

View File

@@ -1,7 +1,7 @@
C Add\sindex\saccess\smethods\sto\sthe\sDBBE\sin\spreparation\sfor\sadding\sa\snew\nDBBE\sfor\sthe\sbtree.c\smodule.\s(CVS\s236)
D 2001-08-19T18:19:46
C Restore\sbtree\sto\sthe\smain\sline.\s(CVS\s237)
D 2001-08-20T00:33:58
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in a4595a83d56549b527dace5415729d20995f717b
F Makefile.in 9eea999e1d95531de4dd0a96a6ecf6ba0027b05b
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F VERSION 00453ed53ff28fe8e701e1609e81f1b9df12adab
F configure d2051345f49f7e48604423da26e086a745c86a47 x
@@ -13,13 +13,13 @@ F notes/notes2.txt 7e3fafd5e25906c1fe1e95f13b089aa398ca403e
F notes/notes2b.txt 1c17a5b7f6b44a75cd3eb98ed2c24db1eefb06c3
F notes/notes3.txt 71e47be517e3d2578b3b9343a45b772d43b7ba16
F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
F src/btree.c d6bbe3152ce3eb47ffd0c797897bf75c5ca784fc
F src/btree.h 5fb5799bcb39900386ce6cae61fa33e357851ffe
F src/btree.c 049c6a8d6c308b1945bd2f32746f3df187c7f18b
F src/btree.h 6617284287be90afe41bcd5047e44f109ecd1b48
F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651
F src/dbbe.c b18259f99d87240cbe751021cf14dd3aa83a48af
F src/dbbe.h bbb53eafcd1e3186597f6ee4a17ef2501f1b0628
F src/dbbegdbm.c cbb6ebc79a7100324f07b67d4e867faca9f9efa9
F src/dbbemem.c f4534a524e956b1db9af070b896040fc1b9cb80e
F src/dbbemem.c 910ad3bb82fc065a95a762b34593b3386b4833d5
F src/delete.c 40ddb169ee98013d976b2dadd140d98f7876f54f
F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a
F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7
@@ -44,8 +44,10 @@ F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 3e5906f72608f0fd4394dfbb1d7e8d35b8353677
F src/sqliteInt.h 47845c60e2e196b5409d774936a56700b1611f00
F src/table.c adcaf074f6c1075e86359174e68701fa2acfc4d6
F src/tclsqlite.c 386f502060325d9cb05d418bf0f1cf6a4b57c873
F src/tclsqlite.c d328970848c028e13e61e173bef79adcc379568a
F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4
F src/test2.c b3177e061fabd20d48e4b1b4bca610a0d2b28670
F src/test3.c 147b42ec368a10e9f267e7466d30c46e76d7f278
F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf
F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6
F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc
@@ -53,6 +55,8 @@ F src/vdbe.c b019394ebe0de12917a93ec06d787d8d909726cc
F src/vdbe.h 5331b9a3963d13af01a9cf749f57ac46727bdbe6
F src/where.c a49083e59358bac83c80cf0d19626d09bab629bd
F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048
F test/btree.test 5e1eeb03cda22161eec827dc5224ce6c500eaaf9
F test/btree2.test a66add2093843d0e5617fed6924002667832f279
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
@@ -65,6 +69,7 @@ F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
F test/main.test da635f9e078cd21ddf074e727381a715064489ff
F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861
F test/pager.test 775a86d5b4877f3b49cb0f8ef0a1621cc6683e3b
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
F test/quote.test 40a3164af8456933a81312803fa8cdb21b205c12
F test/rowid.test b01e6dec09780c93f55db6cfe7ad097323954f23
@@ -107,7 +112,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P cfc86dc48afb6b7e052e418db1c596b665d5cc66
R 79a41eb08d305d22b658e8f00e7f0110
P c15f6ffc4d41f30a06d750c8015226713ae0126b
R 7b718c617d1cbd654e712509bb5deb19
U drh
Z 385160b9b18c8b4f775dcbb82eee9159
Z a087795b1966c95abd2653a136093358

View File

@@ -1 +1 @@
c15f6ffc4d41f30a06d750c8015226713ae0126b
2e6aff980287825b59d2ebb7005bb08dd601ff1c

View File

@@ -21,7 +21,7 @@
** http://www.hwaci.com/drh/
**
*************************************************************************
** $Id: btree.c,v 1.20 2001/07/02 17:51:46 drh Exp $
** $Id: btree.c,v 1.21 2001/08/20 00:33:58 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -1026,7 +1026,12 @@ int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
** pages, then some other value might be returned to indicate the
** reason for the error.
*/
static int compareKey(BtCursor *pCur, char *pKey, int nKeyOrig, int *pResult){
static int compareKey(
BtCursor *pCur, /* Points to the entry against which we are comparing */
const char *pKey, /* The comparison key */
int nKeyOrig, /* Number of bytes in the comparison key */
int *pResult /* Write the comparison results here */
){
Pgno nextPage;
int nKey = nKeyOrig;
int n, c, rc;
@@ -1178,7 +1183,7 @@ static int moveToLeftmost(BtCursor *pCur){
** *pRes>0 The cursor is left pointing at an entry that
** is larger than pKey.
*/
int sqliteBtreeMoveto(BtCursor *pCur, void *pKey, int nKey, int *pRes){
int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
int rc;
pCur->bSkipNext = 0;
rc = moveToRoot(pCur);
@@ -1382,15 +1387,15 @@ static int clearCell(Btree *pBt, Cell *pCell){
static int fillInCell(
Btree *pBt, /* The whole Btree. Needed to allocate pages */
Cell *pCell, /* Populate this Cell structure */
void *pKey, int nKey, /* The key */
void *pData,int nData /* The data */
const void *pKey, int nKey, /* The key */
const void *pData,int nData /* The data */
){
OverflowPage *pOvfl, *pPrior;
Pgno *pNext;
int spaceLeft;
int n, rc;
int nPayload;
char *pPayload;
const char *pPayload;
char *pSpace;
pCell->h.leftChild = 0;
@@ -1965,9 +1970,9 @@ balance_cleanup:
** is left pointing at the new record.
*/
int sqliteBtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
void *pKey, int nKey, /* The key of the new record */
void *pData, int nData /* The data of the new record */
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;

View File

@@ -24,7 +24,7 @@
** This header file defines the interface that the sqlite B-Tree file
** subsystem.
**
** @(#) $Id: btree.h,v 1.9 2001/07/02 17:51:46 drh Exp $
** @(#) $Id: btree.h,v 1.10 2001/08/20 00:33:58 drh Exp $
*/
typedef struct Btree Btree;
@@ -42,9 +42,10 @@ int sqliteBtreeDropTable(Btree*, int);
int sqliteBtreeClearTable(Btree*, int);
int sqliteBtreeCursor(Btree*, int iTable, BtCursor **ppCur);
int sqliteBtreeMoveto(BtCursor*, void *pKey, int nKey, int *pRes);
int sqliteBtreeMoveto(BtCursor*, const void *pKey, int nKey, int *pRes);
int sqliteBtreeDelete(BtCursor*);
int sqliteBtreeInsert(BtCursor*, void *pKey, int nKey, void *pData, int nData);
int sqliteBtreeInsert(BtCursor*, const void *pKey, int nKey,
const void *pData, int nData);
int sqliteBtreeNext(BtCursor*, int *pRes);
int sqliteBtreeKeySize(BtCursor*, int *pSize);
int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);

View File

@@ -30,7 +30,7 @@
** Nothing is ever written to disk using this backend. All information
** is forgotten when the program exits.
**
** $Id: dbbemem.c,v 1.16 2001/08/19 18:19:46 drh Exp $
** $Id: dbbemem.c,v 1.17 2001/08/20 00:33:58 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -867,9 +867,9 @@ static struct DbbeMethods memoryMethods = {
};
/*
** This routine opens a new database. For the GDBM driver
** implemented here, the database name is the name of the directory
** containing all the files of the database.
** This routine opens a new database. For the MEMORY driver
** implemented here, the database name is ignored. Every MEMORY database
** is unique and is erased when the database is closed.
**
** If successful, a pointer to the Dbbe structure is returned.
** If there are errors, an appropriate error message is left

View File

@@ -23,7 +23,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.21 2001/07/23 14:33:04 drh Exp $
** $Id: tclsqlite.c,v 1.22 2001/08/20 00:33:58 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@@ -510,8 +510,12 @@ int TCLSH_MAIN(int argc, char **argv){
#ifdef SQLITE_TEST
{
extern int Sqlitetest1_Init(Tcl_Interp*);
extern int Sqlitetest2_Init(Tcl_Interp*);
extern int Sqlitetest3_Init(Tcl_Interp*);
extern int Md5_Init(Tcl_Interp*);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
Sqlitetest3_Init(interp);
Md5_Init(interp);
}
#endif

416
src/test2.c Normal file
View File

@@ -0,0 +1,416 @@
/*
** Copyright (c) 2001 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*************************************************************************
** Code for testing the pager.c module in SQLite. This code
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test2.c,v 1.4 2001/08/20 00:33:58 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
/*
** Interpret an SQLite error number
*/
static char *errorName(int rc){
char *zName;
switch( rc ){
case SQLITE_OK: zName = "SQLITE_OK"; break;
case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
case SQLITE_PERM: zName = "SQLITE_PERM"; break;
case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
case SQLITE_FULL: zName = "SQLITE_FULL"; break;
case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
default: zName = "SQLITE_Unknown"; break;
}
return zName;
}
/*
** Usage: pager_open FILENAME N-PAGE
**
** Open a new pager
*/
static int pager_open(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
int nPage;
int rc;
char zBuf[100];
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" FILENAME N-PAGE\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
rc = sqlitepager_open(&pPager, argv[1], nPage, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sprintf(zBuf,"0x%x",(int)pPager);
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: pager_close ID
**
** Close the given pager.
*/
static int pager_close(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
rc = sqlitepager_close(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: pager_rollback ID
**
** Rollback changes
*/
static int pager_rollback(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
rc = sqlitepager_rollback(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: pager_commit ID
**
** Commit all changes
*/
static int pager_commit(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
rc = sqlitepager_commit(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: pager_stats ID
**
** Return pager statistics.
*/
static int pager_stats(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
int i, *a;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
a = sqlitepager_stats(pPager);
for(i=0; i<9; i++){
static char *zName[] = {
"ref", "page", "max", "size", "state", "err",
"hit", "miss", "ovfl",
};
char zBuf[100];
Tcl_AppendElement(interp, zName[i]);
sprintf(zBuf,"%d",a[i]);
Tcl_AppendElement(interp, zBuf);
}
return TCL_OK;
}
/*
** Usage: pager_pagecount ID
**
** Return the size of the database file.
*/
static int pager_pagecount(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
char zBuf[100];
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
sprintf(zBuf,"%d",sqlitepager_pagecount(pPager));
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: page_get ID PGNO
**
** Return a pointer to a page from the database.
*/
static int page_get(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
char zBuf[100];
void *pPage;
int pgno;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID PGNO\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
rc = sqlitepager_get(pPager, pgno, &pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sprintf(zBuf,"0x%x",(int)pPage);
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: page_lookup ID PGNO
**
** Return a pointer to a page if the page is already in cache.
** If not in cache, return an empty string.
*/
static int page_lookup(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Pager *pPager;
char zBuf[100];
void *pPage;
int pgno;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID PGNO\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
pPage = sqlitepager_lookup(pPager, pgno);
if( pPage ){
sprintf(zBuf,"0x%x",(int)pPage);
Tcl_AppendResult(interp, zBuf, 0);
}
return TCL_OK;
}
/*
** Usage: page_unref PAGE
**
** Drop a pointer to a page.
*/
static int page_unref(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
void *pPage;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
rc = sqlitepager_unref(pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: page_read PAGE
**
** Return the content of a page
*/
static int page_read(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
char zBuf[100];
void *pPage;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
memcpy(zBuf, pPage, sizeof(zBuf));
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: page_number PAGE
**
** Return the page number for a page.
*/
static int page_number(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
char zBuf[100];
void *pPage;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
sprintf(zBuf, "%d", sqlitepager_pagenumber(pPage));
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: page_write PAGE DATA
**
** Write something into a page.
*/
static int page_write(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
void *pPage;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE DATA\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
rc = sqlitepager_write(pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
strncpy((char*)pPage, argv[2], SQLITE_PAGE_SIZE-1);
((char*)pPage)[SQLITE_PAGE_SIZE-1] = 0;
return TCL_OK;
}
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest2_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, "pager_open", pager_open, 0, 0);
Tcl_CreateCommand(interp, "pager_close", pager_close, 0, 0);
Tcl_CreateCommand(interp, "pager_commit", pager_commit, 0, 0);
Tcl_CreateCommand(interp, "pager_rollback", pager_rollback, 0, 0);
Tcl_CreateCommand(interp, "pager_stats", pager_stats, 0, 0);
Tcl_CreateCommand(interp, "pager_pagecount", pager_pagecount, 0, 0);
Tcl_CreateCommand(interp, "page_get", page_get, 0, 0);
Tcl_CreateCommand(interp, "page_lookup", page_lookup, 0, 0);
Tcl_CreateCommand(interp, "page_unref", page_unref, 0, 0);
Tcl_CreateCommand(interp, "page_read", page_read, 0, 0);
Tcl_CreateCommand(interp, "page_write", page_write, 0, 0);
Tcl_CreateCommand(interp, "page_number", page_number, 0, 0);
return TCL_OK;
}

844
src/test3.c Normal file
View File

@@ -0,0 +1,844 @@
/*
** Copyright (c) 2001 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*************************************************************************
** Code for testing the btree.c module in SQLite. This code
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.9 2001/08/20 00:33:58 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "btree.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
/*
** Interpret an SQLite error number
*/
static char *errorName(int rc){
char *zName;
switch( rc ){
case SQLITE_OK: zName = "SQLITE_OK"; break;
case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
case SQLITE_PERM: zName = "SQLITE_PERM"; break;
case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
case SQLITE_FULL: zName = "SQLITE_FULL"; break;
case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
default: zName = "SQLITE_Unknown"; break;
}
return zName;
}
/*
** Usage: btree_open FILENAME
**
** Open a new database
*/
static int btree_open(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
char zBuf[100];
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" FILENAME\"", 0);
return TCL_ERROR;
}
rc = sqliteBtreeOpen(argv[1], 0666, 10, &pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sprintf(zBuf,"0x%x",(int)pBt);
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: btree_close ID
**
** Close the given database.
*/
static int btree_close(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
rc = sqliteBtreeClose(pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_begin_transaction ID
**
** Start a new transaction
*/
static int btree_begin_transaction(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
rc = sqliteBtreeBeginTrans(pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_rollback ID
**
** Rollback changes
*/
static int btree_rollback(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
rc = sqliteBtreeRollback(pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_commit ID
**
** Commit all changes
*/
static int btree_commit(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
rc = sqliteBtreeCommit(pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_create_table ID
**
** Create a new table in the database
*/
static int btree_create_table(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc, iTable;
char zBuf[30];
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
rc = sqliteBtreeCreateTable(pBt, &iTable);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sprintf(zBuf, "%d", iTable);
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: btree_drop_table ID TABLENUM
**
** Delete an entire table from the database
*/
static int btree_drop_table(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int iTable;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID TABLENUM\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
rc = sqliteBtreeDropTable(pBt, iTable);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_clear_table ID TABLENUM
**
** Remove all entries from the given table but keep the table around.
*/
static int btree_clear_table(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int iTable;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID TABLENUM\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
rc = sqliteBtreeClearTable(pBt, iTable);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_get_meta ID
**
** Return meta data
*/
static int btree_get_meta(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
int i;
int aMeta[SQLITE_N_BTREE_META];
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
rc = sqliteBtreeGetMeta(pBt, aMeta);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
for(i=0; i<SQLITE_N_BTREE_META; i++){
char zBuf[30];
sprintf(zBuf,"%d",aMeta[i]);
Tcl_AppendElement(interp, zBuf);
}
return TCL_OK;
}
/*
** Usage: btree_update_meta ID METADATA...
**
** Return meta data
*/
static int btree_update_meta(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int rc;
int i;
int aMeta[SQLITE_N_BTREE_META];
if( argc!=2+SQLITE_N_BTREE_META ){
char zBuf[30];
sprintf(zBuf,"%d",SQLITE_N_BTREE_META);
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID METADATA...\" (METADATA is ", zBuf, " integers)", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
for(i=0; i<SQLITE_N_BTREE_META; i++){
if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
}
rc = sqliteBtreeUpdateMeta(pBt, aMeta);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_page_dump ID PAGENUM
**
** Print a disassembly of a page on standard output
*/
static int btree_page_dump(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int iPage;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
rc = sqliteBtreePageDump(pBt, iPage, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_tree_dump ID PAGENUM
**
** Print a disassembly of a page and all its child pages on standard output
*/
static int btree_tree_dump(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int iPage;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
rc = sqliteBtreePageDump(pBt, iPage, 1);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Usage: btree_pager_stats ID
**
** Returns pager statistics
*/
static int btree_pager_stats(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int i;
int *a;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
a = sqlitepager_stats(sqliteBtreePager(pBt));
for(i=0; i<9; i++){
static char *zName[] = {
"ref", "page", "max", "size", "state", "err",
"hit", "miss", "ovfl",
};
char zBuf[100];
Tcl_AppendElement(interp, zName[i]);
sprintf(zBuf,"%d",a[i]);
Tcl_AppendElement(interp, zBuf);
}
return TCL_OK;
}
/*
** Usage: btree_pager_ref_dump ID
**
** Print out all outstanding pages.
*/
static int btree_pager_ref_dump(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
sqlitepager_refdump(sqliteBtreePager(pBt));
return TCL_OK;
}
/*
** Usage: btree_sanity_check ID ROOT ...
**
** Look through every page of the given BTree file to verify correct
** formatting and linkage. Return a line of text for each problem found.
** Return an empty string if everything worked.
*/
static int btree_sanity_check(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
char *zResult;
int nRoot;
int *aRoot;
int i;
if( argc<3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID ROOT ...\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
nRoot = argc-2;
aRoot = malloc( sizeof(int)*(argc-2) );
for(i=0; i<argc-2; i++){
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
}
zResult = sqliteBtreeSanityCheck(pBt, aRoot, nRoot);
if( zResult ){
Tcl_AppendResult(interp, zResult, 0);
free(zResult);
}
return TCL_OK;
}
/*
** Usage: btree_cursor ID TABLENUM
**
** Create a new cursor. Return the ID for the cursor.
*/
static int btree_cursor(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
Btree *pBt;
int iTable;
BtCursor *pCur;
int rc;
char zBuf[30];
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID TABLENUM\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
rc = sqliteBtreeCursor(pBt, iTable, &pCur);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sprintf(zBuf,"0x%x", (int)pCur);
Tcl_AppendResult(interp, zBuf, 0);
return SQLITE_OK;
}
/*
** Usage: btree_close_cursor ID
**
** Close a cursor opened using btree_cursor.
*/
static int btree_close_cursor(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
rc = sqliteBtreeCloseCursor(pCur);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return SQLITE_OK;
}
/*
** Usage: btree_move_to ID KEY
**
** Move the cursor to the entry with the given key.
*/
static int btree_move_to(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
int res;
char zBuf[20];
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID KEY\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
rc = sqliteBtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sprintf(zBuf,"%d",res);
Tcl_AppendResult(interp, zBuf, 0);
return SQLITE_OK;
}
/*
** Usage: btree_delete ID
**
** Delete the entry that the cursor is pointing to
*/
static int btree_delete(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
rc = sqliteBtreeDelete(pCur);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return SQLITE_OK;
}
/*
** Usage: btree_insert ID KEY DATA
**
** Create a new entry with the given key and data. If an entry already
** exists with the same key the old entry is overwritten.
*/
static int btree_insert(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
if( argc!=4 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID KEY DATA\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
rc = sqliteBtreeInsert(pCur, argv[2], strlen(argv[2]),
argv[3], strlen(argv[3]));
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return SQLITE_OK;
}
/*
** Usage: btree_next ID
**
** Move the cursor to the next entry in the table.
*/
static int btree_next(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
rc = sqliteBtreeNext(pCur, 0);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return SQLITE_OK;
}
/*
** Usage: btree_key ID
**
** Return the key for the entry at which the cursor is pointing.
*/
static int btree_key(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
int n;
char *zBuf;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
sqliteBtreeKeySize(pCur, &n);
zBuf = malloc( n+1 );
rc = sqliteBtreeKey(pCur, 0, n, zBuf);
if( rc ){
free(zBuf);
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
zBuf[n] = 0;
Tcl_AppendResult(interp, zBuf, 0);
free(zBuf);
return SQLITE_OK;
}
/*
** Usage: btree_data ID
**
** Return the data for the entry at which the cursor is pointing.
*/
static int btree_data(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
int n;
char *zBuf;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
sqliteBtreeDataSize(pCur, &n);
zBuf = malloc( n+1 );
rc = sqliteBtreeData(pCur, 0, n, zBuf);
if( rc ){
free(zBuf);
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
zBuf[n] = 0;
Tcl_AppendResult(interp, zBuf, 0);
free(zBuf);
return SQLITE_OK;
}
/*
** Usage: btree_cursor_dump ID
**
** Return eight integers containing information about the entry 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
*/
static int btree_cursor_dump(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
BtCursor *pCur;
int rc;
int i, j;
int aResult[8];
char zBuf[400];
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
rc = sqliteBtreeCursorDump(pCur, aResult);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
j = 0;
for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){
sprintf(&zBuf[j]," %d", aResult[i]);
j += strlen(&zBuf[j]);
}
Tcl_AppendResult(interp, &zBuf[1], 0);
return SQLITE_OK;
}
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest3_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, "btree_open", btree_open, 0, 0);
Tcl_CreateCommand(interp, "btree_close", btree_close, 0, 0);
Tcl_CreateCommand(interp, "btree_begin_transaction",
btree_begin_transaction, 0, 0);
Tcl_CreateCommand(interp, "btree_commit", btree_commit, 0, 0);
Tcl_CreateCommand(interp, "btree_rollback", btree_rollback, 0, 0);
Tcl_CreateCommand(interp, "btree_create_table", btree_create_table, 0, 0);
Tcl_CreateCommand(interp, "btree_drop_table", btree_drop_table, 0, 0);
Tcl_CreateCommand(interp, "btree_clear_table", btree_clear_table, 0, 0);
Tcl_CreateCommand(interp, "btree_get_meta", btree_get_meta, 0, 0);
Tcl_CreateCommand(interp, "btree_update_meta", btree_update_meta, 0, 0);
Tcl_CreateCommand(interp, "btree_page_dump", btree_page_dump, 0, 0);
Tcl_CreateCommand(interp, "btree_tree_dump", btree_tree_dump, 0, 0);
Tcl_CreateCommand(interp, "btree_pager_stats", btree_pager_stats, 0, 0);
Tcl_CreateCommand(interp, "btree_pager_ref_dump", btree_pager_ref_dump, 0, 0);
Tcl_CreateCommand(interp, "btree_cursor", btree_cursor, 0, 0);
Tcl_CreateCommand(interp, "btree_close_cursor", btree_close_cursor, 0, 0);
Tcl_CreateCommand(interp, "btree_move_to", btree_move_to, 0, 0);
Tcl_CreateCommand(interp, "btree_delete", btree_delete, 0, 0);
Tcl_CreateCommand(interp, "btree_insert", btree_insert, 0, 0);
Tcl_CreateCommand(interp, "btree_next", btree_next, 0, 0);
Tcl_CreateCommand(interp, "btree_key", btree_key, 0, 0);
Tcl_CreateCommand(interp, "btree_data", btree_data, 0, 0);
Tcl_CreateCommand(interp, "btree_cursor_dump", btree_cursor_dump, 0, 0);
Tcl_CreateCommand(interp, "btree_sanity_check", btree_sanity_check, 0, 0);
Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager_refinfo_enable,
TCL_LINK_INT);
return TCL_OK;
}

1030
test/btree.test Normal file

File diff suppressed because it is too large Load Diff

449
test/btree2.test Normal file
View File

@@ -0,0 +1,449 @@
# Copyright (c) 1999, 2000 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# Author contact information:
# drh@hwaci.com
# http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is btree database backend
#
# $Id: btree2.test,v 1.4 2001/08/20 00:33:58 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {[info commands btree_open]!=""} {
# Create a new database file containing no entries. The database should
# contain 5 tables:
#
# 2 The descriptor table
# 3 The foreground table
# 4 The background table
# 5 The long key table
# 6 The long data table
#
# An explanation for what all these tables are used for is provided below.
#
do_test btree2-1.1 {
expr srand(1)
file delete -force test2.bt
file delete -force test2.bt-journal
set ::b [btree_open test2.bt]
btree_begin_transaction $::b
btree_create_table $::b
} {3}
do_test btree2-1.2 {
btree_create_table $::b
} {4}
do_test btree2-1.3 {
btree_create_table $::b
} {5}
do_test btree2-1.4 {
btree_create_table $::b
} {6}
do_test btree2-1.5 {
set ::c2 [btree_cursor $::b 2]
btree_insert $::c2 {one} {1}
btree_delete $::c2
btree_close_cursor $::c2
btree_commit $::b
btree_sanity_check $::b 2 3 4 5 6
} {}
# This test module works by making lots of pseudo-random changes to a
# database while simultaneously maintaining an invariant on that database.
# Periodically, the script does a sanity check on the database and verifies
# that the invariant is satisfied.
#
# The invariant is as follows:
#
# 1. The descriptor table always contains 2 enters. An entry keyed by
# "N" is the number of elements in the foreground and background tables
# combined. The entry keyed by "L" is the number of digits in the keys
# for foreground and background tables.
#
# 2. The union of the foreground an background tables consists of N entries
# where each entry an L-digit key. (Actually, some keys can be longer
# than L characters, but they always start with L digits.) The keys
# cover all integers between 1 and N. Whenever an entry is added to
# the foreground it is removed form the background and vice versa.
#
# 3. Some entries in the foreground and background tables have keys that
# begin with an L-digit number but are followed by additional characters.
# For each such entry there is a corresponding entry in the long key
# table. The long key table entry has a key which is just the L-digit
# number and data which is the length of the key in the foreground and
# background tables.
#
# 4. The data for both foreground and background entries is usually a
# short string. But some entries have long data strings. For each
# such entries there is an entry in the long data type. The key to
# long data table is an L-digit number. (The extension on long keys
# is omitted.) The data is the number of charaters in the data of the
# foreground or background entry.
#
# The following function builds a database that satisfies all of the above
# invariants.
#
proc build_db {N L} {
for {set i 2} {$i<=6} {incr i} {
catch {btree_close_cursor [set ::c$i]}
btree_clear_table $::b $i
set ::c$i [btree_cursor $::b $i]
}
btree_insert $::c2 N $N
btree_insert $::c2 L $L
set format %0${L}d
for {set i 1} {$i<=$N} {incr i} {
set key [format $format $i]
set data $key
btree_insert $::c3 $key $data
}
}
# Given a base key number and a length, construct the full text of the key
# or data.
#
proc make_payload {keynum L len} {
set key [format %0${L}d $keynum]
set r $key
set i 1
while {[string length $r]<$len} {
append r " ($i) $key"
incr i
}
return [string range $r 0 [expr {$len-1}]]
}
# Verify the invariants on the database. Return an empty string on
# success or an error message if something is amiss.
#
proc check_invariants {} {
set ck [btree_sanity_check $::b 2 3 4 5 6]
if {$ck!=""} {
puts "\n*** SANITY:\n$ck"
exit
return $ck
}
btree_move_to $::c3 {}
btree_move_to $::c4 {}
btree_move_to $::c2 N
set N [btree_data $::c2]
btree_move_to $::c2 L
set L [btree_data $::c2]
set LM1 [expr {$L-1}]
for {set i 1} {$i<=$N} {incr i} {
set key [btree_key $::c3]
if {[scan $key %d k]<1} {set k 0}
if {$k!=$i} {
set key [btree_key $::c4]
if {[scan $key %d k]<1} {set k 0}
if {$k!=$i} {
# puts "MISSING $i"
# puts {Page 3:}; btree_page_dump $::b 3
# puts {Page 4:}; btree_page_dump $::b 4
# exit
return "Key $i is missing from both foreground and background"
}
set data [btree_data $::c4]
btree_next $::c4
} else {
set data [btree_data $::c3]
btree_next $::c3
}
set skey [string range $key 0 $LM1]
if {[btree_move_to $::c5 $skey]==0} {
set keylen [btree_data $::c5]
} else {
set keylen $L
}
if {[string length $key]!=$keylen} {
return "Key $i is the wrong size.\
Is \"$key\" but should be \"[make_payload $k $L $keylen]\""
}
if {[make_payload $k $L $keylen]!=$key} {
return "Key $i has an invalid extension"
}
if {[btree_move_to $::c6 $skey]==0} {
set datalen [btree_data $::c6]
} else {
set datalen $L
}
if {[string length $data]!=$datalen} {
return "Data for $i is the wrong size.\
Is [string length $data] but should be $datalen"
}
if {[make_payload $k $L $datalen]!=$data} {
return "Entry $i has an incorrect data"
}
}
}
# Make random changes to the database such that each change preserves
# the invariants. The number of changes is $n*N where N is the parameter
# from the descriptor table. Each changes begins with a random key.
# the entry with that key is put in the foreground table with probability
# $I and it is put in background with probability (1.0-$I). It gets
# a long key with probability $K and long data with probability $D.
#
set chngcnt 0
proc random_changes {n I K D} {
btree_move_to $::c2 N
set N [btree_data $::c2]
btree_move_to $::c2 L
set L [btree_data $::c2]
set LM1 [expr {$L-1}]
set total [expr {int($N*$n)}]
set format %0${L}d
for {set i 0} {$i<$total} {incr i} {
set k [expr {int(rand()*$N)+1}]
set insert [expr {rand()<=$I}]
set longkey [expr {rand()<=$K}]
set longdata [expr {rand()<=$D}]
# incr ::chngcnt
# if {$::chngcnt==251} {btree_tree_dump $::b 3}
# puts "CHANGE $::chngcnt: $k $insert $longkey $longdata"
if {$longkey} {
set x [expr {rand()}]
set keylen [expr {int($x*$x*$x*$x*3000)+10}]
} else {
set keylen $L
}
set key [make_payload $k $L $keylen]
if {$longdata} {
set x [expr {rand()}]
set datalen [expr {int($x*$x*$x*$x*3000)+10}]
} else {
set datalen $L
}
set data [make_payload $k $L $datalen]
set basekey [format $format $k]
if {[set c [btree_move_to $::c3 $basekey]]==0} {
btree_delete $::c3
} else {
if {$c<0} {btree_next $::c3}
if {[string match $basekey* [btree_key $::c3]]} {
btree_delete $::c3
}
}
if {[set c [btree_move_to $::c4 $basekey]]==0} {
btree_delete $::c4
} else {
if {$c<0} {btree_next $::c4}
if {[string match $basekey* [btree_key $::c4]]} {
btree_delete $::c4
}
}
if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
if {$kx==$k} {
btree_delete $::c4
}
if {$insert} {
btree_insert $::c3 $key $data
} else {
btree_insert $::c4 $key $data
}
if {$longkey} {
btree_insert $::c5 $basekey $keylen
} elseif {[btree_move_to $::c5 $basekey]==0} {
btree_delete $::c5
}
if {$longdata} {
btree_insert $::c6 $basekey $datalen
} elseif {[btree_move_to $::c6 $basekey]==0} {
btree_delete $::c6
}
# set ck [btree_sanity_check $::b 2 3 4 5 6]
# if {$ck!=""} {
# puts "\nSANITY CHECK FAILED!\n$ck"
# exit
# }
# puts "PAGE 3:"; btree_page_dump $::b 3
# puts "PAGE 4:"; btree_page_dump $::b 4
}
}
# Repeat this test sequence on database of various sizes
#
set testno 2
foreach {N L} {
10 2
50 2
200 3
} {
# 2000 5
puts "**** N=$N L=$L ****"
set hash [md5file test2.bt]
do_test btree2-$testno.1 [subst -nocommands {
set ::c2 [btree_cursor $::b 2]
set ::c3 [btree_cursor $::b 3]
set ::c4 [btree_cursor $::b 4]
set ::c5 [btree_cursor $::b 5]
set ::c6 [btree_cursor $::b 6]
btree_begin_transaction $::b
build_db $N $L
check_invariants
}] {}
do_test btree2-$testno.2 {
btree_close_cursor $::c2
btree_close_cursor $::c3
btree_close_cursor $::c4
btree_close_cursor $::c5
btree_close_cursor $::c6
btree_rollback $::b
md5file test2.bt
} $hash
do_test btree2-$testno.3 [subst -nocommands {
btree_begin_transaction $::b
set ::c2 [btree_cursor $::b 2]
set ::c3 [btree_cursor $::b 3]
set ::c4 [btree_cursor $::b 4]
set ::c5 [btree_cursor $::b 5]
set ::c6 [btree_cursor $::b 6]
build_db $N $L
check_invariants
}] {}
do_test btree2-$testno.4 {
btree_commit $::b
check_invariants
} {}
do_test btree2-$testno.5 {
lindex [btree_pager_stats $::b] 1
} {6}
do_test btree2-$testno.6 {
btree_close_cursor $::c2
btree_close_cursor $::c3
btree_close_cursor $::c4
btree_close_cursor $::c5
btree_close_cursor $::c6
lindex [btree_pager_stats $::b] 1
} {0}
do_test btree2-$testno.7 {
btree_close $::b
set ::b [btree_open test2.bt]
set ::c2 [btree_cursor $::b 2]
set ::c3 [btree_cursor $::b 3]
set ::c4 [btree_cursor $::b 4]
set ::c5 [btree_cursor $::b 5]
set ::c6 [btree_cursor $::b 6]
check_invariants
} {}
# For each database size, run various changes tests.
#
set num2 1
foreach {n I K D} {
0.5 0.5 0.1 0.1
1.0 0.2 0.1 0.1
1.0 0.8 0.1 0.1
2.0 0.0 0.1 0.1
2.0 1.0 0.1 0.1
2.0 0.0 0.0 0.0
2.0 1.0 0.0 0.0
} {
set testid btree2-$testno.8.$num2
set cnt 6
for {set i 2} {$i<=6} {incr i} {
if {[lindex [btree_cursor_dump [set ::c$i]] 0]!=$i} {incr cnt}
}
do_test $testid.1 {
btree_begin_transaction $::b
lindex [btree_pager_stats $::b] 1
} $cnt
set hash [md5file test2.bt]
# exec cp test2.bt test2.bt.bu1
do_test $testid.2 [subst {
random_changes $n $I $K $D
}] {}
do_test $testid.3 {
check_invariants
} {}
do_test $testid.4 {
btree_close_cursor $::c2
btree_close_cursor $::c3
btree_close_cursor $::c4
btree_close_cursor $::c5
btree_close_cursor $::c6
btree_rollback $::b
md5file test2.bt
} $hash
# exec cp test2.bt test2.bt.bu2
btree_begin_transaction $::b
set ::c2 [btree_cursor $::b 2]
set ::c3 [btree_cursor $::b 3]
set ::c4 [btree_cursor $::b 4]
set ::c5 [btree_cursor $::b 5]
set ::c6 [btree_cursor $::b 6]
do_test $testid.5 [subst {
random_changes $n $I $K $D
}] {}
do_test $testid.6 {
check_invariants
} {}
do_test $testid.7 {
btree_commit $::b
check_invariants
} {}
set hash [md5file test2.bt]
do_test $testid.8 {
btree_close_cursor $::c2
btree_close_cursor $::c3
btree_close_cursor $::c4
btree_close_cursor $::c5
btree_close_cursor $::c6
lindex [btree_pager_stats $::b] 1
} {0}
do_test $testid.9 {
btree_close $::b
set ::b [btree_open test2.bt]
set ::c2 [btree_cursor $::b 2]
set ::c3 [btree_cursor $::b 3]
set ::c4 [btree_cursor $::b 4]
set ::c5 [btree_cursor $::b 5]
set ::c6 [btree_cursor $::b 6]
check_invariants
} {}
incr num2
}
btree_close_cursor $::c2
btree_close_cursor $::c3
btree_close_cursor $::c4
btree_close_cursor $::c5
btree_close_cursor $::c6
incr testno
}
# Testing is complete. Shut everything down.
#
do_test btree-999.1 {
lindex [btree_pager_stats $::b] 1
} {0}
do_test btree-999.2 {
btree_close $::b
} {}
do_test btree-999.3 {
file delete -force test2.bt
file exists test2.bt-journal
} {0}
} ;# end if( not mem: and has pager_open command );
finish_test

261
test/pager.test Normal file
View File

@@ -0,0 +1,261 @@
# Copyright (c) 1999, 2000 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# Author contact information:
# drh@hwaci.com
# http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is page cache subsystem.
#
# $Id: pager.test,v 1.8 2001/08/20 00:33:58 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$dbprefix!="memory:" && [info commands pager_open]!=""} {
# Basic sanity check. Open and close a pager.
#
do_test pager-1.0 {
catch {file delete -force ptf1.db}
catch {file delete -force ptf1.db-journal}
set v [catch {
set ::p1 [pager_open ptf1.db 10]
} msg]
} {0}
do_test pager-1.1 {
pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager-1.2 {
pager_pagecount $::p1
} {0}
do_test pager-1.3 {
pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager-1.4 {
pager_close $::p1
} {}
# Try to write a few pages.
#
do_test pager-2.1 {
set v [catch {
set ::p1 [pager_open ptf1.db 10]
} msg]
} {0}
do_test pager-2.2 {
set v [catch {
set ::g1 [page_get $::p1 0]
} msg]
lappend v $msg
} {1 SQLITE_ERROR}
do_test pager-2.3.1 {
set ::gx [page_lookup $::p1 1]
} {}
do_test pager-2.3.2 {
pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager-2.3.3 {
set v [catch {
set ::g1 [page_get $::p1 1]
} msg]
if {$v} {lappend v $msg}
set v
} {0}
do_test pager-2.3.3 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.3.4 {
set ::gx [page_lookup $::p1 1]
expr {$::gx!=""}
} {1}
do_test pager-2.3.5 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.3.6 {
expr $::g1==$::gx
} {1}
do_test pager-2.3.7 {
page_unref $::gx
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.4 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.5 {
pager_pagecount $::p1
} {0}
do_test pager-2.6 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.7 {
page_number $::g1
} {1}
do_test pager-2.8 {
page_read $::g1
} {}
do_test pager-2.9 {
page_unref $::g1
} {}
do_test pager-2.10 {
pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.11 {
set ::g1 [page_get $::p1 1]
expr {$::g1!=0}
} {1}
do_test pager-2.12 {
page_number $::g1
} {1}
do_test pager-2.13 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.14 {
set v [catch {
page_write $::g1 "Page-One"
} msg]
lappend v $msg
} {0 {}}
do_test pager-2.15 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.16 {
page_read $::g1
} {Page-One}
do_test pager-2.17 {
set v [catch {
pager_commit $::p1
} msg]
lappend v $msg
} {0 {}}
do_test pager-2.20 {
pager_stats $::p1
} {ref 1 page 1 max 10 size -1 state 1 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.19 {
pager_pagecount $::p1
} {1}
do_test pager-2.21 {
pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.22 {
page_unref $::g1
} {}
do_test pager-2.23 {
pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.24 {
set v [catch {
page_get $::p1 1
} ::g1]
if {$v} {lappend v $::g1}
set v
} {0}
do_test pager-2.25 {
page_read $::g1
} {Page-One}
do_test pager-2.26 {
set v [catch {
page_write $::g1 {page-one}
} msg]
lappend v $msg
} {0 {}}
do_test pager-2.27 {
page_read $::g1
} {page-one}
do_test pager-2.28 {
set v [catch {
pager_rollback $::p1
} msg]
lappend v $msg
} {0 {}}
do_test pager-2.29 {
page_read $::g1
} {Page-One}
do_test pager-2.99 {
pager_close $::p1
} {}
do_test pager-3.1 {
set v [catch {
set ::p1 [pager_open ptf1.db 15]
} msg]
if {$v} {lappend v $msg}
set v
} {0}
do_test pager-3.2 {
pager_pagecount $::p1
} {1}
do_test pager-3.3 {
set v [catch {
set ::g(1) [page_get $::p1 1]
} msg]
if {$v} {lappend v $msg}
set v
} {0}
do_test pager-3.4 {
page_read $::g(1)
} {Page-One}
do_test pager-3.5 {
for {set i 2} {$i<=20} {incr i} {
set gx [page_get $::p1 $i]
page_write $gx "Page-$i"
page_unref $gx
}
pager_commit $::p1
} {}
for {set i 2} {$i<=20} {incr i} {
do_test pager-3.6.[expr {$i-1}] [subst {
set gx \[page_get $::p1 $i\]
set v \[page_read \$gx\]
page_unref \$gx
set v
}] "Page-$i"
}
for {set i 1} {$i<=20} {incr i} {
regsub -all CNT {
set ::g1 [page_get $::p1 CNT]
set ::g2 [page_get $::p1 CNT]
set ::vx [page_read $::g2]
expr {$::g1==$::g2}
} $i body;
do_test pager-3.7.$i.1 $body {1}
regsub -all CNT {
page_unref $::g2
set vy [page_read $::g1]
expr {$vy==$::vx}
} $i body;
do_test pager-3.7.$i.2 $body {1}
regsub -all CNT {
page_unref $::g1
set gx [page_get $::p1 CNT]
set vy [page_read $gx]
page_unref $gx
expr {$vy==$::vx}
} $i body;
do_test pager-3.7.$i.3 $body {1}
}
do_test pager-3.99 {
pager_close $::p1
} {}
} ;# end if( not mem: and has pager_open command );
finish_test