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:
18
Makefile.in
18
Makefile.in
@@ -47,8 +47,8 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
|
||||
|
||||
# Object files for the SQLite library.
|
||||
#
|
||||
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 \
|
||||
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 \
|
||||
tokenize.o update.o util.o vdbe.o where.o tclsqlite.o
|
||||
|
||||
# All of the source code files.
|
||||
@@ -83,8 +83,6 @@ SRC = \
|
||||
#
|
||||
TESTSRC = \
|
||||
$(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
|
||||
@@ -118,15 +116,10 @@ lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
||||
HDR = \
|
||||
sqlite.h \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/btree.h \
|
||||
$(TOP)/src/dbbe.h \
|
||||
$(TOP)/src/pager.h \
|
||||
$(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
|
||||
|
||||
@@ -195,9 +188,6 @@ tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
printf.o: $(TOP)/src/printf.c $(HDR)
|
||||
$(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
|
||||
$(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)
|
||||
$(TCC) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c $(TOP)/src/btree.c \
|
||||
$(TOP)/src/pager.c libsqlite.a $(LIBGDBM) $(LIBTCL)
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c \
|
||||
libsqlite.a $(LIBGDBM) $(LIBTCL)
|
||||
|
||||
test: testfixture sqlite
|
||||
./testfixture $(TOP)/test/all.test
|
||||
|
29
manifest
29
manifest
@@ -1,16 +1,17 @@
|
||||
C BTree\sand\spager\sare\sworking\spretty\swell\snow.\s(CVS\s234)
|
||||
D 2001-07-02T17:51:46
|
||||
C Add\sability\sto\squote\stable\sand\scolumn\snames\sin\sexpression.\s(CVS\s235)
|
||||
D 2001-07-23T14:33:03
|
||||
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
||||
F Makefile.in df14e0f23d6946304d4681c24799d1ece965bf74
|
||||
F Makefile.in a4595a83d56549b527dace5415729d20995f717b
|
||||
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
|
||||
F VERSION 71874cb7e2a53c2bd22bb6affa7d223dd94a7a13
|
||||
F VERSION 00453ed53ff28fe8e701e1609e81f1b9df12adab
|
||||
F configure d2051345f49f7e48604423da26e086a745c86a47 x
|
||||
F configure.in e7465c88bbfb76882f97769c2dd90dbba8eca5db
|
||||
F doc/lemon.html 3ddeef6e5dee69a2bb6f5d8e4975b58f2fd8e11c
|
||||
F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e
|
||||
F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464
|
||||
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/btree.c d6bbe3152ce3eb47ffd0c797897bf75c5ca784fc
|
||||
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.h 23a4ac807b0546ec2bb6239ec8bd3e06926572cd
|
||||
F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7
|
||||
F src/expr.c c4c24c3af1eba094a816522eb0e085bed518ee16
|
||||
F src/expr.c f64760004afc10c1c1232ae7ece2947452aa70dd
|
||||
F src/insert.c aa528e20a787af85432a61daaea6df394bd251d7
|
||||
F src/main.c 0a13c7a2beb8ce36aee43daf8c95989b200727a7
|
||||
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
|
||||
@@ -43,10 +44,8 @@ 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 7acb8887c44622214edb0dedeaab2593a3f86c62
|
||||
F src/tclsqlite.c 386f502060325d9cb05d418bf0f1cf6a4b57c873
|
||||
F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4
|
||||
F src/test2.c 0183625225a860397b4fd3041aefb48f77e4630a
|
||||
F src/test3.c e13021bfd3bbbe6ec6c26d1de15d1a86ba5aae44
|
||||
F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf
|
||||
F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6
|
||||
F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc
|
||||
@@ -54,8 +53,6 @@ F src/vdbe.c f93be4414ba892df9c5589815d2a57c1fb12c820
|
||||
F src/vdbe.h dc1205da434c6a9da03b5d6b089270bbc8e6d437
|
||||
F src/where.c 0c542fc44bd85152dfb8507862cfe2e60c629e9f
|
||||
F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048
|
||||
F test/btree.test 084f03bfc05551baff13b5e6ba61713d31e5621d
|
||||
F test/btree2.test 485210a30a8efaf629bdc5d923918bbce6fae658
|
||||
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
|
||||
F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
|
||||
F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
|
||||
@@ -68,8 +65,8 @@ F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
|
||||
F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
|
||||
F test/main.test da635f9e078cd21ddf074e727381a715064489ff
|
||||
F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861
|
||||
F test/pager.test aa902a867ce6b925214d28e17400001946e0e5a4
|
||||
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
|
||||
F test/quote.test 40a3164af8456933a81312803fa8cdb21b205c12
|
||||
F test/rowid.test 128453599def7435e988216f7fe89c7450b8a9a3
|
||||
F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f
|
||||
F test/select2.test 04ac3bd69298f58c7d0883159bab42ab9ad6021c
|
||||
@@ -99,7 +96,7 @@ F www/arch.fig 4f246003b7da23bd63b8b0af0618afb4ee3055c8
|
||||
F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6
|
||||
F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be
|
||||
F www/c_interface.tcl ddca19005c47dd5a15882addc02fff5de83d8ed9
|
||||
F www/changes.tcl 822b425cc50cb8e21563dd1aa0e4b79cf780f3dc
|
||||
F www/changes.tcl a805374f79bba9a77fd88516163681dab323b5d0
|
||||
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
|
||||
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
|
||||
F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
|
||||
@@ -110,7 +107,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
|
||||
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
|
||||
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
|
||||
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
|
||||
P 55c89bfdd35f1ad494618a451f9a1ed08502ae07
|
||||
R 3d46d052f2a18aacc3a120e98e99a6ad
|
||||
P a84fb078baf96dbfb5983981127dfc905074b7f9
|
||||
R eec7e6db07d9a5655c1c80f7d8ed8318
|
||||
U drh
|
||||
Z 32466dc4499f5824fce13920537543bc
|
||||
Z 7c7623637c745880923fb1ff59c11d78
|
||||
|
@@ -1 +1 @@
|
||||
a84fb078baf96dbfb5983981127dfc905074b7f9
|
||||
029e3a3a5dd8d4923af50bb2c9f31b1b7cd9439e
|
26
notes/notes2b.txt
Normal file
26
notes/notes2b.txt
Normal 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
|
||||
|
||||
}
|
146
notes/notes3.txt
146
notes/notes3.txt
@@ -1,65 +1,125 @@
|
||||
The Proposed New SQLite 2.0 Interface design. (April 16, 2001)
|
||||
|
||||
Primary access routines:
|
||||
|
||||
sqlite *sqlite_open(const char *zFilename, int mode);
|
||||
Control functions:
|
||||
sqlite *sqlite_open(const char *zFilename);
|
||||
int sqlite_compile(sqlite*, const char *zSql);
|
||||
int sqlite_row(sqlite*, int *argc, const char ***argv);
|
||||
int sqlite_next(sqlite*);
|
||||
int sqlite_abort(sqlite*);
|
||||
int sqlite_finish(sqlite*);
|
||||
sqlite *sqlite_dup(sqlite*);
|
||||
int sqlite_close(sqlite*);
|
||||
|
||||
Secondary access routines:
|
||||
|
||||
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:
|
||||
Control functions:
|
||||
int sqlite_complete(const char *);
|
||||
sqlite *sqlite_dup(sqlite*);
|
||||
int sqlite_abort(sqlite*);
|
||||
void sqlite_interrupt(sqlite*);
|
||||
char *sqlite_errmsg(sqlite*);
|
||||
const char **sqlite_columns(sqlite*);
|
||||
int sqlite_argc(sqlite*);
|
||||
const char **sqlite_argv(sqlite*);
|
||||
char *sqlite_vmprintf(const char *zFormat, va_list);
|
||||
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:
|
||||
|
||||
char *sqlite_mprintf(const char *zFormat, ...);
|
||||
int sqlite_compile_vprintf(sqlite*, const char *zFormat, va_list);
|
||||
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);
|
||||
|
||||
The C++ interface is obvious...
|
||||
Usage examples:
|
||||
Getting an entire result table in one go:
|
||||
sqlite *p = sqlite_open("ex.db");
|
||||
sqlite_eval(p, "SELECT * FROM table_one");
|
||||
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);
|
||||
|
||||
Deprecated legacy interfaces:
|
||||
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);
|
||||
|
||||
int sqlite_exec(
|
||||
sqlite*,
|
||||
char *sql,
|
||||
int (*)(void*,int,char**,char**),
|
||||
void*,
|
||||
char **errmsg
|
||||
);
|
||||
int sqlite_exec_printf(...);
|
||||
int sqlite_exec_vprintf(...);
|
||||
int sqlite_get_table(
|
||||
sqlite*,
|
||||
char *sql,
|
||||
const char ***result,
|
||||
int *nrow,
|
||||
int *ncolumn,
|
||||
char **errmsg
|
||||
);
|
||||
void sqlite_free_table(char**);
|
||||
int sqlite_get_table_printf(...);
|
||||
int sqlite_get_table_vprintf(...);
|
||||
Getting an entire result table with error and lock detection:
|
||||
sqlite *p = sqlite_open("ex.db");
|
||||
if( p==0 ){
|
||||
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);
|
||||
|
||||
Getting one row at a time with manual control of lock conflicts:
|
||||
sqlite *p = sqlite_open("ex.db");
|
||||
if( p==0 ){
|
||||
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_compile(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; sqlite_status(p)==SQLITE_OK; i++ ){
|
||||
for(j=0; j<50 && sqlite_next(p)==SQLITE_BUSY; j++){
|
||||
usleep(100000);
|
||||
}
|
||||
if( sqlite_status(p)!=SQLITE_OK ) break;
|
||||
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);
|
||||
|
||||
TCL Interface
|
||||
|
||||
sqlite DB FILENAME ?MODE?
|
||||
DB compile SQL
|
||||
DB next
|
||||
DB status
|
||||
DB errortext
|
||||
DB row VAR
|
||||
DB argc
|
||||
DB argv ?N?
|
||||
|
@@ -24,7 +24,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** 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"
|
||||
|
||||
@@ -183,6 +183,8 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
|
||||
sqliteFree(zRight);
|
||||
return 1;
|
||||
}
|
||||
sqliteDequote(zLeft);
|
||||
sqliteDequote(zRight);
|
||||
pExpr->iTable = -1;
|
||||
for(i=0; i<pTabList->nId; i++){
|
||||
int j;
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*************************************************************************
|
||||
** 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 */
|
||||
|
||||
@@ -510,12 +510,8 @@ 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
416
src/test2.c
@@ -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;
|
||||
}
|
844
src/test3.c
844
src/test3.c
@@ -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;
|
||||
}
|
1030
test/btree.test
1030
test/btree.test
File diff suppressed because it is too large
Load Diff
449
test/btree2.test
449
test/btree2.test
@@ -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
|
261
test/pager.test
261
test/pager.test
@@ -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
84
test/quote.test
Normal 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
|
@@ -17,6 +17,13 @@ proc chng {date desc} {
|
||||
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)} {
|
||||
<li>Pager subsystem added but not yet used.</li>
|
||||
<li>More robust handling of out-of-memory errors.</li>
|
||||
|
Reference in New Issue
Block a user