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

Add ability to quote table and column names in expression. (CVS 235)

FossilOrigin-Name: 029e3a3a5dd8d4923af50bb2c9f31b1b7cd9439e
This commit is contained in:
drh
2001-07-23 14:33:02 +00:00
parent 6019e168a0
commit 87c40e88a0
15 changed files with 250 additions and 3088 deletions

View File

@@ -47,8 +47,8 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
# Object files for the SQLite library. # Object files for the SQLite library.
# #
LIBOBJ = btree.o build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \ LIBOBJ = 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 \ main.o parse.o printf.o random.o select.o table.o \
tokenize.o update.o util.o vdbe.o where.o tclsqlite.o tokenize.o update.o util.o vdbe.o where.o tclsqlite.o
# All of the source code files. # All of the source code files.
@@ -83,8 +83,6 @@ SRC = \
# #
TESTSRC = \ TESTSRC = \
$(TOP)/src/test1.c \ $(TOP)/src/test1.c \
$(TOP)/src/test2.c \
$(TOP)/src/test3.c \
$(TOP)/src/md5.c $(TOP)/src/md5.c
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
@@ -118,15 +116,10 @@ lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
HDR = \ HDR = \
sqlite.h \ sqlite.h \
$(TOP)/src/sqliteInt.h \ $(TOP)/src/sqliteInt.h \
$(TOP)/src/btree.h \
$(TOP)/src/dbbe.h \ $(TOP)/src/dbbe.h \
$(TOP)/src/pager.h \
$(TOP)/src/vdbe.h \ $(TOP)/src/vdbe.h \
parse.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) build.o: $(TOP)/src/build.c $(HDR)
$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/build.c $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/build.c
@@ -195,9 +188,6 @@ tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
printf.o: $(TOP)/src/printf.c $(HDR) printf.o: $(TOP)/src/printf.c $(HDR)
$(TCC) $(GDBM_FLAGS) $(TCL_FLAGS) -c $(TOP)/src/printf.c $(TCC) $(GDBM_FLAGS) $(TCL_FLAGS) -c $(TOP)/src/printf.c
pager.o: $(TOP)/src/pager.c $(HDR)
$(TCC) $(GDBM_FLAGS) $(TCL_FLAGS) -c $(TOP)/src/pager.c
gdbmdump: $(TOP)/tool/gdbmdump.c gdbmdump: $(TOP)/tool/gdbmdump.c
$(TCC) $(GDBM_FLAGS) -o gdbmdump $(TOP)/tool/gdbmdump.c $(LIBGDBM) $(TCC) $(GDBM_FLAGS) -o gdbmdump $(TOP)/tool/gdbmdump.c $(LIBGDBM)
@@ -207,8 +197,8 @@ tclsqlite: $(TOP)/src/tclsqlite.c libsqlite.a
testfixture: $(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC) testfixture: $(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC)
$(TCC) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture \ $(TCC) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture \
$(TESTSRC) $(TOP)/src/tclsqlite.c $(TOP)/src/btree.c \ $(TESTSRC) $(TOP)/src/tclsqlite.c \
$(TOP)/src/pager.c libsqlite.a $(LIBGDBM) $(LIBTCL) libsqlite.a $(LIBGDBM) $(LIBTCL)
test: testfixture sqlite test: testfixture sqlite
./testfixture $(TOP)/test/all.test ./testfixture $(TOP)/test/all.test

View File

@@ -1 +1 @@
1.0.31 1.0.32

View File

