diff --git a/Makefile.in b/Makefile.in index c317a99c4c..a1362aa016 100644 --- a/Makefile.in +++ b/Makefile.in @@ -196,16 +196,16 @@ gdbmdump: $(TOP)/tool/gdbmdump.c $(TCC) $(GDBM_FLAGS) -o gdbmdump $(TOP)/tool/gdbmdump.c $(LIBGDBM) tclsqlite: $(TOP)/src/tclsqlite.c libsqlite.a - $(TCC) $(TCL_FLAGS) -DTCLSH=1 -o sqlite_tester \ + $(TCC) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite \ $(TOP)/src/tclsqlite.c libsqlite.a $(LIBGDBM) $(LIBTCL) -sqlite_tester: $(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC) - $(TCC) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o sqlite_tester \ +testfixture: $(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC) + $(TCC) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture \ $(TESTSRC) $(TOP)/src/tclsqlite.c \ libsqlite.a $(LIBGDBM) $(LIBTCL) -test: sqlite_tester sqlite - ./sqlite_tester $(TOP)/test/all.test +test: testfixture sqlite + ./testfixture $(TOP)/test/all.test sqlite.tar.gz: pwd=`pwd`; cd $(TOP)/..; tar czf $$pwd/sqlite.tar.gz sqlite diff --git a/configure b/configure index 23639edbc5..5d1c70a6bc 100755 --- a/configure +++ b/configure @@ -15,6 +15,8 @@ ac_help="$ac_help --with-hints=FILE Read configuration options from FILE" ac_help="$ac_help --enable-utf8 Use UTF-8 encodings" +ac_help="$ac_help + --disable-gdbm Omit the GDBM drivers" # Initialize some variables set by options. # The variables have the same names as the options, with @@ -527,7 +529,7 @@ fi # The following RCS revision string applies to configure.in -# $Revision: 1.9 $ +# $Revision: 1.10 $ ######### # Make sure we are not building in a subdirectory of the source tree. @@ -602,7 +604,7 @@ if test "$config_BUILD_CC" = ""; then # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:606: checking for $ac_word" >&5 +echo "configure:608: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -632,7 +634,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:636: checking for $ac_word" >&5 +echo "configure:638: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -683,7 +685,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:687: checking for $ac_word" >&5 +echo "configure:689: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -715,7 +717,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:719: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:721: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -726,12 +728,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 730 "configure" +#line 732 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:737: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -757,12 +759,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:761: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:763: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:766: checking whether we are using GNU C" >&5 +echo "configure:768: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -771,7 +773,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:775: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:777: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -790,7 +792,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:794: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:796: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -829,12 +831,12 @@ fi else BUILD_CC=$config_BUILD_CC echo $ac_n "checking host compiler""... $ac_c" 1>&6 -echo "configure:833: checking host compiler" >&5 +echo "configure:835: checking host compiler" >&5 CC=$BUILD_CC echo "$ac_t""$BUILD_CC" 1>&6 fi echo $ac_n "checking switches for the host compiler""... $ac_c" 1>&6 -echo "configure:838: checking switches for the host compiler" >&5 +echo "configure:840: checking switches for the host compiler" >&5 if test "$config_BUILD_CFLAGS" != ""; then CFLAGS=$config_BUILD_CFLAGS BUILD_CFLAGS=$config_BUILD_CFLAGS @@ -854,7 +856,7 @@ fi # the target machine. # echo $ac_n "checking target compiler""... $ac_c" 1>&6 -echo "configure:858: checking target compiler" >&5 +echo "configure:860: checking target compiler" >&5 if test "$config_TARGET_CC" != ""; then TARGET_CC=$config_TARGET_CC else @@ -862,7 +864,7 @@ else fi echo "$ac_t""$TARGET_CC" 1>&6 echo $ac_n "checking switches on the target compiler""... $ac_c" 1>&6 -echo "configure:866: checking switches on the target compiler" >&5 +echo "configure:868: checking switches on the target compiler" >&5 if test "$config_TARGET_CFLAGS" != ""; then TARGET_CFLAGS=$config_TARGET_CFLAGS else @@ -870,7 +872,7 @@ else fi echo "$ac_t""$TARGET_CFLAGS" 1>&6 echo $ac_n "checking target linker""... $ac_c" 1>&6 -echo "configure:874: checking target linker" >&5 +echo "configure:876: checking target linker" >&5 if test "$config_TARGET_LINK" = ""; then TARGET_LINK=$TARGET_CC else @@ -878,7 +880,7 @@ else fi echo "$ac_t""$TARGET_LINK" 1>&6 echo $ac_n "checking switches on the target compiler""... $ac_c" 1>&6 -echo "configure:882: checking switches on the target compiler" >&5 +echo "configure:884: checking switches on the target compiler" >&5 if test "$config_TARGET_TFLAGS" != ""; then TARGET_TFLAGS=$config_TARGET_TFLAGS else @@ -890,7 +892,7 @@ else # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:894: checking for $ac_word" >&5 +echo "configure:896: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -936,7 +938,7 @@ echo "$ac_t""$TARGET_TFLAGS" 1>&6 # it 0 if we are not. # echo $ac_n "checking if host and target compilers are the same""... $ac_c" 1>&6 -echo "configure:940: checking if host and target compilers are the same" >&5 +echo "configure:942: checking if host and target compilers are the same" >&5 if test "$BUILD_CC" = "$TARGET_CC"; then cross=0 echo "$ac_t""yes" 1>&6 @@ -957,7 +959,7 @@ else fi echo $ac_n "checking character encoding""... $ac_c" 1>&6 -echo "configure:961: checking character encoding" >&5 +echo "configure:963: checking character encoding" >&5 if test "$enable_utf8" = "no"; then ENCODING=ISO8859 echo "$ac_t""iso8859" 1>&6 @@ -973,7 +975,7 @@ fi # things accordingly. # echo $ac_n "checking if executables have the .exe suffix""... $ac_c" 1>&6 -echo "configure:977: checking if executables have the .exe suffix" >&5 +echo "configure:979: checking if executables have the .exe suffix" >&5 if test "$config_BUILD_EXEEXT" = ".exe"; then CYGWIN=yes echo "$ac_t""yes" 1>&6 @@ -982,12 +984,12 @@ else fi if test "$CYGWIN" != "yes"; then echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 -echo "configure:986: checking for Cygwin environment" >&5 +echo "configure:988: checking for Cygwin environment" >&5 if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1004: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else @@ -1062,12 +1064,12 @@ else fi CC=$TARGET_CC echo $ac_n "checking for sin""... $ac_c" 1>&6 -echo "configure:1066: checking for sin" >&5 +echo "configure:1068: checking for sin" >&5 if eval "test \"`echo '$''{'ac_cv_func_sin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1096: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_sin=yes" else @@ -1111,7 +1113,7 @@ LIBS="-lm" fi echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:1115: checking for dlopen in -ldl" >&5 +echo "configure:1117: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1119,7 +1121,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1164,14 +1166,14 @@ fi LIBS="" echo $ac_n "checking for library containing Tcl_Init""... $ac_c" 1>&6 -echo "configure:1168: checking for library containing Tcl_Init" >&5 +echo "configure:1170: checking for library containing Tcl_Init" >&5 if eval "test \"`echo '$''{'ac_cv_search_Tcl_Init'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_Tcl_Init="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1188: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_Tcl_Init="none required" else @@ -1193,7 +1195,7 @@ rm -f conftest* test "$ac_cv_search_Tcl_Init" = "no" && for i in tcl8.4 tcl8.3 tcl8.2 tcl8.1 tcl8.0 tcl80 tcl; do LIBS="-l$i $otherlibs $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_Tcl_Init="-l$i" break @@ -1233,7 +1235,7 @@ fi # Figure out where to get the TCL header files. # echo $ac_n "checking TCL header files""... $ac_c" 1>&6 -echo "configure:1237: checking TCL header files" >&5 +echo "configure:1239: checking TCL header files" >&5 found=no if test "$config_TARGET_TCL_INC" != ""; then TARGET_TCL_INC=$config_TARGET_TCL_INC @@ -1252,7 +1254,7 @@ if test "$found" = "yes"; then else echo "$ac_t""not specified: still searching..." 1>&6 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1256: checking how to run the C preprocessor" >&5 +echo "configure:1258: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1267,13 +1269,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1277: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1279: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1284,13 +1286,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1294: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1296: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1301,13 +1303,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1311: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1313: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1333,17 +1335,17 @@ echo "$ac_t""$CPP" 1>&6 ac_safe=`echo "tcl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for tcl.h""... $ac_c" 1>&6 -echo "configure:1337: checking for tcl.h" >&5 +echo "configure:1339: checking for tcl.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1347: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1349: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1370,7 +1372,7 @@ if test "$found" = "no"; then ac_safe=`echo "$dir/include/tcl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $dir/include/tcl.h""... $ac_c" 1>&6 -echo "configure:1374: checking for $dir/include/tcl.h" >&5 +echo "configure:1376: checking for $dir/include/tcl.h" >&5 if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1407,21 +1409,34 @@ fi # Figure out what C libraries are required to compile programs # that use GDBM. # -if test "$config_TARGET_GDBM_LIBS" != ""; then - TARGET_GDBM_LIBS="$config_TARGET_GDBM_LIBS" +use_gdbm=true +# Check whether --enable-gdbm or --disable-gdbm was given. +if test "${enable_gdbm+set}" = set; then + enableval="$enable_gdbm" + use_gdbm=$enableval else - CC=$TARGET_CC - LIBS="" - + use_gdbm=true + +fi + +if test "$use_gdbm" = "no"; then use_gdbm=false; fi +if test "$use_gdbm" = "yes"; then use_gdbm=true; fi +if $use_gdbm; then + if test "$config_TARGET_GDBM_LIBS" != ""; then + TARGET_GDBM_LIBS="$config_TARGET_GDBM_LIBS" + else + CC=$TARGET_CC + LIBS="" + echo $ac_n "checking for library containing gdbm_open""... $ac_c" 1>&6 -echo "configure:1418: checking for library containing gdbm_open" >&5 +echo "configure:1433: checking for library containing gdbm_open" >&5 if eval "test \"`echo '$''{'ac_cv_search_gdbm_open'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_gdbm_open="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_gdbm_open="none required" else @@ -1443,7 +1458,7 @@ rm -f conftest* test "$ac_cv_search_gdbm_open" = "no" && for i in gdbm; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1473: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_gdbm_open="-l$i" break @@ -1474,37 +1489,39 @@ if test "$ac_cv_search_gdbm_open" != "no"; then else : fi - TARGET_GDBM_LIBS="$LIBS" + TARGET_GDBM_LIBS="$LIBS" + fi fi ########## # Figure out where to get the GDBM header files. # -echo $ac_n "checking GDBM header files""... $ac_c" 1>&6 -echo "configure:1486: checking GDBM header files" >&5 -found=no -if test "$config_TARGET_GDBM_INC" != ""; then - TARGET_GDBM_INC=$config_TARGET_GDBM_INC - found=yes -fi -if test "$found" = "yes"; then - echo "$ac_t""$TARGET_GDBM_INC" 1>&6 -else - echo "$ac_t""not specified: still searching..." 1>&6 - ac_safe=`echo "gdbm.h" | sed 'y%./+-%__p_%'` +if $use_gdbm; then + echo $ac_n "checking GDBM header files""... $ac_c" 1>&6 +echo "configure:1503: checking GDBM header files" >&5 + found=no + if test "$config_TARGET_GDBM_INC" != ""; then + TARGET_GDBM_INC=$config_TARGET_GDBM_INC + found=yes + fi + if test "$found" = "yes"; then + echo "$ac_t""$TARGET_GDBM_INC" 1>&6 + else + echo "$ac_t""not specified: still searching..." 1>&6 + ac_safe=`echo "gdbm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for gdbm.h""... $ac_c" 1>&6 -echo "configure:1498: checking for gdbm.h" >&5 +echo "configure:1515: checking for gdbm.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1508: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1525: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1525,13 +1542,13 @@ else echo "$ac_t""no" 1>&6 fi -fi -if test "$found" = "no"; then - for dir in /usr/local /usr/pkg /usr/contrib; do - + fi + if test "$found" = "no"; then + for dir in /usr/local /usr/pkg /usr/contrib; do + ac_safe=`echo "$dir/include/gdbm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $dir/include/gdbm.h""... $ac_c" 1>&6 -echo "configure:1535: checking for $dir/include/gdbm.h" >&5 +echo "configure:1552: checking for $dir/include/gdbm.h" >&5 if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1553,11 +1570,14 @@ else fi - if test "$found" = "yes"; then - TARGET_GDBM_INC="-I$dir/include" - break - fi - done + if test "$found" = "yes"; then + TARGET_GDBM_INC="-I$dir/include" + break + fi + done + fi +else + TARGET_GDBM_INC="-DDISABLE_GDBM" fi @@ -1572,14 +1592,14 @@ else LIBS="" echo $ac_n "checking for library containing readline""... $ac_c" 1>&6 -echo "configure:1576: checking for library containing readline" >&5 +echo "configure:1596: checking for library containing readline" >&5 if eval "test \"`echo '$''{'ac_cv_search_readline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_readline="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1614: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_readline="none required" else @@ -1601,7 +1621,7 @@ rm -f conftest* test "$ac_cv_search_readline" = "no" && for i in readline; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1636: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_readline="-l$i" break @@ -1640,7 +1660,7 @@ fi # Figure out where to get the READLINE header files. # echo $ac_n "checking readline header files""... $ac_c" 1>&6 -echo "configure:1644: checking readline header files" >&5 +echo "configure:1664: checking readline header files" >&5 found=no if test "$config_TARGET_READLINE_INC" != ""; then TARGET_READLINE_INC=$config_TARGET_READLINE_INC @@ -1652,17 +1672,17 @@ else echo "$ac_t""not specified: still searching..." 1>&6 ac_safe=`echo "readline.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for readline.h""... $ac_c" 1>&6 -echo "configure:1656: checking for readline.h" >&5 +echo "configure:1676: checking for readline.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1666: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1686: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1689,7 +1709,7 @@ if test "$found" = "no"; then ac_safe=`echo "$dir/include/readline.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $dir/include/readline.h""... $ac_c" 1>&6 -echo "configure:1693: checking for $dir/include/readline.h" >&5 +echo "configure:1713: checking for $dir/include/readline.h" >&5 if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1718,7 +1738,7 @@ fi ac_safe=`echo "$dir/include/readline/readline.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $dir/include/readline/readline.h""... $ac_c" 1>&6 -echo "configure:1722: checking for $dir/include/readline/readline.h" >&5 +echo "configure:1742: checking for $dir/include/readline/readline.h" >&5 if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1762,12 +1782,12 @@ fi # Figure out whether or not we have a "usleep()" function. # echo $ac_n "checking for usleep""... $ac_c" 1>&6 -echo "configure:1766: checking for usleep" >&5 +echo "configure:1786: checking for usleep" >&5 if eval "test \"`echo '$''{'ac_cv_func_usleep'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_usleep=yes" else diff --git a/configure.in b/configure.in index 82e4efa987..8e0ec93c76 100644 --- a/configure.in +++ b/configure.in @@ -151,7 +151,7 @@ AC_INIT(src/sqlite.h.in) dnl Put the RCS revision string after AC_INIT so that it will also dnl show in in configure. # The following RCS revision string applies to configure.in -# $Revision: 1.9 $ +# $Revision: 1.10 $ ######### # Make sure we are not building in a subdirectory of the source tree. @@ -440,39 +440,52 @@ AC_SUBST(TARGET_TCL_INC) # Figure out what C libraries are required to compile programs # that use GDBM. # -if test "$config_TARGET_GDBM_LIBS" != ""; then - TARGET_GDBM_LIBS="$config_TARGET_GDBM_LIBS" -else - CC=$TARGET_CC - LIBS="" - AC_SEARCH_LIBS(gdbm_open, gdbm,,,) - TARGET_GDBM_LIBS="$LIBS" +use_gdbm=true +AC_ARG_ENABLE(gdbm, +[ --disable-gdbm Omit the GDBM drivers], + use_gdbm=$enableval, use_gdbm=true +) +if test "$use_gdbm" = "no"; then use_gdbm=false; fi +if test "$use_gdbm" = "yes"; then use_gdbm=true; fi +if $use_gdbm; then + if test "$config_TARGET_GDBM_LIBS" != ""; then + TARGET_GDBM_LIBS="$config_TARGET_GDBM_LIBS" + else + CC=$TARGET_CC + LIBS="" + AC_SEARCH_LIBS(gdbm_open, gdbm,,,) + TARGET_GDBM_LIBS="$LIBS" + fi fi AC_SUBST(TARGET_GDBM_LIBS) ########## # Figure out where to get the GDBM header files. # -AC_MSG_CHECKING([GDBM header files]) -found=no -if test "$config_TARGET_GDBM_INC" != ""; then - TARGET_GDBM_INC=$config_TARGET_GDBM_INC - found=yes -fi -if test "$found" = "yes"; then - AC_MSG_RESULT($TARGET_GDBM_INC) +if $use_gdbm; then + AC_MSG_CHECKING([GDBM header files]) + found=no + if test "$config_TARGET_GDBM_INC" != ""; then + TARGET_GDBM_INC=$config_TARGET_GDBM_INC + found=yes + fi + if test "$found" = "yes"; then + AC_MSG_RESULT($TARGET_GDBM_INC) + else + AC_MSG_RESULT(not specified: still searching...) + AC_CHECK_HEADER(gdbm.h, [found=yes]) + fi + if test "$found" = "no"; then + for dir in /usr/local /usr/pkg /usr/contrib; do + AC_CHECK_FILE($dir/include/gdbm.h, found=yes) + if test "$found" = "yes"; then + TARGET_GDBM_INC="-I$dir/include" + break + fi + done + fi else - AC_MSG_RESULT(not specified: still searching...) - AC_CHECK_HEADER(gdbm.h, [found=yes]) -fi -if test "$found" = "no"; then - for dir in /usr/local /usr/pkg /usr/contrib; do - AC_CHECK_FILE($dir/include/gdbm.h, found=yes) - if test "$found" = "yes"; then - TARGET_GDBM_INC="-I$dir/include" - break - fi - done + TARGET_GDBM_INC="-DDISABLE_GDBM" fi AC_SUBST(TARGET_GDBM_INC) diff --git a/manifest b/manifest index 4c7f7a84e2..f1036bf40e 100644 --- a/manifest +++ b/manifest @@ -1,24 +1,24 @@ -C :-)\s(CVS\s1719) -D 2001-04-17T20:09:44 +C :-)\s(CVS\s214) +D 2001-04-28T16:52:41 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 -F Makefile.in ac01d6145714b0d1c9e99382caf03cf30d6f4c8d +F Makefile.in acef0f0275a5ca8e68bda165f7f05d810a207664 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 F VERSION 71874cb7e2a53c2bd22bb6affa7d223dd94a7a13 -F configure 260d3be664b6d9b4d2d985e66b6dae1ef723c86e x -F configure.in 6940e3f88bf3d28a10c73b06ab99fd3a7e039a61 +F configure d2051345f49f7e48604423da26e086a745c86a47 x +F configure.in e7465c88bbfb76882f97769c2dd90dbba8eca5db F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47 F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464 -F notes/notes2.txt 30b1d05005731ff8b49e430921daf40e5d8c764c +F notes/notes2.txt 80a0c3e3a0063b81fa8df6aab01bd014353dde01 F notes/notes3.txt cd5e7bd2167d7ef89b1077abdfa68f0af6337744 F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4 -F src/btree.c 670b20349bd1d1448cc90f7b9487c2bf7a5c039c +F src/btree.c 71381fdaec3122f80c53f7f4f38887bcff19d273 F src/btree.h f21c240d0c95f93e2a128106d04a6c448ed0eb94 F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651 -F src/dbbe.c ec82c602c598748204a61a35ab0c31e34ca58223 +F src/dbbe.c b18259f99d87240cbe751021cf14dd3aa83a48af F src/dbbe.h 7235b15c6c5d8be0c4da469cef9620cee70b1cc8 -F src/dbbegdbm.c 9d3a3c18b27f9f2533a3aaa3741e8668bdda7e98 -F src/dbbemem.c b62821ba8cec4b1d7392157e94f72baf1ff015f2 +F src/dbbegdbm.c d75c45d39f15970c6e2881e955b799643649ebb1 +F src/dbbemem.c f76343d1ad1f92f1367536973e2c1d17c2f7686f F src/delete.c 40ddb169ee98013d976b2dadd140d98f7876f54f F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7 @@ -30,9 +30,9 @@ F src/ex/pg.h 23a4ac807b0546ec2bb6239ec8bd3e06926572cd F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7 F src/expr.c c4c24c3af1eba094a816522eb0e085bed518ee16 F src/insert.c aa528e20a787af85432a61daaea6df394bd251d7 -F src/main.c 92ce30a89f622ba36cc8b7d912829e14a480722c -F src/pager.c cc49d7e22a4fc0264f584d7938f990a1897f7edd -F src/pager.h 8678d9a97fdf1c111b619a13a351e5c8ab97cb81 +F src/main.c 0a13c7a2beb8ce36aee43daf8c95989b200727a7 +F src/pager.c 4081e3e9765c272554e22d1dcec0647ac71ea706 +F src/pager.h ed12ac3ddebd3afe61a0ed4bf530e7846d578e46 F src/parse.y 8fc096948994a7ffbf61ba13129cc589f794a9cb F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9 F src/random.c b36c3f57dc80c8f354e6bfbf39cf1e1de021d54a @@ -40,22 +40,22 @@ F src/select.c 52bb7d081ac00dfad3687d52c917d2d90165331d F src/shell.c d9c64418765d90909e9e200b207ff9e355afb5c4 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in 3e5906f72608f0fd4394dfbb1d7e8d35b8353677 -F src/sqliteInt.h fc1000f023b41882bbdb8db4f80172f77b44307b +F src/sqliteInt.h 47845c60e2e196b5409d774936a56700b1611f00 F src/table.c adcaf074f6c1075e86359174e68701fa2acfc4d6 F src/tclsqlite.c 1f2bf4691a6bd81fbff1856ae4a12db24d1265f7 F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4 -F src/test2.c 49e27f03d1866635c2c4539e0983e5590a322872 +F src/test2.c 0183625225a860397b4fd3041aefb48f77e4630a F src/tokenize.c 0118b57702cb6550769316e8443b06760b067acf F src/update.c 0cf789656a936d4356668393267692fa4b03ffc6 F src/util.c 1b396ac34e30dd6222d82e996c17b161bbc906bc -F src/vdbe.c ee5a6ab95c8c84497f6685ebde153da6fb06e825 +F src/vdbe.c f93be4414ba892df9c5589815d2a57c1fb12c820 F src/vdbe.h dc1205da434c6a9da03b5d6b089270bbc8e6d437 F src/where.c 0c542fc44bd85152dfb8507862cfe2e60c629e9f F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048 F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf -F test/expr.test e55eb507744f771b814fdbea14fddb69caa4538a +F test/expr.test 80bf8f0e9aa6b9c35bf97ce5d603a28381168d8a F test/func.test ac3def2a673d1042750ae1a4ad1768bb7c7ae90b F test/in.test ea48016c4fcc479d315932ae2b8568146686ffaf F test/index.test b189ac11bf8d4fbcf87402f4028c25c8a6d91bb5 @@ -106,7 +106,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2 F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad -P bdb1c425f577d455155982ee2cd8cb686bcaf0da -R 71de057d1d30d3f00126006f203367a6 +P 8e0476f9004a7db8a3426e57f477393645ff5629 +R 3f48b136215cd8bc470d216a44941a5e U drh -Z ab8bc94b1c7db1acb4a5bcaf00ffbb81 +Z f40f8ecab433b0ffb267dc5ca6c7154e diff --git a/manifest.uuid b/manifest.uuid index fa424b975e..f03409e717 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e0476f9004a7db8a3426e57f477393645ff5629 \ No newline at end of file +73a1ed61265040925f1a41c9c0cfeea50db70b01 \ No newline at end of file diff --git a/notes/notes2.txt b/notes/notes2.txt index e31a7db3bc..2420530d0f 100644 --- a/notes/notes2.txt +++ b/notes/notes2.txt @@ -3,16 +3,46 @@ How to do a B*Tree insert: add_to_page(cursor, data, ptr){ if( data_fits_on_page ){ add data to page; return; } if( page==root ){ - newpage1 = lowerpart( page+(data+ptr) ); - newpage2 = upperpart( page+(data+ptr) ); - page = newpage1 + center + newpage2; + split currentpage+(data+ptr) into lowerpart, center, upperpart + newpage1 = lowerpart; + newpage2 = upperpart; + page = ptr(newpage1) + center + ptr(newpage2); return; } if( move_some_data_left || move_some_data_right ){ add data to page return } - newpage = upperhalf( page+(data+ptr) ); + split currentpage+(data+ptr) into lowerpart, center, upperpart + newpage = upperpart + currentpage = lowerpart pop cursor one level - add_to_page(cursor, center, newpage); + add_to_page(cursor, center, ptr(newpage)); +} + +unlink_entry(cursor, olddata){ + if( !is_a_leaf ){ + n = next_entry() + if( n fits pageof(cursor) ){ + if( olddata!=nil ) copy dataof(cursor) into olddata + copy dataof(n) into dataof(cursor) + unlink_entry(n, nil) + return + } + n = prev_entry() + if( n fits pageof(cursor) ){ + if( olddata!=nil ) copy dataof(cursor) into olddata + copy dataof(n) into dataof(cursor) + unlink_entry(n, nil) + return + } + unlink_entry(n, leafdata) + move cursor data and ptr into olddata, oldptr + add_to_page(cursor, leafdata, oldptr) + return + } + move cursor data into olddata + if( !underfull(pageof(cursor)) ) return + + } diff --git a/src/btree.c b/src/btree.c index 5e5f71ec6c..bfca825bd0 100644 --- a/src/btree.c +++ b/src/btree.c @@ -21,7 +21,7 @@ ** http://www.hwaci.com/drh/ ** ************************************************************************* -** $Id: btree.c,v 1.1 2001/04/17 20:09:11 drh Exp $ +** $Id: btree.c,v 1.2 2001/04/28 16:52:41 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -30,17 +30,90 @@ typedef unsigned int u32; +/* +** The maximum number of database entries that can be held in a single +** page of the database. Each entry has a 16-byte header consisting of +** 4 unsigned 32-bit numbers, as follows: +** +** nKey Number of byte in the key +** nData Number of byte in the data +** pgno Page number of the right child block +** next index in MemPage.aPage[] of the next entry in sorted order +** +** The key and data follow this header. The key and data are packed together +** and the total rounded up to the next multiple of 4 bytes. There must +** be at least 4 bytes in the key/data packet, so each entry consumes at +** least 20 bytes of space on the page. +*/ +#define MX_CELL (SQLITE_PAGE_SIZE/20) + +/* +** Freeblocks are divided by cells, so there can be at most one more +** free block than there are cells. +*/ +#define MX_FREE (MX_CELL+1) + +/* +** The maximum amount of data (in bytes) that can be stored locally for a +** database entry. If the entry contains more data than this, the +** extra goes onto overflow pages. +*/ +#define MX_LOCAL_PAYLOAD ((SQLITE_PAGE_SIZE-20-4*24)/4) + +/* +** On a single disk page, there are sections of the page that are used +** to hold data and sections that are unused and available for holding +** new data. A single instance of this structure describes a contiguous +** block of free space on a disk page. +*/ +struct FreeBlk { + int idx; /* Index into MemPage.aPage[] of the start of freeblock */ + int size; /* Number of MemPage.aPage[] slots used by this block */ +}; +typedef struct FreeBlk; + +/* +** For every page in the database file, an instance of the following structure +** is stored in memory. The aPage[] array contains the data obtained from +** the disk. The rest is auxiliary data that held in memory only. +*/ +struct MemPage { + u32 aPage[SQLITE_PAGE_SIZE/sizeof(u32)]; /* Page data stored on disk */ + unsigned char isInit; /* True if sequel is initialized */ + unsigned char validUp; /* True if MemPage.up is valid */ + unsigned char validLeft; /* True if MemPage.left is valid */ + unsigned char validRight; /* True if MemPage.right is valid */ + Pgno up; /* The parent page. 0 means this is the root */ + Pgno left; /* Left sibling page. 0==none */ + Pgno right; /* Right sibling page. 0==none */ + int idxStart; /* Index in aPage[] of real data */ + int nCell; /* Number of entries on this page */ + u32 *aCell[MX_CELL]; /* All entires in sorted order */ + int nFree; /* Number of free blocks on this page */ + int nFreeSlot; /* Number of free elements of aPage[] */ + FreeBlk aFree[MX_FREE]; /* Free blocks in no particular order */ +} +typedef struct MemPage; + +/* +** The in-memory image of a disk page has the auxiliary information appended +** to the end. EXTRA_SIZE is the number of bytes of space needed to hold +** that extra information. +*/ +#define EXTRA_SIZE (sizeof(MemPage)-SQLITE_PAGE_SIZE) + /* ** Everything we need to know about an open database */ struct Btree { Pager *pPager; /* The page cache */ BtCursor *pCursor; /* All open cursors */ - u32 *page1; /* First page of the database */ + MemPage *page1; /* First page of the database */ int inTrans; /* True if a transaction is current */ }; typedef Btree Bt; + /* ** The maximum depth of a cursor */ @@ -55,6 +128,7 @@ struct BtIdxpt { Pgno pgno; /* The page number */ u32 *aPage; /* The page data */ int idx; /* Index into pPage[] */ + u32 *aIdx; /* Pointer to pPage[idx] */ }; /* @@ -65,6 +139,7 @@ struct BtCursor { BtCursor *pPrev, *pNext; /* Linked list of all cursors */ int valid; /* True if the cursor points to something */ int nLevel; /* Number of levels of indexing used */ + BtIdxpt *pLevel; /* Pointer to aLevel[nLevel] */ BtIdxpt aLevel[MX_LEVEL]; /* The index levels */ }; @@ -79,6 +154,108 @@ struct BtCursor { #define MAGIC_1 0x7264dc61 #define MAGIC_2 0x54e55d9e +/* +** Each database page has a header as follows: +** +** page1_header Extra numbers found on page 1 only. +** leftmost_pgno Page number of the leftmost child +** first_cell Index into MemPage.aPage of first cell +** +** MemPage.pStart always points to the leftmost_pgno. +*/ + +/* +** Mark a section of the memory block as in-use. +*/ +static void useSpace(MemPage *pPage, int start, int size){ + int i; + FreeBlk *p; + + /* Some basic sanity checking */ + assert( pPage && pPage->isInit ); + assert( pPage->nFree>0 && pPage->nFree<=MX_FREE ); + assert( pPage->nFreeSlot >= size ); + assert( start > pPage->idxStart ); + assert( size>0 ); + assert( start + size < SQLITE_PAGE_SIZE/sizeof(pPage->aPage[0]) ); + + /* Search for the freeblock that describes the space to be used */ + for(i=0; inFree; i++){ + p = &pPage->aFree[i] + if( p->idx<=start && p->idx+p->size>start ) break; + } + + /* The freeblock must contain all the space that is to be used */ + assert( inFree ); + assert( p->idx+p->size >= start+size ); + + /* Remove the used space from the freeblock */ + if( p->idx==start ){ + /* The space is at the beginning of the block + p->size -= size; + if( p->size==0 ){ + *p = pPage->aFree[pPage->nFree-1]; + pPage->nFree--; + } + }else if( p->idx+p->size==start+size ){ + /* Space at the end of the block */ + p->size -= size; + }else{ + /* Space in the middle of the freeblock. We have to split the + ** freeblock in two */ + /******* TBD *********/ + } + pPage->nFreeSlot -= size; +} + +/* +** Return a section of the MemPage.aPage[] to the freelist. +*/ +static void freeSpace(MemPage *pPage, int start, int size){ +} + +/* +** Defragment the freespace +*/ +static void defragmentSpace(MemPage *pPage){ +} + +/* +** Initialize the auxiliary information for a disk block. +*/ +static int initPage(MemPage *pPage, Pgno pgnoThis, Pgno pgnoParent){ + u32 idx; + pPage->isInit = 1; + pPage->validUp = 1; + pPage->up = pgnoParent; + pPage->nFreeSlot = SQLITE_PAGE_SIZE/sizeof(pPage->aPage[0]) - 2; + pPage->nFree = 1; + if( pgnoThis==1 ){ + pPage->idxStart = EXTRA_PAGE_1_CELLS; + pPage->nFreeByte -= EXTRA_PAGE_1_CELLS; + } + pPage->aFree[0].idx = pPage->idxStart + 2; + pPage->aFree[0].size = pPage->nFreeByte; + pPage->nCell = 0; + idx = pPage->aPage[pPage->idxStart+1]; + while( idx!=0 ){ + int size; + pPage->aCell[pPage->nCell++] = idx; + size = pPage->aPage[idx] + pPage->aPage[idx+1]; + if( size>MX_LOCAL_PAYLOAD ){ + if( size>MX_DIRECT_PAYLOAD ){ + size = MX_LOCAL_PAYLOAD + 2*sizeof(u32); + }else{ + size = MX_LOCAL_PAYLOAD + sizeof(u32); + } + } + size = (size + sizeof(u32) - 1)/sizeof(u32) + 4; + useSpace(pPage, idx, size); + idx = pPage->aPage[idx+3]; + } + return SQLITE_OK; +} + /* ** Open a new database */ @@ -90,7 +267,7 @@ int sqliteBtreeOpen(const char *zFilename, int mode, Btree **ppBtree){ **ppBtree = 0; return SQLITE_NOMEM; } - rc = sqlitepager_open(&pBt->pPager, zFilename, 100); + rc = sqlitepager_open(&pBt->pPager, zFilename, 100, EXTRA_SPACE); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlitepager_close(pBt->pPager); sqliteFree(pBt); @@ -122,7 +299,7 @@ int sqliteBtreeBeginTrans(Btree *pBt){ int rc; if( pBt->inTrans ) return SQLITE_ERROR; if( pBt->page1==0 ){ - rc = sqlitepager_get(pBt->pPager, 1, &pBt->page1); + rc = lockBtree(pBt); if( rc!=SQLITE_OK ) return rc; } rc = sqlitepager_write(pBt->page1); @@ -141,6 +318,12 @@ static int lockBtree(Btree *pBt){ if( pBt->page1 ) return SQLITE_OK; rc = sqlitepager_get(pBt->pPager, 1, &pBt->page1); if( rc!=SQLITE_OK ) return rc; + rc = initPage(pBt->page1); + if( rc!=SQLITE_OK ){ + sqlitepager_unref(pBt->page1); + pBt->page1 = 0; + return rc; + } /* Sanity checking on the database file format */ return rc; } @@ -237,6 +420,11 @@ int sqliteBtreeCloseCursor(BtCursor *pCur){ sqliteFree(pCur); } +/* +** Return the number of bytes in the key of the entry to which +** the cursor is currently point. If the cursor has not been +** initialized or is pointed to a deleted entry, then return 0. +*/ int sqliteBtreeKeySize(BtCursor *pCur){ int nEntry; u32 *aPage; diff --git a/src/dbbe.c b/src/dbbe.c index 8c57cba6d9..469efc82a6 100644 --- a/src/dbbe.c +++ b/src/dbbe.c @@ -30,10 +30,9 @@ ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** -** $Id: dbbe.c,v 1.27 2001/04/11 14:28:42 drh Exp $ +** $Id: dbbe.c,v 1.28 2001/04/28 16:52:41 drh Exp $ */ #include "sqliteInt.h" -#include #include /* @@ -54,15 +53,21 @@ Dbbe *sqliteDbbeOpen( int createFlag, /* True to create database if it doesn't exist */ char **pzErrMsg /* Write error messages (if any) here */ ){ + extern Dbbe *sqliteMemOpen(const char*,int,int,char**); +#ifndef DISABLE_GDBM extern Dbbe *sqliteGdbmOpen(const char*,int,int,char**); if( strncmp(zName, "gdbm:", 5)==0 ){ return sqliteGdbmOpen(&zName[5], writeFlag, createFlag, pzErrMsg); } +#endif if( strncmp(zName, "memory:", 7)==0 ){ - extern Dbbe *sqliteMemOpen(const char*,int,int,char**); return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg); } +#ifndef DISABLE_GDBM return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg); +#else + return sqliteMemOpen(zName, writeFlag, createFlag, pzErrMsg); +#endif } #if 0 /* NOT USED */ diff --git a/src/dbbegdbm.c b/src/dbbegdbm.c index 142dd08632..269cf00006 100644 --- a/src/dbbegdbm.c +++ b/src/dbbegdbm.c @@ -30,8 +30,9 @@ ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** -** $Id: dbbegdbm.c,v 1.7 2001/04/11 14:28:42 drh Exp $ +** $Id: dbbegdbm.c,v 1.8 2001/04/28 16:52:41 drh Exp $ */ +#ifndef DISABLE_GDBM #include "sqliteInt.h" #include #include @@ -674,3 +675,4 @@ Dbbe *sqliteGdbmOpen( pNew->pOpen = 0; return &pNew->dbbe; } +#endif /* DISABLE_GDBM */ diff --git a/src/dbbemem.c b/src/dbbemem.c index b37b20e66f..d5c8220d31 100644 --- a/src/dbbemem.c +++ b/src/dbbemem.c @@ -30,13 +30,10 @@ ** Nothing is ever written to disk using this backend. All information ** is forgotten when the program exits. ** -** $Id: dbbemem.c,v 1.14 2001/04/11 14:28:42 drh Exp $ +** $Id: dbbemem.c,v 1.15 2001/04/28 16:52:42 drh Exp $ */ #include "sqliteInt.h" -#include -#include #include -#include typedef struct Array Array; diff --git a/src/main.c b/src/main.c index 431aacea6e..f32850b6c0 100644 --- a/src/main.c +++ b/src/main.c @@ -26,10 +26,12 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.28 2001/04/11 14:28:42 drh Exp $ +** $Id: main.c,v 1.29 2001/04/28 16:52:42 drh Exp $ */ #include "sqliteInt.h" +#if defined(HAVE_USLEEP) && HAVE_USLEEP #include +#endif /* ** This is the callback routine for the code that initializes the diff --git a/src/pager.c b/src/pager.c index 04492d00ba..2e5f9b8ef4 100644 --- a/src/pager.c +++ b/src/pager.c @@ -27,7 +27,7 @@ ** all writes in order to support rollback. Locking is used to limit ** access to one or more reader or on writer. ** -** @(#) $Id: pager.c,v 1.4 2001/04/15 02:27:25 drh Exp $ +** @(#) $Id: pager.c,v 1.5 2001/04/28 16:52:42 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -83,6 +83,7 @@ struct PgHdr { char inJournal; /* TRUE if has been written to journal */ char dirty; /* TRUE if we need to write back changes */ /* SQLITE_PAGE_SIZE bytes of page data follow this header */ + /* Pager.nExtra bytes of local data follow the page data */ }; /* @@ -91,6 +92,7 @@ struct PgHdr { */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) +#define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE]) /* ** How big to make the hash table used for locating in-memory pages @@ -107,6 +109,7 @@ struct Pager { int fd, jfd; /* File descriptors for database and journal */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ + int nExtra; /* Add this many bytes to each in-memory page */ int nPage; /* Total number of in-memory pages */ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ @@ -427,7 +430,12 @@ static int pager_playback(Pager *pPager){ ** the first call to sqlitepager_get() and is only held open until the ** last page is released using sqlitepager_unref(). */ -int sqlitepager_open(Pager **ppPager, const char *zFilename, int mxPage){ +int sqlitepager_open( + Pager **ppPager, /* Return the Pager structure here */ + const char *zFilename, /* Name of the database file to open */ + int mxPage, /* Max number of in-memory cache pages */ + int nExtra /* Extra bytes append to each in-memory page */ +){ Pager *pPager; int nameLen; int fd; @@ -531,6 +539,29 @@ Pgno sqlitepager_pagenumber(void *pData){ return p->pgno; } +/* +** Increment the reference count for a page. If the page is +** currently on the freelist (the reference count is zero) then +** remove it from the freelist. +*/ +static void sqlitepager_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + /* The page is currently on the freelist. Remove it. */ + if( pPg->pPrevFree ){ + pPg->pPrevFree->pNextFree = pPg->pNextFree; + }else{ + pPg->pPager->pFirst = pPg->pNextFree; + } + if( pPg->pNextFree ){ + pPg->pNextFree->pPrevFree = pPg->pPrevFree; + }else{ + pPg->pPager->pLast = pPg->pPrevFree; + } + pPg->pPager->nRef++; + } + pPg->nRef++; +} + /* ** Acquire a page. ** @@ -539,6 +570,14 @@ Pgno sqlitepager_pagenumber(void *pData){ ** ** The acquisition might fail for several reasons. In all cases, ** an appropriate error code is returned and *ppPage is set to NULL. +** +** See also sqlitepager_lookup(). Both this routine and _lookup() attempt +** to find a page in the in-memory cache first. If the page is not already +** in cache, this routine goes to disk to read it in whereas _lookup() +** just returns 0. This routine acquires a read-lock the first time it +** has to go to disk, and could also playback an old journal if necessary. +** Since _lookup() never goes to disk, it never has to deal with locks +** or journal files. */ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ PgHdr *pPg; @@ -596,18 +635,17 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ } } pPg = 0; - pPager->nMiss++; }else{ /* Search for page in cache */ pPg = pager_lookup(pPager, pgno); - pPager->nHit++; } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; + pPager->nMiss++; if( pPager->nPagemxPage || pPager->pFirst==0 ){ /* Create a new page */ - pPg = sqliteMalloc( sizeof(*pPg) + SQLITE_PAGE_SIZE ); + pPg = sqliteMalloc( sizeof(*pPg) + SQLITE_PAGE_SIZE + pPager->nExtra ); if( pPg==0 ){ *ppPage = 0; pager_unwritelock(pPager); @@ -691,28 +729,49 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ } pager_seek(pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE); pager_read(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); + if( pPager->nExtra>0 ){ + memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); + } }else{ /* The requested page is in the page cache. */ - if( pPg->nRef==0 ){ - /* The page is currently on the freelist. Remove it. */ - if( pPg->pPrevFree ){ - pPg->pPrevFree->pNextFree = pPg->pNextFree; - }else{ - pPager->pFirst = pPg->pNextFree; - } - if( pPg->pNextFree ){ - pPg->pNextFree->pPrevFree = pPg->pPrevFree; - }else{ - pPager->pLast = pPg->pPrevFree; - } - pPager->nRef++; - } - pPg->nRef++; + pPager->nHit++; + sqlitepager_ref(pPg); } *ppPage = PGHDR_TO_DATA(pPg); return SQLITE_OK; } +/* +** Acquire a page if it is already in the in-memory cache. Do +** not read the page from disk. Return a pointer to the page, +** or 0 if the page is not in cache. +** +** See also sqlitepager_get(). The difference between this routine +** and sqlitepager_get() is that _get() will go to the disk and read +** in the page if the page is not already in cache. This routine +** returns NULL if the page is not in cache and no disk I/O ever +** occurs. +*/ +void *sqlitepager_lookup(Pager *pPager, Pgno pgno){ + PgHdr *pPg; + + /* Make sure we have not hit any critical errors. + */ + if( pPager==0 || pgno==0 ){ + return 0; + } + if( pPager->errMask & ~(PAGER_ERR_FULL) ){ + return 0; + } + if( pPager->nRef==0 ){ + return 0; + } + pPg = pager_lookup(pPager, pgno); + if( pPg==0 ) return 0; + sqlitepager_ref(pPg); + return PGHDR_TO_DATA(pPg); +} + /* ** Release a page. ** diff --git a/src/pager.h b/src/pager.h index 8935a80e20..577f5482bf 100644 --- a/src/pager.h +++ b/src/pager.h @@ -25,7 +25,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.2 2001/04/15 00:37:09 drh Exp $ +** @(#) $Id: pager.h,v 1.3 2001/04/28 16:52:42 drh Exp $ */ /* @@ -44,14 +44,14 @@ typedef unsigned int Pgno; */ typedef struct Pager Pager; -int sqlitepager_open(Pager **ppPager, const char *zFilename, int nPage); +int sqlitepager_open(Pager **ppPager, const char *zFilename,int nPage,int nEx); int sqlitepager_close(Pager *pPager); int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage); +void *sqlitepager_lookup(Pager *pPager, Pgno pgno); int sqlitepager_unref(void*); Pgno sqlitepager_pagenumber(void*); int sqlitepager_write(void*); int sqlitepager_pagecount(Pager*); int sqlitepager_commit(Pager*); int sqlitepager_rollback(Pager*); - int *sqlitepager_stats(Pager*); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4a62e12492..10a077bb1c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -23,13 +23,15 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.41 2001/04/11 14:28:43 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.42 2001/04/28 16:52:42 drh Exp $ */ #include "sqlite.h" #include "dbbe.h" #include "vdbe.h" #include "parse.h" +#ifndef DISABLE_GDBM #include +#endif #include #include #include diff --git a/src/test2.c b/src/test2.c index 036f454e28..92ac2f5d68 100644 --- a/src/test2.c +++ b/src/test2.c @@ -25,7 +25,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.1 2001/04/15 00:37:09 drh Exp $ +** $Id: test2.c,v 1.2 2001/04/28 16:52:42 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -80,7 +80,7 @@ static int pager_open( return TCL_ERROR; } if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; - rc = sqlitepager_open(&pPager, argv[1], nPage); + rc = sqlitepager_open(&pPager, argv[1], nPage, 0); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; @@ -261,6 +261,37 @@ static int page_get( 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 ** @@ -376,6 +407,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){ 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); diff --git a/src/vdbe.c b/src/vdbe.c index 9df47ed042..0458bcfcfb 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -41,10 +41,9 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.57 2001/04/11 14:28:43 drh Exp $ +** $Id: vdbe.c,v 1.58 2001/04/28 16:52:42 drh Exp $ */ #include "sqliteInt.h" -#include #include /* diff --git a/test/expr.test b/test/expr.test index c97c02d1e1..3e8c8166fe 100644 --- a/test/expr.test +++ b/test/expr.test @@ -23,7 +23,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing expressions. # -# $Id: expr.test,v 1.13 2001/04/06 16:13:43 drh Exp $ +# $Id: expr.test,v 1.14 2001/04/28 16:52:42 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -180,11 +180,19 @@ if {"\u1234"!="u1234" && [sqlite -encoding]=="UTF-8"} { # Theses tests are for when SQLite assumes iso8859 characters. # if {[sqlite -encoding]=="iso8859"} { - catch {encoding system iso8859-1} - test_expr expr-5.50 "t1='a\266c', t2='A_C'" {t1 LIKE t2} 1 - test_expr expr-5.51 "t1='a\347', t2='A_'" {t1 LIKE t2} 1 - test_expr expr-5.52 "t1='ax\351', t2='A_\351'" {t1 LIKE t2} 1 - test_expr expr-5.53 "t1='ax\241', t2='A_%'" {t1 LIKE t2} 1 + set go 1 + if {[info command encoding]!=""} { + if {[catch {encoding system iso8859-1} msg]} { + puts "skipping tests of LIKE operator: $msg" + set go 0 + } + } + if {$go} { + test_expr expr-5.50 "t1='a\266c', t2='A_C'" {t1 LIKE t2} 1 + test_expr expr-5.51 "t1='a\347', t2='A_'" {t1 LIKE t2} 1 + test_expr expr-5.52 "t1='ax\351', t2='A_\351'" {t1 LIKE t2} 1 + test_expr expr-5.53 "t1='ax\241', t2='A_%'" {t1 LIKE t2} 1 + } } test_expr expr-6.1 {t1='abc', t2='xyz'} {t1 GLOB t2} 0 @@ -237,20 +245,28 @@ if {"\u1234"!="u1234" && [sqlite -encoding]=="UTF-8"} { # Theses tests are for when SQLite assumes iso8859 characters. # if {[sqlite -encoding]=="iso8859"} { - catch {encoding system iso8859-1} - test_expr expr-6.50 "t1='a\266c', t2='a?c'" {t1 GLOB t2} 1 - test_expr expr-6.51 "t1='a\266', t2='a?'" {t1 GLOB t2} 1 - test_expr expr-6.52 "t1='a\266', t2='a??'" {t1 GLOB t2} 0 - test_expr expr-6.53 "t1='ax\266', t2='a??'" {t1 GLOB t2} 1 - test_expr expr-6.54 "t1='ax\266', t2='a?\266'" {t1 GLOB t2} 1 - test_expr expr-6.55 "t1='ax\266y\266', t2='a*\266'" {t1 GLOB t2} 1 - test_expr expr-6.56 "t1='a\266b', t2='a\[x\266y\]b'" {t1 GLOB t2} 1 - test_expr expr-6.57 "t1='a\266b', t2='a\[\260-\270\]b'" {t1 GLOB t2} 1 - test_expr expr-6.58 "t1='a\266b', t2='a\[\266-\270\]b'" {t1 GLOB t2} 1 - test_expr expr-6.59 "t1='a\266b', t2='a\[\267-\270\]b'" {t1 GLOB t2} 0 - test_expr expr-6.60 "t1='a\266b', t2='a\[x-\267\]b'" {t1 GLOB t2} 1 - test_expr expr-6.61 "t1='a\266b', t2='a\[x-\266\]b'" {t1 GLOB t2} 1 - test_expr expr-6.62 "t1='a\266b', t2='a\[x-\265\]b'" {t1 GLOB t2} 0 + set go 1 + if {[info command encoding]!=""} { + if {[catch {encoding system iso8859-1} msg]} { + puts "skipping tests of GLOB operator: $msg" + set go 0 + } + } + if {$go} { + test_expr expr-6.50 "t1='a\266c', t2='a?c'" {t1 GLOB t2} 1 + test_expr expr-6.51 "t1='a\266', t2='a?'" {t1 GLOB t2} 1 + test_expr expr-6.52 "t1='a\266', t2='a??'" {t1 GLOB t2} 0 + test_expr expr-6.53 "t1='ax\266', t2='a??'" {t1 GLOB t2} 1 + test_expr expr-6.54 "t1='ax\266', t2='a?\266'" {t1 GLOB t2} 1 + test_expr expr-6.55 "t1='ax\266y\266', t2='a*\266'" {t1 GLOB t2} 1 + test_expr expr-6.56 "t1='a\266b', t2='a\[x\266y\]b'" {t1 GLOB t2} 1 + test_expr expr-6.57 "t1='a\266b', t2='a\[\260-\270\]b'" {t1 GLOB t2} 1 + test_expr expr-6.58 "t1='a\266b', t2='a\[\266-\270\]b'" {t1 GLOB t2} 1 + test_expr expr-6.59 "t1='a\266b', t2='a\[\267-\270\]b'" {t1 GLOB t2} 0 + test_expr expr-6.60 "t1='a\266b', t2='a\[x-\267\]b'" {t1 GLOB t2} 1 + test_expr expr-6.61 "t1='a\266b', t2='a\[x-\266\]b'" {t1 GLOB t2} 1 + test_expr expr-6.62 "t1='a\266b', t2='a\[x-\265\]b'" {t1 GLOB t2} 0 + } } # The sqliteExprIfFalse and sqliteExprIfTrue routines are only