Whitespace, cleanup, and work to get the test harness functional

again.  It compiles, but still needs to be debugged.  Then, it's
time to run the tests and fix everything they find (a lot I
expect).
This commit is contained in:
Gregory Burd 2009-09-03 17:31:03 -04:00
parent e7dc5d2d04
commit fb683f6a7e
12 changed files with 2805 additions and 582 deletions

64
TODO
View file

@ -1,4 +1,9 @@
* Rename dbsql_strerror to dbsql_strerr
* Fix logic issue in query processing
tests/smoke2.sql produces incorrect joins
* Check all DB API calls
Make sure a) we check return codes for for all calls into DB and
that b) when there is an error we output it only when configured
@ -13,34 +18,40 @@
The library should never print messages unless configured to be
verbose.
* splint
Clean up all items pointed out by splint.
* tests/
Fix testing infrastructure.
- api.c/__os_sleep()
This is now static in DB's code, so to hack the compile I
commented out the use of __os_sleep() in api.c
- test/scr026
This test has not been updated to check for DBSQL API calls
rather than DB API calls. Review and fix it.
- test/scr030
Update this test to match the configure script. Augment it so
that as the configure script changes the script reports options
not tested.
- A few scr??? < 050
Some of these tests examine source code but do not include the
TCL testing code and so produce false positive FAILures.
- Add test/scr0?? to highlight code notes
FIXME, TODO, and other source source markers
* makedepend
* Code quality and build tools
- valgrind
Fix all memory related bugs.
- splint
Clean up all items pointed out by splint.
- makedepend
Finish integrating this into the dist/Makefile
* valgrind
Fix all memory related bugs.
* Review code for trailing spaces, tab characters, lines > 79 col
* review dbsql/dbsql.c
General clean-up including changing calls to malloc, free, etc to
__os_malloc, __os_free, etc.
* Review SQLite's latest lemon.c and lempar.c code
* Review code for trailing spaces, tab characters, lines > 79 col
* api.c/__os_sleep()
This is now static in DB's code, so to hack the compile I commented
out the use of __os_sleep() in api.c
* test/scr026
This test has not been updated to check for DBSQL API calls rather
than DB API calls. Review and fix it.
* test/scr030
Update this test to match the configure script. Augment it so that
as the configure script changes the script reports options not
tested.
Consider updating to the newest versions of the parser generator.
* Use LIST/QUEUE macros for linked lists, queues, etc.
Find/replace all custom code implementing these simple data
@ -48,13 +59,20 @@
* Review memory allocation code in general
* A few scr??? < 050 examine source but do not include the TCL testing code
* Consider using MPOOL to manage some of DBSQL state across processes
Function pools and other aspects of the DBSQL runtime need not be
re-created in-memory across multiple processes. When doing this
revisit data structures using the LIST/QUEUE macros and shift them
to the SH_ equivalents.
* Investigate the TCL Extension Architecture (http://www.tcl.tk/doc/tea/)
* Random number generator
SQLite implements its own suggesting that rand32_r() (and other
random number generators) are both truely random and bug free.
Some portion of the VDBE requires random numbers to be,
well... random, or as close as possible.
* Review src/vdbe, finish converting to DBSQL-style
* Investigate the TCL Extension Architecture
http://www.tcl.tk/doc/tea/

View file

@ -98,12 +98,12 @@ __init_callback(init, argc, argv, col_name)
case 'v': /* FALLTHROUGH */
case 'i': /* FALLTHROUGH */
case 't':
/* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
/* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
if (argv[2] == 0 || argv[4] == 0) {
__corrupt_schema(data);
return 1;
}
/*
/*
* Call the parser to process a CREATE TABLE, INDEX or VIEW.
* But because sParse.initFlag is set to 1, no VDBE code is
* generated or executed. All the parser does is build the
@ -185,7 +185,7 @@ __init_db_file(dbp, dbi, err_msgs)
/*
* The master database table has a structure like this
*/
static char master_schema[] =
static char master_schema[] =
"CREATE TABLE " MASTER_NAME "(\n"
" type text,\n"
" name text,\n"
@ -298,7 +298,7 @@ __init_db_file(dbp, dbi, err_msgs)
* used to store temporary tables, and any additional database files
* created using ATTACH statements. Return a success code. If an
* error occurs, write an error message into *pzErrMsg.
*
*
* After the database is initialized, the DBSQL_Initialized
* bit is set in the flags field of the dbsql_t structure. An
* attempt is made to initialize the database as soon as it
@ -315,7 +315,7 @@ __init_databases(dbp, err_msgs)
{
int i = 0;
int rc = DBSQL_SUCCESS;
DBSQL_ASSERT((dbp->flags & DBSQL_Initialized) == 0);
for(i = 0; rc == DBSQL_SUCCESS && i < dbp->nDb; i++) {
@ -408,7 +408,7 @@ __api_open(dbp, filename, mode, err_msgs)
dbp->priorNewRowid = 0;
dbp->magic = DBSQL_STATUS_BUSY;
dbp->nDb = 2;
if (__dbsql_calloc(dbp, 2, sizeof(dbsql_db_t), &dbp->aDb) == ENOMEM)
goto no_mem_on_open1;
@ -598,7 +598,7 @@ __process_sql(dbp, sql, callback, arg, tail, vm, err_msgs)
*err_msgs = 0;
}
}
/* TODO: in the __meta subdatabase get:'format_version'
/* TODO: in the __meta subdatabase get:'format_version'
if (dbp->file_format < 3) {
__safety_off(dbp);
__str_append(err_msgs, "obsolete database file format",
@ -700,7 +700,7 @@ int __api_exec(dbp, sql, callback, arg, err_msgs)
* err_msgs OUT: Write error messages here
*/
int
__api_prepare(dbp, sql, tail, stmt, err_msgs)
__api_prepare(dbp, sql, tail, stmt, err_msgs)
DBSQL *dbp;
const char *sql;
const char **tail;
@ -965,7 +965,7 @@ __api_get_encoding()
* user_data User data
* func The function's implementation
* step Step is used by aggregate functions
* finalize When finished with
* finalize When finished with
*/
int
__api_create_function(dbp, name, num_arg, user_data, encoding, func,
@ -1165,7 +1165,7 @@ __api_func_return_type(dbp, name, data_type)
func_def_t *p = (func_def_t*)__hash_find((hash_t*)dbp->fns, name,
strlen(name));
while(p) {
p->dataType = data_type;
p->dataType = data_type;
p = p->pNext;
}
return DBSQL_SUCCESS;
@ -1174,7 +1174,7 @@ __api_func_return_type(dbp, name, data_type)
/*
* __api_set_trace_callback --
* Register a trace function. The 'arg' from the previously
* registered trace is returned.
* registered trace is returned.
* A NULL trace function means that no tracing is executes. A non-NULL
* trace is a pointer to a function that is invoked at the start of each
* __api_exec().
@ -1339,7 +1339,7 @@ dbsql_create_env(dbpp, dir, crypt, mode, flags)
int env_open_flags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
DB_INIT_TXN | DB_CREATE;
/* Setup the DB_ENV with that directory as DB_HOME */
/* Setup the DB_ENV with that directory as DB_HOME */
if ((rc = db_env_create(&dbenv, 0)) != 0) {
__dbsql_err(NULL, "%s", db_strerror(rc));
return DBSQL_CANTOPEN;
@ -1349,11 +1349,12 @@ dbsql_create_env(dbpp, dir, crypt, mode, flags)
if (dir == 0 || dir[0] == '\0') {
/* When dir is NULL, place all resources in memory. */
env_open_flags |= DB_PRIVATE;
if ((rc = dbenv->log_set_config(dbenv, DB_LOG_IN_MEMORY, 1))!= 0) {
rc = dbenv->log_set_config(dbenv, DB_LOG_IN_MEMORY, 1);
if (rc) {
__dbsql_err(NULL, "%s\n", db_strerror(rc));
return DBSQL_CANTOPEN;
}
/* Specify the size of the in-memory log buffer. */
/* Specify the size of the in-memory log buffer. */
if ((rc = dbenv->set_lg_bsize(dbenv, 10 * 1024 * 1024)) != 0) {
__dbsql_err(NULL, "%s\n", db_strerror(rc));
return DBSQL_CANTOPEN;
@ -1430,7 +1431,7 @@ dbsql_create(dbpp, dbenv, flags)
{
DBSQL *dbp;
DBSQL_ASSERT(dbpp != 0);
if (dbenv == NULL)
return EINVAL; /* TODO better error message */
@ -1446,7 +1447,7 @@ dbsql_create(dbpp, dbenv, flags)
#else
DBSQL_GLOBAL(encoding) = "iso8859";
#endif
if (__dbsql_calloc(NULL, 1, sizeof(DBSQL), &dbp) == ENOMEM)
return DBSQL_NOMEM;

View file

@ -1026,8 +1026,8 @@ int __expr_resolve_ids(parser, slist, elist, expr)
* __get_function_name --
* 'expr' is a node that defines a function of some kind. It might
* be a syntactic function like "count(x)" or it might be a function
* that implements an operator, like "a LIKE b".
* This routine makes 'name' point to the name of the function and
* that implements an operator, like "a LIKE b".
* This routine makes 'name' point to the name of the function and
* 'len' hold the number of characters in the function name.
*
* STATIC: static void __get_function_name __P((expr_t *, const char **,
@ -1107,7 +1107,7 @@ __expr_check(parser, expr, agg_allowed, agg)
def = __find_function(parser->db, id, nid, -1, 0);
if (def == 0) {
if (n == 1 && nid == 6 &&
strncasecmp(id, "typeof",6) == 0) {
strncasecmp(id, "typeof",6) == 0) {
is_type_of = 1;
} else {
no_such_func = 1;
@ -1131,7 +1131,7 @@ __expr_check(parser, expr, agg_allowed, agg)
parser->nErr++;
nerr++;
} else if (wrong_num_args) {
__str_nappend(&parser->zErrMsg,
__str_nappend(&parser->zErrMsg,
"wrong number of arguments to function ",
-1, id, nid, "()", 2, NULL);
parser->nErr++;
@ -1159,8 +1159,7 @@ __expr_check(parser, expr, agg_allowed, agg)
}
} else if (def->dataType >= 0) {
if (def->dataType < n) {
expr->dataType =
__expr_type(expr->pList->a[def->dataType].pExpr);
expr->dataType = __expr_type(expr->pList->a[def->dataType].pExpr);
} else {
expr->dataType = DBSQL_SO_NUM;
}

View file

@ -218,7 +218,7 @@ struct __dbsql {
void (*get_errpfx) __P((DBSQL *, const char **));
DB_ENV *(*get_dbenv) __P((DBSQL *));
/* Callback access functions. */
/* Callback access functions. */
void *(*set_tracecall) __P((DBSQL *, void(*)(void *, const char *),\
void *));
#ifndef DBSQL_NO_PROGRESS
@ -247,9 +247,9 @@ struct __dbsql {
const char ***));
int (*create_function) __P((DBSQL *, const char *, int, int, void *,\
void (*)(dbsql_func_t *, int, const char**),\
void (*)(dbsql_func_t *, int, const char**),\
void (*)(dbsql_func_t *)));
void (*)(dbsql_func_t *, int, const char**), \
void (*)(dbsql_func_t *, int, const char**), \
void (*)(dbsql_func_t *)));
int (*func_return_type) __P((DBSQL *, const char *, int));
#define DBSQL_NUMERIC (-1)
#define DBSQL_TEXT (-2)
@ -307,8 +307,8 @@ struct __dbsql {
#define DBSQL_DETACH 25 /* Database Name NULL */
/* Non-callback access functions. */
int (*prepare) __P((DBSQL *, const char *, const char **, dbsql_stmt_t **,\
char **));
int (*prepare) __P((DBSQL *, const char *, const char **,\
dbsql_stmt_t **, char **));
int (*finalize) __P((dbsql_stmt_t *, char **));
int (*reset) __P((dbsql_stmt_t *, char **));
int (*bind) __P((dbsql_stmt_t *, int, const char *, int, int));
@ -400,7 +400,7 @@ void *dbsql_user_data __P((dbsql_func_t *));
void *dbsql_aggregate_context __P((dbsql_func_t *, int));
int dbsql_aggregate_count __P((dbsql_func_t *));
/*
/*
* The fifth parameter to dbsql_set_result_blob(), and
* dbsql_set_result_varchar() is a destructor used to dispose of the BLOB
* or text after DBSQL has finished with it. If the fifth argument is the

View file

@ -42,7 +42,7 @@ __min_func(context, argc, argv)
int argc;
const char **argv;
{
const char *best;
const char *best;
int i;
if (argc == 0)
@ -70,7 +70,7 @@ __max_func(context, argc, argv)
int argc;
const char **argv;
{
const char *best;
const char *best;
int i;
if (argc == 0)
@ -324,7 +324,7 @@ __lower_func(context, argc, argv)
/*
* __ifnull_func --
* Implementation of the IFNULL(), NVL(), and COALESCE() functions.
* Implementation of the IFNULL(), NVL(), and COALESCE() functions.
* All three do the same thing. They return the first non-NULL
* argument.
*/
@ -345,7 +345,7 @@ __ifnull_func(context, argc, argv)
/*
* __random_func --
* Implementation of random(). Return a random integer.
* Implementation of random(). Return a random integer.
*/
static void
__random_func(context, argc, argv)
@ -397,7 +397,7 @@ __like_func(context, argc, argv)
{
if (argv[0] == 0 || argv[1] == 0)
return;
dbsql_set_result_int(context,
dbsql_set_result_int(context,
__str_like_cmp((const unsigned char*)argv[0],
(const unsigned char*)argv[1]));
}

View file

@ -2980,12 +2980,8 @@ case OP_NewRecno: {
* than for this algorithm to fail.
*
* The analysis in the previous paragraph assumes that you
* have a good source of random numbers. Is a library
* function like lrand48() good enough? Maybe. Maybe not.
* It's hard to know whether there might be subtle bugs is
* some implementations of lrand48() that could cause problems.
* To avoid uncertainty, we implement our own random number
* generator based on the RC4 algorithm.
* have a good source of random numbers. We depend on the
* operating system's implementation of rand32_r().
*
* To promote locality of reference for repetitive inserts, the
* first few attempts at chosing a random rowid pick values

View file

@ -1,125 +1,58 @@
srcdir= ./
tstdir= ./tests
platform=unix
builddir=../../build_$(platform)
##################################################
# Installation directories and permissions.
##################################################
prefix= @prefix@
exec_prefix=@exec_prefix@
bindir= @bindir@
includedir=@includedir@
libdir= @libdir@
dmode= 755
emode= 555
fmode= 444
transform=@program_transform_name@
srcdir= ./
tstdir= ./tests
platform= unix
builddir= ../../build_$(platform)
##################################################
# Paths for standard user-level commands.
##################################################
SHELL= @db_cv_path_sh@
ar= @db_cv_path_ar@
awk= @db_cv_path_awk@
chmod= @db_cv_path_chmod@
cp= @db_cv_path_cp@
depend= @db_cv_path_makedepend@
grep= @db_cv_path_grep@
ln= @db_cv_path_ln@
mkdir= @db_cv_path_mkdir@
ranlib= @db_cv_path_ranlib@
rm= @db_cv_path_rm@
rpm= @db_cv_path_rpm@
sed= @db_cv_path_sed@
splint= @db_cv_path_splint@
strip= @db_cv_path_strip@
##################################################
# General library information.
##################################################
DEF_LIB= @DEFAULT_LIB@
DEF_LIB_CXX= @DEFAULT_LIB_CXX@
INSTALLER= @INSTALLER@
LIBTOOL= $(SHELL) $(builddir)/libtool
POSTLINK= @POSTLINK@
SOLINK= @MAKEFILE_SOLINK@
SOFLAGS= @SOFLAGS@
LIBMAJOR= @DBSQL_VERSION_MAJOR@
LIBVERSION= @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@
CPPFLAGS= -I$(builddir) -I$(srcdir) -I../../src \
@TCL_CFLAGS@ \
@CPPFLAGS@
DBSQL_LIB= dbsql-$(LIBVERSION)
##################################################
# C API.
##################################################
CFLAGS= -c $(CPPFLAGS) @CFLAGS@
CFLAGS= -c $(CPPFLAGS) @CFLAGS@
CC= @MAKEFILE_CC@
CCLINK= @MAKEFILE_CCLINK@
LDFLAGS= @LDFLAGS@ @TCL_LD_FLAGS@
LIBS= @LIBS@ @TCL_LIBS@ @TCL_LIB_SPEC@ @LIBSO_LIBS@
##################################################
# TCL testing harness.
##################################################
libtso_base= libdbsql_tcl
libtso= $(libtso_base)-$(LIBVERSION)@MODSUFFIX@
libtso_static= $(libtso_base)-$(LIBVERSION).a
libtso_target= $(libtso_base)-$(LIBVERSION).la
libtso_default= $(libtso_base)@MODSUFFIX@
libtso_major= $(libtso_base)-$(LIBMAJOR)@MODSUFFIX@
##################################################
# NOTHING BELOW THIS LINE SHOULD EVER NEED TO BE MODIFIED.
##################################################
CPPFLAGS= -I$(builddir) -I$(srcdir) -I../../src \
@TCL_CFLAGS@ \
@CPPFLAGS@
##################################################
# Source file lists.
##################################################
TCL_FILES=\
$(scrdir)/tcl_internal.c \
$(scrdir)/tcl_dbsql.c $(scrdir)/tcl_printf.c \
$(scrdir)/tcl_randstr.c $(scrdir)/tcl_sql_funcs.c \
$(scrdir)/tcl_test_sh.c $(scrdir)/tcl_threads.c \
$(scrdir)/tcl_md5.c
TCL_OBJS=\
tcl_md5@o@ tcl_printf@o@ tcl_randstr@o@ tcl_threads@o@ \
tcl_sql_funcs@o@ tcl_internal@o@ \
tcl_dbsql@o@
tcl_md5@o@
##################################################
# Note: "all" must be the first target in the Makefile.
##################################################
all: @BUILD_TARGET@ dbsql_tclsh
##################################################
# Library and standard utilities build.
##################################################
library_build: @INSTALL_LIBS@ @ADDITIONAL_LANG@ $(UTIL_PROGS)
# Shared Tcl library.
$(libtso_target): $(builddir)/dbsql_int.h $(builddir)/sql_parser.h $(builddir)/opcodes.h $(TCL_OBJS) $(C_OBJS)
$(SOLINK) @LIBTSO_MODULE@ $(SOFLAGS) $(LDFLAGS) \
-o $@ $(TCL_OBJS) $(C_OBJS)
all: dbsql_tclsh
##################################################
# Utilities
##################################################
dbsql_tclsh: $(libtso_target) dbsql_tclsh@o@
$(CCLINK) -o $@ $(LDFLAGS) dbsql_tclsh@o@\
.libs/$(libtso_static)\
-L../../build_unix -ldbsql-0.2\
$(LIBS)
dbsql_tclsh: $(TCL_OBJS) dbsql_tclsh@o@
$(CCLINK) -o $@ $(LDFLAGS) $(TCL_OBJS) dbsql_tclsh@o@ \
-L$(builddir) -l$(DBSQL_LIB) $(LIBS)
$(POSTLINK) $@
##################################################
@ -145,29 +78,12 @@ REALCLEAN_LIST=\
Makefile
##################################################
# Tcl API build rules.
##################################################
tcl_dbsql@o@: $(srcdir)/tcl_dbsql.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_dbsql_pkg@o@: $(srcdir)/tcl_dbsql_pkg.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_internal@o@: $(srcdir)/tcl_internal.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_md5@o@: $(srcdir)/tcl_md5.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_printf@o@: $(srcdir)/tcl_printf.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_randstr@o@: $(srcdir)/tcl_randstr.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_sql_funcs@o@: $(srcdir)/tcl_sql_funcs.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
tcl_threads@o@: $(srcdir)/tcl_threads.c
$(CC) $(CFLAGS) $(TCL_CFLAGS) $?
##################################################
# Utility build rules.
# Build rules.
##################################################
dbsql_tclsh@o@: $(srcdir)/dbsql_tclsh.c
$(CC) $(CFLAGS) $?
tcl_md5@o@: $(srcdir)/tcl_md5.c
$(CC) $(CFLAGS) $?

File diff suppressed because it is too large Load diff

View file

@ -1035,7 +1035,7 @@ __tcl_dbsql_cmd_impl(_dbctx, interp, objc, objv)
* The mode of the database to be created.
*
* ?-key KEY?
*
*
*
* -encoding
* Return the encoding used by LIKE and GLOB operators. Choices
@ -1046,7 +1046,7 @@ __tcl_dbsql_cmd_impl(_dbctx, interp, objc, objv)
*
* -tcl-uses-utf
* Return "1" if compiled with a Tcl uses UTF-8. Return "0" if
* not. Used by tests to make sure the library was compiled
* not. Used by tests to make sure the library was compiled
* correctly.
*/
static int
@ -1100,7 +1100,7 @@ __tcl_dbsql_impl(_dbctx, interp, objc, objv)
}
}
if (objc != 3 && objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv,
Tcl_WrongNumArgs(interp, 1, objv,
"HANDLE FILENAME ?MODE? ?-key CRYPTOKEY?");
return TCL_ERROR;
}
@ -1117,8 +1117,8 @@ __tcl_dbsql_impl(_dbctx, interp, objc, objv)
}
memset(dbctx, 0, sizeof(*dbctx));
filename = Tcl_GetStringFromObj(objv[2], 0);
/* First setup the DB_ENV */
/* First setup the DB_ENV */
if ((rc = db_env_create(&dbctx->dbenv, 0)) != 0) {
Tcl_SetResult(interp, db_strerror(rc), TCL_STATIC);
return TCL_ERROR;

View file

@ -47,7 +47,7 @@
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
struct Context {
u_int32_t buf[4];
@ -64,13 +64,13 @@ byteReverse(buf, longs)
unsigned char *buf;
unsigned longs;
{
u_int32_t t;
do {
t = (u_int32_t)((unsigned)buf[3] << 8 | buf[2]) << 16 |
u_int32_t t;
do {
t = (u_int32_t)((unsigned)buf[3] << 8 | buf[2]) << 16 |
((unsigned)buf[1] << 8 | buf[0]);
*(u_int32_t *)buf = t;
buf += 4;
} while (--longs);
*(u_int32_t *)buf = t;
buf += 4;
} while (--longs);
}
/*
@ -83,85 +83,85 @@ MD5Transform(buf, in)
u_int32_t buf[4];
const u_int32_t in[16];
{
register u_int32_t a, b, c, d;
register u_int32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
@ -172,72 +172,71 @@ static void
MD5Init(pCtx)
MD5Context *pCtx;
{
struct Context *ctx = (struct Context *)pCtx;
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
struct Context *ctx = (struct Context *)pCtx;
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
static
void
static void
MD5Update(pCtx, buf, len)
MD5Context *pCtx;
const unsigned char *buf;
unsigned int len;
{
struct Context *ctx = (struct Context *)pCtx;
u_int32_t t;
struct Context *ctx = (struct Context *)pCtx;
u_int32_t t;
/* Update bitcount */
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((u_int32_t)len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((u_int32_t)len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
/* Handle any leading odd-sized chunks */
if ( t ) {
unsigned char *p = (unsigned char *)ctx->in + t;
if ( t ) {
unsigned char *p = (unsigned char *)ctx->in + t;
t = 64-t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
buf += t;
len -= t;
}
t = 64-t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
buf += 64;
len -= 64;
}
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
static void
@ -245,44 +244,44 @@ MD5Final(digest, pCtx)
unsigned char digest[16];
MD5Context *pCtx;
{
struct Context *ctx = (struct Context *)pCtx;
unsigned count;
unsigned char *p;
struct Context *ctx = (struct Context *)pCtx;
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count-8);
}
byteReverse(ctx->in, 14);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count-8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((u_int32_t *)ctx->in)[ 14 ] = ctx->bits[0];
((u_int32_t *)ctx->in)[ 15 ] = ctx->bits[1];
/* Append length in bits and transform */
((u_int32_t *)ctx->in)[ 14 ] = ctx->bits[0];
((u_int32_t *)ctx->in)[ 15 ] = ctx->bits[1];
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
MD5Transform(ctx->buf, (u_int32_t *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
/*
@ -309,7 +308,7 @@ DigestToBase16(digest, zBuf)
/*
* A TCL command for md5. The argument is the text to be hashed. The
* Result is the hash in base64.
* Result is the hash in base64.
*/
static int
md5_cmd(cd, interp, argc, argv)
@ -350,13 +349,13 @@ md5file_cmd(cd, interp, argc, argv)
char zBuf[10240];
if( argc!=2 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
" FILENAME\"", 0);
return TCL_ERROR;
}
in = fopen(argv[1],"rb");
if( in==0 ){
Tcl_AppendResult(interp,"unable to open file \"", argv[1],
Tcl_AppendResult(interp,"unable to open file \"", argv[1],
"\" for reading", 0);
return TCL_ERROR;
}

View file

@ -1,6 +1,6 @@
/*
* Code for testing the xprintf() function. This code is used for testing
* only and will not be included when the library is built without
* only and will not be included when the library is built without
* CONFIG_TEST set.
*/
@ -14,7 +14,7 @@
#include "dbsql_int.h"
#include "tcl.h"
/* __testset_1 --------------------------------------------------------------*/
#ifdef DB_WIN32
#define PTR_FMT "%x"
#else
@ -31,7 +31,7 @@ get_dbsql_from_ptr(interp, args, dbsqlp)
const char *args;
DBSQL **dbsqlp;
{
if (sscanf(args, PTR_FMT, (void**)dbsqlp) != 1 &&
if (sscanf(args, PTR_FMT, (void**)dbsqlp) != 1 &&
(args[0] != '0' || args[1] != 'x' ||
sscanf(&args[2], PTR_FMT, (void**)dbsqlp) != 1)) {
Tcl_AppendResult(interp,
@ -120,7 +120,7 @@ test_dbsql_env_create(notused, interp, argc, argv)
argv[0], " FILENAME\"", 0);
return TCL_ERROR;
}
if ((rc = dbsql_create_env(&db, argv[1], NULL, 0, DBSQL_THREAD))
!= DBSQL_SUCCESS) {
Tcl_AppendResult(interp, dbsql_strerror(rc), 0);
@ -1157,15 +1157,16 @@ TODO
for(i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
}
Tcl_LinkVar(interp, "dbsql_search_count",
Tcl_LinkVar(interp, "dbsql_search_count",
(char*)&dbsql_search_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "dbsql_interrupt_count",
Tcl_LinkVar(interp, "dbsql_interrupt_count",
(char*)&dbsql_interrupt_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "dbsql_open_file_count",
Tcl_LinkVar(interp, "dbsql_open_file_count",
(char*)&dbsql_open_file_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "dbsql_current_time",
Tcl_LinkVar(interp, "dbsql_current_time",
(char*)&_fake_current_time, TCL_LINK_INT);
Tcl_LinkVar(interp, "dbsql_static_bind_value",
(char*)&dbsql_static_bind_value, TCL_LINK_STRING);
return TCL_OK;
}
/* end of __testset_1 -------------------------------------------------------*/

View file

@ -1,242 +0,0 @@
# This file implements some common TCL routines used for regression
# testing the DBSQL library
# Make sure the Tcl API was compiled such that we encode/decode strings
# passed between the two libraries properly. Abort now with an error
# message if not.
#
if {[dbsql -tcl-uses-utf]} {
if {"\u1234"=="u1234"} {
puts stderr "***** BUILD PROBLEM *****"
puts stderr "$argv0 was linked against an older version"
puts stderr "of Tcl that does not support Unicode, but uses a header"
puts stderr "file (\"tcl.h\") from a new Tcl version that does support"
puts stderr "Unicode. This combination causes internal errors."
puts stderr "Recompile using a Tcl library and header file that match"
puts stderr "and try again."
puts stderr "**************************"
exit 1
}
} else {
if {"\u1234"!="u1234"} {
puts stderr "***** BUILD PROBLEM *****"
puts stderr "$argv0 was linked against an newer version"
puts stderr "of Tcl that supports Unicode, but uses a header file"
puts stderr "(\"tcl.h\") from a old Tcl version that does not support"
puts stderr "Unicode. This combination causes internal errors."
puts stderr "Recompile using a Tcl library and header file that match"
puts stderr "and try again."
puts stderr "**************************"
exit 1
}
}
# Create a test database.
#
catch {db close}
file delete -force test.db
file delete -force test.db-journal
dbsql db ./test.db
if {[info exists ::SETUP_SQL]} {
db eval $::SETUP_SQL
}
# Abort early if this script has been run before.
#
if {[info exists nTest]} return
# Set the test counters to zero.
#
set nErr 0
set nTest 0
set nProb 0
set skip_test 0
set failList {}
# Invoke the do_test procedure to run a single test
#
proc do_test {name cmd expected} {
global argv nErr nTest skip_test
if {$skip_test} {
set skip_test 0
return
}
if {[llength $argv]==0} {
set go 1
} else {
set go 0
foreach pattern $argv {
if {[string match $pattern $name]} {
set go 1
break
}
}
}
if {!$go} return
incr nTest
puts -nonewline $name...
flush stdout
if {[catch {uplevel #0 "$cmd;\n"} result]} {
puts "\nError: $result"
incr nErr
lappend ::failList $name
if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
} elseif {[string compare $result $expected]} {
puts "\nExpected: \[$expected\]\n Got: \[$result\]"
incr nErr
lappend ::failList $name
if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
} else {
puts " Ok"
}
}
# Invoke this procedure on a test that is probabilistic
# and might fail sometimes.
#
proc do_probtest {name cmd expected} {
global argv nProb nTest skip_test
if {$skip_test} {
set skip_test 0
return
}
if {[llength $argv]==0} {
set go 1
} else {
set go 0
foreach pattern $argv {
if {[string match $pattern $name]} {
set go 1
break
}
}
}
if {!$go} return
incr nTest
puts -nonewline $name...
flush stdout
if {[catch {uplevel #0 "$cmd;\n"} result]} {
puts "\nError: $result"
incr nErr
} elseif {[string compare $result $expected]} {
puts "\nExpected: \[$expected\]\n Got: \[$result\]"
puts "NOTE: The results of the previous test depend on system load"
puts "and processor speed. The test may sometimes fail even if the"
puts "library is working correctly."
incr nProb
} else {
puts " Ok"
}
}
# The procedure uses the special "dbsql_malloc_stat" command
# (which is only available if Dbsql is compiled with -DMEMORY_DEBUG=1)
# to see how many malloc()s have not been free()ed. The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
if {[info command dbsql_malloc_stat]!=""} {
set r [dbsql_malloc_stat]
set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
}
}
# Run this routine last
#
proc finish_test {} {
finalize_testing
}
proc finalize_testing {} {
global nTest nErr nProb dbsql_open_file_count
if {$nErr==0} memleak_check
catch {db close}
puts "$nErr errors out of $nTest tests"
puts "Failures on these tests: $::failList"
if {$nProb>0} {
puts "$nProb probabilistic tests also failed, but this does"
puts "not necessarily indicate a malfunction."
}
if {$dbsql_open_file_count} {
puts "$dbsql_open_file_count files were left open"
incr nErr
}
exit [expr {$nErr>0}]
}
# A procedure to execute SQL
#
proc execsql {sql {db db}} {
# puts "SQL = $sql"
return [$db eval $sql]
}
# Execute SQL and catch exceptions.
#
proc catchsql {sql {db db}} {
# puts "SQL = $sql"
set r [catch {$db eval $sql} msg]
lappend r $msg
return $r
}
# Do an VDBE code dump on the SQL given
#
proc explain {sql {db db}} {
puts ""
puts "addr opcode p1 p2 p3 "
puts "---- ------------ ------ ------ ---------------"
$db eval "explain $sql" {} {
puts [format {%-4d %-12.12s %-6d %-6d %s} $addr $opcode $p1 $p2 $p3]
}
}
# Another procedure to execute SQL. This one includes the field
# names in the returned list.
#
proc execsql2 {sql} {
set result {}
db eval $sql data {
foreach f $data(*) {
lappend result $f $data($f)
}
}
return $result
}
# Use the non-callback API to execute multiple SQL statements
#
proc stepsql {dbptr sql} {
set sql [string trim $sql]
set r 0
while {[string length $sql]>0} {
if {[catch {dbsql_compile $dbptr $sql sqltail} vm]} {
return [list 1 $vm]
}
set sql [string trim $sqltail]
while {[dbsql_step $vm N VAL COL]=="DBSQL_ROW"} {
foreach v $VAL {lappend r $v}
}
if {[catch {dbsql_close_sqlvm $vm} errmsg]} {
return [list 1 $errmsg]
}
}
return $r
}
# Delete a file or directory
#
proc forcedelete {filename} {
if {[catch {file delete -force $filename}]} {
exec rm -rf $filename
}
}
# Do an integrity check of the entire database
#
proc integrity_check {name} {
do_test $name {
execsql {PRAGMA integrity_check}
} {ok}
}