@@ -1,16 +1,17 @@
C BTree\sand\spager\sare\sworking\spretty\swell\snow.\s(CVS\s234) C Add\sability\sto\squote\stable\sand\scolumn\snames\sin\sexpression.\s(CVS\s235)
D 2001-07-02T17:51:46 D 2001-07-23T14:33:03
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in df14e0f23d6946304d4681c24799d1ece965bf74 F Makefile.in a4595a83d56549b527dace5415729d20995f717b
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F VERSION 71874cb7e2a53c2bd22bb6affa7d223dd94a7a13 F VERSION 00453ed53ff28fe8e701e1609e81f1b9df12adab
F configure d2051345f49f7e48604423da26e086a745c86a47 x F configure d2051345f49f7e48604423da26e086a745c86a47 x
F configure.in e7465c88bbfb76882f97769c2dd90dbba8eca5db F configure.in e7465c88bbfb76882f97769c2dd90dbba8eca5db
F doc/lemon.html 3ddeef6e5dee69a2bb6f5d8e4975b58f2fd8e11c F doc/lemon.html 3ddeef6e5dee69a2bb6f5d8e4975b58f2fd8e11c
F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e
F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464 F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464
F notes/notes2.txt 7e3fafd5e25906c1fe1e95f13b089aa398ca403e F notes/notes2.txt 7e3fafd5e25906c1fe1e95f13b089aa398ca403e
F notes/notes3.txt 985bf688b59f1f52bfe6e4b1f896efdeffac1432 F notes/notes2b.txt 1c17a5b7f6b44a75cd3eb98ed2c24db1eefb06c3
F notes/notes3.txt 71e47be517e3d2578b3b9343a45b772d43b7ba16
F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4 F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
F src/btree.c d6bbe3152ce3eb47ffd0c797897bf75c5ca784fc F src/btree.c d6bbe3152ce3eb47ffd0c797897bf75c5ca784fc
F src/btree.h 5fb5799bcb39900386ce6cae61fa33e357851ffe F src/btree.h 5fb5799bcb39900386ce6cae61fa33e357851ffe
@@ -28,7 +29,7 @@ F src/ex/dbbemird.c b00aef85656fa0a101dac2c32e12922ad106715a
F src/ex/pg.c 2bbf6a94f37226d06337868b6bf4d7affc60197f F src/ex/pg.c 2bbf6a94f37226d06337868b6bf4d7affc60197f
F src/ex/pg.h 23a4ac807b0546ec2bb6239ec8bd3e06926572cd F src/ex/pg.h 23a4ac807b0546ec2bb6239ec8bd3e06926572cd
F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7 F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7
F src/expr.c c4c24c3af1eba094a816522eb0e085bed518ee16 F src/expr.c f64760004afc10c1c1232ae7ece2947452aa70dd
F src/insert.c aa528e20a787af85432a61daaea6df394bd251d7 F src/insert.c aa528e20a787af85432a61daaea6df394bd251d7
F src/main.c 0a13c7a2beb8ce36aee43daf8c95989b200727a7 F src/main.c 0a13c7a2beb8ce36aee43daf8c95989b200727a7
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
@@ -43,10 +44,8 @@ F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 3e5906f72608f0fd4394dfbb1d7e8d35b8353677 F src/sqlite.h.in 3e5906f72608f0fd4394dfbb1d7e8d35b8353677
F src/sqliteInt.h 47845c60e2e196b5409d774936a56700b1611f00 F src/sqliteInt.h 47845c60e2e196b5409d774936a56700b1611f00
F src/table.c adcaf074f6c1075e86359174e68701fa2acfc4d6 F src/table.c adcaf074f6c1075e86359174e68701fa2acfc4d6
F src/tclsqlite.c 7acb8887c44622214edb0dedeaab2593a3f86c62 F src/tclsqlite.c 386f502060325d9cb05d418bf0f1cf6a4b57c873
F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4 F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4
F src/test2.c 0183625225a860397b4fd3041aefb48f77e4630a
F src/test3.c e13021bfd3bbbe6ec6c26d1de15d1a86ba5aae44
F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf
F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6 F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6
F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc
@@ -54,8 +53,6 @@ F src/vdbe.c f93be4414ba892df9c5589815d2a57c1fb12c820
F src/vdbe.h dc1205da434c6a9da03b5d6b089270bbc8e6d437 F src/vdbe.h dc1205da434c6a9da03b5d6b089270bbc8e6d437
F src/where.c 0c542fc44bd85152dfb8507862cfe2e60c629e9f F src/where.c 0c542fc44bd85152dfb8507862cfe2e60c629e9f
F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048 F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048
F test/btree.test 084f03bfc05551baff13b5e6ba61713d31e5621d
F test/btree2.test 485210a30a8efaf629bdc5d923918bbce6fae658
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
@@ -68,8 +65,8 @@ F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
F test/main.test da635f9e078cd21ddf074e727381a715064489ff F test/main.test da635f9e078cd21ddf074e727381a715064489ff
F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861 F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861
F test/pager.test aa902a867ce6b925214d28e17400001946e0e5a4
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
F test/quote.test 40a3164af8456933a81312803fa8cdb21b205c12
F test/rowid.test 128453599def7435e988216f7fe89c7450b8a9a3 F test/rowid.test 128453599def7435e988216f7fe89c7450b8a9a3
F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f
F test/select2.test 04ac3bd69298f58c7d0883159bab42ab9ad6021c F test/select2.test 04ac3bd69298f58c7d0883159bab42ab9ad6021c
@@ -99,7 +96,7 @@ F www/arch.fig 4f246003b7da23bd63b8b0af0618afb4ee3055c8
F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6 F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6
F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be
F www/c_interface.tcl ddca19005c47dd5a15882addc02fff5de83d8ed9 F www/c_interface.tcl ddca19005c47dd5a15882addc02fff5de83d8ed9
F www/changes.tcl 822b425cc50cb8e21563dd1aa0e4b79cf780f3dc F www/changes.tcl a805374f79bba9a77fd88516163681dab323b5d0
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9 F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
@@ -110,7 +107,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2 F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P 55c89bfdd35f1ad494618a451f9a1ed08502ae07 P a84fb078baf96dbfb5983981127dfc905074b7f9
R 3d46d052f2a18aacc3a120e98e99a6ad R eec7e6db07d9a5655c1c80f7d8ed8318
U drh U drh
Z 32466dc4499f5824fce13920537543bc Z 7c7623637c745880923fb1ff59c11d78

View File

@@ -1 +1 @@
a84fb078baf96dbfb5983981127dfc905074b7f9 029e3a3a5dd8d4923af50bb2c9f31b1b7cd9439e

26
notes/notes2b.txt Normal file
View File

@@ -0,0 +1,26 @@
add_to_page(cursor, payload, child){
if( fits-on-current-page ){
insert (child,payload) into cursor
return
}
if( cursor is root page ){
split cursor+(child,payload) into page1, center, page2
set cursor page to page1,center,page2
return
}
if( move_some_data_left || move_some_data_right ){
add (child,payload) to cursor
return
}
split cursor+(child,payload) into self, center, page2
move_up(cursor)
add_to_page(cursor, center, page2)
}
split(in_page, payload, child_pgno, out_page1, center_payload, out_page2){
// It might be that in_page==out_page1
}

View File

@@ -1,65 +1,125 @@
The Proposed New SQLite 2.0 Interface design. (April 16, 2001) The Proposed New SQLite 2.0 Interface design. (April 16, 2001)
Primary access routines: Primary access routines:
Control functions:
sqlite *sqlite_open(const char *zFilename, int mode); sqlite *sqlite_open(const char *zFilename);
int sqlite_compile(sqlite*, const char *zSql); int sqlite_compile(sqlite*, const char *zSql);
int sqlite_row(sqlite*, int *argc, const char ***argv); int sqlite_next(sqlite*);
int sqlite_finish(sqlite*); int sqlite_abort(sqlite*);
int sqlite_close(sqlite*); int sqlite_finish(sqlite*);
sqlite *sqlite_dup(sqlite*);
int sqlite_close(sqlite*);
Access functions:
int sqlite_status(sqlite*);
char *sqlite_error_text(sqlite*);
int sqlite_column_count(sqlite*);
char **sqlite_column_names(sqlite*);
char **sqlite_values(sqlite*);
const char sqlite_version[];
const char sqlite_encoding[];
Secondary access routines: Secondary access routines:
Control functions:
int sqlite_complete(const char *);
char *sqlite_mprintf(const char *zFormat, ...)
char *sqlite_vmprintf(const char *zFormat, va_list ap);
int sqlite_compile_printf(sqlite*, const char *zFormat, ...);
int sqlite_compile_vprintf(sqlite*, const char *zFormat, va_list ap);
int sqlite_eval(sqlite*, const char *zSql);
int sqlite_retry(sqlite*);
int sqlite_eval_printf(sqlite*, const char *zFormat, ...);
int sqlite_eval_vprintf(sqlite*, const char *zFormat, va_list ap);
int sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*);
int sqlite_busy_timeout(sqlite*, int ms);
Access functions:
int sqlite_row_count(sqlite*);
char ***sqlite_rows(sqlite*, int iRow);
const char sqlite_version[]; Usage examples:
const char sqlite_encoding[]; Getting an entire result table in one go:
int sqlite_complete(const char *); sqlite *p = sqlite_open("ex.db");
sqlite *sqlite_dup(sqlite*); sqlite_eval(p, "SELECT * FROM table_one");
int sqlite_abort(sqlite*); for(i=0; i<sqlite_row_count(p); i++){
void sqlite_interrupt(sqlite*); if( i>0 ) printf("\n");
char *sqlite_errmsg(sqlite*); for(j=0; j<sqlite_column_count(p); j++){
const char **sqlite_columns(sqlite*); printf("%s = %s\n", sqlite_column_names(p)[j], sqlite_row(p,i)[j]);
int sqlite_argc(sqlite*); }
const char **sqlite_argv(sqlite*); }
char *sqlite_vmprintf(const char *zFormat, va_list); sqlite_close(p);
int sqlite_table(sqlite*, int *nrow, int *ncolumn, const char ***argv);
void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*);
Access routines that are derived from primary and secondary: Getting one row at a time:
sqlite *p = sqlite_open("ex.db");
sqlite_compile(p, "SELECT * FROM table_one");
for(i=0; sqlite_next(p)==SQLITE_OK; i++ ){
if( i>0 ) printf("\n");
for(j=0; j<sqlite_column_count(p); j++){
printf("%s = %s\n", sqlite_column_names(p)[j], sqlite_values(p)[j];
}
}
sqlite_close(p);
char *sqlite_mprintf(const char *zFormat, ...); Getting an entire result table with error and lock detection:
int sqlite_compile_vprintf(sqlite*, const char *zFormat, va_list); sqlite *p = sqlite_open("ex.db");
int sqlite_compile_printf(sqlite*, const char *zFormat, ...); if( p==0 ){
int sqlite_busy_timeout(sqlite*, int ms); fprintf(stderr,"out of memory");
return;
}
if( sqlite_status(p)!=SQLITE_OK ){
fprintf(stderr,"Error opening database: %s", sqlite_error_text(p));
sqlite_close(p);
return;
}
sqlite_busy_timeout(p, 5000);
sqlite_eval(p, "SELECT * FROM table_one");
if( sqlite_status(p)!=SQLITE_OK ){
fprintf(stderr,"Query error: %s\n", sqlite_error_text(p));
sqlite_close(p);
return;
}
for(i=0; i<sqlite_row_count(p); i++){
if( i>0 ) printf("\n");
for(j=0; j<sqlite_column_count(p); j++){
printf("%s = %s\n", sqlite_column_names(p)[j], sqlite_row(p,i)[j]);
}
}
sqlite_close(p);
The C++ interface is obvious... Getting one row at a time with manual control of lock conflicts:
sqlite *p = sqlite_open("ex.db");
Deprecated legacy interfaces: if( p==0 ){
fprintf(stderr,"out of memory");
int sqlite_exec( return;
sqlite*, }
char *sql, if( sqlite_status(p)!=SQLITE_OK ){
int (*)(void*,int,char**,char**), fprintf(stderr,"Error opening database: %s", sqlite_error_text(p));
void*, sqlite_close(p);
char **errmsg return;
); }
int sqlite_exec_printf(...); sqlite_compile(p, "SELECT * FROM table_one");
int sqlite_exec_vprintf(...); if( sqlite_status(p)!=SQLITE_OK ){
int sqlite_get_table( fprintf(stderr,"Query error: %s\n", sqlite_error_text(p));
sqlite*, sqlite_close(p);
char *sql, return;
const char ***result, }
int *nrow, for(i=0; sqlite_status(p)==SQLITE_OK; i++ ){
int *ncolumn, for(j=0; j<50 && sqlite_next(p)==SQLITE_BUSY; j++){
char **errmsg usleep(100000);
); }
void sqlite_free_table(char**); if( sqlite_status(p)!=SQLITE_OK ) break;
int sqlite_get_table_printf(...); if( i>0 ) printf("\n");
int sqlite_get_table_vprintf(...); for(j=0; j<sqlite_column_count(p); j++){
printf("%s = %s\n", sqlite_column_names(p)[j], sqlite_values(p)[j];
}
}
sqlite_close(p);
TCL Interface TCL Interface
sqlite DB FILENAME ?MODE? sqlite DB FILENAME ?MODE?
DB compile SQL DB compile SQL
DB next
DB status
DB errortext
DB row VAR DB row VAR
DB argc DB argc
DB argv ?N? DB argv ?N?

View File

@@ -24,7 +24,7 @@
** This file contains routines used for analyzing expressions and ** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions. ** for generating VDBE code that evaluates expressions.
** **
** $Id: expr.c,v 1.24 2001/04/11 14:28:42 drh Exp $ ** $Id: expr.c,v 1.25 2001/07/23 14:33:04 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -183,6 +183,8 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
sqliteFree(zRight); sqliteFree(zRight);
return 1; return 1;
} }
sqliteDequote(zLeft);
sqliteDequote(zRight);
pExpr->iTable = -1; pExpr->iTable = -1;
for(i=0; i<pTabList->nId; i++){ for(i=0; i<pTabList->nId; i++){
int j; int j;

View File

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

View File

@@ -1,416 +0,0 @@
/*
** 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.2 2001/04/28 16:52:42 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;
}

View File

@@ -1,844 +0,0 @@
/*
** 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.7 2001/07/02 17:51:46 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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,449 +0,0 @@
# 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.2 2001/07/02 17:51:47 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$dbprefix!="memory:" && [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

View File

@@ -1,261 +0,0 @@
# 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.6 2001/06/24 20:39:41 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

84
test/quote.test Normal file
View File

@@ -0,0 +1,84 @@
# 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/
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is the ability to specify table and column names
# as quoted strings.
#
# $Id: quote.test,v 1.1 2001/07/23 14:33:04 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Create a table with a strange name and with strange column names.
#
do_test quote-1.0 {
set r [catch {
execsql {CREATE TABLE '@abc' ( '#xyz' int, '!pqr' text );}
} msg]
lappend r $msg
} {0 {}}
# Insert, update and query the table.
#
do_test quote-1.1 {
set r [catch {
execsql {INSERT INTO '@abc' VALUES(5,'hello')}
} msg]
lappend r $msg
} {0 {}}
do_test quote-1.2 {
set r [catch {
execsql {SELECT * FROM '@abc'}
} msg ]
lappend r $msg
} {0 {5 hello}}
do_test quote-1.3 {
set r [catch {
execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
} msg ]
lappend r $msg
} {0 {hello 10}}
do_test quote-1.4 {
set r [catch {
execsql {UPDATE '@abc' SET '#xyz'=11}
} msg ]
lappend r $msg
} {0 {}}
do_test quote-1.5 {
set r [catch {
execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
} msg ]
lappend r $msg
} {0 {hello 16}}
# Drop the table with the strange name.
#
do_test quote-1.6 {
set r [catch {
execsql {DROP TABLE '@abc'}
} msg ]
lappend r $msg
} {0 {}}
finish_test

View File

@@ -17,6 +17,13 @@ proc chng {date desc} {
puts "<DD><P><UL>$desc</UL></P></DD>" puts "<DD><P><UL>$desc</UL></P></DD>"
} }
chng {2001 Jul 23 (1.0.32)} {
<li>Pager and btree subsystems removed. These will be used in a follow-on
SQL server library named "SQLus".</li>
<li>Add the ability to use quoted strings as table and column names in
expressions.</li>
}
chng {2001 Apr 14 (1.0.31)} { chng {2001 Apr 14 (1.0.31)} {
<li>Pager subsystem added but not yet used.</li> <li>Pager subsystem added but not yet used.</li>
<li>More robust handling of out-of-memory errors.</li> <li>More robust handling of out-of-memory errors.</li>