├── Makefile.in ├── Makefile.template ├── README ├── VERSION ├── aclocal.m4 ├── config.guess ├── config.sub ├── configure ├── configure.ac ├── doc ├── lemon.html └── report1.txt ├── install-sh ├── libtool ├── ltmain.sh ├── manifest ├── manifest.uuid ├── publish.sh ├── spec.template ├── sqlite.1 ├── src ├── TODO ├── btree.c ├── btree.h ├── build.c ├── delete.c ├── encode.c ├── expr.c ├── func.c ├── hash.c ├── hash.h ├── insert.c ├── main.c ├── md5.c ├── os.c ├── os.h ├── pager.c ├── pager.h ├── parse.y ├── printf.c ├── random.c ├── select.c ├── shell.c ├── shell.tcl ├── sqlite.h.in ├── sqliteInt.h ├── table.c ├── tclsqlite.c ├── test1.c ├── test2.c ├── test3.c ├── threadtest.c ├── tokenize.c ├── trigger.c ├── update.c ├── util.c ├── vdbe.c ├── vdbe.h └── where.c ├── test ├── all.test ├── bigrow.test ├── btree.test ├── btree2.test ├── btree3.test ├── conflict.test ├── copy.test ├── delete.test ├── expr.test ├── func.test ├── in.test ├── index.test ├── insert.test ├── insert2.test ├── intpkey.test ├── ioerr.test ├── join.test ├── limit.test ├── lock.test ├── main.test ├── malloc.test ├── minmax.test ├── misc1.test ├── misuse.test ├── notnull.test ├── null.test ├── pager.test ├── pragma.test ├── printf.test ├── quick.test ├── quote.test ├── rowid.test ├── select1.test ├── select2.test ├── select3.test ├── select4.test ├── select5.test ├── select6.test ├── sort.test ├── subselect.test ├── table.test ├── tableapi.test ├── tclsqlite.test ├── temptable.test ├── tester.tcl ├── trans.test ├── trigger1.test ├── trigger2.test ├── trigger3.test ├── unique.test ├── update.test ├── vacuum.test ├── view.test └── where.test ├── tool ├── lemon.c ├── lempar.c ├── memleak.awk ├── opNames.awk ├── opcodeDoc.awk ├── renumberOps.awk ├── report1.txt ├── speedtest.tcl └── speedtest2.tcl └── www ├── arch.fig ├── arch.png ├── arch.tcl ├── c_interface.tcl ├── changes.tcl ├── conflict.tcl ├── crosscompile.tcl ├── download.tcl ├── dynload.tcl ├── faq.tcl ├── formatchng.tcl ├── index.tcl ├── lang.tcl ├── mingw.tcl ├── opcode.tcl ├── speed.tcl ├── sqlite.tcl ├── tclsqlite.tcl └── vdbe.tcl /README: -------------------------------------------------------------------------------- 1 | This project is forked from 2.5.0 SQLite, and fixed for modern C compilers like GCC. 2 | 3 | Earlier SQLite is perfect source for code reading, and for database design and implementation. 4 | For SQLite 2.5.0, it has a core code base less than 20000 LOC in ANSI C which is easy to understand. 5 | 6 | I digged into historical versions of SQLite, and fixed this version against GCC on MacOS 10.13 and Debian 8. 7 | 8 | $sloccount SQLite-2.5.0-for-code-reading 9 | SLOC Directory SLOC-by-Language (Sorted) 10 | 20914 src_top_dir ansic=19895,yacc=584,tcl=435 11 | 6831 top_dir sh=6831 12 | 6363 www tcl=6363 13 | 4051 tool ansic=3606,tcl=372,awk=73 14 | 156 test tcl=156 15 | 0 doc (none) 16 | 17 | 18 | SQLite: An SQL Database Engine in a C Library 19 | 20 | To compile the project, first create a directory in which to place 21 | the build products. It is recommended, but not required, that the 22 | build directory be separate from the source directory. Cd into the 23 | build directory and then from the build directory run the configure 24 | script found at the root of the source tree. Then run "make". 25 | 26 | For example: 27 | 28 | tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" 29 | mkdir bld ;# Build will occur in a sibling directory 30 | cd bld ;# Change to the build directory 31 | ../sqlite/configure ;# Run the configure script 32 | make ;# Run the makefile. 33 | 34 | The configure script uses autoconf 2.50 and libtool. If the configure 35 | script does not work out for you, there is a generic makefile named 36 | "Makefile.template" in the top directory of the source tree that you 37 | can copy and edit to suite your needs. Comments on the generic makefile 38 | show what changes are needed. 39 | 40 | The windows binaries on the website are created using MinGW32 configured 41 | as a cross-compiler running under Linux. For details, see the ./publish.sh 42 | script at the top-level of the source tree. 43 | 44 | Contacts: 45 | 46 | http://www.hwaci.com/sw/sqlite/ 47 | http://groups.yahoo.com/group/sqlite/ 48 | drh@hwaci.com 49 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.5.0 2 | -------------------------------------------------------------------------------- /doc/report1.txt: -------------------------------------------------------------------------------- 1 | An SQLite (version 1.0) database was used in a large military application 2 | where the database contained 105 tables and indices. The following is 3 | a breakdown on the sizes of keys and data within these tables and indices: 4 | 5 | Entries: 967089 6 | Size: 45896104 7 | Avg Size: 48 8 | Key Size: 11112265 9 | Avg Key Size: 12 10 | Max Key Size: 99 11 | 12 | 0..8 263 0% 13 | 9..12 5560 0% 14 | 13..16 71394 7% 15 | 17..24 180717 26% 16 | 25..32 215442 48% 17 | 33..40 151118 64% 18 | 41..48 77479 72% 19 | 49..56 13983 74% 20 | 57..64 14481 75% 21 | 65..80 41342 79% 22 | 81..96 127098 92% 23 | 97..112 38054 96% 24 | 113..128 14197 98% 25 | 129..144 8208 99% 26 | 145..160 3326 99% 27 | 161..176 1242 99% 28 | 177..192 604 99% 29 | 193..208 222 99% 30 | 209..224 213 99% 31 | 225..240 132 99% 32 | 241..256 58 99% 33 | 257..288 515 99% 34 | 289..320 64 99% 35 | 321..352 39 99% 36 | 353..384 44 99% 37 | 385..416 25 99% 38 | 417..448 24 99% 39 | 449..480 26 99% 40 | 481..512 27 99% 41 | 513..1024 470 99% 42 | 1025..2048 396 99% 43 | 2049..4096 187 99% 44 | 4097..8192 78 99% 45 | 8193..16384 35 99% 46 | 16385..32768 17 99% 47 | 32769..65536 6 99% 48 | 65537..65541 3 100% 49 | 50 | If the indices are omitted, the statistics for the 49 tables 51 | become the following: 52 | 53 | Entries: 451103 54 | Size: 30930282 55 | Avg Size: 69 56 | Key Size: 1804412 57 | Avg Key Size: 4 58 | Max Key Size: 4 59 | 60 | 0..24 89 0% 61 | 25..32 9417 2% 62 | 33..40 119162 28% 63 | 41..48 68710 43% 64 | 49..56 9539 45% 65 | 57..64 12435 48% 66 | 65..80 38650 57% 67 | 81..96 126877 85% 68 | 97..112 38030 93% 69 | 113..128 14183 96% 70 | 129..144 7668 98% 71 | 145..160 3302 99% 72 | 161..176 1238 99% 73 | 177..192 597 99% 74 | 193..208 217 99% 75 | 209..224 211 99% 76 | 225..240 130 99% 77 | 241..256 57 99% 78 | 257..288 100 99% 79 | 289..320 62 99% 80 | 321..352 34 99% 81 | 353..384 43 99% 82 | 385..416 24 99% 83 | 417..448 24 99% 84 | 449..480 25 99% 85 | 481..512 27 99% 86 | 513..1024 153 99% 87 | 1025..2048 92 99% 88 | 2049..4096 7 100% 89 | 90 | The 56 indices have these statistics: 91 | 92 | Entries: 512422 93 | Size: 14879828 94 | Avg Size: 30 95 | Key Size: 9253204 96 | Avg Key Size: 19 97 | Max Key Size: 99 98 | 99 | 0..8 246 0% 100 | 9..12 5486 1% 101 | 13..16 70717 14% 102 | 17..24 178246 49% 103 | 25..32 205722 89% 104 | 33..40 31951 96% 105 | 41..48 8768 97% 106 | 49..56 4444 98% 107 | 57..64 2046 99% 108 | 65..80 2691 99% 109 | 81..96 202 99% 110 | 97..112 11 99% 111 | 113..144 527 99% 112 | 145..160 20 99% 113 | 161..288 406 99% 114 | 289..1024 316 99% 115 | 1025..2048 304 99% 116 | 2049..4096 180 99% 117 | 4097..8192 78 99% 118 | 8193..16384 35 99% 119 | 16385..32768 17 99% 120 | 32769..65536 6 99% 121 | 65537..65541 3 100% 122 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5 (mit/util/scripts/install.sh). 5 | # 6 | # Copyright 1991 by the Massachusetts Institute of Technology 7 | # 8 | # Permission to use, copy, modify, distribute, and sell this software and its 9 | # documentation for any purpose is hereby granted without fee, provided that 10 | # the above copyright notice appear in all copies and that both that 11 | # copyright notice and this permission notice appear in supporting 12 | # documentation, and that the name of M.I.T. not be used in advertising or 13 | # publicity pertaining to distribution of the software without specific, 14 | # written prior permission. M.I.T. makes no representations about the 15 | # suitability of this software for any purpose. It is provided "as is" 16 | # without express or implied warranty. 17 | # 18 | # Calling this script install-sh is preferred over install.sh, to prevent 19 | # `make' implicit rules from creating a file called install from it 20 | # when there is no Makefile. 21 | # 22 | # This script is compatible with the BSD install script, but was written 23 | # from scratch. It can only install one file at a time, a restriction 24 | # shared with many OS's install programs. 25 | 26 | 27 | # set DOITPROG to echo to test this script 28 | 29 | # Don't use :- since 4.3BSD and earlier shells don't like it. 30 | doit="${DOITPROG-}" 31 | 32 | 33 | # put in absolute paths if you don't have them in your path; or use env. vars. 34 | 35 | mvprog="${MVPROG-mv}" 36 | cpprog="${CPPROG-cp}" 37 | chmodprog="${CHMODPROG-chmod}" 38 | chownprog="${CHOWNPROG-chown}" 39 | chgrpprog="${CHGRPPROG-chgrp}" 40 | stripprog="${STRIPPROG-strip}" 41 | rmprog="${RMPROG-rm}" 42 | mkdirprog="${MKDIRPROG-mkdir}" 43 | 44 | transformbasename="" 45 | transform_arg="" 46 | instcmd="$mvprog" 47 | chmodcmd="$chmodprog 0755" 48 | chowncmd="" 49 | chgrpcmd="" 50 | stripcmd="" 51 | rmcmd="$rmprog -f" 52 | mvcmd="$mvprog" 53 | src="" 54 | dst="" 55 | dir_arg="" 56 | 57 | while [ x"$1" != x ]; do 58 | case $1 in 59 | -c) instcmd="$cpprog" 60 | shift 61 | continue;; 62 | 63 | -d) dir_arg=true 64 | shift 65 | continue;; 66 | 67 | -m) chmodcmd="$chmodprog $2" 68 | shift 69 | shift 70 | continue;; 71 | 72 | -o) chowncmd="$chownprog $2" 73 | shift 74 | shift 75 | continue;; 76 | 77 | -g) chgrpcmd="$chgrpprog $2" 78 | shift 79 | shift 80 | continue;; 81 | 82 | -s) stripcmd="$stripprog" 83 | shift 84 | continue;; 85 | 86 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87 | shift 88 | continue;; 89 | 90 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91 | shift 92 | continue;; 93 | 94 | *) if [ x"$src" = x ] 95 | then 96 | src=$1 97 | else 98 | # this colon is to work around a 386BSD /bin/sh bug 99 | : 100 | dst=$1 101 | fi 102 | shift 103 | continue;; 104 | esac 105 | done 106 | 107 | if [ x"$src" = x ] 108 | then 109 | echo "install: no input file specified" 110 | exit 1 111 | else 112 | true 113 | fi 114 | 115 | if [ x"$dir_arg" != x ]; then 116 | dst=$src 117 | src="" 118 | 119 | if [ -d $dst ]; then 120 | instcmd=: 121 | chmodcmd="" 122 | else 123 | instcmd=mkdir 124 | fi 125 | else 126 | 127 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 128 | # might cause directories to be created, which would be especially bad 129 | # if $src (and thus $dsttmp) contains '*'. 130 | 131 | if [ -f $src -o -d $src ] 132 | then 133 | true 134 | else 135 | echo "install: $src does not exist" 136 | exit 1 137 | fi 138 | 139 | if [ x"$dst" = x ] 140 | then 141 | echo "install: no destination specified" 142 | exit 1 143 | else 144 | true 145 | fi 146 | 147 | # If destination is a directory, append the input filename; if your system 148 | # does not like double slashes in filenames, you may need to add some logic 149 | 150 | if [ -d $dst ] 151 | then 152 | dst="$dst"/`basename $src` 153 | else 154 | true 155 | fi 156 | fi 157 | 158 | ## this sed command emulates the dirname command 159 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 160 | 161 | # Make sure that the destination directory exists. 162 | # this part is taken from Noah Friedman's mkinstalldirs script 163 | 164 | # Skip lots of stat calls in the usual case. 165 | if [ ! -d "$dstdir" ]; then 166 | defaultIFS=' 167 | ' 168 | IFS="${IFS-${defaultIFS}}" 169 | 170 | oIFS="${IFS}" 171 | # Some sh's can't handle IFS=/ for some reason. 172 | IFS='%' 173 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 174 | IFS="${oIFS}" 175 | 176 | pathcomp='' 177 | 178 | while [ $# -ne 0 ] ; do 179 | pathcomp="${pathcomp}${1}" 180 | shift 181 | 182 | if [ ! -d "${pathcomp}" ] ; 183 | then 184 | $mkdirprog "${pathcomp}" 185 | else 186 | true 187 | fi 188 | 189 | pathcomp="${pathcomp}/" 190 | done 191 | fi 192 | 193 | if [ x"$dir_arg" != x ] 194 | then 195 | $doit $instcmd $dst && 196 | 197 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && 198 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && 199 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && 200 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi 201 | else 202 | 203 | # If we're going to rename the final executable, determine the name now. 204 | 205 | if [ x"$transformarg" = x ] 206 | then 207 | dstfile=`basename $dst` 208 | else 209 | dstfile=`basename $dst $transformbasename | 210 | sed $transformarg`$transformbasename 211 | fi 212 | 213 | # don't allow the sed command to completely eliminate the filename 214 | 215 | if [ x"$dstfile" = x ] 216 | then 217 | dstfile=`basename $dst` 218 | else 219 | true 220 | fi 221 | 222 | # Make a temp file name in the proper directory. 223 | 224 | dsttmp=$dstdir/#inst.$$# 225 | 226 | # Move or copy the file name to the temp name 227 | 228 | $doit $instcmd $src $dsttmp && 229 | 230 | trap "rm -f ${dsttmp}" 0 && 231 | 232 | # and set any options; do chmod last to preserve setuid bits 233 | 234 | # If any of these fail, we abort the whole thing. If we want to 235 | # ignore errors from any of these, just make sure not to ignore 236 | # errors from the above "$doit $instcmd $src $dsttmp" command. 237 | 238 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && 239 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && 240 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && 241 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && 242 | 243 | # Now rename the file to the real destination. 244 | 245 | $doit $rmcmd -f $dstdir/$dstfile && 246 | $doit $mvcmd $dsttmp $dstdir/$dstfile 247 | 248 | fi && 249 | 250 | 251 | exit 0 252 | -------------------------------------------------------------------------------- /manifest.uuid: -------------------------------------------------------------------------------- 1 | 9baef3e240c4ffd90881ac4664efd205bd9e65f4 2 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This script is used to compile SQLite and all its documentation and 4 | # ship everything up to the SQLite website. This script will only work 5 | # on the system "zadok" at the Hwaci offices. But others might find 6 | # the script useful as an example. 7 | # 8 | 9 | # Set srcdir to the name of the directory that contains the publish.sh 10 | # script. 11 | # 12 | srcdir=`echo "$0" | sed 's%\(^.*\)/[^/][^/]*$%\1%'` 13 | 14 | # Get the makefile. 15 | # 16 | cp $srcdir/Makefile.template ./Makefile 17 | 18 | # Start building stuff. 19 | # 20 | make clean 21 | make sqlite 22 | strip sqlite 23 | mv sqlite sqlite.bin 24 | rm -f sqlite.bin.gz 25 | gzip sqlite.bin 26 | 27 | # Build the tclsqlite.so shared library for import into tclsh or wish 28 | # under Linux 29 | # 30 | make target_source 31 | rm sqlite_source.zip 32 | cd tsrc 33 | zip ../sqlite_source.zip * 34 | rm shell.c 35 | TCLDIR=/home/drh/tcltk/8.2linux 36 | TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a 37 | OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1' 38 | gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so 39 | strip tclsqlite.so 40 | mv tclsqlite.so .. 41 | rm tclsqlite.c 42 | gcc -fPIC -DNDEBUG=1 -O2 -I. -shared *.c -o sqlite.so 43 | strip sqlite.so 44 | mv sqlite.so .. 45 | cd .. 46 | rm -f tclsqlite.so.gz sqlite.so.gz 47 | gzip tclsqlite.so 48 | gzip sqlite.so 49 | 50 | # Build the tclsqlite.dll shared library that can be imported into tclsh 51 | # or wish on windows. 52 | # 53 | make target_source 54 | cd tsrc 55 | rm shell.c 56 | TCLDIR=/home/drh/tcltk/8.2win 57 | TCLSTUBLIB=$TCLDIR/tclstub82.a 58 | PATH=$PATH:/opt/mingw/bin 59 | OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1 -DTHREADSAFE=1' 60 | CC="i386-mingw32-gcc -O2 $OPTS -I. -I$TCLDIR" 61 | rm shell.c 62 | for i in *.c; do 63 | CMD="$CC -c $i" 64 | echo $CMD 65 | $CMD 66 | done 67 | echo 'EXPORTS' >tclsqlite.def 68 | echo 'Tclsqlite_Init' >>tclsqlite.def 69 | echo 'Sqlite_Init' >>tclsqlite.def 70 | i386-mingw32-dllwrap \ 71 | --def tclsqlite.def -v --export-all \ 72 | --driver-name i386-mingw32-gcc \ 73 | --dlltool-name i386-mingw32-dlltool \ 74 | --as i386-mingw32-as \ 75 | --target i386-mingw32 \ 76 | -dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB 77 | i386-mingw32-strip tclsqlite.dll 78 | mv tclsqlite.dll .. 79 | rm tclsqlite.o 80 | cat >sqlite.def <<\END_OF_FILE 81 | EXPORTS 82 | sqlite_open 83 | sqlite_close 84 | sqlite_exec 85 | sqlite_last_insert_rowid 86 | sqlite_error_string 87 | sqlite_interrupt 88 | sqlite_complete 89 | sqlite_busy_handler 90 | sqlite_busy_timeout 91 | sqlite_get_table 92 | sqlite_free_table 93 | sqlite_mprintf 94 | sqlite_vmprintf 95 | sqlite_exec_printf 96 | sqlite_exec_vprintf 97 | sqlite_get_table_printf 98 | sqlite_get_table_vprintf 99 | sqlite_freemem 100 | sqlite_libversion 101 | sqlite_libencoding 102 | sqlite_changes 103 | sqliteMalloc 104 | sqliteFree 105 | sqliteRealloc 106 | END_OF_FILE 107 | i386-mingw32-dllwrap \ 108 | --def sqlite.def -v --export-all \ 109 | --driver-name i386-mingw32-gcc \ 110 | --dlltool-name i386-mingw32-dlltool \ 111 | --as i386-mingw32-as \ 112 | --target i386-mingw32 \ 113 | -dllname sqlite.dll -lmsvcrt *.o 114 | i386-mingw32-strip sqlite.dll 115 | mv sqlite.dll sqlite.def .. 116 | cd .. 117 | rm -f tclsqlite.zip sqlitedll.zip 118 | zip tclsqlite.zip tclsqlite.dll 119 | zip sqlitedll.zip sqlite.dll sqlite.def 120 | 121 | # Build the sqlite.exe executable for windows. 122 | # 123 | make target_source 124 | cd tsrc 125 | rm tclsqlite.c 126 | OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1' 127 | i386-mingw32-gcc -O2 $OPTS -I. -I$TCLDIR *.c -o sqlite.exe 128 | mv sqlite.exe .. 129 | cd .. 130 | rm -f sqlite.zip 131 | zip sqlite.zip sqlite.exe 132 | 133 | # Construct a tarball of the source tree 134 | # 135 | ORIGIN=`pwd` 136 | cd $srcdir 137 | cd .. 138 | EXCLUDE=`find sqlite -print | grep CVS | sed 's,sqlite/, --exclude sqlite/,'` 139 | tar czf $ORIGIN/sqlite.tar.gz $EXCLUDE sqlite 140 | cd $ORIGIN 141 | vers=`cat $srcdir/VERSION` 142 | rm -f sqlite-$vers.tar.gz 143 | ln sqlite.tar.gz sqlite-$vers.tar.gz 144 | 145 | # 146 | # Build RPMS (binary) and Source RPM 147 | # 148 | 149 | # Make sure we are properly setup to build RPMs 150 | # 151 | echo "%HOME %{expand:%%(cd; pwd)}" > $HOME/.rpmmacros 152 | echo "%_topdir %{HOME}/rpm" >> $HOME/.rpmmacros 153 | mkdir $HOME/rpm 154 | mkdir $HOME/rpm/BUILD 155 | mkdir $HOME/rpm/SOURCES 156 | mkdir $HOME/rpm/RPMS 157 | mkdir $HOME/rpm/SRPMS 158 | mkdir $HOME/rpm/SPECS 159 | 160 | # create the spec file from the template 161 | sed s/SQLITE_VERSION/$vers/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec 162 | 163 | # copy the source tarball to the rpm directory 164 | cp sqlite-$vers.tar.gz $HOME/rpm/SOURCES/. 165 | 166 | # build all the rpms 167 | rpm -ba $HOME/rpm/SPECS/sqlite.spec >& rpm-$vers.log 168 | 169 | # copy the RPMs into the build directory. 170 | ln $HOME/rpm/RPMS/i386/sqlite*-$vers*.rpm . 171 | ln $HOME/rpm/SRPMS/sqlite-$vers*.rpm . 172 | 173 | 174 | # Build the website 175 | # 176 | cp $srcdir/../historical/* . 177 | rm -rf doc 178 | make doc 179 | ln sqlite.bin.gz sqlite.zip sqlite*.tar.gz tclsqlite.so.gz tclsqlite.zip doc 180 | ln sqlitedll.zip sqlite.so.gz sqlite_source.zip doc 181 | ln *.rpm doc 182 | -------------------------------------------------------------------------------- /spec.template: -------------------------------------------------------------------------------- 1 | %define name sqlite 2 | %define version SQLITE_VERSION 3 | %define release 1 4 | 5 | Name: %{name} 6 | Summary: SQLite is a C library that implements an embeddable SQL database engine 7 | Version: %{version} 8 | Release: %{release} 9 | Source: %{name}-%{version}.tar.gz 10 | Group: System/Libraries 11 | URL: http://www.hwaci.com/sw/sqlite/ 12 | License: Public Domain 13 | BuildRoot: %{_tmppath}/%{name}-%{version}-root 14 | 15 | %description 16 | SQLite is a C library that implements an embeddable SQL database engine. 17 | Programs that link with the SQLite library can have SQL database access 18 | without running a separate RDBMS process. The distribution comes with a 19 | standalone command-line access program (sqlite) that can be used to 20 | administer an SQLite database and which serves as an example of how to 21 | use the SQLite library. 22 | 23 | %package -n %{name}-devel 24 | Summary: Header files and libraries for developing apps which will use sqlite 25 | Group: Development/C 26 | Requires: %{name} = %{version}-%{release} 27 | 28 | %description -n %{name}-devel 29 | The sqlite-devel package contains the header files and libraries needed 30 | to develop programs that use the sqlite database library. 31 | 32 | %prep 33 | %setup -q -n %{name} 34 | 35 | %build 36 | CFLAGS="%optflags -DNDEBUG=1" CXXFLAGS="%optflags -DNDEBUG=1" ./configure --prefix=%{_prefix} 37 | 38 | make 39 | make doc 40 | 41 | %install 42 | install -d $RPM_BUILD_ROOT/%{_prefix} 43 | install -d $RPM_BUILD_ROOT/%{_prefix}/bin 44 | install -d $RPM_BUILD_ROOT/%{_prefix}/include 45 | install -d $RPM_BUILD_ROOT/%{_prefix}/lib 46 | make install prefix=$RPM_BUILD_ROOT/%{_prefix} 47 | 48 | %clean 49 | rm -fr $RPM_BUILD_ROOT 50 | 51 | %files 52 | %defattr(-, root, root) 53 | %{_libdir}/*.so* 54 | %{_bindir}/* 55 | 56 | %files -n %{name}-devel 57 | %defattr(-, root, root) 58 | %{_libdir}/*.a 59 | %{_libdir}/*.la 60 | %{_includedir}/* 61 | %doc doc/* 62 | -------------------------------------------------------------------------------- /src/TODO: -------------------------------------------------------------------------------- 1 | * Document all the changes and release Sqlite 2.0. 2 | * Implement CLUSTER command like in PostgreSQL. 3 | * "OPTIMIZE select" statement to automatically create indices and/or 4 | invoke a CLUSTER command. 5 | * "CREATE INDEX FOR select" to automatically generate needed indices. 6 | * Parse and use constraints. 7 | -------------------------------------------------------------------------------- /src/btree.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 15 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This header file defines the interface that the sqlite B-Tree file 13 | ** subsystem. See comments in the source code for a detailed description 14 | ** of what each interface routine does. 15 | ** 16 | ** @(#) $Id: btree.h,v 1.24 2002/02/19 15:00:08 drh Exp $ 17 | */ 18 | #ifndef _BTREE_H_ 19 | #define _BTREE_H_ 20 | 21 | typedef struct Btree Btree; 22 | typedef struct BtCursor BtCursor; 23 | 24 | int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); 25 | int sqliteBtreeClose(Btree*); 26 | int sqliteBtreeSetCacheSize(Btree*, int); 27 | 28 | int sqliteBtreeBeginTrans(Btree*); 29 | int sqliteBtreeCommit(Btree*); 30 | int sqliteBtreeRollback(Btree*); 31 | int sqliteBtreeBeginCkpt(Btree*); 32 | int sqliteBtreeCommitCkpt(Btree*); 33 | int sqliteBtreeRollbackCkpt(Btree*); 34 | 35 | int sqliteBtreeCreateTable(Btree*, int*); 36 | int sqliteBtreeCreateIndex(Btree*, int*); 37 | int sqliteBtreeDropTable(Btree*, int); 38 | int sqliteBtreeClearTable(Btree*, int); 39 | 40 | int sqliteBtreeCursor(Btree*, int iTable, int wrFlag, BtCursor **ppCur); 41 | int sqliteBtreeMoveto(BtCursor*, const void *pKey, int nKey, int *pRes); 42 | int sqliteBtreeDelete(BtCursor*); 43 | int sqliteBtreeInsert(BtCursor*, const void *pKey, int nKey, 44 | const void *pData, int nData); 45 | int sqliteBtreeFirst(BtCursor*, int *pRes); 46 | int sqliteBtreeLast(BtCursor*, int *pRes); 47 | int sqliteBtreeNext(BtCursor*, int *pRes); 48 | int sqliteBtreeKeySize(BtCursor*, int *pSize); 49 | int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf); 50 | int sqliteBtreeKeyCompare(BtCursor*, const void *pKey, int nKey, 51 | int nIgnore, int *pRes); 52 | int sqliteBtreeDataSize(BtCursor*, int *pSize); 53 | int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf); 54 | int sqliteBtreeCloseCursor(BtCursor*); 55 | 56 | #define SQLITE_N_BTREE_META 4 57 | int sqliteBtreeGetMeta(Btree*, int*); 58 | int sqliteBtreeUpdateMeta(Btree*, int*); 59 | 60 | char *sqliteBtreeIntegrityCheck(Btree*, int*, int); 61 | 62 | #ifdef SQLITE_TEST 63 | int sqliteBtreePageDump(Btree*, int, int); 64 | int sqliteBtreeCursorDump(BtCursor*, int*); 65 | struct Pager *sqliteBtreePager(Btree*); 66 | #endif 67 | 68 | #endif /* _BTREE_H_ */ 69 | -------------------------------------------------------------------------------- /src/encode.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2002 April 25 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This file contains helper routines used to translate binary data into 13 | ** a null-terminated string (suitable for use in SQLite) and back again. 14 | ** These are convenience routines for use by people who want to store binary 15 | ** data in an SQLite database. The code in this file is used by any other 16 | ** part of the SQLite library. 17 | ** 18 | ** $Id: encode.c,v 1.2 2002/04/25 23:06:47 drh Exp $ 19 | */ 20 | 21 | /* 22 | ** Encode a binary buffer "in" of size n bytes so that it contains 23 | ** no instances of characters '\'' or '\000'. The output is 24 | ** null-terminated and can be used as a string value in an INSERT 25 | ** or UPDATE statement. Use sqlite_decode_binary() to convert the 26 | ** string back into its original binary. 27 | ** 28 | ** The result is written into a preallocated output buffer "out". 29 | ** "out" must be able to hold at least (256*n + 1262)/253 bytes. 30 | ** In other words, the output will be expanded by as much as 3 31 | ** bytes for every 253 bytes of input plus 2 bytes of fixed overhead. 32 | ** (This is approximately 2 + 1.019*n or about a 2% size increase.) 33 | */ 34 | void sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){ 35 | int i, j, e, m; 36 | int cnt[256]; 37 | memset(cnt, 0, sizeof(cnt)); 38 | for(i=n-1; i>=0; i--){ cnt[in[i]]++; } 39 | m = n; 40 | for(i=1; i<256; i++){ 41 | int sum; 42 | if( i=='\'' ) continue; 43 | sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff]; 44 | if( sum%d (max %d)", n, strlen(out)+1, m); 129 | if( strlen(out)+1>m ){ 130 | printf(" ERROR output too big\n"); 131 | exit(1); 132 | } 133 | for(j=0; out[j]; j++){ 134 | if( out[j]=='\'' ){ 135 | printf(" ERROR contains (')\n"); 136 | exit(1); 137 | } 138 | } 139 | j = sqlite_decode_binary(out, out); 140 | if( j!=n ){ 141 | printf(" ERROR decode size %d\n", j); 142 | exit(1); 143 | } 144 | if( memcmp(in, out, n)!=0 ){ 145 | printf(" ERROR decode mismatch\n"); 146 | exit(1); 147 | } 148 | printf(" OK\n"); 149 | } 150 | } 151 | #endif /* ENCODER_TEST */ 152 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 22 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This is the header file for the generic hash-table implemenation 13 | ** used in SQLite. 14 | ** 15 | ** $Id: hash.h,v 1.5 2002/06/08 23:25:09 drh Exp $ 16 | */ 17 | #ifndef _SQLITE_HASH_H_ 18 | #define _SQLITE_HASH_H_ 19 | 20 | /* Forward declarations of structures. */ 21 | typedef struct Hash Hash; 22 | typedef struct HashElem HashElem; 23 | 24 | /* A complete hash table is an instance of the following structure. 25 | ** The internals of this structure are intended to be opaque -- client 26 | ** code should not attempt to access or modify the fields of this structure 27 | ** directly. Change this structure only by using the routines below. 28 | ** However, many of the "procedures" and "functions" for modifying and 29 | ** accessing this structure are really macros, so we can't really make 30 | ** this structure opaque. 31 | */ 32 | struct Hash { 33 | char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */ 34 | char copyKey; /* True if copy of key made on insert */ 35 | int count; /* Number of entries in this table */ 36 | HashElem *first; /* The first element of the array */ 37 | int htsize; /* Number of buckets in the hash table */ 38 | struct _ht { /* the hash table */ 39 | int count; /* Number of entries with this hash */ 40 | HashElem *chain; /* Pointer to first entry with this hash */ 41 | } *ht; 42 | }; 43 | 44 | /* Each element in the hash table is an instance of the following 45 | ** structure. All elements are stored on a single doubly-linked list. 46 | ** 47 | ** Again, this structure is intended to be opaque, but it can't really 48 | ** be opaque because it is used by macros. 49 | */ 50 | struct HashElem { 51 | HashElem *next, *prev; /* Next and previous elements in the table */ 52 | void *data; /* Data associated with this element */ 53 | void *pKey; int nKey; /* Key associated with this element */ 54 | }; 55 | 56 | /* 57 | ** There are 4 different modes of operation for a hash table: 58 | ** 59 | ** SQLITE_HASH_INT nKey is used as the key and pKey is ignored. 60 | ** 61 | ** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored. 62 | ** 63 | ** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long 64 | ** (including the null-terminator, if any). Case 65 | ** is ignored in comparisons. 66 | ** 67 | ** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long. 68 | ** memcmp() is used to compare keys. 69 | ** 70 | ** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY 71 | ** if the copyKey parameter to HashInit is 1. 72 | */ 73 | #define SQLITE_HASH_INT 1 74 | #define SQLITE_HASH_POINTER 2 75 | #define SQLITE_HASH_STRING 3 76 | #define SQLITE_HASH_BINARY 4 77 | 78 | /* 79 | ** Access routines. To delete, insert a NULL pointer. 80 | */ 81 | void sqliteHashInit(Hash*, int keytype, int copyKey); 82 | void *sqliteHashInsert(Hash*, const void *pKey, int nKey, void *pData); 83 | void *sqliteHashFind(const Hash*, const void *pKey, int nKey); 84 | void sqliteHashClear(Hash*); 85 | 86 | /* 87 | ** Macros for looping over all elements of a hash table. The idiom is 88 | ** like this: 89 | ** 90 | ** Hash h; 91 | ** HashElem *p; 92 | ** ... 93 | ** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ 94 | ** SomeStructure *pData = sqliteHashData(p); 95 | ** // do something with pData 96 | ** } 97 | */ 98 | #define sqliteHashFirst(H) ((H)->first) 99 | #define sqliteHashNext(E) ((E)->next) 100 | #define sqliteHashData(E) ((E)->data) 101 | #define sqliteHashKey(E) ((E)->pKey) 102 | #define sqliteHashKeysize(E) ((E)->nKey) 103 | 104 | /* 105 | ** Number of entries in a hash table 106 | */ 107 | #define sqliteHashCount(H) ((H)->count) 108 | 109 | #endif /* _SQLITE_HASH_H_ */ 110 | -------------------------------------------------------------------------------- /src/os.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 16 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ****************************************************************************** 12 | ** 13 | ** This header file (together with is companion C source-code file 14 | ** "os.c") attempt to abstract the underlying operating system so that 15 | ** the SQLite library will work on both POSIX and windows systems. 16 | */ 17 | #ifndef _SQLITE_OS_H_ 18 | #define _SQLITE_OS_H_ 19 | 20 | #ifndef OS_UNIX 21 | # ifndef OS_WIN 22 | # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) 23 | # define OS_WIN 1 24 | # define OS_UNIX 0 25 | # else 26 | # define OS_WIN 0 27 | # define OS_UNIX 1 28 | # endif 29 | # else 30 | # define OS_UNIX 0 31 | # endif 32 | #endif 33 | #ifndef OS_WIN 34 | # define OS_WIN 0 35 | #endif 36 | 37 | /* 38 | ** A handle for an open file is stored in an OsFile object. 39 | */ 40 | #if OS_UNIX 41 | typedef struct OsFile OsFile; 42 | struct OsFile { 43 | struct lockInfo *pLock; /* Information about locks on this inode */ 44 | int fd; /* The file descriptor */ 45 | int locked; /* True if this user holds the lock */ 46 | }; 47 | # define SQLITE_TEMPNAME_SIZE 200 48 | # if defined(HAVE_USLEEP) && HAVE_USLEEP 49 | # define SQLITE_MIN_SLEEP_MS 1 50 | # else 51 | # define SQLITE_MIN_SLEEP_MS 1000 52 | # endif 53 | #endif 54 | 55 | #if OS_WIN 56 | #include 57 | #include 58 | typedef struct OsFile OsFile; 59 | struct OsFile { 60 | HANDLE h; 61 | int locked; 62 | }; 63 | # define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) 64 | # define SQLITE_MIN_SLEEP_MS 1 65 | #endif 66 | 67 | int sqliteOsDelete(const char*); 68 | int sqliteOsFileExists(const char*); 69 | int sqliteOsOpenReadWrite(const char*, OsFile*, int*); 70 | int sqliteOsOpenExclusive(const char*, OsFile*, int); 71 | int sqliteOsOpenReadOnly(const char*, OsFile*); 72 | int sqliteOsTempFileName(char*); 73 | int sqliteOsClose(OsFile*); 74 | int sqliteOsRead(OsFile*, void*, int amt); 75 | int sqliteOsWrite(OsFile*, const void*, int amt); 76 | int sqliteOsSeek(OsFile*, int offset); 77 | int sqliteOsSync(OsFile*); 78 | int sqliteOsTruncate(OsFile*, int size); 79 | int sqliteOsFileSize(OsFile*, int *pSize); 80 | int sqliteOsReadLock(OsFile*); 81 | int sqliteOsWriteLock(OsFile*); 82 | int sqliteOsUnlock(OsFile*); 83 | int sqliteOsRandomSeed(char*); 84 | int sqliteOsSleep(int ms); 85 | void sqliteOsEnterMutex(void); 86 | void sqliteOsLeaveMutex(void); 87 | 88 | 89 | 90 | #endif /* _SQLITE_OS_H_ */ 91 | -------------------------------------------------------------------------------- /src/pager.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 15 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This header file defines the interface that the sqlite page cache 13 | ** subsystem. The page cache subsystem reads and writes a file a page 14 | ** at a time and provides a journal for rollback. 15 | ** 16 | ** @(#) $Id: pager.h,v 1.16 2002/03/05 12:41:20 drh Exp $ 17 | */ 18 | 19 | /* 20 | ** The size of one page 21 | ** 22 | ** You can change this value to another (reasonable) power of two 23 | ** such as 512, 2048, 4096, or 8192 and things will still work. But 24 | ** experiments show that a page size of 1024 gives the best speed. 25 | ** (The speed differences are minimal.) 26 | */ 27 | #define SQLITE_PAGE_SIZE 1024 28 | 29 | /* 30 | ** Maximum number of pages in one database. (This is a limitation of 31 | ** imposed by 4GB files size limits.) 32 | */ 33 | #define SQLITE_MAX_PAGE 1073741823 34 | 35 | /* 36 | ** The type used to represent a page number. The first page in a file 37 | ** is called page 1. 0 is used to represent "not a page". 38 | */ 39 | typedef unsigned int Pgno; 40 | 41 | /* 42 | ** Each open file is managed by a separate instance of the "Pager" structure. 43 | */ 44 | typedef struct Pager Pager; 45 | 46 | /* 47 | ** See source code comments for a detailed description of the following 48 | ** routines: 49 | */ 50 | int sqlitepager_open(Pager **ppPager,const char *zFilename,int nPage,int nEx); 51 | void sqlitepager_set_destructor(Pager*, void(*)(void*)); 52 | void sqlitepager_set_cachesize(Pager*, int); 53 | int sqlitepager_close(Pager *pPager); 54 | int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage); 55 | void *sqlitepager_lookup(Pager *pPager, Pgno pgno); 56 | int sqlitepager_ref(void*); 57 | int sqlitepager_unref(void*); 58 | Pgno sqlitepager_pagenumber(void*); 59 | int sqlitepager_write(void*); 60 | int sqlitepager_iswriteable(void*); 61 | int sqlitepager_pagecount(Pager*); 62 | int sqlitepager_begin(void*); 63 | int sqlitepager_commit(Pager*); 64 | int sqlitepager_rollback(Pager*); 65 | int sqlitepager_isreadonly(Pager*); 66 | int sqlitepager_ckpt_begin(Pager*); 67 | int sqlitepager_ckpt_commit(Pager*); 68 | int sqlitepager_ckpt_rollback(Pager*); 69 | void sqlitepager_dont_rollback(void*); 70 | void sqlitepager_dont_write(Pager*, Pgno); 71 | int *sqlitepager_stats(Pager*); 72 | 73 | #ifdef SQLITE_TEST 74 | void sqlitepager_refdump(Pager*); 75 | int pager_refinfo_enable; 76 | #endif 77 | -------------------------------------------------------------------------------- /src/random.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 15 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This file contains code to implement a pseudo-random number 13 | ** generator (PRNG) for SQLite. 14 | ** 15 | ** Random numbers are used by some of the database backends in order 16 | ** to generate random integer keys for tables or random filenames. 17 | ** 18 | ** $Id: random.c,v 1.10 2002/02/19 13:39:23 drh Exp $ 19 | */ 20 | #include "sqliteInt.h" 21 | #include "os.h" 22 | 23 | 24 | /* 25 | ** Get a single 8-bit random value from the RC4 PRNG. The Mutex 26 | ** must be held while executing this routine. 27 | ** 28 | ** Why not just use a library random generator like lrand48() for this? 29 | ** Because the OP_NewRecno opcode in the VDBE depends on having a very 30 | ** good source of random numbers. The lrand48() library function may 31 | ** well be good enough. But maybe not. Or maybe lrand48() has some 32 | ** subtle problems on some systems that could cause problems. It is hard 33 | ** to know. To minimize the risk of problems due to bad lrand48() 34 | ** implementations, SQLite uses this random number generator based 35 | ** on RC4, which we know works very well. 36 | */ 37 | static int randomByte(){ 38 | int t; 39 | 40 | /* All threads share a single random number generator. 41 | ** This structure is the current state of the generator. 42 | */ 43 | static struct { 44 | int isInit; /* True if initialized */ 45 | int i, j; /* State variables */ 46 | int s[256]; /* State variables */ 47 | } prng; 48 | 49 | /* Initialize the state of the random number generator once, 50 | ** the first time this routine is called. The seed value does 51 | ** not need to contain a lot of randomness since we are not 52 | ** trying to do secure encryption or anything like that... 53 | ** 54 | ** Nothing in this file or anywhere else in SQLite does any kind of 55 | ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random 56 | ** number generator) not as an encryption device. 57 | */ 58 | if( !prng.isInit ){ 59 | int i; 60 | char k[256]; 61 | prng.j = 0; 62 | prng.i = 0; 63 | sqliteOsRandomSeed(k); 64 | for(i=0; i<256; i++){ 65 | prng.s[i] = i; 66 | } 67 | for(i=0; i<256; i++){ 68 | int t; 69 | prng.j = (prng.j + prng.s[i] + k[i]) & 0xff; 70 | t = prng.s[prng.j]; 71 | prng.s[prng.j] = prng.s[i]; 72 | prng.s[i] = t; 73 | } 74 | prng.isInit = 1; 75 | } 76 | 77 | /* Generate and return single random byte 78 | */ 79 | prng.i = (prng.i + 1) & 0xff; 80 | prng.j = (prng.j + prng.s[prng.i]) & 0xff; 81 | t = prng.s[prng.i]; 82 | prng.s[prng.i] = prng.s[prng.j]; 83 | prng.s[prng.j] = t; 84 | t = prng.s[prng.i] + prng.s[prng.j]; 85 | return prng.s[t & 0xff]; 86 | } 87 | 88 | /* 89 | ** Return an random 8-bit integer. 90 | */ 91 | int sqliteRandomByte(){ 92 | int r; 93 | sqliteOsEnterMutex(); 94 | r = randomByte(); 95 | sqliteOsLeaveMutex(); 96 | return r; 97 | } 98 | 99 | /* 100 | ** Return a random 32-bit integer. The integer is generated by making 101 | ** 4 calls to sqliteRandomByte(). 102 | */ 103 | int sqliteRandomInteger(){ 104 | int r; 105 | int i; 106 | sqliteOsEnterMutex(); 107 | r = randomByte(); 108 | for(i=1; i<4; i++){ 109 | r = (r<<8) + randomByte(); 110 | } 111 | sqliteOsLeaveMutex(); 112 | return r; 113 | } 114 | -------------------------------------------------------------------------------- /src/table.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2001 September 15 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This file contains the sqlite_get_table() and sqlite_free_table() 13 | ** interface routines. These are just wrappers around the main 14 | ** interface routine of sqlite_exec(). 15 | ** 16 | ** These routines are in a separate files so that they will not be linked 17 | ** if they are not used. 18 | */ 19 | #include 20 | #include 21 | #include "sqliteInt.h" 22 | 23 | /* 24 | ** This structure is used to pass data from sqlite_get_table() through 25 | ** to the callback function is uses to build the result. 26 | */ 27 | typedef struct TabResult { 28 | char **azResult; 29 | char *zErrMsg; 30 | int nResult; 31 | int nAlloc; 32 | int nRow; 33 | int nColumn; 34 | int nData; 35 | int rc; 36 | } TabResult; 37 | 38 | /* 39 | ** This routine is called once for each row in the result table. Its job 40 | ** is to fill in the TabResult structure appropriately, allocating new 41 | ** memory as necessary. 42 | */ 43 | static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ 44 | TabResult *p = (TabResult*)pArg; 45 | int need; 46 | int i; 47 | char *z; 48 | 49 | /* Make sure there is enough space in p->azResult to hold everything 50 | ** we need to remember from this invocation of the callback. 51 | */ 52 | if( p->nRow==0 && argv!=0 ){ 53 | need = nCol*2; 54 | }else{ 55 | need = nCol; 56 | } 57 | if( p->nData + need >= p->nAlloc ){ 58 | char **azNew; 59 | p->nAlloc = p->nAlloc*2 + need + 1; 60 | azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc ); 61 | if( azNew==0 ){ 62 | p->rc = SQLITE_NOMEM; 63 | return 1; 64 | } 65 | p->azResult = azNew; 66 | } 67 | 68 | /* If this is the first row, then generate an extra row containing 69 | ** the names of all columns. 70 | */ 71 | if( p->nRow==0 ){ 72 | p->nColumn = nCol; 73 | for(i=0; irc = SQLITE_NOMEM; 80 | return 1; 81 | } 82 | strcpy(z, colv[i]); 83 | } 84 | p->azResult[p->nData++] = z; 85 | } 86 | }else if( p->nColumn!=nCol ){ 87 | sqliteSetString(&p->zErrMsg, 88 | "sqlite_get_table() called with two or more incompatible queries", 0); 89 | p->rc = SQLITE_ERROR; 90 | return 1; 91 | } 92 | 93 | /* Copy over the row data 94 | */ 95 | if( argv!=0 ){ 96 | for(i=0; irc = SQLITE_NOMEM; 103 | return 1; 104 | } 105 | strcpy(z, argv[i]); 106 | } 107 | p->azResult[p->nData++] = z; 108 | } 109 | p->nRow++; 110 | } 111 | return 0; 112 | } 113 | 114 | /* 115 | ** Query the database. But instead of invoking a callback for each row, 116 | ** malloc() for space to hold the result and return the entire results 117 | ** at the conclusion of the call. 118 | ** 119 | ** The result that is written to ***pazResult is held in memory obtained 120 | ** from malloc(). But the caller cannot free this memory directly. 121 | ** Instead, the entire table should be passed to sqlite_free_table() when 122 | ** the calling procedure is finished using it. 123 | */ 124 | int sqlite_get_table( 125 | sqlite *db, /* The database on which the SQL executes */ 126 | const char *zSql, /* The SQL to be executed */ 127 | char ***pazResult, /* Write the result table here */ 128 | int *pnRow, /* Write the number of rows in the result here */ 129 | int *pnColumn, /* Write the number of columns of result here */ 130 | char **pzErrMsg /* Write error messages here */ 131 | ){ 132 | int rc; 133 | TabResult res; 134 | if( pazResult==0 ){ return SQLITE_ERROR; } 135 | *pazResult = 0; 136 | if( pnColumn ) *pnColumn = 0; 137 | if( pnRow ) *pnRow = 0; 138 | res.zErrMsg = 0; 139 | res.nResult = 0; 140 | res.nRow = 0; 141 | res.nColumn = 0; 142 | res.nData = 1; 143 | res.nAlloc = 20; 144 | res.rc = SQLITE_OK; 145 | res.azResult = malloc( sizeof(char*)*res.nAlloc ); 146 | if( res.azResult==0 ){ 147 | return SQLITE_NOMEM; 148 | } 149 | res.azResult[0] = 0; 150 | rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg); 151 | if( res.azResult ){ 152 | res.azResult[0] = (char*)res.nData; 153 | } 154 | if( rc==SQLITE_ABORT ){ 155 | sqlite_free_table(&res.azResult[1]); 156 | if( res.zErrMsg ){ 157 | if( pzErrMsg ){ 158 | free(*pzErrMsg); 159 | *pzErrMsg = res.zErrMsg; 160 | sqliteStrRealloc(pzErrMsg); 161 | }else{ 162 | sqliteFree(res.zErrMsg); 163 | } 164 | } 165 | return res.rc; 166 | } 167 | sqliteFree(res.zErrMsg); 168 | if( rc!=SQLITE_OK ){ 169 | sqlite_free_table(&res.azResult[1]); 170 | return rc; 171 | } 172 | if( res.nAlloc>res.nData ){ 173 | char **azNew; 174 | azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) ); 175 | if( res.azResult==0 ){ 176 | sqlite_free_table(&res.azResult[1]); 177 | return SQLITE_NOMEM; 178 | } 179 | res.azResult = azNew; 180 | } 181 | *pazResult = &res.azResult[1]; 182 | if( pnColumn ) *pnColumn = res.nColumn; 183 | if( pnRow ) *pnRow = res.nRow; 184 | return rc; 185 | } 186 | 187 | /* 188 | ** This routine frees the space the sqlite_get_table() malloced. 189 | */ 190 | void sqlite_free_table( 191 | char **azResult /* Result returned from from sqlite_get_table() */ 192 | ){ 193 | if( azResult ){ 194 | int i, n; 195 | azResult--; 196 | n = (int)azResult[0]; 197 | for(i=1; i=0} continue 49 | source $testfile 50 | } 51 | if {[info exists Leak]} { 52 | lappend LeakList $Leak 53 | } 54 | } 55 | 56 | # Do one last test to look for a memory leak in the library. This will 57 | # only work if SQLite is compiled with the -DMEMORY_DEBUG=1 flag. 58 | # 59 | if {$LeakList!=""} { 60 | puts -nonewline memory-leak-test... 61 | incr ::nTest 62 | foreach x $LeakList { 63 | if {$x!=[lindex $LeakList 0]} { 64 | puts " failed!" 65 | puts "Expected: all values to be the same" 66 | puts " Got: $LeakList" 67 | incr ::nErr 68 | lappend ::failList memory-leak-test 69 | break 70 | } 71 | } 72 | puts " Ok" 73 | } 74 | 75 | # Run the malloc tests and the misuse test after memory leak detection. 76 | # Both tests leak memory. 77 | # 78 | catch {source $testdir/misuse.test} 79 | catch {source $testdir/malloc.test} 80 | 81 | really_finish_test 82 | -------------------------------------------------------------------------------- /test/bigrow.test: -------------------------------------------------------------------------------- 1 | # 2001 September 23 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is stressing the library by putting large amounts 13 | # of data in a single row of a table. 14 | # 15 | # $Id: bigrow.test,v 1.4 2001/11/24 00:31:47 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Make a big string that we can use for test data 21 | # 22 | do_test bigrow-1.0 { 23 | set ::bigstr {} 24 | for {set i 1} {$i<=9999} {incr i} { 25 | set sep [string index "abcdefghijklmnopqrstuvwxyz" [expr {$i%26}]] 26 | append ::bigstr "$sep [format %04d $i] " 27 | } 28 | string length $::bigstr 29 | } {69993} 30 | 31 | # Make a table into which we can insert some but records. 32 | # 33 | do_test bigrow-1.1 { 34 | execsql { 35 | CREATE TABLE t1(a text, b text, c text); 36 | SELECT name FROM sqlite_master 37 | WHERE type='table' OR type='index' 38 | ORDER BY name 39 | } 40 | } {t1} 41 | 42 | do_test bigrow-1.2 { 43 | set ::big1 [string range $::bigstr 0 65519] 44 | set sql "INSERT INTO t1 VALUES('abc'," 45 | append sql "'$::big1', 'xyz');" 46 | execsql $sql 47 | execsql {SELECT a, c FROM t1} 48 | } {abc xyz} 49 | do_test bigrow-1.3 { 50 | execsql {SELECT b FROM t1} 51 | } [list $::big1] 52 | do_test bigrow-1.4 { 53 | set ::big2 [string range $::bigstr 0 65520] 54 | set sql "INSERT INTO t1 VALUES('abc2'," 55 | append sql "'$::big2', 'xyz2');" 56 | set r [catch {execsql $sql} msg] 57 | lappend r $msg 58 | } {0 {}} 59 | do_test bigrow-1.4.1 { 60 | execsql {SELECT b FROM t1 ORDER BY c} 61 | } [list $::big1 $::big2] 62 | do_test bigrow-1.4.2 { 63 | execsql {SELECT c FROM t1 ORDER BY c} 64 | } {xyz xyz2} 65 | do_test bigrow-1.4.3 { 66 | execsql {DELETE FROM t1 WHERE a='abc2'} 67 | execsql {SELECT c FROM t1} 68 | } {xyz} 69 | 70 | do_test bigrow-1.5 { 71 | execsql { 72 | UPDATE t1 SET a=b, b=a; 73 | SELECT b,c FROM t1 74 | } 75 | } {abc xyz} 76 | do_test bigrow-1.6 { 77 | execsql { 78 | SELECT * FROM t1 79 | } 80 | } [list $::big1 abc xyz] 81 | do_test bigrow-1.7 { 82 | execsql { 83 | INSERT INTO t1 VALUES('1','2','3'); 84 | INSERT INTO t1 VALUES('A','B','C'); 85 | SELECT b FROM t1 WHERE a=='1'; 86 | } 87 | } {2} 88 | do_test bigrow-1.8 { 89 | execsql "SELECT b FROM t1 WHERE a=='$::big1'" 90 | } {abc} 91 | do_test bigrow-1.9 { 92 | execsql "SELECT b FROM t1 WHERE a!='$::big1' ORDER BY a" 93 | } {2 B} 94 | 95 | # Try doing some indexing on big columns 96 | # 97 | do_test bigrow-2.1 { 98 | execsql { 99 | CREATE INDEX i1 ON t1(a) 100 | } 101 | execsql "SELECT b FROM t1 WHERE a=='$::big1'" 102 | } {abc} 103 | do_test bigrow-2.2 { 104 | execsql { 105 | UPDATE t1 SET a=b, b=a 106 | } 107 | execsql "SELECT b FROM t1 WHERE a=='abc'" 108 | } [list $::big1] 109 | do_test bigrow-2.3 { 110 | execsql { 111 | UPDATE t1 SET a=b, b=a 112 | } 113 | execsql "SELECT b FROM t1 WHERE a=='$::big1'" 114 | } {abc} 115 | catch {unset ::bigstr} 116 | catch {unset ::big1} 117 | catch {unset ::big2} 118 | 119 | # Mosts of the tests above were created back when rows were limited in 120 | # size to 64K. Now rows can be much bigger. Test that logic. Also 121 | # make sure things work correctly at the transition boundries between 122 | # row sizes of 256 to 257 bytes and from 65536 to 65537 bytes. 123 | # 124 | # We begin by testing the 256..257 transition. 125 | # 126 | do_test bigrow-3.1 { 127 | execsql { 128 | DELETE FROM t1; 129 | INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi'); 130 | } 131 | execsql {SELECT a,length(b),c FROM t1} 132 | } {one 30 hi} 133 | do_test bigrow-3.2 { 134 | execsql { 135 | UPDATE t1 SET b=b||b; 136 | UPDATE t1 SET b=b||b; 137 | UPDATE t1 SET b=b||b; 138 | } 139 | execsql {SELECT a,length(b),c FROM t1} 140 | } {one 240 hi} 141 | for {set i 1} {$i<10} {incr i} { 142 | do_test bigrow-3.3.$i { 143 | execsql "UPDATE t1 SET b=b||'$i'" 144 | execsql {SELECT a,length(b),c FROM t1} 145 | } "one [expr {240+$i}] hi" 146 | } 147 | 148 | # Now test the 65536..65537 row-size transition. 149 | # 150 | do_test bigrow-4.1 { 151 | execsql { 152 | DELETE FROM t1; 153 | INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi'); 154 | } 155 | execsql {SELECT a,length(b),c FROM t1} 156 | } {one 30 hi} 157 | do_test bigrow-4.2 { 158 | execsql { 159 | UPDATE t1 SET b=b||b; 160 | UPDATE t1 SET b=b||b; 161 | UPDATE t1 SET b=b||b; 162 | UPDATE t1 SET b=b||b; 163 | UPDATE t1 SET b=b||b; 164 | UPDATE t1 SET b=b||b; 165 | UPDATE t1 SET b=b||b; 166 | UPDATE t1 SET b=b||b; 167 | UPDATE t1 SET b=b||b; 168 | UPDATE t1 SET b=b||b; 169 | UPDATE t1 SET b=b||b; 170 | UPDATE t1 SET b=b||b; 171 | } 172 | execsql {SELECT a,length(b),c FROM t1} 173 | } {one 122880 hi} 174 | do_test bigrow-4.3 { 175 | execsql { 176 | UPDATE t1 SET b=substr(b,1,65515) 177 | } 178 | execsql {SELECT a,length(b),c FROM t1} 179 | } {one 65515 hi} 180 | for {set i 1} {$i<10} {incr i} { 181 | do_test bigrow-4.4.$i { 182 | execsql "UPDATE t1 SET b=b||'$i'" 183 | execsql {SELECT a,length(b),c FROM t1} 184 | } "one [expr {65515+$i}] hi" 185 | } 186 | 187 | # Check to make sure the library recovers safely if a row contains 188 | # too much data. 189 | # 190 | do_test bigrow-5.1 { 191 | execsql { 192 | DELETE FROM t1; 193 | INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi'); 194 | } 195 | execsql {SELECT a,length(b),c FROM t1} 196 | } {one 30 hi} 197 | set i 1 198 | for {set sz 60} {$sz<1048560} {incr sz $sz} { 199 | do_test bigrow-5.2.$i { 200 | execsql { 201 | UPDATE t1 SET b=b||b; 202 | SELECT a,length(b),c FROM t1; 203 | } 204 | } "one $sz hi" 205 | incr i 206 | } 207 | do_test bigrow-5.3 { 208 | set r [catch {execsql {UPDATE t1 SET b=b||b}} msg] 209 | lappend r $msg 210 | } {1 {too much data for one table row}} 211 | do_test bigrow-5.4 { 212 | execsql {DROP TABLE t1} 213 | } {} 214 | 215 | finish_test 216 | -------------------------------------------------------------------------------- /test/btree3.test: -------------------------------------------------------------------------------- 1 | # 2001 November 22 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this script is btree database backend 13 | # 14 | # In particular, this file tests a small part of the Delete logic 15 | # for the BTree backend. When a row is deleted from a table, the 16 | # cursor is suppose to be left pointing at either the previous or 17 | # next entry in that table. If the cursor is left pointing at the 18 | # next entry, then the next Next operation is ignored. So the 19 | # sequence of operations (Delete, Next) should always leave the 20 | # cursor pointing at the first entry past the one that was deleted. 21 | # This test is designed to verify that behavior. 22 | # 23 | # $Id: btree3.test,v 1.1 2001/11/23 00:24:12 drh Exp $ 24 | 25 | 26 | set testdir [file dirname $argv0] 27 | source $testdir/tester.tcl 28 | 29 | if {[info commands btree_open]!=""} { 30 | 31 | # Open a test database. 32 | # 33 | file delete -force test1.bt 34 | file delete -force test1.bt-journal 35 | set b1 [btree_open test1.bt] 36 | btree_begin_transaction $::b1 37 | 38 | # Insert a few one records 39 | # 40 | set data {abcdefghijklmnopqrstuvwxyz0123456789} 41 | append data $data 42 | append data $data 43 | append data $data 44 | append data $data 45 | for {set k 2} {$k<=10} {incr k} { 46 | for {set j 1} {$j<=$k} {incr j} { 47 | set jkey [format %02d $j] 48 | btree_clear_table $::b1 2 49 | set ::c1 [btree_cursor $::b1 2 1] 50 | for {set i 1} {$i<=$k+1} {incr i} { 51 | set key [format %02d $i] 52 | do_test btree3-$k.$j.1.$i { 53 | btree_insert $::c1 $::key $::data 54 | } {} 55 | # btree_tree_dump $::b1 2 56 | } 57 | do_test btree3-$k.$j.2 { 58 | btree_move_to $::c1 $::jkey 59 | btree_key $::c1 60 | } $::jkey 61 | do_test btree3-$k.$j.3 { 62 | btree_delete $::c1 63 | } {} 64 | do_test btree3-$k.$j.4 { 65 | btree_next $::c1 66 | btree_key $::c1 67 | } [format %02d [expr $j+1]] 68 | btree_close_cursor $::c1 69 | } 70 | } 71 | 72 | btree_rollback $::b1 73 | btree_pager_ref_dump $::b1 74 | btree_close $::b1 75 | 76 | } ;# end if( not mem: and has pager_open command ); 77 | 78 | finish_test 79 | -------------------------------------------------------------------------------- /test/copy.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the COPY statement. 13 | # 14 | # $Id: copy.test,v 1.10 2002/02/19 13:39:23 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # Create a file of data from which to copy. 20 | # 21 | set f [open data1.txt w] 22 | puts $f "11\t22\t33" 23 | puts $f "22\t33\t11" 24 | close $f 25 | set f [open data2.txt w] 26 | puts $f "11\t22\t33" 27 | puts $f "\\." 28 | puts $f "22\t33\t11" 29 | close $f 30 | set f [open data3.txt w] 31 | puts $f "11\t22\t33\t44" 32 | puts $f "22\t33\t11" 33 | close $f 34 | set f [open data4.txt w] 35 | puts $f "11 | 22 | 33" 36 | puts $f "22 | 33 | 11" 37 | close $f 38 | set f [open data5.txt w] 39 | puts $f "11|22|33" 40 | puts $f "22|33|11" 41 | close $f 42 | 43 | # Try to COPY into a non-existant table. 44 | # 45 | do_test copy-1.1 { 46 | set v [catch {execsql {COPY test1 FROM 'data1.txt'}} msg] 47 | lappend v $msg 48 | } {1 {no such table: test1}} 49 | 50 | # Try to insert into sqlite_master 51 | # 52 | do_test copy-1.2 { 53 | set v [catch {execsql {COPY sqlite_master FROM 'data2.txt'}} msg] 54 | lappend v $msg 55 | } {1 {table sqlite_master may not be modified}} 56 | 57 | # Do some actual inserts 58 | # 59 | do_test copy-1.3 { 60 | execsql {CREATE TABLE test1(one int, two int, three int)} 61 | execsql {COPY test1 FROM 'data1.txt'} 62 | execsql {SELECT * FROM test1 ORDER BY one} 63 | } {11 22 33 22 33 11} 64 | 65 | # Make sure input terminates at \. 66 | # 67 | do_test copy-1.4 { 68 | execsql {DELETE FROM test1} 69 | execsql {COPY test1 FROM 'data2.txt'} 70 | execsql {SELECT * FROM test1 ORDER BY one} 71 | } {11 22 33} 72 | 73 | # Test out the USING DELIMITERS clause 74 | # 75 | do_test copy-1.5 { 76 | execsql {DELETE FROM test1} 77 | execsql {COPY test1 FROM 'data4.txt' USING DELIMITERS ' | '} 78 | execsql {SELECT * FROM test1 ORDER BY one} 79 | } {11 22 33 22 33 11} 80 | do_test copy-1.6 { 81 | execsql {DELETE FROM test1} 82 | execsql {COPY test1 FROM 'data5.txt' USING DELIMITERS '|'} 83 | execsql {SELECT * FROM test1 ORDER BY one} 84 | } {11 22 33 22 33 11} 85 | do_test copy-1.7 { 86 | execsql {DELETE FROM test1} 87 | execsql {COPY test1 FROM 'data4.txt' USING DELIMITERS '|'} 88 | execsql {SELECT * FROM test1 ORDER BY one} 89 | } {{11 } { 22 } { 33} {22 } { 33 } { 11}} 90 | 91 | # Try copying into a table that has one or more indices. 92 | # 93 | do_test copy-1.8 { 94 | execsql {DELETE FROM test1} 95 | execsql {CREATE INDEX index1 ON test1(one)} 96 | execsql {CREATE INDEX index2 ON test1(two)} 97 | execsql {CREATE INDEX index3 ON test1(three)} 98 | execsql {COPY test1 from 'data1.txt'} 99 | execsql {SELECT * FROM test1 WHERE one=11} 100 | } {11 22 33} 101 | do_test copy-1.8b { 102 | execsql {SELECT * FROM test1 WHERE one=22} 103 | } {22 33 11} 104 | do_test copy-1.8c { 105 | execsql {SELECT * FROM test1 WHERE two=22} 106 | } {11 22 33} 107 | do_test copy-1.8d { 108 | execsql {SELECT * FROM test1 WHERE three=11} 109 | } {22 33 11} 110 | 111 | 112 | # Try inserting really long data 113 | # 114 | set x {} 115 | for {set i 0} {$i<100} {incr i} { 116 | append x "($i)-abcdefghijklmnopqrstyvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-" 117 | } 118 | do_test copy-2.1 { 119 | execsql {CREATE TABLE test2(a int, x text)} 120 | set f [open data21.txt w] 121 | puts $f "123\t$x" 122 | close $f 123 | execsql {COPY test2 FROM 'data21.txt'} 124 | execsql {SELECT x from test2} 125 | } $x 126 | file delete -force data21.txt 127 | 128 | # Test the escape character mechanism 129 | # 130 | do_test copy-3.1 { 131 | set fd [open data6.txt w] 132 | puts $fd "hello\\\tworld\t1" 133 | puts $fd "hello\tworld\\\t2" 134 | close $fd 135 | execsql { 136 | CREATE TABLE t1(a text, b text); 137 | COPY t1 FROM 'data6.txt'; 138 | SELECT * FROM t1 ORDER BY a; 139 | } 140 | } {hello {world 2} {hello world} 1} 141 | do_test copy-3.2 { 142 | set fd [open data6.txt w] 143 | puts $fd "1\thello\\\nworld" 144 | puts $fd "2\thello world" 145 | close $fd 146 | execsql { 147 | DELETE FROM t1; 148 | COPY t1 FROM 'data6.txt'; 149 | SELECT * FROM t1 ORDER BY a; 150 | } 151 | } {1 {hello 152 | world} 2 {hello world}} 153 | 154 | # Test the embedded NULL logic. 155 | # 156 | do_test copy-4.1 { 157 | set fd [open data6.txt w] 158 | puts $fd "1\t\\N" 159 | puts $fd "\\N\thello world" 160 | close $fd 161 | execsql { 162 | DELETE FROM t1; 163 | COPY t1 FROM 'data6.txt'; 164 | SELECT * FROM t1 WHERE a IS NULL; 165 | } 166 | } {{} {hello world}} 167 | do_test copy-4.2 { 168 | execsql { 169 | SELECT * FROM t1 WHERE b IS NULL; 170 | } 171 | } {1 {}} 172 | 173 | # Test the conflict resolution logic for COPY 174 | # 175 | do_test copy-5.1 { 176 | execsql { 177 | DROP TABLE t1; 178 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c); 179 | COPY t1 FROM 'data5.txt' USING DELIMITERS '|'; 180 | SELECT * FROM t1; 181 | } 182 | } {11 22 33 22 33 11} 183 | do_test copy-5.2 { 184 | set fd [open data6.txt w] 185 | puts $fd "33|22|44" 186 | close $fd 187 | catchsql { 188 | COPY t1 FROM 'data6.txt' USING DELIMITERS '|'; 189 | SELECT * FROM t1; 190 | } 191 | } {1 {constraint failed}} 192 | do_test copy-5.3 { 193 | set fd [open data6.txt w] 194 | puts $fd "33|22|44" 195 | close $fd 196 | catchsql { 197 | COPY OR IGNORE t1 FROM 'data6.txt' USING DELIMITERS '|'; 198 | SELECT * FROM t1; 199 | } 200 | } {0 {11 22 33 22 33 11}} 201 | do_test copy-5.4 { 202 | set fd [open data6.txt w] 203 | puts $fd "33|22|44" 204 | close $fd 205 | catchsql { 206 | COPY OR REPLACE t1 FROM 'data6.txt' USING DELIMITERS '|'; 207 | SELECT * FROM t1; 208 | } 209 | } {0 {22 33 11 33 22 44}} 210 | 211 | do_test copy-5.5 { 212 | execsql { 213 | DELETE FROM t1; 214 | PRAGMA count_changes=on; 215 | COPY t1 FROM 'data5.txt' USING DELIMITERS '|'; 216 | } 217 | } {2} 218 | do_test copy-5.6 { 219 | execsql { 220 | COPY OR REPLACE t1 FROM 'data5.txt' USING DELIMITERS '|'; 221 | } 222 | } {2} 223 | do_test copy-5.7 { 224 | execsql { 225 | COPY OR IGNORE t1 FROM 'data5.txt' USING DELIMITERS '|'; 226 | } 227 | } {0} 228 | 229 | do_test copy-6.0 { 230 | set x [execsql {PRAGMA integrity_check}] 231 | if {$x==""} {set x ok} 232 | set x 233 | } {ok} 234 | 235 | 236 | # Cleanup 237 | # 238 | file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt data6.txt 239 | 240 | finish_test 241 | -------------------------------------------------------------------------------- /test/delete.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the DELETE FROM statement. 13 | # 14 | # $Id: delete.test,v 1.10 2001/10/15 00:44:36 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # Try to delete from a non-existant table. 20 | # 21 | do_test delete-1.1 { 22 | set v [catch {execsql {DELETE FROM test1}} msg] 23 | lappend v $msg 24 | } {1 {no such table: test1}} 25 | 26 | # Try to delete from sqlite_master 27 | # 28 | do_test delete-2.1 { 29 | set v [catch {execsql {DELETE FROM sqlite_master}} msg] 30 | lappend v $msg 31 | } {1 {table sqlite_master may not be modified}} 32 | 33 | # Delete selected entries from a table with and without an index. 34 | # 35 | do_test delete-3.1.1 { 36 | execsql {CREATE TABLE table1(f1 int, f2 int)} 37 | execsql {INSERT INTO table1 VALUES(1,2)} 38 | execsql {INSERT INTO table1 VALUES(2,4)} 39 | execsql {INSERT INTO table1 VALUES(3,8)} 40 | execsql {INSERT INTO table1 VALUES(4,16)} 41 | execsql {SELECT * FROM table1 ORDER BY f1} 42 | } {1 2 2 4 3 8 4 16} 43 | do_test delete-3.1.2 { 44 | execsql {DELETE FROM table1 WHERE f1=3} 45 | } {} 46 | do_test delete-3.1.3 { 47 | execsql {SELECT * FROM table1 ORDER BY f1} 48 | } {1 2 2 4 4 16} 49 | do_test delete-3.1.4 { 50 | execsql {CREATE INDEX index1 ON table1(f1)} 51 | execsql {PRAGMA count_changes=on} 52 | execsql {DELETE FROM 'table1' WHERE f1=3} 53 | } {0} 54 | do_test delete-3.1.5 { 55 | execsql {SELECT * FROM table1 ORDER BY f1} 56 | } {1 2 2 4 4 16} 57 | do_test delete-3.1.6 { 58 | execsql {DELETE FROM table1 WHERE f1=2} 59 | } {1} 60 | do_test delete-3.1.7 { 61 | execsql {SELECT * FROM table1 ORDER BY f1} 62 | } {1 2 4 16} 63 | 64 | # Semantic errors in the WHERE clause 65 | # 66 | do_test delete-4.1 { 67 | execsql {CREATE TABLE table2(f1 int, f2 int)} 68 | set v [catch {execsql {DELETE FROM table2 WHERE f3=5}} msg] 69 | lappend v $msg 70 | } {1 {no such column: f3}} 71 | 72 | do_test delete-4.2 { 73 | set v [catch {execsql {DELETE FROM table2 WHERE xyzzy(f1+4)}} msg] 74 | lappend v $msg 75 | } {1 {no such function: xyzzy}} 76 | 77 | # Lots of deletes 78 | # 79 | do_test delete-5.1.1 { 80 | execsql {DELETE FROM table1} 81 | } {2} 82 | do_test delete-5.1.2 { 83 | execsql {SELECT count(*) FROM table1} 84 | } {0} 85 | do_test delete-5.2.1 { 86 | execsql {BEGIN TRANSACTION} 87 | for {set i 1} {$i<=200} {incr i} { 88 | execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])" 89 | } 90 | execsql {COMMIT} 91 | execsql {SELECT count(*) FROM table1} 92 | } {200} 93 | do_test delete-5.2.2 { 94 | execsql {DELETE FROM table1} 95 | } {200} 96 | do_test delete-5.2.3 { 97 | execsql {BEGIN TRANSACTION} 98 | for {set i 1} {$i<=200} {incr i} { 99 | execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])" 100 | } 101 | execsql {COMMIT} 102 | execsql {SELECT count(*) FROM table1} 103 | } {200} 104 | do_test delete-5.2.4 { 105 | execsql {PRAGMA count_changes=off} 106 | execsql {DELETE FROM table1} 107 | } {} 108 | do_test delete-5.2.5 { 109 | execsql {SELECT count(*) FROM table1} 110 | } {0} 111 | do_test delete-5.2.6 { 112 | execsql {BEGIN TRANSACTION} 113 | for {set i 1} {$i<=200} {incr i} { 114 | execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])" 115 | } 116 | execsql {COMMIT} 117 | execsql {SELECT count(*) FROM table1} 118 | } {200} 119 | do_test delete-5.3 { 120 | for {set i 1} {$i<=200} {incr i 4} { 121 | execsql "DELETE FROM table1 WHERE f1==$i" 122 | } 123 | execsql {SELECT count(*) FROM table1} 124 | } {150} 125 | do_test delete-5.4 { 126 | execsql "DELETE FROM table1 WHERE f1>50" 127 | execsql {SELECT count(*) FROM table1} 128 | } {37} 129 | do_test delete-5.5 { 130 | for {set i 1} {$i<=70} {incr i 3} { 131 | execsql "DELETE FROM table1 WHERE f1==$i" 132 | } 133 | execsql {SELECT f1 FROM table1 ORDER BY f1} 134 | } {2 3 6 8 11 12 14 15 18 20 23 24 26 27 30 32 35 36 38 39 42 44 47 48 50} 135 | do_test delete-5.6 { 136 | for {set i 1} {$i<40} {incr i} { 137 | execsql "DELETE FROM table1 WHERE f1==$i" 138 | } 139 | execsql {SELECT f1 FROM table1 ORDER BY f1} 140 | } {42 44 47 48 50} 141 | do_test delete-5.7 { 142 | execsql "DELETE FROM table1 WHERE f1!=48" 143 | execsql {SELECT f1 FROM table1 ORDER BY f1} 144 | } {48} 145 | 146 | # Delete large quantities of data. We want to test the List overflow 147 | # mechanism in the vdbe. 148 | # 149 | do_test delete-6.1 { 150 | set fd [open data1.txt w] 151 | for {set i 1} {$i<=3000} {incr i} { 152 | puts $fd "[expr {$i}]\t[expr {$i*$i}]" 153 | } 154 | close $fd 155 | execsql {DELETE FROM table1} 156 | execsql {COPY table1 FROM 'data1.txt'} 157 | execsql {DELETE FROM table2} 158 | execsql {COPY table2 FROM 'data1.txt'} 159 | file delete data1.txt 160 | execsql {SELECT count(*) FROM table1} 161 | } {3000} 162 | do_test delete-6.2 { 163 | execsql {SELECT count(*) FROM table2} 164 | } {3000} 165 | do_test delete-6.3 { 166 | execsql {SELECT f1 FROM table1 WHERE f1<10 ORDER BY f1} 167 | } {1 2 3 4 5 6 7 8 9} 168 | do_test delete-6.4 { 169 | execsql {SELECT f1 FROM table2 WHERE f1<10 ORDER BY f1} 170 | } {1 2 3 4 5 6 7 8 9} 171 | do_test delete-6.5 { 172 | execsql {DELETE FROM table1 WHERE f1>7} 173 | execsql {SELECT f1 FROM table1 ORDER BY f1} 174 | } {1 2 3 4 5 6 7} 175 | do_test delete-6.6 { 176 | execsql {DELETE FROM table2 WHERE f1>7} 177 | execsql {SELECT f1 FROM table2 ORDER BY f1} 178 | } {1 2 3 4 5 6 7} 179 | do_test delete-6.7 { 180 | execsql {DELETE FROM table1} 181 | execsql {SELECT f1 FROM table1} 182 | } {} 183 | do_test delete-6.8 { 184 | execsql {INSERT INTO table1 VALUES(2,3)} 185 | execsql {SELECT f1 FROM table1} 186 | } {2} 187 | do_test delete-6.9 { 188 | execsql {DELETE FROM table2} 189 | execsql {SELECT f1 FROM table2} 190 | } {} 191 | do_test delete-6.10 { 192 | execsql {INSERT INTO table2 VALUES(2,3)} 193 | execsql {SELECT f1 FROM table2} 194 | } {2} 195 | 196 | 197 | 198 | finish_test 199 | -------------------------------------------------------------------------------- /test/insert.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the INSERT statement. 13 | # 14 | # $Id: insert.test,v 1.10 2002/04/12 13:11:53 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # Try to insert into a non-existant table. 20 | # 21 | do_test insert-1.1 { 22 | set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3)}} msg] 23 | lappend v $msg 24 | } {1 {no such table: test1}} 25 | 26 | # Try to insert into sqlite_master 27 | # 28 | do_test insert-1.2 { 29 | set v [catch {execsql {INSERT INTO sqlite_master VALUES(1,2,3,4)}} msg] 30 | lappend v $msg 31 | } {1 {table sqlite_master may not be modified}} 32 | 33 | # Try to insert the wrong number of entries. 34 | # 35 | do_test insert-1.3 { 36 | execsql {CREATE TABLE test1(one int, two int, three int)} 37 | set v [catch {execsql {INSERT INTO test1 VALUES(1,2)}} msg] 38 | lappend v $msg 39 | } {1 {table test1 has 3 columns but 2 values were supplied}} 40 | do_test insert-1.3b { 41 | set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3,4)}} msg] 42 | lappend v $msg 43 | } {1 {table test1 has 3 columns but 4 values were supplied}} 44 | do_test insert-1.3c { 45 | set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1,2,3,4)}} msg] 46 | lappend v $msg 47 | } {1 {4 values for 2 columns}} 48 | do_test insert-1.3d { 49 | set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1)}} msg] 50 | lappend v $msg 51 | } {1 {1 values for 2 columns}} 52 | 53 | # Try to insert into a non-existant column of a table. 54 | # 55 | do_test insert-1.4 { 56 | set v [catch {execsql {INSERT INTO test1(one,four) VALUES(1,2)}} msg] 57 | lappend v $msg 58 | } {1 {table test1 has no column named four}} 59 | 60 | # Make sure the inserts actually happen 61 | # 62 | do_test insert-1.5 { 63 | execsql {INSERT INTO test1 VALUES(1,2,3)} 64 | execsql {SELECT * FROM test1} 65 | } {1 2 3} 66 | do_test insert-1.5b { 67 | execsql {INSERT INTO test1 VALUES(4,5,6)} 68 | execsql {SELECT * FROM test1 ORDER BY one} 69 | } {1 2 3 4 5 6} 70 | do_test insert-1.5c { 71 | execsql {INSERT INTO test1 VALUES(7,8,9)} 72 | execsql {SELECT * FROM test1 ORDER BY one} 73 | } {1 2 3 4 5 6 7 8 9} 74 | 75 | do_test insert-1.6 { 76 | execsql {DELETE FROM test1} 77 | execsql {INSERT INTO test1(one,two) VALUES(1,2)} 78 | execsql {SELECT * FROM test1 ORDER BY one} 79 | } {1 2 {}} 80 | do_test insert-1.6b { 81 | execsql {INSERT INTO test1(two,three) VALUES(5,6)} 82 | execsql {SELECT * FROM test1 ORDER BY one} 83 | } {{} 5 6 1 2 {}} 84 | do_test insert-1.6c { 85 | execsql {INSERT INTO test1(three,one) VALUES(7,8)} 86 | execsql {SELECT * FROM test1 ORDER BY one} 87 | } {{} 5 6 1 2 {} 8 {} 7} 88 | 89 | # A table to use for testing default values 90 | # 91 | do_test insert-2.1 { 92 | execsql { 93 | CREATE TABLE test2( 94 | f1 int default -111, 95 | f2 real default +4.32, 96 | f3 int default +222, 97 | f4 int default 7.89 98 | ) 99 | } 100 | execsql {SELECT * from test2} 101 | } {} 102 | do_test insert-2.2 { 103 | execsql {INSERT INTO test2(f1,f3) VALUES(+10,-10)} 104 | execsql {SELECT * FROM test2} 105 | } {10 4.32 -10 7.89} 106 | do_test insert-2.3 { 107 | execsql {INSERT INTO test2(f2,f4) VALUES(1.23,-3.45)} 108 | execsql {SELECT * FROM test2 WHERE f1==-111} 109 | } {-111 1.23 222 -3.45} 110 | do_test insert-2.4 { 111 | execsql {INSERT INTO test2(f1,f2,f4) VALUES(77,+1.23,3.45)} 112 | execsql {SELECT * FROM test2 WHERE f1==77} 113 | } {77 1.23 222 3.45} 114 | do_test insert-2.10 { 115 | execsql { 116 | DROP TABLE test2; 117 | CREATE TABLE test2( 118 | f1 int default 111, 119 | f2 real default -4.32, 120 | f3 text default hi, 121 | f4 text default 'abc-123', 122 | f5 varchar(10) 123 | ) 124 | } 125 | execsql {SELECT * from test2} 126 | } {} 127 | do_test insert-2.11 { 128 | execsql {INSERT INTO test2(f2,f4) VALUES(-2.22,'hi!')} 129 | execsql {SELECT * FROM test2} 130 | } {111 -2.22 hi hi! {}} 131 | do_test insert-2.12 { 132 | execsql {INSERT INTO test2(f1,f5) VALUES(1,'xyzzy')} 133 | execsql {SELECT * FROM test2 ORDER BY f1} 134 | } {1 -4.32 hi abc-123 xyzzy 111 -2.22 hi hi! {}} 135 | 136 | # Do additional inserts with default values, but this time 137 | # on a table that has indices. In particular we want to verify 138 | # that the correct default values are inserted into the indices. 139 | # 140 | do_test insert-3.1 { 141 | execsql { 142 | DELETE FROM test2; 143 | CREATE INDEX index9 ON test2(f1,f2); 144 | CREATE INDEX indext ON test2(f4,f5); 145 | SELECT * from test2; 146 | } 147 | } {} 148 | do_test insert-3.2 { 149 | execsql {INSERT INTO test2(f2,f4) VALUES(-3.33,'hum')} 150 | execsql {SELECT * FROM test2 WHERE f1=111 AND f2=-3.33} 151 | } {111 -3.33 hi hum {}} 152 | do_test insert-3.3 { 153 | execsql {INSERT INTO test2(f1,f2,f5) VALUES(22,-4.44,'wham')} 154 | execsql {SELECT * FROM test2 WHERE f1=111 AND f2=-3.33} 155 | } {111 -3.33 hi hum {}} 156 | do_test insert-3.4 { 157 | execsql {SELECT * FROM test2 WHERE f1=22 AND f2=-4.44} 158 | } {22 -4.44 hi abc-123 wham} 159 | do_test insert-3.5 { 160 | set x [execsql {PRAGMA integrity_check}] 161 | if {$x==""} {set x ok} 162 | set x 163 | } {ok} 164 | 165 | # Test of expressions in the VALUES clause 166 | # 167 | do_test insert-4.1 { 168 | execsql { 169 | CREATE TABLE t3(a,b,c); 170 | INSERT INTO t3 VALUES(1+2+3,4,5); 171 | SELECT * FROM t3; 172 | } 173 | } {6 4 5} 174 | do_test insert-4.2 { 175 | execsql { 176 | INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,5,6); 177 | SELECT * FROM t3 ORDER BY a; 178 | } 179 | } {6 4 5 7 5 6} 180 | do_test insert-4.3 { 181 | catchsql { 182 | INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,t3.a,6); 183 | SELECT * FROM t3 ORDER BY a; 184 | } 185 | } {1 {no such column: t3.a}} 186 | do_test insert-4.4 { 187 | execsql { 188 | INSERT INTO t3 VALUES((SELECT b FROM t3 WHERE a=0),6,7); 189 | SELECT * FROM t3 ORDER BY a; 190 | } 191 | } {{} 6 7 6 4 5 7 5 6} 192 | do_test insert-4.5 { 193 | execsql { 194 | SELECT b,c FROM t3 WHERE a IS NULL; 195 | } 196 | } {6 7} 197 | do_test insert-4.6 { 198 | catchsql { 199 | INSERT INTO t3 VALUES(notafunc(2,3),2,3); 200 | } 201 | } {1 {no such function: notafunc}} 202 | do_test insert-4.7 { 203 | execsql { 204 | INSERT INTO t3 VALUES(min(1,2,3),max(1,2,3),99); 205 | SELECT * FROM t3 WHERE c=99; 206 | } 207 | } {1 3 99} 208 | 209 | # Test 210 | 211 | finish_test 212 | -------------------------------------------------------------------------------- /test/insert2.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the INSERT statement that takes is 13 | # result from a SELECT. 14 | # 15 | # $Id: insert2.test,v 1.9 2002/04/12 10:09:00 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Create some tables with data that we can select against 21 | # 22 | do_test insert2-1.0 { 23 | execsql {CREATE TABLE d1(n int, log int);} 24 | for {set i 1} {$i<=20} {incr i} { 25 | for {set j 0} {pow(2,$j)<$i} {incr j} {} 26 | execsql "INSERT INTO d1 VALUES($i,$j)" 27 | } 28 | execsql {SELECT * FROM d1 ORDER BY n} 29 | } {1 0 2 1 3 2 4 2 5 3 6 3 7 3 8 3 9 4 10 4 11 4 12 4 13 4 14 4 15 4 16 4 17 5 18 5 19 5 20 5} 30 | 31 | # Insert into a new table from the old one. 32 | # 33 | do_test insert2-1.1.1 { 34 | execsql { 35 | CREATE TABLE t1(log int, cnt int); 36 | PRAGMA count_changes=on; 37 | INSERT INTO t1 SELECT log, count(*) FROM d1 GROUP BY log; 38 | } 39 | } {6} 40 | do_test insert2-1.1.2 { 41 | db changes 42 | } {6} 43 | do_test insert2-1.1.3 { 44 | execsql {SELECT * FROM t1 ORDER BY log} 45 | } {0 1 1 1 2 2 3 4 4 8 5 4} 46 | 47 | do_test insert2-1.2.1 { 48 | catch {execsql {DROP TABLE t1}} 49 | execsql { 50 | CREATE TABLE t1(log int, cnt int); 51 | INSERT INTO t1 52 | SELECT log, count(*) FROM d1 GROUP BY log 53 | EXCEPT SELECT n-1,log FROM d1; 54 | } 55 | } {4} 56 | do_test insert2-1.2.2 { 57 | execsql { 58 | SELECT * FROM t1 ORDER BY log; 59 | } 60 | } {0 1 3 4 4 8 5 4} 61 | do_test insert2-1.3.1 { 62 | catch {execsql {DROP TABLE t1}} 63 | execsql { 64 | CREATE TABLE t1(log int, cnt int); 65 | PRAGMA count_changes=off; 66 | INSERT INTO t1 67 | SELECT log, count(*) FROM d1 GROUP BY log 68 | INTERSECT SELECT n-1,log FROM d1; 69 | } 70 | } {} 71 | do_test insert2-1.3.2 { 72 | execsql { 73 | SELECT * FROM t1 ORDER BY log; 74 | } 75 | } {1 1 2 2} 76 | do_test insert2-1.4 { 77 | catch {execsql {DROP TABLE t1}} 78 | set r [execsql { 79 | CREATE TABLE t1(log int, cnt int); 80 | CREATE INDEX i1 ON t1(log); 81 | CREATE INDEX i2 ON t1(cnt); 82 | INSERT INTO t1 SELECT log, count() FROM d1 GROUP BY log; 83 | SELECT * FROM t1 ORDER BY log; 84 | }] 85 | lappend r [execsql {SELECT cnt FROM t1 WHERE log=3}] 86 | lappend r [execsql {SELECT log FROM t1 WHERE cnt=4 ORDER BY log}] 87 | } {0 1 1 1 2 2 3 4 4 8 5 4 4 {3 5}} 88 | 89 | do_test insert2-2.0 { 90 | execsql { 91 | CREATE TABLE t3(a,b,c); 92 | CREATE TABLE t4(x,y); 93 | INSERT INTO t4 VALUES(1,2); 94 | SELECT * FROM t4; 95 | } 96 | } {1 2} 97 | do_test insert2-2.1 { 98 | execsql { 99 | INSERT INTO t3(a,c) SELECT * FROM t4; 100 | SELECT * FROM t3; 101 | } 102 | } {1 {} 2} 103 | do_test insert2-2.2 { 104 | execsql { 105 | DELETE FROM t3; 106 | INSERT INTO t3(c,b) SELECT * FROM t4; 107 | SELECT * FROM t3; 108 | } 109 | } {{} 2 1} 110 | do_test insert2-2.3 { 111 | execsql { 112 | DELETE FROM t3; 113 | INSERT INTO t3(c,a,b) SELECT x, 'hi', y FROM t4; 114 | SELECT * FROM t3; 115 | } 116 | } {hi 2 1} 117 | 118 | do_test insert2-3.0 { 119 | set x [execsql {PRAGMA integrity_check}] 120 | if {$x==""} {set x ok} 121 | set x 122 | } {ok} 123 | 124 | # File table t4 with lots of data 125 | # 126 | do_test insert2-3.1 { 127 | execsql { 128 | SELECT * from t4; 129 | } 130 | } {1 2} 131 | do_test insert2-3.2 { 132 | execsql { 133 | BEGIN; 134 | INSERT INTO t4 VALUES(2,4); 135 | INSERT INTO t4 VALUES(3,6); 136 | INSERT INTO t4 VALUES(4,8); 137 | INSERT INTO t4 VALUES(5,10); 138 | INSERT INTO t4 VALUES(6,12); 139 | INSERT INTO t4 VALUES(7,14); 140 | INSERT INTO t4 VALUES(8,16); 141 | INSERT INTO t4 VALUES(9,18); 142 | INSERT INTO t4 VALUES(10,20); 143 | COMMIT; 144 | } 145 | db changes 146 | } {9} 147 | do_test insert2-3.2.1 { 148 | execsql { 149 | SELECT count(*) FROM t4; 150 | } 151 | } {10} 152 | do_test insert2-3.3 { 153 | execsql { 154 | BEGIN; 155 | INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; 156 | INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; 157 | INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; 158 | INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; 159 | COMMIT; 160 | SELECT count(*) FROM t4; 161 | } 162 | } {160} 163 | do_test insert2-3.4 { 164 | execsql { 165 | BEGIN; 166 | UPDATE t4 SET y='lots of data for the row where x=' || x 167 | || ' and y=' || y || ' - even more data to fill space'; 168 | COMMIT; 169 | SELECT count(*) FROM t4; 170 | } 171 | } {160} 172 | do_test insert2-3.5 { 173 | execsql { 174 | BEGIN; 175 | INSERT INTO t4 SELECT x+(SELECT max(x)+1 FROM t4),y FROM t4; 176 | SELECT count(*) from t4; 177 | ROLLBACK; 178 | } 179 | } {320} 180 | do_test insert2-3.6 { 181 | execsql { 182 | SELECT count(*) FROM t4; 183 | } 184 | } {160} 185 | do_test insert2-3.7 { 186 | execsql { 187 | BEGIN; 188 | DELETE FROM t4 WHERE x!=123; 189 | SELECT count(*) FROM t4; 190 | ROLLBACK; 191 | } 192 | } {1} 193 | do_test insert2-3.8 { 194 | db changes 195 | } {159} 196 | 197 | finish_test 198 | -------------------------------------------------------------------------------- /test/ioerr.test: -------------------------------------------------------------------------------- 1 | # 2001 October 12 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing for correct handling of I/O errors 13 | # such as writes failing because the disk is full. 14 | # 15 | # The tests in this file use special facilities that are only 16 | # available in the SQLite test fixture. 17 | # 18 | # $Id: ioerr.test,v 1.1 2001/10/12 17:30:05 drh Exp $ 19 | 20 | set testdir [file dirname $argv0] 21 | source $testdir/tester.tcl 22 | 23 | set ::go 1 24 | for {set n 1} {$go} {incr n} { 25 | do_test ioerr-1.$n.1 { 26 | set ::sqlite_io_error_pending 0 27 | db close 28 | catch {file delete -force test.db} 29 | sqlite db test.db 30 | execsql {SELECT * FROM sqlite_master} 31 | } {} 32 | do_test ioerr-1.$n.2 [subst { 33 | set ::sqlite_io_error_pending $n 34 | }] $n 35 | do_test ioerr-1.$n.3 { 36 | set r [catch {db eval { 37 | CREATE TABLE t1(a,b,c); 38 | SELECT * FROM sqlite_master; 39 | BEGIN TRANSACTION; 40 | INSERT INTO t1 VALUES(1,2,3); 41 | INSERT INTO t1 VALUES(4,5,6); 42 | ROLLBACK; 43 | SELECT * FROM t1; 44 | BEGIN TRANSACTION; 45 | INSERT INTO t1 VALUES(1,2,3); 46 | INSERT INTO t1 VALUES(4,5,6); 47 | COMMIT; 48 | SELECT * FROM t1; 49 | DELETE FROM t1 WHERE a<100; 50 | }} msg] 51 | # if {$r} {puts $msg} 52 | set ::go [expr {$::sqlite_io_error_pending<=0}] 53 | expr {$::sqlite_io_error_pending>0 || $r!=0} 54 | } {1} 55 | } 56 | set ::sqlite_io_error_pending 0 57 | 58 | 59 | finish_test 60 | -------------------------------------------------------------------------------- /test/join.test: -------------------------------------------------------------------------------- 1 | # 2002 May 24 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. 12 | # 13 | # This file implements tests for joins, including outer joins. 14 | # 15 | # $Id: join.test,v 1.2 2002/05/25 00:18:21 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | do_test join-1.1 { 21 | execsql { 22 | CREATE TABLE t1(a,b,c); 23 | INSERT INTO t1 VALUES(1,2,3); 24 | INSERT INTO t1 VALUES(2,3,4); 25 | INSERT INTO t1 VALUES(3,4,5); 26 | SELECT * FROM t1; 27 | } 28 | } {1 2 3 2 3 4 3 4 5} 29 | do_test join-1.2 { 30 | execsql { 31 | CREATE TABLE t2(b,c,d); 32 | INSERT INTO t2 VALUES(1,2,3); 33 | INSERT INTO t2 VALUES(2,3,4); 34 | INSERT INTO t2 VALUES(3,4,5); 35 | SELECT * FROM t2; 36 | } 37 | } {1 2 3 2 3 4 3 4 5} 38 | 39 | do_test join-1.3 { 40 | execsql2 { 41 | SELECT * FROM t1 NATURAL JOIN t2; 42 | } 43 | } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5} 44 | do_test join-1.3.1 { 45 | execsql2 { 46 | SELECT * FROM t2 NATURAL JOIN t1; 47 | } 48 | } {t2.b 2 t2.c 3 t2.d 4 t1.a 1 t2.b 3 t2.c 4 t2.d 5 t1.a 2} 49 | do_test join-1.4 { 50 | execsql2 { 51 | SELECT * FROM t1 INNER JOIN t2 USING(b,c); 52 | } 53 | } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5} 54 | do_test join-1.5 { 55 | execsql2 { 56 | SELECT * FROM t1 INNER JOIN t2 USING(b); 57 | } 58 | } {t1.a 1 t1.b 2 t1.c 3 t2.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.c 4 t2.d 5} 59 | do_test join-1.6 { 60 | execsql2 { 61 | SELECT * FROM t1 INNER JOIN t2 USING(c); 62 | } 63 | } {t1.a 1 t1.b 2 t1.c 3 t2.b 2 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.b 3 t2.d 5} 64 | do_test join-1.7 { 65 | execsql2 { 66 | SELECT * FROM t1 INNER JOIN t2 USING(c,b); 67 | } 68 | } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5} 69 | 70 | do_test join-1.8 { 71 | execsql { 72 | SELECT * FROM t1 NATURAL CROSS JOIN t2; 73 | } 74 | } {1 2 3 4 2 3 4 5} 75 | do_test join-1.9 { 76 | execsql { 77 | SELECT * FROM t1 CROSS JOIN t2 USING(b,c); 78 | } 79 | } {1 2 3 4 2 3 4 5} 80 | do_test join-1.10 { 81 | execsql { 82 | SELECT * FROM t1 NATURAL INNER JOIN t2; 83 | } 84 | } {1 2 3 4 2 3 4 5} 85 | do_test join-1.11 { 86 | execsql { 87 | SELECT * FROM t1 INNER JOIN t2 USING(b,c); 88 | } 89 | } {1 2 3 4 2 3 4 5} 90 | do_test join-1.12 { 91 | execsql { 92 | SELECT * FROM t1 natural inner join t2; 93 | } 94 | } {1 2 3 4 2 3 4 5} 95 | do_test join-1.13 { 96 | execsql2 { 97 | SELECT * FROM t1 NATURAL JOIN 98 | (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as t3 99 | } 100 | } {t1.a 1 t1.b 2 t1.c 3 t3.d 4 t3.e 5} 101 | do_test join-1.14 { 102 | execsql2 { 103 | SELECT * FROM (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as 'tx' 104 | NATURAL JOIN t1 105 | } 106 | } {tx.c 3 tx.d 4 tx.e 5 t1.a 1 t1.b 2} 107 | 108 | do_test join-1.15 { 109 | execsql { 110 | CREATE TABLE t3(c,d,e); 111 | INSERT INTO t3 VALUES(2,3,4); 112 | INSERT INTO t3 VALUES(3,4,5); 113 | INSERT INTO t3 VALUES(4,5,6); 114 | SELECT * FROM t3; 115 | } 116 | } {2 3 4 3 4 5 4 5 6} 117 | do_test join-1.16 { 118 | execsql { 119 | SELECT * FROM t1 natural join t2 natural join t3; 120 | } 121 | } {1 2 3 4 5 2 3 4 5 6} 122 | do_test join-1.17 { 123 | execsql2 { 124 | SELECT * FROM t1 natural join t2 natural join t3; 125 | } 126 | } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t3.e 5 t1.a 2 t1.b 3 t1.c 4 t2.d 5 t3.e 6} 127 | do_test join-1.18 { 128 | execsql { 129 | CREATE TABLE t4(d,e,f); 130 | INSERT INTO t4 VALUES(2,3,4); 131 | INSERT INTO t4 VALUES(3,4,5); 132 | INSERT INTO t4 VALUES(4,5,6); 133 | SELECT * FROM t4; 134 | } 135 | } {2 3 4 3 4 5 4 5 6} 136 | do_test join-1.19 { 137 | execsql { 138 | SELECT * FROM t1 natural join t2 natural join t4; 139 | } 140 | } {1 2 3 4 5 6} 141 | do_test join-1.19 { 142 | execsql2 { 143 | SELECT * FROM t1 natural join t2 natural join t4; 144 | } 145 | } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t4.e 5 t4.f 6} 146 | do_test join-1.20 { 147 | execsql { 148 | SELECT * FROM t1 natural join t2 natural join t3 WHERE t1.a=1 149 | } 150 | } {1 2 3 4 5} 151 | 152 | do_test join-2.1 { 153 | execsql { 154 | SELECT * FROM t1 NATURAL LEFT JOIN t2; 155 | } 156 | } {1 2 3 4 2 3 4 5 3 4 5 {}} 157 | do_test join-2.2 { 158 | execsql { 159 | SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1; 160 | } 161 | } {1 2 3 {} 2 3 4 1 3 4 5 2} 162 | do_test join-2.3 { 163 | catchsql { 164 | SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2; 165 | } 166 | } {1 {RIGHT and FULL OUTER JOINs are not currently supported}} 167 | 168 | do_test join-3.1 { 169 | catchsql { 170 | SELECT * FROM t1 NATURAL JOIN t2 ON t1.a=t2.b; 171 | } 172 | } {1 {a NATURAL join may not have an ON or USING clause}} 173 | do_test join-3.2 { 174 | catchsql { 175 | SELECT * FROM t1 NATURAL JOIN t2 USING(b); 176 | } 177 | } {1 {a NATURAL join may not have an ON or USING clause}} 178 | do_test join-3.3 { 179 | catchsql { 180 | SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b); 181 | } 182 | } {1 {cannot have both ON and USING clauses in the same join}} 183 | do_test join-3.4 { 184 | catchsql { 185 | SELECT * FROM t1 JOIN t2 USING(a); 186 | } 187 | } {1 {cannot join using column a - column not present in both tables}} 188 | do_test join-3.5 { 189 | catchsql { 190 | SELECT * FROM t1 USING(a); 191 | } 192 | } {0 {1 2 3 2 3 4 3 4 5}} 193 | do_test join-3.6 { 194 | catchsql { 195 | SELECT * FROM t1 JOIN t2 ON t3.a=t2.b; 196 | } 197 | } {1 {no such column: t3.a}} 198 | do_test join-3.7 { 199 | catchsql { 200 | SELECT * FROM t1 INNER OUTER JOIN t2; 201 | } 202 | } {1 {unknown or unsupported join type: INNER OUTER}} 203 | do_test join-3.7 { 204 | catchsql { 205 | SELECT * FROM t1 BOGUS JOIN t2; 206 | } 207 | } {1 {unknown or unsupported join type: BOGUS}} 208 | 209 | 210 | finish_test 211 | -------------------------------------------------------------------------------- /test/limit.test: -------------------------------------------------------------------------------- 1 | # 2001 November 6 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the LIMIT ... OFFSET ... clause 13 | # of SELECT statements. 14 | # 15 | # $Id: limit.test,v 1.3 2002/06/14 22:38:43 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Build some test data 21 | # 22 | set fd [open data1.txt w] 23 | for {set i 1} {$i<=32} {incr i} { 24 | for {set j 0} {pow(2,$j)<$i} {incr j} {} 25 | puts $fd "[expr {32-$i}]\t[expr {10-$j}]" 26 | } 27 | close $fd 28 | execsql { 29 | CREATE TABLE t1(x int, y int); 30 | COPY t1 FROM 'data1.txt' 31 | } 32 | file delete data1.txt 33 | 34 | do_test limit-1.0 { 35 | execsql {SELECT count(*) FROM t1} 36 | } {32} 37 | do_test limit-1.1 { 38 | execsql {SELECT count(*) FROM t1 LIMIT 5} 39 | } {32} 40 | do_test limit-1.2 { 41 | execsql {SELECT x FROM t1 ORDER BY x LIMIT 5} 42 | } {0 1 2 3 4} 43 | do_test limit-1.3 { 44 | execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 5} 45 | } {5 6 7 8 9} 46 | do_test limit-1.4 { 47 | execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 30} 48 | } {30 31} 49 | do_test limit-1.5 { 50 | execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 50} 51 | } {} 52 | do_test limit-1.6 { 53 | execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5} 54 | } {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5} 55 | do_test limit-1.7 { 56 | execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5 OFFSET 32} 57 | } {1 5 0 5 1 5 1 5 1 5 2 5 1 5 3 5 1 5 4 5} 58 | 59 | do_test limit-2.1 { 60 | execsql { 61 | CREATE VIEW v1 AS SELECT * FROM t1 LIMIT 2; 62 | SELECT count(*) FROM (SELECT * FROM v1); 63 | } 64 | } 2 65 | do_test limit-2.2 { 66 | execsql { 67 | CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 2; 68 | SELECT count(*) FROM t2; 69 | } 70 | } 2 71 | do_test limit-2.3 { 72 | execsql { 73 | SELECT count(*) FROM t1 WHERE rowid IN (SELECT rowid FROM t1 LIMIT 2); 74 | } 75 | } 2 76 | 77 | 78 | finish_test 79 | -------------------------------------------------------------------------------- /test/main.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is exercising the code in main.c. 13 | # 14 | # $Id: main.test,v 1.11 2002/05/15 14:17:45 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # Tests of the sqlite_complete() function. 20 | # 21 | do_test main-1.1 { 22 | db complete {This is a test} 23 | } {0} 24 | do_test main-1.2 { 25 | db complete { 26 | } 27 | } {0} 28 | do_test main-1.3 { 29 | db complete { 30 | -- a comment ; 31 | } 32 | } {0} 33 | do_test main-1.4 { 34 | db complete { 35 | -- a comment ; 36 | ; 37 | } 38 | } {1} 39 | do_test main-1.5 { 40 | db complete {DROP TABLE 'xyz;} 41 | } {0} 42 | do_test main-1.6 { 43 | db complete {DROP TABLE 'xyz';} 44 | } {1} 45 | do_test main-1.7 { 46 | db complete {DROP TABLE "xyz;} 47 | } {0} 48 | do_test main-1.8 { 49 | db complete {DROP TABLE "xyz';} 50 | } {0} 51 | do_test main-1.9 { 52 | db complete {DROP TABLE "xyz";} 53 | } {1} 54 | do_test main-1.10 { 55 | db complete {DROP TABLE xyz; hi} 56 | } {0} 57 | do_test main-1.11 { 58 | db complete {DROP TABLE xyz; } 59 | } {1} 60 | do_test main-1.12 { 61 | db complete {DROP TABLE xyz; -- hi } 62 | } {1} 63 | do_test main-1.13 { 64 | db complete {DROP TABLE xyz; -- hi 65 | } 66 | } {1} 67 | do_test main-1.14 { 68 | db complete {SELECT a-b FROM t1; } 69 | } {1} 70 | do_test main-1.15 { 71 | db complete {SELECT a-b FROM t1 } 72 | } {0} 73 | do_test main-1.16 { 74 | db complete { 75 | CREATE TABLE abc(x,y); 76 | } 77 | } {1} 78 | do_test main-1.17 { 79 | db complete { 80 | CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr; 81 | } 82 | } {0} 83 | do_test main-1.18 { 84 | db complete { 85 | CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr; END; 86 | } 87 | } {1} 88 | do_test main-1.19 { 89 | db complete { 90 | CREATE TRIGGER xyz AFTER DELETE abc BEGIN 91 | UPDATE pqr; 92 | unknown command; 93 | } 94 | } {0} 95 | do_test main-1.20 { 96 | db complete { 97 | CREATE TRIGGER xyz AFTER DELETE backend BEGIN 98 | UPDATE pqr; 99 | } 100 | } {0} 101 | do_test main-1.21 { 102 | db complete { 103 | CREATE TRIGGER xyz AFTER DELETE end BEGIN 104 | SELECT a, b FROM end; 105 | } 106 | } {0} 107 | do_test main-1.22 { 108 | db complete { 109 | CREATE TRIGGER xyz AFTER DELETE end BEGIN 110 | SELECT a, b FROM end; 111 | END; 112 | } 113 | } {1} 114 | do_test main-1.23 { 115 | db complete { 116 | CREATE TRIGGER xyz AFTER DELETE end BEGIN 117 | SELECT a, b FROM end; 118 | END; 119 | SELECT a, b FROM end; 120 | } 121 | } {1} 122 | do_test main-1.24 { 123 | db complete { 124 | CREATE TRIGGER xyz AFTER DELETE [;end;] BEGIN 125 | UPDATE pqr; 126 | } 127 | } {0} 128 | do_test main-1.25 { 129 | db complete { 130 | CREATE TRIGGER xyz AFTER DELETE backend BEGIN 131 | UPDATE pqr SET a=[;end;];;; 132 | } 133 | } {0} 134 | do_test main-1.26 { 135 | db complete { 136 | CREATE -- a comment 137 | TRIGGER xyz AFTER DELETE backend BEGIN 138 | UPDATE pqr SET a=5; 139 | } 140 | } {0} 141 | do_test main-1.27 { 142 | db complete { 143 | CREATE -- a comment 144 | TRIGGERX xyz AFTER DELETE backend BEGIN 145 | UPDATE pqr SET a=5; 146 | } 147 | } {1} 148 | do_test main-1.28 { 149 | db complete { 150 | CREATE TEMP TRIGGER xyz AFTER DELETE backend BEGIN 151 | UPDATE pqr SET a=5; 152 | } 153 | } {1} 154 | do_test main-1.29 { 155 | db complete { 156 | CREATE TRIGGER xyz AFTER DELETE backend BEGIN 157 | UPDATE pqr SET a=5; 158 | EXPLAIN select * from xyz; 159 | } 160 | } {0} 161 | 162 | 163 | # Try to open a database with a corrupt database file. 164 | # 165 | do_test main-2.0 { 166 | catch {db close} 167 | file delete -force test.db 168 | set fd [open test.db w] 169 | puts $fd hi! 170 | close $fd 171 | set v [catch {sqlite db test.db} msg] 172 | if {$v} {lappend v $msg} {lappend v {}} 173 | } {0 {}} 174 | 175 | # Here are some tests for tokenize.c. 176 | # 177 | do_test main-3.1 { 178 | catch {db close} 179 | foreach f [glob -nocomplain testdb/*] {file delete -force $f} 180 | file delete -force testdb 181 | sqlite db testdb 182 | set v [catch {execsql {SELECT * from T1 where x!!5}} msg] 183 | lappend v $msg 184 | } {1 {unrecognized token: "!!"}} 185 | do_test main-3.2 { 186 | catch {db close} 187 | foreach f [glob -nocomplain testdb/*] {file delete -force $f} 188 | file delete -force testdb 189 | sqlite db testdb 190 | set v [catch {execsql {SELECT * from T1 where @x}} msg] 191 | lappend v $msg 192 | } {1 {unrecognized token: "@"}} 193 | 194 | do_test main-3.3 { 195 | catch {db close} 196 | foreach f [glob -nocomplain testdb/*] {file delete -force $f} 197 | file delete -force testdb 198 | sqlite db testdb 199 | execsql { 200 | create table T1(X REAL); 201 | insert into T1 values(.5); 202 | insert into T1 values(0.5e2); 203 | insert into T1 values(0.5e-002); 204 | insert into T1 values(5e-002); 205 | insert into T1 values(-5.0e-2); 206 | insert into T1 values(-5.1e-2); 207 | insert into T1 values(.5e2); 208 | insert into T1 values(.5E+02); 209 | insert into T1 values(5E+02); 210 | insert into T1 values(5.E+03); 211 | select x*10 from T1 order by x*5; 212 | } 213 | } {-0.51 -0.5 0.05 0.5 5 500 500 500 5000 50000} 214 | do_test main-3.4 { 215 | set v [catch {execsql {create bogus}} msg] 216 | lappend v $msg 217 | } {1 {near "bogus": syntax error}} 218 | do_test main-3.5 { 219 | set v [catch {execsql {create}} msg] 220 | lappend v $msg 221 | } {1 {near "create": syntax error}} 222 | 223 | finish_test 224 | -------------------------------------------------------------------------------- /test/minmax.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing SELECT statements that contain 13 | # aggregate min() and max() functions and which are handled as 14 | # as a special case. 15 | # 16 | # $Id: minmax.test,v 1.4 2002/05/31 15:51:26 drh Exp $ 17 | 18 | set testdir [file dirname $argv0] 19 | source $testdir/tester.tcl 20 | 21 | do_test minmax-1.0 { 22 | execsql { 23 | BEGIN; 24 | CREATE TABLE t1(x, y); 25 | INSERT INTO t1 VALUES(1,1); 26 | INSERT INTO t1 VALUES(2,2); 27 | INSERT INTO t1 VALUES(3,2); 28 | INSERT INTO t1 VALUES(4,3); 29 | INSERT INTO t1 VALUES(5,3); 30 | INSERT INTO t1 VALUES(6,3); 31 | INSERT INTO t1 VALUES(7,3); 32 | INSERT INTO t1 VALUES(8,4); 33 | INSERT INTO t1 VALUES(9,4); 34 | INSERT INTO t1 VALUES(10,4); 35 | INSERT INTO t1 VALUES(11,4); 36 | INSERT INTO t1 VALUES(12,4); 37 | INSERT INTO t1 VALUES(13,4); 38 | INSERT INTO t1 VALUES(14,4); 39 | INSERT INTO t1 VALUES(15,4); 40 | INSERT INTO t1 VALUES(16,5); 41 | INSERT INTO t1 VALUES(17,5); 42 | INSERT INTO t1 VALUES(18,5); 43 | INSERT INTO t1 VALUES(19,5); 44 | INSERT INTO t1 VALUES(20,5); 45 | COMMIT; 46 | SELECT DISTINCT y FROM t1 ORDER BY y; 47 | } 48 | } {1 2 3 4 5} 49 | 50 | do_test minmax-1.1 { 51 | set sqlite_search_count 0 52 | execsql {SELECT min(x) FROM t1} 53 | } {1} 54 | do_test minmax-1.2 { 55 | set sqlite_search_count 56 | } {19} 57 | do_test minmax-1.3 { 58 | set sqlite_search_count 0 59 | execsql {SELECT max(x) FROM t1} 60 | } {20} 61 | do_test minmax-1.4 { 62 | set sqlite_search_count 63 | } {19} 64 | do_test minmax-1.5 { 65 | execsql {CREATE INDEX t1i1 ON t1(x)} 66 | set sqlite_search_count 0 67 | execsql {SELECT min(x) FROM t1} 68 | } {1} 69 | do_test minmax-1.6 { 70 | set sqlite_search_count 71 | } {1} 72 | do_test minmax-1.7 { 73 | set sqlite_search_count 0 74 | execsql {SELECT max(x) FROM t1} 75 | } {20} 76 | do_test minmax-1.8 { 77 | set sqlite_search_count 78 | } {1} 79 | do_test minmax-1.9 { 80 | set sqlite_search_count 0 81 | execsql {SELECT max(y) FROM t1} 82 | } {5} 83 | do_test minmax-1.10 { 84 | set sqlite_search_count 85 | } {19} 86 | 87 | do_test minmax-2.0 { 88 | execsql { 89 | CREATE TABLE t2(a INTEGER PRIMARY KEY, b); 90 | INSERT INTO t2 SELECT * FROM t1; 91 | } 92 | set sqlite_search_count 0 93 | execsql {SELECT min(a) FROM t2} 94 | } {1} 95 | do_test minmax-2.1 { 96 | set sqlite_search_count 97 | } {0} 98 | do_test minmax-2.2 { 99 | set sqlite_search_count 0 100 | execsql {SELECT max(a) FROM t2} 101 | } {20} 102 | do_test minmax-2.3 { 103 | set sqlite_search_count 104 | } {0} 105 | 106 | do_test minmax-3.0 { 107 | execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 108 | set sqlite_search_count 0 109 | execsql {SELECT max(a) FROM t2} 110 | } {21} 111 | do_test minmax-3.1 { 112 | set sqlite_search_count 113 | } {0} 114 | do_test minmax-3.2 { 115 | execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 116 | set sqlite_search_count 0 117 | execsql { 118 | SELECT b FROM t2 WHERE a=(SELECT max(a) FROM t2) 119 | } 120 | } {999} 121 | do_test minmax-3.3 { 122 | set sqlite_search_count 123 | } {0} 124 | 125 | do_test minmax-4.1 { 126 | execsql { 127 | SELECT coalesce(min(x),-1), coalesce(max(x),-1) FROM 128 | (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y') 129 | } 130 | } {1 20} 131 | do_test minmax-4.2 { 132 | execsql { 133 | SELECT y, sum(x) FROM 134 | (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1) 135 | GROUP BY y ORDER BY y; 136 | } 137 | } {1 1 2 5 3 22 4 92 5 90 6 0} 138 | do_test minmax-4.3 { 139 | execsql { 140 | SELECT y, count(x), count(*) FROM 141 | (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1) 142 | GROUP BY y ORDER BY y; 143 | } 144 | } {1 1 1 2 2 3 3 4 5 4 8 9 5 5 6 6 0 1} 145 | 146 | finish_test 147 | -------------------------------------------------------------------------------- /test/misuse.test: -------------------------------------------------------------------------------- 1 | # 2002 May 10 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. 12 | # 13 | # This file implements tests for the SQLITE_MISUSE detection logic. 14 | # This test file leaks memory and file descriptors. 15 | # 16 | # $Id: misuse.test,v 1.3 2002/05/21 11:38:12 drh Exp $ 17 | 18 | set testdir [file dirname $argv0] 19 | source $testdir/tester.tcl 20 | 21 | # Make sure the test logic works 22 | # 23 | do_test misuse-1.1 { 24 | db close 25 | catch {file delete -force test2.db} 26 | set ::DB [sqlite db test2.db] 27 | execsql { 28 | CREATE TABLE t1(a,b); 29 | INSERT INTO t1 VALUES(1,2); 30 | } 31 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 32 | } {0 {a b 1 2}} 33 | do_test misuse-1.2 { 34 | sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {} 35 | } {1 {no such function: x_coalesce}} 36 | do_test misuse-1.3 { 37 | sqlite_create_function $::DB 38 | sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {} 39 | } {0 {xyz 1}} 40 | 41 | # Use the x_sqlite_exec() SQL function to simulate the effect of two 42 | # threads trying to use the same database at the same time. 43 | # 44 | do_test misuse-1.4 { 45 | sqlite_exec_printf $::DB { 46 | SELECT x_sqlite_exec('SELECT * FROM t1'); 47 | } {} 48 | } {21 {library routine called out of sequence}} 49 | do_test misuse-1.5 { 50 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 51 | } {21 {library routine called out of sequence}} 52 | do_test misuse-1.6 { 53 | catchsql { 54 | SELECT * FROM t1 55 | } 56 | } {1 {library routine called out of sequence}} 57 | 58 | # Attempt to register a new SQL function while an sqlite_exec() is active. 59 | # 60 | do_test misuse-2.1 { 61 | db close 62 | set ::DB [sqlite db test2.db] 63 | execsql { 64 | SELECT * FROM t1 65 | } 66 | } {1 2} 67 | do_test misuse-2.2 { 68 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 69 | } {0 {a b 1 2}} 70 | do_test misuse-2.3 { 71 | set v [catch { 72 | db eval {SELECT * FROM t1} {} { 73 | sqlite_create_function $::DB 74 | } 75 | } msg] 76 | lappend v $msg 77 | } {1 {library routine called out of sequence}} 78 | do_test misuse-2.4 { 79 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 80 | } {21 {library routine called out of sequence}} 81 | do_test misuse-2.5 { 82 | catchsql { 83 | SELECT * FROM t1 84 | } 85 | } {1 {library routine called out of sequence}} 86 | 87 | # Attempt to register a new SQL aggregate while an sqlite_exec() is active. 88 | # 89 | do_test misuse-3.1 { 90 | db close 91 | set ::DB [sqlite db test2.db] 92 | execsql { 93 | SELECT * FROM t1 94 | } 95 | } {1 2} 96 | do_test misuse-3.2 { 97 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 98 | } {0 {a b 1 2}} 99 | do_test misuse-3.3 { 100 | set v [catch { 101 | db eval {SELECT * FROM t1} {} { 102 | sqlite_create_aggregate $::DB 103 | } 104 | } msg] 105 | lappend v $msg 106 | } {1 {library routine called out of sequence}} 107 | do_test misuse-3.4 { 108 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 109 | } {21 {library routine called out of sequence}} 110 | do_test misuse-3.5 { 111 | catchsql { 112 | SELECT * FROM t1 113 | } 114 | } {1 {library routine called out of sequence}} 115 | 116 | # Attempt to close the database from an sqlite_exec callback. 117 | # 118 | do_test misuse-4.1 { 119 | db close 120 | set ::DB [sqlite db test2.db] 121 | execsql { 122 | SELECT * FROM t1 123 | } 124 | } {1 2} 125 | do_test misuse-4.2 { 126 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 127 | } {0 {a b 1 2}} 128 | do_test misuse-4.3 { 129 | set v [catch { 130 | db eval {SELECT * FROM t1} {} { 131 | sqlite_close $::DB 132 | } 133 | } msg] 134 | lappend v $msg 135 | } {1 {library routine called out of sequence}} 136 | do_test misuse-4.4 { 137 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 138 | } {21 {library routine called out of sequence}} 139 | do_test misuse-4.5 { 140 | catchsql { 141 | SELECT * FROM t1 142 | } 143 | } {1 {library routine called out of sequence}} 144 | 145 | # Attempt to use a database after it has been closed. 146 | # 147 | do_test misuse-5.1 { 148 | db close 149 | set ::DB [sqlite db test2.db] 150 | execsql { 151 | SELECT * FROM t1 152 | } 153 | } {1 2} 154 | do_test misuse-5.2 { 155 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 156 | } {0 {a b 1 2}} 157 | do_test misuse-5.3 { 158 | db close 159 | sqlite_exec_printf $::DB {SELECT * FROM t1} {} 160 | } {21 {library routine called out of sequence}} 161 | 162 | finish_test 163 | -------------------------------------------------------------------------------- /test/null.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. 12 | # 13 | # This file implements tests for proper treatment of the special 14 | # value NULL. 15 | # 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Create a table and some data to work with. 21 | # 22 | do_test null-1.0 { 23 | execsql { 24 | begin; 25 | create table t1(a,b,c); 26 | insert into t1 values(1,0,0); 27 | insert into t1 values(2,0,1); 28 | insert into t1 values(3,1,0); 29 | insert into t1 values(4,1,1); 30 | insert into t1 values(5,null,0); 31 | insert into t1 values(6,null,1); 32 | insert into t1 values(7,null,null); 33 | commit; 34 | select * from t1; 35 | } 36 | } {1 0 0 2 0 1 3 1 0 4 1 1 5 {} 0 6 {} 1 7 {} {}} 37 | 38 | # Check for how arithmetic expressions handle NULL 39 | # 40 | do_test null-1.1 { 41 | execsql { 42 | select ifnull(a+b,99) from t1; 43 | } 44 | } {1 2 4 5 99 99 99} 45 | do_test null-1.2 { 46 | execsql { 47 | select ifnull(b*c,99) from t1; 48 | } 49 | } {0 0 0 1 99 99 99} 50 | 51 | # Check to see how the CASE expression handles NULL values. The 52 | # first WHEN for which the test expression is TRUE is selected. 53 | # FALSE and UNKNOWN test expressions are skipped. 54 | # 55 | do_test null-2.1 { 56 | execsql { 57 | select ifnull(case when b<>0 then 1 else 0 end, 99) from t1; 58 | } 59 | } {0 0 1 1 0 0 0} 60 | do_test null-2.2 { 61 | execsql { 62 | select ifnull(case when not b<>0 then 1 else 0 end, 99) from t1; 63 | } 64 | } {1 1 0 0 0 0 0} 65 | do_test null-2.3 { 66 | execsql { 67 | select ifnull(case when b<>0 and c<>0 then 1 else 0 end, 99) from t1; 68 | } 69 | } {0 0 0 1 0 0 0} 70 | do_test null-2.4 { 71 | execsql { 72 | select ifnull(case when not (b<>0 and c<>0) then 1 else 0 end, 99) from t1; 73 | } 74 | } {1 1 1 0 1 0 0} 75 | do_test null-2.5 { 76 | execsql { 77 | select ifnull(case when b<>0 or c<>0 then 1 else 0 end, 99) from t1; 78 | } 79 | } {0 1 1 1 0 1 0} 80 | do_test null-2.6 { 81 | execsql { 82 | select ifnull(case when not (b<>0 or c<>0) then 1 else 0 end, 99) from t1; 83 | } 84 | } {1 0 0 0 0 0 0} 85 | do_test null-2.7 { 86 | execsql { 87 | select ifnull(case b when c then 1 else 0 end, 99) from t1; 88 | } 89 | } {1 0 0 1 0 0 0} 90 | do_test null-2.8 { 91 | execsql { 92 | select ifnull(case c when b then 1 else 0 end, 99) from t1; 93 | } 94 | } {1 0 0 1 0 0 0} 95 | 96 | # Check to see that NULL values are ignored in aggregate functions. 97 | # 98 | do_test null-3.1 { 99 | execsql { 100 | select count(*), count(b), count(c), sum(b), sum(c), 101 | avg(b), avg(c), min(b), max(b) from t1; 102 | } 103 | } {7 4 6 2 3 0.5 0.5 0 1} 104 | 105 | # Check to see how WHERE clauses handle NULL values. A NULL value 106 | # is the same as UNKNOWN. The WHERE clause should only select those 107 | # rows that are TRUE. FALSE and UNKNOWN rows are rejected. 108 | # 109 | do_test null-4.1 { 110 | execsql { 111 | select a from t1 where b<10 112 | } 113 | } {1 2 3 4} 114 | do_test null-4.2 { 115 | execsql { 116 | select a from t1 where not b>10 117 | } 118 | } {1 2 3 4} 119 | do_test null-4.3 { 120 | execsql { 121 | select a from t1 where b<10 or c=1; 122 | } 123 | } {1 2 3 4 6} 124 | do_test null-4.4 { 125 | execsql { 126 | select a from t1 where b<10 and c=1; 127 | } 128 | } {2 4} 129 | do_test null-4.5 { 130 | execsql { 131 | select a from t1 where not (b<10 and c=1); 132 | } 133 | } {1 3 5} 134 | 135 | # The DISTINCT keyword on a SELECT statement should treat NULL values 136 | # as distinct 137 | # 138 | do_test null-5.1 { 139 | execsql { 140 | select distinct b from t1 order by b; 141 | } 142 | } {{} 0 1} 143 | 144 | # A UNION to two queries should treat NULL values 145 | # as distinct 146 | # 147 | do_test null-6.1 { 148 | execsql { 149 | select b from t1 union select c from t1 order by c; 150 | } 151 | } {{} 0 1} 152 | 153 | # The UNIQUE constraint only applies to non-null values 154 | # 155 | do_test null-7.1 { 156 | execsql { 157 | create table t2(a, b unique on conflict ignore); 158 | insert into t2 values(1,1); 159 | insert into t2 values(2,null); 160 | insert into t2 values(3,null); 161 | insert into t2 values(4,1); 162 | select a from t2; 163 | } 164 | } {1 2 3} 165 | do_test null-7.2 { 166 | execsql { 167 | create table t3(a, b, c, unique(b,c) on conflict ignore); 168 | insert into t3 values(1,1,1); 169 | insert into t3 values(2,null,1); 170 | insert into t3 values(3,null,1); 171 | insert into t3 values(4,1,1); 172 | select a from t3; 173 | } 174 | } {1 2 3} 175 | 176 | 177 | 178 | finish_test 179 | -------------------------------------------------------------------------------- /test/pragma.test: -------------------------------------------------------------------------------- 1 | # 2002 March 6 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. 12 | # 13 | # This file implements tests for the PRAGMA command. 14 | # 15 | # $Id: pragma.test,v 1.1 2002/03/06 22:01:37 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Delete the preexisting database to avoid the special setup 21 | # that the "all.test" script does. 22 | # 23 | db close 24 | file delete test.db 25 | sqlite db test.db 26 | 27 | do_test pragma-1.1 { 28 | execsql { 29 | PRAGMA cache_size; 30 | PRAGMA default_cache_size; 31 | PRAGMA synchronous; 32 | PRAGMA default_synchronous; 33 | } 34 | } {2000 2000 1 1} 35 | do_test pragma-1.2 { 36 | execsql { 37 | PRAGMA cache_size=1234; 38 | PRAGMA cache_size; 39 | PRAGMA default_cache_size; 40 | PRAGMA synchronous; 41 | PRAGMA default_synchronous; 42 | } 43 | } {1234 2000 1 1} 44 | do_test pragma-1.3 { 45 | db close 46 | sqlite db test.db 47 | execsql { 48 | PRAGMA cache_size; 49 | PRAGMA default_cache_size; 50 | PRAGMA synchronous; 51 | PRAGMA default_synchronous; 52 | } 53 | } {2000 2000 1 1} 54 | do_test pragma-1.4 { 55 | execsql { 56 | PRAGMA synchronous=OFF; 57 | PRAGMA cache_size; 58 | PRAGMA default_cache_size; 59 | PRAGMA synchronous; 60 | PRAGMA default_synchronous; 61 | } 62 | } {2000 2000 0 1} 63 | do_test pragma-1.5 { 64 | execsql { 65 | PRAGMA cache_size=4321; 66 | PRAGMA cache_size; 67 | PRAGMA default_cache_size; 68 | PRAGMA synchronous; 69 | PRAGMA default_synchronous; 70 | } 71 | } {4321 2000 0 1} 72 | do_test pragma-1.6 { 73 | execsql { 74 | PRAGMA synchronous=ON; 75 | PRAGMA cache_size; 76 | PRAGMA default_cache_size; 77 | PRAGMA synchronous; 78 | PRAGMA default_synchronous; 79 | } 80 | } {4321 2000 1 1} 81 | do_test pragma-1.7 { 82 | db close 83 | sqlite db test.db 84 | execsql { 85 | PRAGMA cache_size; 86 | PRAGMA default_cache_size; 87 | PRAGMA synchronous; 88 | PRAGMA default_synchronous; 89 | } 90 | } {2000 2000 1 1} 91 | do_test pragma-1.8 { 92 | execsql { 93 | PRAGMA default_synchronous=OFF; 94 | PRAGMA cache_size; 95 | PRAGMA default_cache_size; 96 | PRAGMA synchronous; 97 | PRAGMA default_synchronous; 98 | } 99 | } {2000 2000 0 0} 100 | do_test pragma-1.9 { 101 | execsql { 102 | PRAGMA default_cache_size=123; 103 | PRAGMA cache_size; 104 | PRAGMA default_cache_size; 105 | PRAGMA synchronous; 106 | PRAGMA default_synchronous; 107 | } 108 | } {123 123 0 0} 109 | do_test pragma-1.10 { 110 | db close 111 | sqlite db test.db 112 | execsql { 113 | PRAGMA cache_size; 114 | PRAGMA default_cache_size; 115 | PRAGMA synchronous; 116 | PRAGMA default_synchronous; 117 | } 118 | } {123 123 0 0} 119 | 120 | finish_test 121 | -------------------------------------------------------------------------------- /test/printf.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the sqlite_*_printf() interface. 13 | # 14 | # $Id: printf.test,v 1.5 2002/06/16 04:56:37 chw Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | set n 1 20 | foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} { 21 | do_test printf-1.$n.1 [subst { 22 | sqlite_mprintf_int {Three integers: %d %x %o} $v $v $v 23 | }] [format {Three integers: %d %x %o} $v $v $v] 24 | do_test printf-1.$n.2 [subst { 25 | sqlite_mprintf_int {Three integers: (%6d) (%6x) (%6o)} $v $v $v 26 | }] [format {Three integers: (%6d) (%6x) (%6o)} $v $v $v] 27 | do_test printf-1.$n.3 [subst { 28 | sqlite_mprintf_int {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v 29 | }] [format {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v] 30 | do_test printf-1.$n.4 [subst { 31 | sqlite_mprintf_int {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v 32 | }] [format {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v] 33 | do_test printf-1.$n.5 [subst { 34 | sqlite_mprintf_int {Three integers: (%06d) (%06x) (%06o)} $v $v $v 35 | }] [format {Three integers: (%06d) (%06x) (%06o)} $v $v $v] 36 | do_test printf-1.$n.6 [subst { 37 | sqlite_mprintf_int {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v 38 | }] [format {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v] 39 | incr n 40 | } 41 | 42 | 43 | if {$::tcl_platform(platform)!="windows"} { 44 | 45 | set m 1 46 | foreach {a b} {1 1 5 5 10 10 10 5} { 47 | set n 1 48 | foreach x {0.001 1.0e-20 1.0 0.0 100.0 9.99999 -0.00543 -1.0 -99.99999} { 49 | do_test printf-2.$m.$n.1 [subst { 50 | sqlite_mprintf_double {A double: %*.*f} $a $b $x 51 | }] [format {A double: %*.*f} $a $b $x] 52 | do_test printf-2.$m.$n.2 [subst { 53 | sqlite_mprintf_double {A double: %*.*e} $a $b $x 54 | }] [format {A double: %*.*e} $a $b $x] 55 | do_test printf-2.$m.$n.3 [subst { 56 | sqlite_mprintf_double {A double: %*.*g} $a $b $x 57 | }] [format {A double: %*.*g} $a $b $x] 58 | do_test printf-2.$m.$n.4 [subst { 59 | sqlite_mprintf_double {A double: %d %d %g} $a $b $x 60 | }] [format {A double: %d %d %g} $a $b $x] 61 | do_test printf-2.$m.$n.5 [subst { 62 | sqlite_mprintf_double {A double: %d %d %#g} $a $b $x 63 | }] [format {A double: %d %d %#g} $a $b $x] 64 | incr n 65 | } 66 | incr m 67 | } 68 | 69 | } 70 | 71 | do_test printf-3.1 { 72 | sqlite_mprintf_str {A String: (%*.*s)} 10 10 {This is the string} 73 | } [format {A String: (%*.*s)} 10 10 {This is the string}] 74 | do_test printf-3.2 { 75 | sqlite_mprintf_str {A String: (%*.*s)} 10 5 {This is the string} 76 | } [format {A String: (%*.*s)} 10 5 {This is the string}] 77 | do_test printf-3.3 { 78 | sqlite_mprintf_str {A String: (%*.*s)} -10 5 {This is the string} 79 | } [format {A String: (%*.*s)} -10 5 {This is the string}] 80 | do_test printf-3.4 { 81 | sqlite_mprintf_str {%d %d A String: (%s)} 1 2 {This is the string} 82 | } [format {%d %d A String: (%s)} 1 2 {This is the string}] 83 | do_test printf-3.5 { 84 | sqlite_mprintf_str {%d %d A String: (%30s)} 1 2 {This is the string} 85 | } [format {%d %d A String: (%30s)} 1 2 {This is the string}] 86 | do_test printf-3.6 { 87 | sqlite_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string} 88 | } [format {%d %d A String: (%-30s)} 1 2 {This is the string}] 89 | 90 | do_test printf-4.1 { 91 | sqlite_mprintf_str {%d %d A quoted string: '%q'} 1 2 {Hi Y'all} 92 | } {1 2 A quoted string: 'Hi Y''all'} 93 | do_test printf-4.2 { 94 | sqlite_mprintf_str {%d %d A NULL pointer in %%q: '%q'} 1 2 95 | } {1 2 A NULL pointer in %q: '(NULL)'} 96 | do_test printf-4.3 { 97 | sqlite_mprintf_str {%d %d A quoted string: %Q} 1 2 {Hi Y'all} 98 | } {1 2 A quoted string: 'Hi Y''all'} 99 | do_test printf-4.4 { 100 | sqlite_mprintf_str {%d %d A NULL pointer in %%Q: %Q} 1 2 101 | } {1 2 A NULL pointer in %Q: NULL} 102 | 103 | do_test printf-5.1 { 104 | set x [sqlite_mprintf_str {%d %d %100000s} 0 0 {Hello}] 105 | string length $x 106 | } {994} 107 | do_test printf-5.2 { 108 | sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello} 109 | } {-9 -10 (HelloHello) %} 110 | do_test printf-5.3 { 111 | sqlite_mprintf_str {%% %d %d (%=10s)} 5 6 Hello 112 | } {% 5 6 ( Hello )} 113 | 114 | finish_test 115 | -------------------------------------------------------------------------------- /test/quick.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file runs all tests. 12 | # 13 | # $Id: quick.test,v 1.2 2001/10/22 02:58:11 drh Exp $ 14 | 15 | set testdir [file dirname $argv0] 16 | source $testdir/tester.tcl 17 | rename finish_test really_finish_test 18 | proc finish_test {} {} 19 | 20 | set EXCLUDE { 21 | all.test 22 | quick.test 23 | btree2.test 24 | malloc.test 25 | } 26 | 27 | foreach testfile [lsort -dictionary [glob $testdir/*.test]] { 28 | set tail [file tail $testfile] 29 | if {[lsearch -exact $EXCLUDE $tail]>=0} continue 30 | source $testfile 31 | } 32 | 33 | really_finish_test 34 | -------------------------------------------------------------------------------- /test/quote.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is the ability to specify table and column names 13 | # as quoted strings. 14 | # 15 | # $Id: quote.test,v 1.3 2002/05/21 13:43:04 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Create a table with a strange name and with strange column names. 21 | # 22 | do_test quote-1.0 { 23 | set r [catch { 24 | execsql {CREATE TABLE '@abc' ( '#xyz' int, '!pqr' text );} 25 | } msg] 26 | lappend r $msg 27 | } {0 {}} 28 | 29 | # Insert, update and query the table. 30 | # 31 | do_test quote-1.1 { 32 | set r [catch { 33 | execsql {INSERT INTO '@abc' VALUES(5,'hello')} 34 | } msg] 35 | lappend r $msg 36 | } {0 {}} 37 | do_test quote-1.2 { 38 | set r [catch { 39 | execsql {SELECT * FROM '@abc'} 40 | } msg ] 41 | lappend r $msg 42 | } {0 {5 hello}} 43 | do_test quote-1.3 { 44 | set r [catch { 45 | execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'} 46 | } msg ] 47 | lappend r $msg 48 | } {0 {hello 10}} 49 | do_test quote-1.3.1 { 50 | catchsql { 51 | SELECT '!pqr', '#xyz'+5 FROM '@abc' 52 | } 53 | } {0 {!pqr 5}} 54 | do_test quote-1.3.2 { 55 | catchsql { 56 | SELECT "!pqr", "#xyz"+5 FROM '@abc' 57 | } 58 | } {0 {hello 10}} 59 | do_test quote-1.3 { 60 | set r [catch { 61 | execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'} 62 | } msg ] 63 | lappend r $msg 64 | } {0 {hello 10}} 65 | do_test quote-1.4 { 66 | set r [catch { 67 | execsql {UPDATE '@abc' SET '#xyz'=11} 68 | } msg ] 69 | lappend r $msg 70 | } {0 {}} 71 | do_test quote-1.5 { 72 | set r [catch { 73 | execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'} 74 | } msg ] 75 | lappend r $msg 76 | } {0 {hello 16}} 77 | 78 | # Drop the table with the strange name. 79 | # 80 | do_test quote-1.6 { 81 | set r [catch { 82 | execsql {DROP TABLE '@abc'} 83 | } msg ] 84 | lappend r $msg 85 | } {0 {}} 86 | 87 | 88 | finish_test 89 | -------------------------------------------------------------------------------- /test/select2.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the SELECT statement. 13 | # 14 | # $Id: select2.test,v 1.18 2002/04/02 13:26:11 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # Create a table with some data 20 | # 21 | execsql {CREATE TABLE tbl1(f1 int, f2 int)} 22 | set f [open ./testdata1.txt w] 23 | for {set i 0} {$i<=30} {incr i} { 24 | puts $f "[expr {$i%9}]\t[expr {$i%10}]" 25 | } 26 | close $f 27 | execsql {COPY tbl1 FROM './testdata1.txt'} 28 | file delete -force ./testdata1.txt 29 | catch {unset data} 30 | 31 | # Do a second query inside a first. 32 | # 33 | do_test select2-1.1 { 34 | set sql {SELECT DISTINCT f1 FROM tbl1 ORDER BY f1} 35 | set r {} 36 | db eval $sql data { 37 | set f1 $data(f1) 38 | lappend r $f1: 39 | set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2" 40 | db eval $sql2 d2 { 41 | lappend r $d2(f2) 42 | } 43 | } 44 | set r 45 | } {0: 0 7 8 9 1: 0 1 8 9 2: 0 1 2 9 3: 0 1 2 3 4: 2 3 4 5: 3 4 5 6: 4 5 6 7: 5 6 7 8: 6 7 8} 46 | 47 | do_test select2-1.2 { 48 | set sql {SELECT DISTINCT f1 FROM tbl1 WHERE f1>3 AND f1<5} 49 | set r {} 50 | db eval $sql data { 51 | set f1 $data(f1) 52 | lappend r $f1: 53 | set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2" 54 | db eval $sql2 d2 { 55 | lappend r $d2(f2) 56 | } 57 | } 58 | set r 59 | } {4: 2 3 4} 60 | 61 | # Create a largish table 62 | # 63 | do_test select2-2.0 { 64 | execsql {CREATE TABLE tbl2(f1 int, f2 int, f3 int)} 65 | set f [open ./testdata1.txt w] 66 | for {set i 1} {$i<=30000} {incr i} { 67 | puts $f "$i\t[expr {$i*2}]\t[expr {$i*3}]" 68 | } 69 | close $f 70 | # execsql {--vdbe-trace-on--} 71 | execsql {COPY tbl2 FROM './testdata1.txt'} 72 | file delete -force ./testdata1.txt 73 | } {} 74 | 75 | do_test select2-2.1 { 76 | execsql {SELECT count(*) FROM tbl2} 77 | } {30000} 78 | do_test select2-2.2 { 79 | execsql {SELECT count(*) FROM tbl2 WHERE f2>1000} 80 | } {29500} 81 | 82 | do_test select2-3.1 { 83 | execsql {SELECT f1 FROM tbl2 WHERE 1000=f2} 84 | } {500} 85 | 86 | do_test select2-3.2a { 87 | execsql {CREATE INDEX idx1 ON tbl2(f2)} 88 | } {} 89 | 90 | do_test select2-3.2b { 91 | execsql {SELECT f1 FROM tbl2 WHERE 1000=f2} 92 | } {500} 93 | do_test select2-3.2c { 94 | execsql {SELECT f1 FROM tbl2 WHERE f2=1000} 95 | } {500} 96 | do_test select2-3.2d { 97 | set sqlite_search_count 0 98 | execsql {SELECT * FROM tbl2 WHERE 1000=f2} 99 | set sqlite_search_count 100 | } {3} 101 | do_test select2-3.2e { 102 | set sqlite_search_count 0 103 | execsql {SELECT * FROM tbl2 WHERE f2=1000} 104 | set sqlite_search_count 105 | } {3} 106 | 107 | # Make sure queries run faster with an index than without 108 | # 109 | do_test select2-3.3 { 110 | execsql {DROP INDEX idx1} 111 | set sqlite_search_count 0 112 | execsql {SELECT f1 FROM tbl2 WHERE f2==2000} 113 | set sqlite_search_count 114 | } {29999} 115 | 116 | # Make sure we can optimize functions in the WHERE clause that 117 | # use fields from two or more different table. (Bug #6) 118 | # 119 | do_test select2-4.1 { 120 | execsql { 121 | CREATE TABLE aa(a); 122 | CREATE TABLE bb(b); 123 | INSERT INTO aa VALUES(1); 124 | INSERT INTO aa VALUES(3); 125 | INSERT INTO bb VALUES(2); 126 | INSERT INTO bb VALUES(4); 127 | SELECT * FROM aa, bb WHERE max(a,b)>2; 128 | } 129 | } {1 4 3 2 3 4} 130 | do_test select2-4.2 { 131 | execsql { 132 | INSERT INTO bb VALUES(0); 133 | SELECT * FROM aa, bb WHERE b; 134 | } 135 | } {1 2 1 4 3 2 3 4} 136 | do_test select2-4.3 { 137 | execsql { 138 | SELECT * FROM aa, bb WHERE NOT b; 139 | } 140 | } {1 0 3 0} 141 | do_test select2-4.4 { 142 | execsql { 143 | SELECT * FROM aa, bb WHERE min(a,b); 144 | } 145 | } {1 2 1 4 3 2 3 4} 146 | do_test select2-4.5 { 147 | execsql { 148 | SELECT * FROM aa, bb WHERE NOT min(a,b); 149 | } 150 | } {1 0 3 0} 151 | do_test select2-4.6 { 152 | execsql { 153 | SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 1 END; 154 | } 155 | } {1 2 3 4} 156 | do_test select2-4.7 { 157 | execsql { 158 | SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 0 ELSE 1 END; 159 | } 160 | } {1 4 1 0 3 2 3 0} 161 | 162 | finish_test 163 | -------------------------------------------------------------------------------- /test/select3.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing aggregate functions and the 13 | # GROUP BY and HAVING clauses of SELECT statements. 14 | # 15 | # $Id: select3.test,v 1.5 2002/01/22 14:11:30 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Build some test data 21 | # 22 | do_test select3-1.0 { 23 | set fd [open data1.txt w] 24 | for {set i 1} {$i<32} {incr i} { 25 | for {set j 0} {pow(2,$j)<$i} {incr j} {} 26 | puts $fd "$i\t$j" 27 | } 28 | close $fd 29 | execsql { 30 | CREATE TABLE t1(n int, log int); 31 | COPY t1 FROM 'data1.txt' 32 | } 33 | file delete data1.txt 34 | execsql {SELECT DISTINCT log FROM t1 ORDER BY log} 35 | } {0 1 2 3 4 5} 36 | 37 | # Basic aggregate functions. 38 | # 39 | do_test select3-1.1 { 40 | execsql {SELECT count(*) FROM t1} 41 | } {31} 42 | do_test select3-1.2 { 43 | execsql { 44 | SELECT min(n),min(log),max(n),max(log),sum(n),sum(log),avg(n),avg(log) 45 | FROM t1 46 | } 47 | } {1 0 31 5 496 124 16 4} 48 | do_test select3-1.3 { 49 | execsql {SELECT max(n)/avg(n), max(log)/avg(log) FROM t1} 50 | } {1.9375 1.25} 51 | 52 | # Try some basic GROUP BY clauses 53 | # 54 | do_test select3-2.1 { 55 | execsql {SELECT log, count(*) FROM t1 GROUP BY log ORDER BY log} 56 | } {0 1 1 1 2 2 3 4 4 8 5 15} 57 | do_test select3-2.2 { 58 | execsql {SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log} 59 | } {0 1 1 2 2 3 3 5 4 9 5 17} 60 | do_test select3-2.3 { 61 | execsql {SELECT log, avg(n) FROM t1 GROUP BY log ORDER BY log} 62 | } {0 1 1 2 2 3.5 3 6.5 4 12.5 5 24} 63 | do_test select3-2.3 { 64 | execsql {SELECT log, avg(n)+1 FROM t1 GROUP BY log ORDER BY log} 65 | } {0 2 1 3 2 4.5 3 7.5 4 13.5 5 25} 66 | do_test select3-2.4 { 67 | execsql {SELECT log, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log} 68 | } {0 0 1 0 2 0.5 3 1.5 4 3.5 5 7} 69 | do_test select3-2.5 { 70 | execsql {SELECT log*2+1, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log} 71 | } {1 0 3 0 5 0.5 7 1.5 9 3.5 11 7} 72 | do_test select3-2.6 { 73 | execsql { 74 | SELECT log*2+1 as x, count(*) FROM t1 GROUP BY x ORDER BY x 75 | } 76 | } {1 1 3 1 5 2 7 4 9 8 11 15} 77 | do_test select3-2.7 { 78 | execsql { 79 | SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY y 80 | } 81 | } {1 1 3 1 5 2 7 4 9 8 11 15} 82 | do_test select3-2.8 { 83 | execsql { 84 | SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY 10-(x+y) 85 | } 86 | } {11 15 9 8 7 4 5 2 3 1 1 1} 87 | do_test select3-2.9 { 88 | catchsql { 89 | SELECT log, count(*) FROM t1 GROUP BY 8 ORDER BY log; 90 | } 91 | } {1 {GROUP BY expressions should not be constant}} 92 | 93 | # Cannot have a HAVING without a GROUP BY 94 | # 95 | do_test select3-3.1 { 96 | set v [catch {execsql {SELECT log, count(*) FROM t1 HAVING log>=4}} msg] 97 | lappend v $msg 98 | } {1 {a GROUP BY clause is required before HAVING}} 99 | 100 | # Toss in some HAVING clauses 101 | # 102 | do_test select3-4.1 { 103 | execsql {SELECT log, count(*) FROM t1 GROUP BY log HAVING log>=4 ORDER BY log} 104 | } {4 8 5 15} 105 | do_test select3-4.2 { 106 | execsql { 107 | SELECT log, count(*) FROM t1 108 | GROUP BY log 109 | HAVING count(*)>=4 110 | ORDER BY log 111 | } 112 | } {3 4 4 8 5 15} 113 | do_test select3-4.3 { 114 | execsql { 115 | SELECT log, count(*) FROM t1 116 | GROUP BY log 117 | HAVING count(*)>=4 118 | ORDER BY max(n) 119 | } 120 | } {3 4 4 8 5 15} 121 | do_test select3-4.4 { 122 | execsql { 123 | SELECT log AS x, count(*) AS y FROM t1 124 | GROUP BY x 125 | HAVING y>=4 126 | ORDER BY max(n) 127 | } 128 | } {3 4 4 8 5 15} 129 | 130 | do_test select3-5.1 { 131 | execsql { 132 | SELECT log, count(*), avg(n), max(n+log*2) FROM t1 133 | GROUP BY log 134 | ORDER BY max(n+log*2), avg(n) 135 | } 136 | } {0 1 1 1 1 1 2 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24 41} 137 | do_test select3-5.2 { 138 | execsql { 139 | SELECT log, count(*), avg(n), max(n+log*2) FROM t1 140 | GROUP BY log 141 | ORDER BY max(n+log*2), min(log,avg(n)) 142 | } 143 | } {0 1 1 1 1 1 2 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24 41} 144 | 145 | finish_test 146 | -------------------------------------------------------------------------------- /test/select5.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing aggregate functions and the 13 | # GROUP BY and HAVING clauses of SELECT statements. 14 | # 15 | # $Id: select5.test,v 1.6 2001/10/15 00:44:36 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Build some test data 21 | # 22 | set fd [open data1.txt w] 23 | for {set i 1} {$i<32} {incr i} { 24 | for {set j 0} {pow(2,$j)<$i} {incr j} {} 25 | puts $fd "[expr {32-$i}]\t[expr {10-$j}]" 26 | } 27 | close $fd 28 | execsql { 29 | CREATE TABLE t1(x int, y int); 30 | COPY t1 FROM 'data1.txt' 31 | } 32 | file delete data1.txt 33 | 34 | do_test select5-1.0 { 35 | execsql {SELECT DISTINCT y FROM t1 ORDER BY y} 36 | } {5 6 7 8 9 10} 37 | 38 | # Sort by an aggregate function. 39 | # 40 | do_test select5-1.1 { 41 | execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY y} 42 | } {5 15 6 8 7 4 8 2 9 1 10 1} 43 | do_test select5-1.2 { 44 | execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY count(*), y} 45 | } {9 1 10 1 8 2 7 4 6 8 5 15} 46 | do_test select5-1.3 { 47 | execsql {SELECT count(*), y FROM t1 GROUP BY y ORDER BY count(*), y} 48 | } {1 9 1 10 2 8 4 7 8 6 15 5} 49 | 50 | # Some error messages associated with aggregates and GROUP BY 51 | # 52 | do_test select5-2.1 { 53 | set v [catch {execsql { 54 | SELECT y, count(*) FROM t1 GROUP BY z ORDER BY y 55 | }} msg] 56 | lappend v $msg 57 | } {1 {no such column: z}} 58 | do_test select5-2.2 { 59 | set v [catch {execsql { 60 | SELECT y, count(*) FROM t1 GROUP BY z(y) ORDER BY y 61 | }} msg] 62 | lappend v $msg 63 | } {1 {no such function: z}} 64 | do_test select5-2.3 { 65 | set v [catch {execsql { 66 | SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<3 ORDER BY y 67 | }} msg] 68 | lappend v $msg 69 | } {0 {8 2 9 1 10 1}} 70 | do_test select5-2.4 { 71 | set v [catch {execsql { 72 | SELECT y, count(*) FROM t1 GROUP BY y HAVING z(y)<3 ORDER BY y 73 | }} msg] 74 | lappend v $msg 75 | } {1 {no such function: z}} 76 | do_test select5-2.5 { 77 | set v [catch {execsql { 78 | SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)100 96 | } 97 | } {{}} 98 | do_test select5-4.2 { 99 | execsql { 100 | SELECT count(x) FROM t1 WHERE x>100 101 | } 102 | } {0} 103 | do_test select5-4.3 { 104 | execsql { 105 | SELECT min(x) FROM t1 WHERE x>100 106 | } 107 | } {{}} 108 | do_test select5-4.4 { 109 | execsql { 110 | SELECT max(x) FROM t1 WHERE x>100 111 | } 112 | } {{}} 113 | do_test select5-4.5 { 114 | execsql { 115 | SELECT sum(x) FROM t1 WHERE x>100 116 | } 117 | } {0} 118 | 119 | finish_test 120 | -------------------------------------------------------------------------------- /test/sort.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the CREATE TABLE statement. 13 | # 14 | # $Id: sort.test,v 1.4 2002/01/22 14:11:30 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # Create a bunch of data to sort against 20 | # 21 | do_test sort-1.0 { 22 | set fd [open data.txt w] 23 | puts $fd "1\tone\t0\tI\t3.141592653" 24 | puts $fd "2\ttwo\t1\tII\t2.15" 25 | puts $fd "3\tthree\t1\tIII\t4221.0" 26 | puts $fd "4\tfour\t2\tIV\t-0.0013442" 27 | puts $fd "5\tfive\t2\tV\t-11" 28 | puts $fd "6\tsix\t2\tVI\t0.123" 29 | puts $fd "7\tseven\t2\tVII\t123.0" 30 | puts $fd "8\teight\t3\tVIII\t-1.6" 31 | close $fd 32 | execsql { 33 | CREATE TABLE t1( 34 | n int, 35 | v varchar(10), 36 | log int, 37 | roman varchar(10), 38 | flt real 39 | ); 40 | COPY t1 FROM 'data.txt' 41 | } 42 | file delete data.txt 43 | execsql {SELECT count(*) FROM t1} 44 | } {8} 45 | 46 | do_test sort-1.1 { 47 | execsql {SELECT n FROM t1 ORDER BY n} 48 | } {1 2 3 4 5 6 7 8} 49 | do_test sort-1.1.1 { 50 | execsql {SELECT n FROM t1 ORDER BY n ASC} 51 | } {1 2 3 4 5 6 7 8} 52 | do_test sort-1.1.1 { 53 | execsql {SELECT ALL n FROM t1 ORDER BY n ASC} 54 | } {1 2 3 4 5 6 7 8} 55 | do_test sort-1.2 { 56 | execsql {SELECT n FROM t1 ORDER BY n DESC} 57 | } {8 7 6 5 4 3 2 1} 58 | do_test sort-1.3a { 59 | execsql {SELECT v FROM t1 ORDER BY v} 60 | } {eight five four one seven six three two} 61 | do_test sort-1.3b { 62 | execsql {SELECT n FROM t1 ORDER BY v} 63 | } {8 5 4 1 7 6 3 2} 64 | do_test sort-1.4 { 65 | execsql {SELECT n FROM t1 ORDER BY v DESC} 66 | } {2 3 6 7 1 4 5 8} 67 | do_test sort-1.5 { 68 | execsql {SELECT flt FROM t1 ORDER BY flt} 69 | } {-11 -1.6 -0.0013442 0.123 2.15 3.141592653 123.0 4221.0} 70 | do_test sort-1.6 { 71 | execsql {SELECT flt FROM t1 ORDER BY flt DESC} 72 | } {4221.0 123.0 3.141592653 2.15 0.123 -0.0013442 -1.6 -11} 73 | do_test sort-1.7 { 74 | execsql {SELECT roman FROM t1 ORDER BY roman} 75 | } {I II III IV V VI VII VIII} 76 | do_test sort-1.8 { 77 | execsql {SELECT n FROM t1 ORDER BY log, flt} 78 | } {1 2 3 5 4 6 7 8} 79 | do_test sort-1.8.1 { 80 | execsql {SELECT n FROM t1 ORDER BY log asc, flt} 81 | } {1 2 3 5 4 6 7 8} 82 | do_test sort-1.8.2 { 83 | execsql {SELECT n FROM t1 ORDER BY log, flt ASC} 84 | } {1 2 3 5 4 6 7 8} 85 | do_test sort-1.8.3 { 86 | execsql {SELECT n FROM t1 ORDER BY log ASC, flt asc} 87 | } {1 2 3 5 4 6 7 8} 88 | do_test sort-1.9 { 89 | execsql {SELECT n FROM t1 ORDER BY log, flt DESC} 90 | } {1 3 2 7 6 4 5 8} 91 | do_test sort-1.9.1 { 92 | execsql {SELECT n FROM t1 ORDER BY log ASC, flt DESC} 93 | } {1 3 2 7 6 4 5 8} 94 | do_test sort-1.10 { 95 | execsql {SELECT n FROM t1 ORDER BY log DESC, flt} 96 | } {8 5 4 6 7 2 3 1} 97 | do_test sort-1.11 { 98 | execsql {SELECT n FROM t1 ORDER BY log DESC, flt DESC} 99 | } {8 7 6 4 5 3 2 1} 100 | 101 | # These tests are designed to reach some hard-to-reach places 102 | # inside the string comparison routines. 103 | # 104 | do_test sort-2.1 { 105 | execsql { 106 | UPDATE t1 SET v='x' || -flt; 107 | UPDATE t1 SET v='x-2b' where v=='x-0.123'; 108 | SELECT v FROM t1 ORDER BY v; 109 | } 110 | } {x-2b x-2.15 x-3.141592653 x-123 x-4221 x0.0013442 x1.6 x11} 111 | do_test sort-2.2 { 112 | execsql { 113 | UPDATE t1 SET v='x-2_' where v=='x0.0013442'; 114 | SELECT v FROM t1 ORDER BY v; 115 | } 116 | } {x-2_ x-2b x-2.15 x-3.141592653 x-123 x-4221 x1.6 x11} 117 | do_test sort-2.3 { 118 | execsql { 119 | UPDATE t1 SET v='x ' || (-1.3+0.01*n); 120 | SELECT v FROM t1 ORDER BY v; 121 | } 122 | } {{x -1.29} {x -1.28} {x -1.27} {x -1.26} {x -1.25} {x -1.24} {x -1.23} {x -1.22}} 123 | 124 | # This is a bug fix for 2.2.4. 125 | # Strings are normally mapped to upper-case for a caseless comparison. 126 | # But this can cause problems for characters in between 'Z' and 'a'. 127 | # 128 | do_test sort-3.1 { 129 | execsql { 130 | CREATE TABLE t2(a,b); 131 | INSERT INTO t2 VALUES('AGLIENTU',1); 132 | INSERT INTO t2 VALUES('AGLIE`',2); 133 | INSERT INTO t2 VALUES('AGNA',3); 134 | SELECT a, b FROM t2 ORDER BY a; 135 | } 136 | } {AGLIENTU 1 AGLIE` 2 AGNA 3} 137 | do_test sort-3.2 { 138 | execsql { 139 | SELECT a, b FROM t2 ORDER BY a DESC; 140 | } 141 | } {AGNA 3 AGLIE` 2 AGLIENTU 1} 142 | do_test sort-3.3 { 143 | execsql { 144 | DELETE FROM t2; 145 | INSERT INTO t2 VALUES('aglientu',1); 146 | INSERT INTO t2 VALUES('aglie`',2); 147 | INSERT INTO t2 VALUES('agna',3); 148 | SELECT a, b FROM t2 ORDER BY a; 149 | } 150 | } {aglie` 2 aglientu 1 agna 3} 151 | do_test sort-3.4 { 152 | execsql { 153 | SELECT a, b FROM t2 ORDER BY a DESC; 154 | } 155 | } {agna 3 aglientu 1 aglie` 2} 156 | 157 | 158 | finish_test 159 | -------------------------------------------------------------------------------- /test/subselect.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing SELECT statements that are part of 13 | # expressions. 14 | # 15 | # $Id: subselect.test,v 1.5 2002/05/26 20:54:35 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Basic sanity checking. Try a simple subselect. 21 | # 22 | do_test subselect-1.1 { 23 | execsql { 24 | CREATE TABLE t1(a int, b int); 25 | INSERT INTO t1 VALUES(1,2); 26 | INSERT INTO t1 VALUES(3,4); 27 | INSERT INTO t1 VALUES(5,6); 28 | } 29 | execsql {SELECT * FROM t1 WHERE a = (SELECT count(*) FROM t1)} 30 | } {3 4} 31 | 32 | # Try a select with more than one result column. 33 | # 34 | do_test subselect-1.2 { 35 | set v [catch {execsql {SELECT * FROM t1 WHERE a = (SELECT * FROM t1)}} msg] 36 | lappend v $msg 37 | } {1 {only a single result allowed for a SELECT that is part of an expression}} 38 | 39 | # A subselect without an aggregate. 40 | # 41 | do_test subselect-1.3a { 42 | execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=2)} 43 | } {2} 44 | do_test subselect-1.3b { 45 | execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=4)} 46 | } {4} 47 | do_test subselect-1.3c { 48 | execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=6)} 49 | } {6} 50 | do_test subselect-1.3c { 51 | execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=8)} 52 | } {} 53 | 54 | # What if the subselect doesn't return any value. We should get 55 | # NULL as the result. Check it out. 56 | # 57 | do_test subselect-1.4 { 58 | execsql {SELECT b from t1 where a = coalesce((SELECT a FROM t1 WHERE b=5),1)} 59 | } {2} 60 | 61 | # Try multiple subselects within a single expression. 62 | # 63 | do_test subselect-1.5 { 64 | execsql { 65 | CREATE TABLE t2(x int, y int); 66 | INSERT INTO t2 VALUES(1,2); 67 | INSERT INTO t2 VALUES(2,4); 68 | INSERT INTO t2 VALUES(3,8); 69 | INSERT INTO t2 VALUES(4,16); 70 | } 71 | execsql { 72 | SELECT y from t2 73 | WHERE x = (SELECT sum(b) FROM t1 where a notnull) - (SELECT sum(a) FROM t1) 74 | } 75 | } {8} 76 | 77 | # Try something useful. Delete every entry from t2 where the 78 | # x value is less than half of the maximum. 79 | # 80 | do_test subselect-1.6 { 81 | execsql {DELETE FROM t2 WHERE x < 0.5*(SELECT max(x) FROM t2)} 82 | execsql {SELECT x FROM t2 ORDER BY x} 83 | } {2 3 4} 84 | 85 | finish_test 86 | -------------------------------------------------------------------------------- /test/tableapi.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the sqlite_exec_printf() and 13 | # sqlite_get_table_printf() APIs. 14 | # 15 | # $Id: tableapi.test,v 1.5 2002/03/23 00:52:01 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | do_test tableapi-1.0 { 21 | set ::dbx [sqlite_open testdb] 22 | catch {sqlite_exec_printf $::dbx {DROP TABLE xyz} {}} 23 | sqlite_exec_printf $::dbx {CREATE TABLE %s(a int, b text)} xyz 24 | } {0 {}} 25 | do_test tableapi-1.1 { 26 | sqlite_exec_printf $::dbx { 27 | INSERT INTO xyz VALUES(1,'%q') 28 | } {Hi Y'all} 29 | } {0 {}} 30 | do_test tableapi-1.2 { 31 | sqlite_exec_printf $::dbx {SELECT * FROM xyz} {} 32 | } {0 {a b 1 {Hi Y'all}}} 33 | 34 | do_test tableapi-2.1 { 35 | sqlite_get_table_printf $::dbx { 36 | BEGIN TRANSACTION; 37 | SELECT * FROM xyz WHERE b='%q' 38 | } {Hi Y'all} 39 | } {0 1 2 a b 1 {Hi Y'all}} 40 | do_test tableapi-2.2 { 41 | sqlite_get_table_printf $::dbx { 42 | SELECT * FROM xyz 43 | } {} 44 | } {0 1 2 a b 1 {Hi Y'all}} 45 | do_test tableapi-2.3 { 46 | for {set i 2} {$i<=50} {incr i} { 47 | sqlite_get_table_printf $::dbx \ 48 | "INSERT INTO xyz VALUES($i,'(%s)')" $i 49 | } 50 | sqlite_get_table_printf $::dbx { 51 | SELECT * FROM xyz ORDER BY a 52 | } {} 53 | } {0 50 2 a b 1 {Hi Y'all} 2 (2) 3 (3) 4 (4) 5 (5) 6 (6) 7 (7) 8 (8) 9 (9) 10 (10) 11 (11) 12 (12) 13 (13) 14 (14) 15 (15) 16 (16) 17 (17) 18 (18) 19 (19) 20 (20) 21 (21) 22 (22) 23 (23) 24 (24) 25 (25) 26 (26) 27 (27) 28 (28) 29 (29) 30 (30) 31 (31) 32 (32) 33 (33) 34 (34) 35 (35) 36 (36) 37 (37) 38 (38) 39 (39) 40 (40) 41 (41) 42 (42) 43 (43) 44 (44) 45 (45) 46 (46) 47 (47) 48 (48) 49 (49) 50 (50)} 54 | do_test tableapi-2.3.1 { 55 | sqlite_get_table_printf $::dbx { 56 | SELECT * FROM xyz WHERE a>49 ORDER BY a 57 | } {} 58 | } {0 1 2 a b 50 (50)} 59 | do_test tableapi-2.3.2 { 60 | sqlite_get_table_printf $::dbx { 61 | SELECT * FROM xyz WHERE a>47 ORDER BY a 62 | } {} 63 | } {0 3 2 a b 48 (48) 49 (49) 50 (50)} 64 | do_test tableapi-2.4 { 65 | set ::big_str [sqlite_mprintf_str {%500'* Hello %500'*} 0 0 {}] 66 | sqlite_get_table_printf $::dbx { 67 | INSERT INTO xyz VALUES(51,'%q') 68 | } $::big_str 69 | } {0 0 0} 70 | do_test tableapi-2.5 { 71 | sqlite_get_table_printf $::dbx { 72 | SELECT * FROM xyz WHERE a>49 ORDER BY a; 73 | } {} 74 | } "0 2 2 a b 50 (50) 51 \173$::big_str\175" 75 | do_test tableapi-2.6 { 76 | sqlite_get_table_printf $::dbx { 77 | INSERT INTO xyz VALUES(52,NULL) 78 | } {} 79 | sqlite_get_table_printf $::dbx { 80 | SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC 81 | } {} 82 | } {0 3 2 a b 52 NULL 50 (50) 42 (42)} 83 | do_test tableapi-2.7 { 84 | sqlite_get_table_printf $::dbx { 85 | SELECT * FROM xyz WHERE a>1000 86 | } {} 87 | } {0 0 0} 88 | 89 | # Repeat all tests with the empty_result_callbacks pragma turned on 90 | # 91 | do_test tableapi-3.1 { 92 | sqlite_get_table_printf $::dbx { 93 | ROLLBACK; 94 | PRAGMA empty_result_callbacks = ON; 95 | SELECT * FROM xyz WHERE b='%q' 96 | } {Hi Y'all} 97 | } {0 1 2 a b 1 {Hi Y'all}} 98 | do_test tableapi-3.2 { 99 | sqlite_get_table_printf $::dbx { 100 | SELECT * FROM xyz 101 | } {} 102 | } {0 1 2 a b 1 {Hi Y'all}} 103 | do_test tableapi-3.3 { 104 | for {set i 2} {$i<=50} {incr i} { 105 | sqlite_get_table_printf $::dbx \ 106 | "INSERT INTO xyz VALUES($i,'(%s)')" $i 107 | } 108 | sqlite_get_table_printf $::dbx { 109 | SELECT * FROM xyz ORDER BY a 110 | } {} 111 | } {0 50 2 a b 1 {Hi Y'all} 2 (2) 3 (3) 4 (4) 5 (5) 6 (6) 7 (7) 8 (8) 9 (9) 10 (10) 11 (11) 12 (12) 13 (13) 14 (14) 15 (15) 16 (16) 17 (17) 18 (18) 19 (19) 20 (20) 21 (21) 22 (22) 23 (23) 24 (24) 25 (25) 26 (26) 27 (27) 28 (28) 29 (29) 30 (30) 31 (31) 32 (32) 33 (33) 34 (34) 35 (35) 36 (36) 37 (37) 38 (38) 39 (39) 40 (40) 41 (41) 42 (42) 43 (43) 44 (44) 45 (45) 46 (46) 47 (47) 48 (48) 49 (49) 50 (50)} 112 | do_test tableapi-3.3.1 { 113 | sqlite_get_table_printf $::dbx { 114 | SELECT * FROM xyz WHERE a>49 ORDER BY a 115 | } {} 116 | } {0 1 2 a b 50 (50)} 117 | do_test tableapi-3.3.2 { 118 | sqlite_get_table_printf $::dbx { 119 | SELECT * FROM xyz WHERE a>47 ORDER BY a 120 | } {} 121 | } {0 3 2 a b 48 (48) 49 (49) 50 (50)} 122 | do_test tableapi-3.4 { 123 | set ::big_str [sqlite_mprintf_str {%500'* Hello %500'*} 0 0 {}] 124 | sqlite_get_table_printf $::dbx { 125 | INSERT INTO xyz VALUES(51,'%q') 126 | } $::big_str 127 | } {0 0 0} 128 | do_test tableapi-3.5 { 129 | sqlite_get_table_printf $::dbx { 130 | SELECT * FROM xyz WHERE a>49 ORDER BY a; 131 | } {} 132 | } "0 2 2 a b 50 (50) 51 \173$::big_str\175" 133 | do_test tableapi-3.6 { 134 | sqlite_get_table_printf $::dbx { 135 | INSERT INTO xyz VALUES(52,NULL) 136 | } {} 137 | sqlite_get_table_printf $::dbx { 138 | SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC 139 | } {} 140 | } {0 3 2 a b 52 NULL 50 (50) 42 (42)} 141 | do_test tableapi-3.7 { 142 | sqlite_get_table_printf $::dbx { 143 | SELECT * FROM xyz WHERE a>1000 144 | } {} 145 | } {0 0 2 a b} 146 | 147 | do_test tableapi-4.1 { 148 | set rc [catch { 149 | sqlite_get_table_printf $::dbx { 150 | SELECT * FROM xyz; SELECT * FROM sqlite_master 151 | } {} 152 | } msg] 153 | concat $rc $msg 154 | } {0 1 {sqlite_get_table() called with two or more incompatible queries}} 155 | 156 | do_test tableapi-99.0 { 157 | sqlite_close $::dbx 158 | } {} 159 | 160 | finish_test 161 | -------------------------------------------------------------------------------- /test/tclsqlite.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for TCL interface to the 12 | # SQLite library. 13 | # 14 | # Actually, all tests are based on the TCL interface, so the main 15 | # interface is pretty well tested. This file contains some addition 16 | # tests for fringe issues that the main test suite does not cover. 17 | # 18 | # $Id: tclsqlite.test,v 1.6 2002/04/12 10:09:00 drh Exp $ 19 | 20 | set testdir [file dirname $argv0] 21 | source $testdir/tester.tcl 22 | 23 | # Check the error messages generated by tclsqlite 24 | # 25 | do_test tcl-1.1 { 26 | set v [catch {sqlite bogus} msg] 27 | lappend v $msg 28 | } {1 {wrong # args: should be "sqlite HANDLE FILENAME ?MODE?"}} 29 | do_test tcl-1.2 { 30 | set v [catch {db bogus} msg] 31 | lappend v $msg 32 | } {1 {bad option "bogus": must be busy, changes, close, complete, eval, last_insert_rowid, or timeout}} 33 | do_test tcl-1.3 { 34 | execsql {CREATE TABLE t1(a int, b int)} 35 | execsql {INSERT INTO t1 VALUES(10,20)} 36 | set v [catch { 37 | db eval {SELECT * FROM t1} data { 38 | error "The error message" 39 | } 40 | } msg] 41 | lappend v $msg 42 | } {1 {The error message}} 43 | do_test tcl-1.4 { 44 | set v [catch { 45 | db eval {SELECT * FROM t2} data { 46 | error "The error message" 47 | } 48 | } msg] 49 | lappend v $msg 50 | } {1 {no such table: t2}} 51 | do_test tcl-1.5 { 52 | set v [catch { 53 | db eval {SELECT * FROM t1} data { 54 | break 55 | } 56 | } msg] 57 | lappend v $msg 58 | } {0 {}} 59 | do_test tcl-1.6 { 60 | set v [catch { 61 | db eval {SELECT * FROM t1} data { 62 | expr x* 63 | } 64 | } msg] 65 | regsub {:.*$} $msg {} msg 66 | lappend v $msg 67 | } {1 {syntax error in expression "x*"}} 68 | 69 | if {[sqlite -encoding]=="UTF-8" && [sqlite -tcl-uses-utf]} { 70 | do_test tcl-2.1 { 71 | execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)" 72 | execsql "PRAGMA table_info(t\u0123x)" 73 | } "0 a int 0 {} 1 b\u1235 float 0 {}" 74 | do_test tcl-2.2 { 75 | execsql "INSERT INTO t\u0123x VALUES(1,2.3)" 76 | db eval "SELECT * FROM t\u0123x" result break 77 | set result(*) 78 | } "a b\u1235" 79 | } 80 | 81 | if {[sqlite -encoding]=="iso8859" && [sqlite -tcl-uses-utf]} { 82 | do_test tcl-2.1 { 83 | execsql "CREATE TABLE t\251x(a int, b\306 float)" 84 | execsql "PRAGMA table_info(t\251x)" 85 | } "0 a int 0 {} 1 b\306 float 0 {}" 86 | do_test tcl-2.2 { 87 | execsql "INSERT INTO t\251x VALUES(1,2.3)" 88 | db eval "SELECT * FROM t\251x" result break 89 | set result(*) 90 | } "a b\306" 91 | } 92 | 93 | 94 | finish_test 95 | -------------------------------------------------------------------------------- /test/tester.tcl: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements some common TCL routines used for regression 12 | # testing the SQLite library 13 | # 14 | # $Id: tester.tcl,v 1.22 2002/03/06 22:01:37 drh Exp $ 15 | 16 | # Make sure tclsqlite was compiled correctly. Abort now with an 17 | # error message if not. 18 | # 19 | if {[sqlite -tcl-uses-utf]} { 20 | if {"\u1234"=="u1234"} { 21 | puts stderr "***** BUILD PROBLEM *****" 22 | puts stderr "$argv0 was linked against an older version" 23 | puts stderr "of TCL that does not support Unicode, but uses a header" 24 | puts stderr "file (\"tcl.h\") from a new TCL version that does support" 25 | puts stderr "Unicode. This combination causes internal errors." 26 | puts stderr "Recompile using a TCL library and header file that match" 27 | puts stderr "and try again.\n**************************" 28 | exit 1 29 | } 30 | } else { 31 | if {"\u1234"!="u1234"} { 32 | puts stderr "***** BUILD PROBLEM *****" 33 | puts stderr "$argv0 was linked against an newer version" 34 | puts stderr "of TCL that supports Unicode, but uses a header file" 35 | puts stderr "(\"tcl.h\") from a old TCL version that does not support" 36 | puts stderr "Unicode. This combination causes internal errors." 37 | puts stderr "Recompile using a TCL library and header file that match" 38 | puts stderr "and try again.\n**************************" 39 | exit 1 40 | } 41 | } 42 | 43 | # Create a test database 44 | # 45 | catch {db close} 46 | file delete -force test.db 47 | file delete -force test.db-journal 48 | sqlite db ./test.db 49 | if {[info exists ::SETUP_SQL]} { 50 | db eval $::SETUP_SQL 51 | } 52 | 53 | # Abort early if this script has been run before. 54 | # 55 | if {[info exists nTest]} return 56 | 57 | # Set the test counters to zero 58 | # 59 | set nErr 0 60 | set nTest 0 61 | set nProb 0 62 | set skip_test 0 63 | set failList {} 64 | 65 | # Invoke the do_test procedure to run a single test 66 | # 67 | proc do_test {name cmd expected} { 68 | global argv nErr nTest skip_test 69 | if {$skip_test} { 70 | set skip_test 0 71 | return 72 | } 73 | if {[llength $argv]==0} { 74 | set go 1 75 | } else { 76 | set go 0 77 | foreach pattern $argv { 78 | if {[string match $pattern $name]} { 79 | set go 1 80 | break 81 | } 82 | } 83 | } 84 | if {!$go} return 85 | incr nTest 86 | puts -nonewline $name... 87 | flush stdout 88 | if {[catch {uplevel #0 "$cmd;\n"} result]} { 89 | puts "\nError: $result" 90 | incr nErr 91 | lappend ::failList $name 92 | if {$nErr>10} {puts "*** Giving up..."; finalize_testing} 93 | } elseif {[string compare $result $expected]} { 94 | puts "\nExpected: \[$expected\]\n Got: \[$result\]" 95 | incr nErr 96 | lappend ::failList $name 97 | if {$nErr>10} {puts "*** Giving up..."; finalize_testing} 98 | } else { 99 | puts " Ok" 100 | } 101 | } 102 | 103 | # Invoke this procedure on a test that is probabilistic 104 | # and might fail sometimes. 105 | # 106 | proc do_probtest {name cmd expected} { 107 | global argv nProb nTest skip_test 108 | if {$skip_test} { 109 | set skip_test 0 110 | return 111 | } 112 | if {[llength $argv]==0} { 113 | set go 1 114 | } else { 115 | set go 0 116 | foreach pattern $argv { 117 | if {[string match $pattern $name]} { 118 | set go 1 119 | break 120 | } 121 | } 122 | } 123 | if {!$go} return 124 | incr nTest 125 | puts -nonewline $name... 126 | flush stdout 127 | if {[catch {uplevel #0 "$cmd;\n"} result]} { 128 | puts "\nError: $result" 129 | incr nErr 130 | } elseif {[string compare $result $expected]} { 131 | puts "\nExpected: \[$expected\]\n Got: \[$result\]" 132 | puts "NOTE: The results of the previous test depend on system load" 133 | puts "and processor speed. The test may sometimes fail even if the" 134 | puts "library is working correctly." 135 | incr nProb 136 | } else { 137 | puts " Ok" 138 | } 139 | } 140 | 141 | # The procedure uses the special "sqlite_malloc_stat" command 142 | # (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1) 143 | # to see how many malloc()s have not been free()ed. The number 144 | # of surplus malloc()s is stored in the global variable $::Leak. 145 | # If the value in $::Leak grows, it may mean there is a memory leak 146 | # in the library. 147 | # 148 | proc memleak_check {} { 149 | if {[info command sqlite_malloc_stat]!=""} { 150 | set r [sqlite_malloc_stat] 151 | set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}] 152 | } 153 | } 154 | 155 | # Run this routine last 156 | # 157 | proc finish_test {} { 158 | finalize_testing 159 | } 160 | proc finalize_testing {} { 161 | global nTest nErr nProb 162 | if {$nErr==0} memleak_check 163 | catch {db close} 164 | puts "$nErr errors out of $nTest tests" 165 | puts "Failures on these tests: $::failList" 166 | if {$nProb>0} { 167 | puts "$nProb probabilistic tests also failed, but this does" 168 | puts "not necessarily indicate a malfunction." 169 | } 170 | exit [expr {$nErr>0}] 171 | } 172 | 173 | # A procedure to execute SQL 174 | # 175 | proc execsql {sql {db db}} { 176 | # puts "SQL = $sql" 177 | return [$db eval $sql] 178 | } 179 | 180 | # Execute SQL and catch exceptions. 181 | # 182 | proc catchsql {sql {db db}} { 183 | # puts "SQL = $sql" 184 | set r [catch {$db eval $sql} msg] 185 | lappend r $msg 186 | return $r 187 | } 188 | 189 | # Do an VDBE code dump on the SQL given 190 | # 191 | proc explain {sql {db db}} { 192 | puts "" 193 | puts "addr opcode p1 p2 p3 " 194 | puts "---- ------------ ------ ------ ---------------" 195 | $db eval "explain $sql" {} { 196 | puts [format {%-4d %-12.12s %-6d %-6d %s} $addr $opcode $p1 $p2 $p3] 197 | } 198 | } 199 | 200 | # Another procedure to execute SQL. This one includes the field 201 | # names in the returned list. 202 | # 203 | proc execsql2 {sql} { 204 | set result {} 205 | db eval $sql data { 206 | foreach f $data(*) { 207 | lappend result $f $data($f) 208 | } 209 | } 210 | return $result 211 | } 212 | 213 | # Delete a file or directory 214 | # 215 | proc forcedelete {filename} { 216 | if {[catch {file delete -force $filename}]} { 217 | exec rm -rf $filename 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /test/trigger1.test: -------------------------------------------------------------------------------- 1 | # The author disclaims copyright to this source code. In place of 2 | # a legal notice, here is a blessing: 3 | # 4 | # May you do good and not evil. 5 | # May you find forgiveness for yourself and forgive others. 6 | # May you share freely, never taking more than you give. 7 | # 8 | #*********************************************************************** 9 | # 10 | # This file tests creating and dropping triggers, and interaction thereof 11 | # with the database COMMIT/ROLLBACK logic. 12 | # 13 | # 1. CREATE and DROP TRIGGER tests 14 | # trig-1.1: Error if table does not exist 15 | # trig-1.2: Error if trigger already exists 16 | # trig-1.3: Created triggers are deleted if the transaction is rolled back 17 | # trig-1.4: DROP TRIGGER removes trigger 18 | # trig-1.5: Dropped triggers are restored if the transaction is rolled back 19 | # trig-1.6: Error if dropped trigger doesn't exist 20 | # trig-1.7: Dropping the table automatically drops all triggers 21 | # trig-1.8: A trigger created on a TEMP table is not inserted into sqlite_master 22 | # trig-1.9: Ensure that we cannot create a trigger on sqlite_master 23 | # trig-1.10: 24 | # trig-1.11: 25 | # trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables 26 | # trig-1.13: Ensure that AFTER triggers cannot be created on views 27 | # trig-1.14: Ensure that BEFORE triggers cannot be created on views 28 | # 29 | 30 | set testdir [file dirname $argv0] 31 | source $testdir/tester.tcl 32 | 33 | do_test trig_cd-1.1 { 34 | catchsql { 35 | CREATE TRIGGER trig UPDATE ON no_such_table BEGIN 36 | SELECT * from sqlite_master; 37 | END; 38 | } 39 | } {1 {no such table: no_such_table}} 40 | 41 | execsql { 42 | CREATE TABLE t1(a); 43 | } 44 | execsql { 45 | CREATE TRIGGER tr1 INSERT ON t1 BEGIN 46 | INSERT INTO t1 values(1); 47 | END; 48 | } 49 | do_test trig_cd-1.2 { 50 | catchsql { 51 | CREATE TRIGGER tr1 DELETE ON t1 BEGIN 52 | SELECT * FROM sqlite_master; 53 | END 54 | } 55 | } {1 {trigger tr1 already exists}} 56 | 57 | do_test trig_cd-1.3 { 58 | catchsql { 59 | BEGIN; 60 | CREATE TRIGGER tr2 INSERT ON t1 BEGIN 61 | SELECT * from sqlite_master; END; 62 | ROLLBACK; 63 | CREATE TRIGGER tr2 INSERT ON t1 BEGIN 64 | SELECT * from sqlite_master; END; 65 | } 66 | } {0 {}} 67 | 68 | do_test trig_cd-1.4 { 69 | catchsql { 70 | DROP TRIGGER tr1; 71 | CREATE TRIGGER tr1 DELETE ON t1 BEGIN 72 | SELECT * FROM sqlite_master; 73 | END 74 | } 75 | } {0 {}} 76 | 77 | do_test trig_cd-1.5 { 78 | execsql { 79 | BEGIN; 80 | DROP TRIGGER tr2; 81 | ROLLBACK; 82 | DROP TRIGGER tr2; 83 | } 84 | } {} 85 | 86 | do_test trig_cd-1.6 { 87 | catchsql { 88 | DROP TRIGGER biggles; 89 | } 90 | } {1 {no such trigger: biggles}} 91 | 92 | do_test trig_cd-1.7 { 93 | catchsql { 94 | DROP TABLE t1; 95 | DROP TRIGGER tr1; 96 | } 97 | } {1 {no such trigger: tr1}} 98 | 99 | execsql { 100 | CREATE TEMP TABLE temp_table(a); 101 | } 102 | do_test trig_cd-1.8 { 103 | execsql { 104 | CREATE TRIGGER temp_trig UPDATE ON temp_table BEGIN 105 | SELECT * from sqlite_master; 106 | END; 107 | SELECT count(*) FROM sqlite_master WHERE name = 'temp_trig'; 108 | } 109 | } {0} 110 | 111 | do_test trig_cd-1.9 { 112 | catchsql { 113 | CREATE TRIGGER tr1 AFTER UPDATE ON sqlite_master BEGIN 114 | SELECT * FROM sqlite_master; 115 | END; 116 | } 117 | } {1 {cannot create trigger on system table: sqlite_master}} 118 | 119 | # Check to make sure that a DELETE statement within the body of 120 | # a trigger does not mess up the DELETE that caused the trigger to 121 | # run in the first place. 122 | # 123 | do_test trig_cd-1.10 { 124 | execsql { 125 | create table t1(a,b); 126 | insert into t1 values(1,'a'); 127 | insert into t1 values(2,'b'); 128 | insert into t1 values(3,'c'); 129 | insert into t1 values(4,'d'); 130 | create trigger r1 after delete on t1 for each row begin 131 | delete from t1 WHERE a=old.a+2; 132 | end; 133 | delete from t1 where a in (1,3); 134 | select * from t1; 135 | drop table t1; 136 | } 137 | } {2 b 4 d} 138 | do_test trig_cd-1.11 { 139 | execsql { 140 | create table t1(a,b); 141 | insert into t1 values(1,'a'); 142 | insert into t1 values(2,'b'); 143 | insert into t1 values(3,'c'); 144 | insert into t1 values(4,'d'); 145 | create trigger r1 after update on t1 for each row begin 146 | delete from t1 WHERE a=old.a+2; 147 | end; 148 | update t1 set b='x-' || b where a in (1,3); 149 | select * from t1; 150 | drop table t1; 151 | } 152 | } {1 x-a 2 b 4 d} 153 | 154 | # Ensure that we cannot create INSTEAD OF triggers on tables 155 | do_test trig_cd-1.12 { 156 | catchsql { 157 | create table t1(a,b); 158 | create trigger t1t instead of update on t1 for each row begin 159 | delete from t1 WHERE a=old.a+2; 160 | end; 161 | } 162 | } {1 {cannot create INSTEAD OF trigger on table: t1}} 163 | # Ensure that we cannot create BEFORE triggers on views 164 | do_test trig_cd-1.13 { 165 | catchsql { 166 | create view v1 as select * from t1; 167 | create trigger v1t before update on v1 for each row begin 168 | delete from t1 WHERE a=old.a+2; 169 | end; 170 | } 171 | } {1 {cannot create BEFORE trigger on view: v1}} 172 | # Ensure that we cannot create AFTER triggers on views 173 | do_test trig_cd-1.14 { 174 | catchsql { 175 | create table t1(a,b); 176 | create view v1 as select * from t1; 177 | create trigger v1t AFTER update on v1 for each row begin 178 | delete from t1 WHERE a=old.a+2; 179 | end; 180 | } 181 | } {1 {cannot create AFTER trigger on view: v1}} 182 | 183 | finish_test 184 | -------------------------------------------------------------------------------- /test/trigger3.test: -------------------------------------------------------------------------------- 1 | # The author disclaims copyright to this source code. In place of 2 | # a legal notice, here is a blessing: 3 | # 4 | # May you do good and not evil. 5 | # May you find forgiveness for yourself and forgive others. 6 | # May you share freely, never taking more than you give. 7 | # 8 | #*********************************************************************** 9 | # 10 | # This file tests the RAISE() function. 11 | # 12 | 13 | set testdir [file dirname $argv0] 14 | source $testdir/tester.tcl 15 | 16 | # Test that we can cause ROLLBACK, FAIL and ABORT correctly 17 | # catchsql { DROP TABLE tbl; } 18 | catchsql { CREATE TABLE tbl (a, b, c) } 19 | 20 | execsql { 21 | CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE 22 | WHEN (new.a = 4) THEN RAISE(IGNORE) END; 23 | END; 24 | 25 | CREATE TRIGGER after_tbl_insert AFTER INSERT ON tbl BEGIN SELECT CASE 26 | WHEN (new.a = 1) THEN RAISE(ABORT, 'Trigger abort') 27 | WHEN (new.a = 2) THEN RAISE(FAIL, 'Trigger fail') 28 | WHEN (new.a = 3) THEN RAISE(ROLLBACK, 'Trigger rollback') END; 29 | END; 30 | } 31 | # ABORT 32 | do_test trig-raise-1.1 { 33 | catchsql { 34 | BEGIN; 35 | INSERT INTO tbl VALUES (5, 5, 6); 36 | INSERT INTO tbl VALUES (1, 5, 6); 37 | } 38 | } {1 {Trigger abort}} 39 | 40 | do_test trig-raise-1.2 { 41 | execsql { 42 | SELECT * FROM tbl; 43 | ROLLBACK; 44 | } 45 | } {5 5 6} 46 | 47 | # FAIL 48 | do_test trig-raise-2.1 { 49 | catchsql { 50 | BEGIN; 51 | INSERT INTO tbl VALUES (5, 5, 6); 52 | INSERT INTO tbl VALUES (2, 5, 6); 53 | } 54 | } {1 {Trigger fail}} 55 | do_test trig-raise-2.2 { 56 | execsql { 57 | SELECT * FROM tbl; 58 | ROLLBACK; 59 | } 60 | } {5 5 6 2 5 6} 61 | # ROLLBACK 62 | do_test trig-raise-3.1 { 63 | catchsql { 64 | BEGIN; 65 | INSERT INTO tbl VALUES (5, 5, 6); 66 | INSERT INTO tbl VALUES (3, 5, 6); 67 | } 68 | } {1 {Trigger rollback}} 69 | do_test trig-raise-3.2 { 70 | execsql { 71 | SELECT * FROM tbl; 72 | ROLLBACK; 73 | } 74 | } {} 75 | # IGNORE 76 | do_test trig-raise-4.1 { 77 | catchsql { 78 | BEGIN; 79 | INSERT INTO tbl VALUES (5, 5, 6); 80 | INSERT INTO tbl VALUES (4, 5, 6); 81 | } 82 | } {0 {}} 83 | do_test trig-raise-4.2 { 84 | execsql { 85 | SELECT * FROM tbl; 86 | ROLLBACK; 87 | } 88 | } {5 5 6} 89 | 90 | # Check that we can also do RAISE(IGNORE) for UPDATE and DELETE 91 | execsql {DROP TABLE tbl;} 92 | execsql {CREATE TABLE tbl (a, b, c);} 93 | execsql {INSERT INTO tbl VALUES(1, 2, 3);} 94 | execsql {INSERT INTO tbl VALUES(4, 5, 6);} 95 | execsql { 96 | CREATE TRIGGER before_tbl_update BEFORE UPDATE ON tbl BEGIN 97 | SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END; 98 | END; 99 | 100 | CREATE TRIGGER before_tbl_delete BEFORE DELETE ON tbl BEGIN 101 | SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END; 102 | END; 103 | } 104 | do_test trig-raise-5.1 { 105 | execsql { 106 | UPDATE tbl SET c = 10; 107 | SELECT * FROM tbl; 108 | } 109 | } {1 2 3 4 5 10} 110 | do_test trig-raise-5.2 { 111 | execsql { 112 | DELETE FROM tbl; 113 | SELECT * FROM tbl; 114 | } 115 | } {1 2 3} 116 | 117 | # Check that RAISE(IGNORE) works correctly for nested triggers: 118 | execsql {CREATE TABLE tbl2(a, b, c)} 119 | execsql { 120 | CREATE TRIGGER after_tbl2_insert AFTER INSERT ON tbl2 BEGIN 121 | UPDATE tbl SET c = 10; 122 | INSERT INTO tbl2 VALUES (new.a, new.b, new.c); 123 | END; 124 | } 125 | do_test trig-raise-6 { 126 | execsql { 127 | INSERT INTO tbl2 VALUES (1, 2, 3); 128 | SELECT * FROM tbl2; 129 | SELECT * FROM tbl; 130 | } 131 | } {1 2 3 1 2 3 1 2 3} 132 | 133 | # Check that things also work for view-triggers 134 | execsql {CREATE VIEW tbl_view AS SELECT * FROM tbl} 135 | execsql { 136 | CREATE TRIGGER tbl_view_insert INSTEAD OF INSERT ON tbl_view BEGIN 137 | SELECT CASE WHEN (new.a = 1) THEN RAISE(ROLLBACK, 'View rollback') 138 | WHEN (new.a = 2) THEN RAISE(IGNORE) 139 | WHEN (new.a = 3) THEN RAISE(ABORT, 'View abort') END; 140 | END; 141 | } 142 | 143 | do_test trig-raise-7.1 { 144 | catchsql { 145 | INSERT INTO tbl_view VALUES(1, 2, 3); 146 | } 147 | } {1 {View rollback}} 148 | do_test trig-raise-7.2 { 149 | catchsql { 150 | INSERT INTO tbl_view VALUES(2, 2, 3); 151 | } 152 | } {0 {}} 153 | do_test trig-raise-7.3 { 154 | catchsql { 155 | INSERT INTO tbl_view VALUES(3, 2, 3); 156 | } 157 | } {1 {View abort}} 158 | 159 | catchsql { DROP TABLE tbl; } 160 | catchsql { DROP TABLE tbl2; } 161 | catchsql { DROP VIEW tbl_view; } 162 | 163 | 164 | -------------------------------------------------------------------------------- /test/unique.test: -------------------------------------------------------------------------------- 1 | # 2001 September 27 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the CREATE UNIQUE INDEX statement, 13 | # and primary keys, and the UNIQUE constraint on table columns 14 | # 15 | # $Id: unique.test,v 1.4 2002/05/26 20:54:35 drh Exp $ 16 | 17 | set testdir [file dirname $argv0] 18 | source $testdir/tester.tcl 19 | 20 | # Try to create a table with two primary keys. 21 | # (This is allowed in SQLite even that it is not valid SQL) 22 | # 23 | do_test unique-1.1 { 24 | catchsql { 25 | CREATE TABLE t1( 26 | a int PRIMARY KEY, 27 | b int PRIMARY KEY, 28 | c text 29 | ); 30 | } 31 | } {1 {table "t1" has more than one primary key}} 32 | do_test unique-1.1b { 33 | catchsql { 34 | CREATE TABLE t1( 35 | a int PRIMARY KEY, 36 | b int UNIQUE, 37 | c text 38 | ); 39 | } 40 | } {0 {}} 41 | do_test unique-1.2 { 42 | catchsql { 43 | INSERT INTO t1(a,b,c) VALUES(1,2,3) 44 | } 45 | } {0 {}} 46 | do_test unique-1.3 { 47 | catchsql { 48 | INSERT INTO t1(a,b,c) VALUES(1,3,4) 49 | } 50 | } {1 {constraint failed}} 51 | do_test unique-1.4 { 52 | execsql { 53 | SELECT * FROM t1 ORDER BY a; 54 | } 55 | } {1 2 3} 56 | do_test unique-1.5 { 57 | catchsql { 58 | INSERT INTO t1(a,b,c) VALUES(3,2,4) 59 | } 60 | } {1 {constraint failed}} 61 | do_test unique-1.6 { 62 | execsql { 63 | SELECT * FROM t1 ORDER BY a; 64 | } 65 | } {1 2 3} 66 | do_test unique-1.7 { 67 | catchsql { 68 | INSERT INTO t1(a,b,c) VALUES(3,4,5) 69 | } 70 | } {0 {}} 71 | do_test unique-1.8 { 72 | execsql { 73 | SELECT * FROM t1 ORDER BY a; 74 | } 75 | } {1 2 3 3 4 5} 76 | 77 | do_test unique-2.0 { 78 | execsql { 79 | DROP TABLE t1; 80 | CREATE TABLE t2(a int, b int); 81 | INSERT INTO t2(a,b) VALUES(1,2); 82 | INSERT INTO t2(a,b) VALUES(3,4); 83 | SELECT * FROM t2 ORDER BY a; 84 | } 85 | } {1 2 3 4} 86 | do_test unique-2.1 { 87 | catchsql { 88 | CREATE UNIQUE INDEX i2 ON t2(a) 89 | } 90 | } {0 {}} 91 | do_test unique-2.2 { 92 | catchsql { 93 | SELECT * FROM t2 ORDER BY a 94 | } 95 | } {0 {1 2 3 4}} 96 | do_test unique-2.3 { 97 | catchsql { 98 | INSERT INTO t2 VALUES(1,5); 99 | } 100 | } {1 {constraint failed}} 101 | do_test unique-2.4 { 102 | catchsql { 103 | SELECT * FROM t2 ORDER BY a 104 | } 105 | } {0 {1 2 3 4}} 106 | do_test unique-2.5 { 107 | catchsql { 108 | DROP INDEX i2; 109 | SELECT * FROM t2 ORDER BY a; 110 | } 111 | } {0 {1 2 3 4}} 112 | do_test unique-2.6 { 113 | catchsql { 114 | INSERT INTO t2 VALUES(1,5) 115 | } 116 | } {0 {}} 117 | do_test unique-2.7 { 118 | catchsql { 119 | SELECT * FROM t2 ORDER BY a, b; 120 | } 121 | } {0 {1 2 1 5 3 4}} 122 | do_test unique-2.8 { 123 | catchsql { 124 | CREATE UNIQUE INDEX i2 ON t2(a); 125 | } 126 | } {1 {constraint failed}} 127 | do_test unique-2.9 { 128 | catchsql { 129 | CREATE INDEX i2 ON t2(a); 130 | } 131 | } {0 {}} 132 | 133 | # Test the UNIQUE keyword as used on two or more fields. 134 | # 135 | do_test unique-3.1 { 136 | catchsql { 137 | CREATE TABLE t3( 138 | a int, 139 | b int, 140 | c int, 141 | d int, 142 | unique(a,c,d) 143 | ); 144 | } 145 | } {0 {}} 146 | do_test unique-3.2 { 147 | catchsql { 148 | INSERT INTO t3(a,b,c,d) VALUES(1,2,3,4); 149 | SELECT * FROM t3 ORDER BY a,b,c,d; 150 | } 151 | } {0 {1 2 3 4}} 152 | do_test unique-3.3 { 153 | catchsql { 154 | INSERT INTO t3(a,b,c,d) VALUES(1,2,3,5); 155 | SELECT * FROM t3 ORDER BY a,b,c,d; 156 | } 157 | } {0 {1 2 3 4 1 2 3 5}} 158 | do_test unique-3.4 { 159 | catchsql { 160 | INSERT INTO t3(a,b,c,d) VALUES(1,4,3,5); 161 | SELECT * FROM t3 ORDER BY a,b,c,d; 162 | } 163 | } {1 {constraint failed}} 164 | 165 | # Make sure NULLs are distinct as far as the UNIQUE tests are 166 | # concerned. 167 | # 168 | do_test unique-4.1 { 169 | execsql { 170 | CREATE TABLE t4(a UNIQUE, b, c, UNIQUE(b,c)); 171 | INSERT INTO t4 VALUES(1,2,3); 172 | INSERT INTO t4 VALUES(NULL, 2, NULL); 173 | SELECT * FROM t4; 174 | } 175 | } {1 2 3 {} 2 {}} 176 | do_test unique-4.2 { 177 | catchsql { 178 | INSERT INTO t4 VALUES(NULL, 3, 4); 179 | } 180 | } {0 {}} 181 | do_test unique-4.3 { 182 | execsql { 183 | SELECT * FROM t4 184 | } 185 | } {1 2 3 {} 2 {} {} 3 4} 186 | do_test unique-4.4 { 187 | catchsql { 188 | INSERT INTO t4 VALUES(2, 2, NULL); 189 | } 190 | } {0 {}} 191 | do_test unique-4.5 { 192 | execsql { 193 | SELECT * FROM t4 194 | } 195 | } {1 2 3 {} 2 {} {} 3 4 2 2 {}} 196 | 197 | 198 | finish_test 199 | -------------------------------------------------------------------------------- /test/vacuum.test: -------------------------------------------------------------------------------- 1 | # 2001 September 15 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing the VACUUM statement. 13 | # 14 | # $Id: vacuum.test,v 1.7 2002/03/03 02:49:52 drh Exp $ 15 | 16 | set testdir [file dirname $argv0] 17 | source $testdir/tester.tcl 18 | 19 | # The vacuum command no longer functions. There is 20 | # nothing to test. 21 | 22 | # finish_test 23 | -------------------------------------------------------------------------------- /test/view.test: -------------------------------------------------------------------------------- 1 | # 2002 February 26 2 | # 3 | # The author disclaims copyright to this source code. In place of 4 | # a legal notice, here is a blessing: 5 | # 6 | # May you do good and not evil. 7 | # May you find forgiveness for yourself and forgive others. 8 | # May you share freely, never taking more than you give. 9 | # 10 | #*********************************************************************** 11 | # This file implements regression tests for SQLite library. The 12 | # focus of this file is testing VIEW statements. 13 | # 14 | # $Id: view.test,v 1.5 2002/05/08 21:30:16 drh Exp $ 15 | set testdir [file dirname $argv0] 16 | source $testdir/tester.tcl 17 | 18 | do_test view-1.0 { 19 | execsql { 20 | CREATE TABLE t1(a,b,c); 21 | INSERT INTO t1 VALUES(1,2,3); 22 | INSERT INTO t1 VALUES(4,5,6); 23 | INSERT INTO t1 VALUES(7,8,9); 24 | SELECT * FROM t1; 25 | } 26 | } {1 2 3 4 5 6 7 8 9} 27 | 28 | do_test view-1.1 { 29 | execsql { 30 | BEGIN; 31 | CREATE VIEW v1 AS SELECT a,b FROM t1; 32 | SELECT * FROM v1 ORDER BY a; 33 | } 34 | } {1 2 4 5 7 8} 35 | do_test view-1.2 { 36 | catchsql { 37 | ROLLBACK; 38 | SELECT * FROM v1 ORDER BY a; 39 | } 40 | } {1 {no such table: v1}} 41 | do_test view-1.3 { 42 | execsql { 43 | CREATE VIEW v1 AS SELECT a,b FROM t1; 44 | SELECT * FROM v1 ORDER BY a; 45 | } 46 | } {1 2 4 5 7 8} 47 | do_test view-1.3.1 { 48 | db close 49 | sqlite db test.db 50 | execsql { 51 | SELECT * FROM v1 ORDER BY a; 52 | } 53 | } {1 2 4 5 7 8} 54 | do_test view-1.4 { 55 | catchsql { 56 | DROP VIEW v1; 57 | SELECT * FROM v1 ORDER BY a; 58 | } 59 | } {1 {no such table: v1}} 60 | do_test view-1.5 { 61 | execsql { 62 | CREATE VIEW v1 AS SELECT a,b FROM t1; 63 | SELECT * FROM v1 ORDER BY a; 64 | } 65 | } {1 2 4 5 7 8} 66 | do_test view-1.6 { 67 | catchsql { 68 | DROP TABLE t1; 69 | SELECT * FROM v1 ORDER BY a; 70 | } 71 | } {1 {no such table: t1}} 72 | do_test view-1.7 { 73 | execsql { 74 | CREATE TABLE t1(x,a,b,c); 75 | INSERT INTO t1 VALUES(1,2,3,4); 76 | INSERT INTO t1 VALUES(4,5,6,7); 77 | INSERT INTO t1 VALUES(7,8,9,10); 78 | SELECT * FROM v1 ORDER BY a; 79 | } 80 | } {2 3 5 6 8 9} 81 | do_test view-1.8 { 82 | db close 83 | sqlite db test.db 84 | execsql { 85 | SELECT * FROM v1 ORDER BY a; 86 | } 87 | } {2 3 5 6 8 9} 88 | 89 | do_test view-2.1 { 90 | execsql { 91 | CREATE VIEW v2 AS SELECT * FROM t1 WHERE a>5 92 | }; # No semicolon 93 | execsql2 { 94 | SELECT * FROM v2; 95 | } 96 | } {x 7 a 8 b 9 c 10} 97 | do_test view-2.2 { 98 | catchsql { 99 | INSERT INTO v2 VALUES(1,2,3,4); 100 | } 101 | } {1 {view v2 may not be modified}} 102 | do_test view-2.3 { 103 | catchsql { 104 | UPDATE v2 SET a=10 WHERE a=5; 105 | } 106 | } {1 {view v2 may not be modified}} 107 | do_test view-2.4 { 108 | catchsql { 109 | DELETE FROM v2; 110 | } 111 | } {1 {view v2 may not be modified}} 112 | do_test view-2.5 { 113 | execsql { 114 | INSERT INTO t1 VALUES(11,12,13,14); 115 | SELECT * FROM v2 ORDER BY x; 116 | } 117 | } {7 8 9 10 11 12 13 14} 118 | do_test view-2.6 { 119 | execsql { 120 | SELECT x FROM v2 WHERE a>10 121 | } 122 | } {11} 123 | 124 | # Test that column name of views are generated correctly. 125 | # 126 | do_test view-3.1 { 127 | execsql2 { 128 | SELECT * FROM v1 LIMIT 1 129 | } 130 | } {a 2 b 3} 131 | do_test view-3.2 { 132 | execsql2 { 133 | SELECT * FROM v2 LIMIT 1 134 | } 135 | } {x 7 a 8 b 9 c 10} 136 | do_test view-3.3 { 137 | execsql2 { 138 | DROP VIEW v1; 139 | CREATE VIEW v1 AS SELECT a AS 'xyz', b+c AS 'pqr', c-b FROM t1; 140 | SELECT * FROM v1 LIMIT 1 141 | } 142 | } {xyz 2 pqr 7 c-b 1} 143 | do_test view-3.4 { 144 | execsql2 { 145 | CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY b; 146 | SELECT * FROM v3 LIMIT 4; 147 | } 148 | } {b 2 b 3 b 5 b 6} 149 | do_test view-3.5 { 150 | execsql2 { 151 | CREATE VIEW v4 AS 152 | SELECT a, b FROM t1 153 | UNION 154 | SELECT b AS 'x', a AS 'y' FROM t1 155 | ORDER BY x, y; 156 | SELECT y FROM v4 ORDER BY y LIMIT 4; 157 | } 158 | } {y 2 y 3 y 5 y 6} 159 | 160 | 161 | finish_test 162 | -------------------------------------------------------------------------------- /tool/memleak.awk: -------------------------------------------------------------------------------- 1 | # 2 | # This script looks for memory leaks by analyzing the output of "sqlite" 3 | # when compiled with the MEMORY_DEBUG=2 option. 4 | # 5 | /^malloc / { 6 | mem[$5] = $0 7 | } 8 | /^realloc / { 9 | mem[$7] = ""; 10 | mem[$9] = $0 11 | } 12 | /^free / { 13 | mem[$5] = ""; 14 | str[$5] = "" 15 | } 16 | /^string at / { 17 | addr = $3 18 | sub("string at " addr " is ","") 19 | str[addr] = $0 20 | } 21 | END { 22 | for(addr in mem){ 23 | if( mem[addr]=="" ) continue 24 | print mem[addr], str[addr] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tool/opNames.awk: -------------------------------------------------------------------------------- 1 | # Read the sqliteVdbe.h file and generate a table of opcode names. 2 | # 3 | BEGIN { 4 | printf "static char *zOpName[] = { 0,\n" 5 | n = 0 6 | } 7 | /^#define OP_MAX/ { 8 | next 9 | } 10 | /^#define OP_/ { 11 | name = "\"" substr($2,4) "\"," 12 | if( n<3 ){ 13 | printf " %-19s", name 14 | n++ 15 | } else { 16 | printf " %s\n", name 17 | n = 0 18 | } 19 | } 20 | END { 21 | if( n ){ printf "\n" } 22 | printf "};\n" 23 | } 24 | -------------------------------------------------------------------------------- /tool/opcodeDoc.awk: -------------------------------------------------------------------------------- 1 | # 2 | # Extract opcode documentation for sqliteVdbe.c and generate HTML 3 | # 4 | BEGIN { 5 | print "" 6 | print "

SQLite Virtual Database Engine Opcodes

" 7 | print "" 8 | } 9 | / Opcode: /,/\*\// { 10 | if( $2=="Opcode:" ){ 11 | printf "\n\n" 14 | }else if( NF>1 ){ 15 | sub(/^ *\*\* /,"") 16 | gsub(/" 23 | } 24 | -------------------------------------------------------------------------------- /tool/renumberOps.awk: -------------------------------------------------------------------------------- 1 | # Run this script on sqliteVdbe.h to renumber the opcodes sequentially. 2 | # 3 | BEGIN { cnt = 1 } 4 | /^#define OP_MAX/ { 5 | printf "#define %-20s %3d\n",$2, cnt-1 6 | next 7 | } 8 | /^#define OP_/ { 9 | printf "#define %-20s %3d\n",$2, cnt++ 10 | next 11 | } 12 | { print } 13 | -------------------------------------------------------------------------------- /tool/report1.txt: -------------------------------------------------------------------------------- 1 | The SQL database used for ACD contains 113 tables and indices implemented 2 | in GDBM. The following are statistics on the sizes of keys and data 3 | within these tables and indices. 4 | 5 | Entries: 962080 6 | Size: 45573853 7 | Avg Size: 48 8 | Key Size: 11045299 9 | Avg Key Size: 12 10 | Max Key Size: 99 11 | 12 | 13 | Size of key Cummulative 14 | and data Instances Percentage 15 | ------------ ---------- ----------- 16 | 0..8 266 0% 17 | 9..12 5485 0% 18 | 13..16 73633 8% 19 | 17..24 180918 27% 20 | 25..32 209823 48% 21 | 33..40 148995 64% 22 | 41..48 76304 72% 23 | 49..56 14346 73% 24 | 57..64 15725 75% 25 | 65..80 44916 80% 26 | 81..96 127815 93% 27 | 97..112 34769 96% 28 | 113..128 13314 98% 29 | 129..144 8098 99% 30 | 145..160 3355 99% 31 | 161..176 1159 99% 32 | 177..192 629 99% 33 | 193..208 221 99% 34 | 209..224 210 99% 35 | 225..240 129 99% 36 | 241..256 57 99% 37 | 257..288 496 99% 38 | 289..320 60 99% 39 | 321..352 37 99% 40 | 353..384 46 99% 41 | 385..416 22 99% 42 | 417..448 24 99% 43 | 449..480 26 99% 44 | 481..512 27 99% 45 | 513..1024 471 99% 46 | 1025..2048 389 99% 47 | 2049..4096 182 99% 48 | 4097..8192 74 99% 49 | 8193..16384 34 99% 50 | 16385..32768 17 99% 51 | 32769..65536 5 99% 52 | 65537..131073 3 100% 53 | 54 | 55 | This information is gathered to help design the new built-in 56 | backend for sqlite 2.0. Note in particular that 99% of all 57 | database entries have a combined key and data size of less than 58 | 144 bytes. So if a leaf node in the new database is able to 59 | store 144 bytes of combined key and data, only 1% of the leaves 60 | will require overflow pages. Furthermore, note that no key 61 | is larger than 99 bytes, so if the key will never be on an 62 | overflow page. 63 | 64 | The average combined size of key+data is 48. Add in 16 bytes of 65 | overhead for a total of 64. That means that a 1K page will 66 | store (on average) about 16 entries. 67 | -------------------------------------------------------------------------------- /tool/speedtest2.tcl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/tclsh 2 | # 3 | # Run this script using TCLSH to do a speed comparison between 4 | # various versions of SQLite and PostgreSQL and MySQL 5 | # 6 | 7 | # Run a test 8 | # 9 | set cnt 1 10 | proc runtest {title} { 11 | global cnt 12 | set sqlfile test$cnt.sql 13 | puts "

Test $cnt: $title

" 14 | incr cnt 15 | set fd [open $sqlfile r] 16 | set sql [string trim [read $fd [file size $sqlfile]]] 17 | close $fd 18 | set sx [split $sql \n] 19 | set n [llength $sx] 20 | if {$n>8} { 21 | set sql {} 22 | for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]
\n} 23 | append sql "... [expr {$n-6}] lines omitted
\n" 24 | for {set i [expr {$n-3}]} {$i<$n} {incr i} { 25 | append sql [lindex $sx $i]
\n 26 | } 27 | } else { 28 | regsub -all \n [string trim $sql]
sql 29 | } 30 | puts "
" 31 | puts "$sql" 32 | puts "
%s %s %s %s\n", $3, $4, $5, $6 12 | }else if( $1=="*/" ){ 13 | printf "
" 33 | set format {} 34 | set delay 1000 35 | exec sync; after $delay; 36 | set t [time "exec psql drh <$sqlfile" 1] 37 | set t [expr {[lindex $t 0]/1000000.0}] 38 | puts [format $format PostgreSQL: $t] 39 | exec sync; after $delay; 40 | set t [time "exec mysql -f drh <$sqlfile" 1] 41 | set t [expr {[lindex $t 0]/1000000.0}] 42 | puts [format $format MySQL: $t] 43 | # set t [time "exec ./sqlite232 s232.db <$sqlfile" 1] 44 | # set t [expr {[lindex $t 0]/1000000.0}] 45 | # puts [format $format {SQLite 2.3.2:} $t] 46 | # set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1] 47 | # set t [expr {[lindex $t 0]/1000000.0}] 48 | # puts [format $format {SQLite 2.4 (cache=100):} $t] 49 | exec sync; after $delay; 50 | set t [time "exec ./sqlite240 s2k.db <$sqlfile" 1] 51 | set t [expr {[lindex $t 0]/1000000.0}] 52 | puts [format $format {SQLite 2.4:} $t] 53 | exec sync; after $delay; 54 | set t [time "exec ./sqlite240 sns.db <$sqlfile" 1] 55 | set t [expr {[lindex $t 0]/1000000.0}] 56 | puts [format $format {SQLite 2.4 (nosync):} $t] 57 | # set t [time "exec ./sqlite-t1 st1.db <$sqlfile" 1] 58 | # set t [expr {[lindex $t 0]/1000000.0}] 59 | # puts [format $format {SQLite 2.4 (test):} $t] 60 | puts "
%s   %.3f
" 61 | } 62 | 63 | # Initialize the environment 64 | # 65 | expr srand(1) 66 | catch {exec /bin/sh -c {rm -f s*.db}} 67 | set fd [open clear.sql w] 68 | puts $fd { 69 | drop table t1; 70 | drop table t2; 71 | } 72 | close $fd 73 | catch {exec psql drh =1000} { 96 | set txt "[number_name [expr {$n/1000}]] thousand" 97 | set n [expr {$n%1000}] 98 | } else { 99 | set txt {} 100 | } 101 | if {$n>=100} { 102 | append txt " [lindex $::ones [expr {$n/100}]] hundred" 103 | set n [expr {$n%100}] 104 | } 105 | if {$n>=20} { 106 | append txt " [lindex $::tens [expr {$n/10}]]" 107 | set n [expr {$n%10}] 108 | } 109 | if {$n>0} { 110 | append txt " [lindex $::ones $n]" 111 | } 112 | set txt [string trim $txt] 113 | if {$txt==""} {set txt zero} 114 | return $txt 115 | } 116 | 117 | 118 | set fd [open test$cnt.sql w] 119 | puts $fd "BEGIN;" 120 | puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));" 121 | for {set i 1} {$i<=25000} {incr i} { 122 | set r [expr {int(rand()*500000)}] 123 | puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" 124 | } 125 | puts $fd "COMMIT;" 126 | close $fd 127 | runtest {25000 INSERTs in a transaction} 128 | 129 | 130 | set fd [open test$cnt.sql w] 131 | puts $fd "DELETE FROM t1;" 132 | close $fd 133 | runtest {DELETE everything} 134 | 135 | 136 | set fd [open test$cnt.sql w] 137 | puts $fd "BEGIN;" 138 | for {set i 1} {$i<=25000} {incr i} { 139 | set r [expr {int(rand()*500000)}] 140 | puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" 141 | } 142 | puts $fd "COMMIT;" 143 | close $fd 144 | runtest {25000 INSERTs in a transaction} 145 | 146 | 147 | set fd [open test$cnt.sql w] 148 | puts $fd "DELETE FROM t1;" 149 | close $fd 150 | runtest {DELETE everything} 151 | 152 | 153 | set fd [open test$cnt.sql w] 154 | puts $fd "BEGIN;" 155 | for {set i 1} {$i<=25000} {incr i} { 156 | set r [expr {int(rand()*500000)}] 157 | puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" 158 | } 159 | puts $fd "COMMIT;" 160 | close $fd 161 | runtest {25000 INSERTs in a transaction} 162 | 163 | 164 | set fd [open test$cnt.sql w] 165 | puts $fd "DELETE FROM t1;" 166 | close $fd 167 | runtest {DELETE everything} 168 | 169 | 170 | set fd [open test$cnt.sql w] 171 | puts $fd "BEGIN;" 172 | for {set i 1} {$i<=25000} {incr i} { 173 | set r [expr {int(rand()*500000)}] 174 | puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" 175 | } 176 | puts $fd "COMMIT;" 177 | close $fd 178 | runtest {25000 INSERTs in a transaction} 179 | 180 | 181 | set fd [open test$cnt.sql w] 182 | puts $fd "DELETE FROM t1;" 183 | close $fd 184 | runtest {DELETE everything} 185 | 186 | 187 | set fd [open test$cnt.sql w] 188 | puts $fd "BEGIN;" 189 | for {set i 1} {$i<=25000} {incr i} { 190 | set r [expr {int(rand()*500000)}] 191 | puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" 192 | } 193 | puts $fd "COMMIT;" 194 | close $fd 195 | runtest {25000 INSERTs in a transaction} 196 | 197 | 198 | set fd [open test$cnt.sql w] 199 | puts $fd "DELETE FROM t1;" 200 | close $fd 201 | runtest {DELETE everything} 202 | 203 | 204 | set fd [open test$cnt.sql w] 205 | puts $fd {DROP TABLE t1;} 206 | close $fd 207 | runtest {DROP TABLE} 208 | -------------------------------------------------------------------------------- /www/arch.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 2 | Portrait 3 | Center 4 | Inches 5 | Letter 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 11 | 1 1 3.00 75.00 135.00 12 | 3675 8550 3675 9075 13 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 14 | 1 1 3.00 75.00 135.00 15 | 3675 7200 3675 7725 16 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 17 | 1 1 3.00 75.00 135.00 18 | 3675 5775 3675 6300 19 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 20 | 1 1 3.00 75.00 135.00 21 | 3675 3975 3675 4500 22 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 23 | 1 1 3.00 75.00 135.00 24 | 3675 2625 3675 3150 25 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 26 | 1 1 3.00 75.00 135.00 27 | 3675 1275 3675 1800 28 | 2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 29 | 1 1 3.00 75.00 135.00 30 | 3675 9900 3675 10425 31 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 32 | 2550 10425 4875 10425 4875 11250 2550 11250 2550 10425 33 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 34 | 2550 9075 4875 9075 4875 9900 2550 9900 2550 9075 35 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 36 | 2550 7725 4875 7725 4875 8550 2550 8550 2550 7725 37 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 38 | 2550 6300 4875 6300 4875 7200 2550 7200 2550 6300 39 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 40 | 2550 4500 4875 4500 4875 5775 2550 5775 2550 4500 41 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 42 | 2550 3150 4875 3150 4875 3975 2550 3975 2550 3150 43 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 44 | 2550 1800 4875 1800 4875 2625 2550 2625 2550 1800 45 | 2 2 0 1 0 11 100 0 20 0.000 0 0 7 0 0 5 46 | 2550 450 4875 450 4875 1275 2550 1275 2550 450 47 | 4 1 0 100 0 0 20 0.0000 4 195 1020 3675 750 Interface\001 48 | 4 1 0 100 0 0 14 0.0000 4 195 2040 3675 1125 main.c table.c tclsqlite.c\001 49 | 4 1 0 100 0 0 20 0.0000 4 195 1920 3675 6675 Virtual Machine\001 50 | 4 1 0 100 0 0 14 0.0000 4 150 570 3675 7050 vdbe.c\001 51 | 4 1 0 100 0 0 20 0.0000 4 195 1830 3675 4875 Code Generator\001 52 | 4 1 0 100 0 0 14 0.0000 4 195 1860 3675 5175 build.c delete.c expr.c\001 53 | 4 1 0 100 0 0 14 0.0000 4 195 2115 3675 5400 insert.c select.c update.c\001 54 | 4 1 0 100 0 0 14 0.0000 4 150 705 3675 5625 where.c\001 55 | 4 1 0 100 0 0 20 0.0000 4 195 735 3675 3450 Parser\001 56 | 4 1 0 100 0 0 20 0.0000 4 195 1140 3675 2100 Tokenizer\001 57 | 4 1 0 100 0 0 14 0.0000 4 150 870 3675 2475 tokenize.c\001 58 | 4 1 0 100 0 0 20 0.0000 4 255 1350 3675 9375 Page Cache\001 59 | 4 1 0 100 0 0 14 0.0000 4 150 630 3675 3825 parse.y\001 60 | 4 1 0 100 0 0 14 0.0000 4 150 600 3675 8400 btree.c\001 61 | 4 1 0 100 0 0 14 0.0000 4 150 645 3675 9750 pager.c\001 62 | 4 1 0 100 0 0 20 0.0000 4 195 1620 3675 8025 B-tree Driver\001 63 | 4 1 0 100 0 0 14 0.0000 4 105 345 3675 11100 os.c\001 64 | 4 1 0 100 0 0 20 0.0000 4 195 1470 3675 10725 OS Interface\001 65 | -------------------------------------------------------------------------------- /www/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davideuler/SQLite-2.5.0-for-code-reading/95c98088ffd4fff76aea62a4f79b7d08bf9a3b7d/www/arch.png -------------------------------------------------------------------------------- /www/conflict.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Run this Tcl script to generate the constraint.html file. 3 | # 4 | set rcsid {$Id: conflict.tcl,v 1.2 2002/02/03 00:56:11 drh Exp $ } 5 | 6 | puts { 7 | 8 | Constraint Conflict Resolution in SQLite 9 | 10 | 11 |

12 | Constraint Conflict Resolution in SQLite 13 |

} 14 | puts "

15 | (This page was last modified on [lrange $rcsid 3 4] UTC) 16 |

" 17 | 18 | puts { 19 |

Introduction

20 | 21 |

22 | In most SQL databases, if you have a UNIQUE constraint on 23 | a table and you try to do an UPDATE or INSERT that violates 24 | that constraint, the database will aborts the operation in 25 | progress, back out any prior changes associated with that 26 | one UPDATE or INSERT command, and return an error. 27 | This is the default behavior of SQLite. 28 | Beginning with version 2.3.0, though, SQLite allows you to 29 | define alternative ways for dealing with constraint violations. 30 | This article describes those alternatives and how to use them. 31 |

32 | 33 |

Conflict Resolution Algorithms

34 | 35 |

36 | SQLite defines five constraint conflict resolution algorithms 37 | as follows: 38 |

39 | 40 |
41 |
ROLLBACK
42 |

When a constraint violation occurs, an immediate ROLLBACK 43 | occurs, thus ending the current transaction, and the command aborts 44 | with a return code of SQLITE_CONSTRAINT. If no transaction is 45 | active (other than the implied transaction that is created on every 46 | command) then this algorithm works the same as ABORT.

47 | 48 |
ABORT
49 |

When a constraint violation occurs, the command backs out 50 | any prior changes it might have made and aborts with a return code 51 | of SQLITE_CONSTRAINT. But no ROLLBACK is executed so changes 52 | from prior commands within the same transaction 53 | are preserved. This is the default behavior for SQLite.

54 | 55 |
FAIL
56 |

When a constraint violation occurs, the command aborts with a 57 | return code SQLITE_CONSTRAINT. But any changes to the database that 58 | the command made prior to encountering the constraint violation 59 | are preserved and are not backed out. For example, if an UPDATE 60 | statement encountered a constraint violation on the 100th row that 61 | it attempts to update, then the first 99 row changes are preserved 62 | by change to rows 100 and beyond never occur.

63 | 64 |
IGNORE
65 |

When a constraint violation occurs, the one row that contains 66 | the constraint violation is not inserted or changed. But the command 67 | continues executing normally. Other rows before and after the row that 68 | contained the constraint violation continue to be inserted or updated 69 | normally. No error is returned.

70 | 71 |
REPLACE
72 |

When a UNIQUE constraint violation occurs, the pre-existing row 73 | that caused the constraint violation is removed prior to inserting 74 | or updating the current row. Thus the insert or update always occurs. 75 | The command continues executing normally. No error is returned.

76 |
77 | 78 |

Why So Many Choices?

79 | 80 |

SQLite provides multiple conflict resolution algorithms for a 81 | couple of reasons. First, SQLite tries to be roughly compatible with as 82 | many other SQL databases as possible, but different SQL database 83 | engines exhibit different conflict resolution strategies. For 84 | example, PostgreSQL always uses ROLLBACK, Oracle always uses ABORT, and 85 | MySQL usually uses FAIL but can be instructed to use IGNORE or REPLACE. 86 | By supporting all five alternatives, SQLite provides maximum 87 | portability.

88 | 89 |

Another reason for supporing multiple algorithms is that sometimes 90 | it is useful to use an algorithm other than the default. 91 | Suppose, for example, you are 92 | inserting 1000 records into a database, all within a single 93 | transaction, but one of those records is malformed and causes 94 | a constraint error. Under PostgreSQL or Oracle, none of the 95 | 1000 records would get inserted. In MySQL, some subset of the 96 | records that appeared before the malformed record would be inserted 97 | but the rest would not. Neither behavior is espeically helpful. 98 | What you really want is to use the IGNORE algorithm to insert 99 | all but the malformed record.

100 | 101 | } 102 | 103 | puts { 104 |


105 |

106 | Back to the SQLite Home Page 107 |

108 | 109 | } 110 | -------------------------------------------------------------------------------- /www/crosscompile.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Run this Tcl script to generate the crosscompile.html file. 3 | # 4 | set rcsid {$Id: crosscompile.tcl,v 1.5 2001/11/24 13:23:05 drh Exp $} 5 | 6 | puts { 7 | 8 | Notes On How To Compile SQLite Using The MinGW Cross-Compiler 9 | 10 | 11 |

12 | Notes On How To Compile SQLite Using The MinGW Cross-Compiler 13 |

} 14 | puts "

15 | (This page was last modified on [lrange $rcsid 3 4] UTC) 16 |

" 17 | 18 | puts { 19 |

MinGW or 20 | Minimalist GNU For Windows 21 | is a version of the popular GCC compiler that builds Win95/Win98/WinNT 22 | binaries. See the website for details.

23 | 24 |

This page describes how you can use MinGW configured as a 25 | cross-compiler running under RedHat 6.0 Linux to generate a 26 | binary for SQLite that runs under WinNT. 27 | Some additional steps (described below) 28 | are needed to target Win95/98.

29 | } 30 | 31 | proc Code {body} { 32 | puts {
}
 33 |   regsub -all {&} [string trim $body] {\&} body
 34 |   regsub -all {>} $body {\>} body
 35 |   regsub -all {<} $body {\<} body
 36 |   regsub -all {\(\(\(} $body {} body
 37 |   regsub -all {\)\)\)} $body {} body
 38 |   puts $body
 39 |   puts {
} 40 | } 41 | 42 | puts { 43 |

Here are the steps:

44 | 45 |
    46 |
  1. 47 |

    Get a copy of the MinGW compiler and all 48 | its associated tools that run under Linux. No binary versions of 49 | MinGW in this configuration are available for net downloads, as far 50 | as I know. You will probably have to download the source code and 51 | compile it all yourself. 52 | A separate bulletin describes how this 53 | can be done. 54 | When you are done, make sure the compiler and all its associated tools 55 | are located somewhere on your PATH environment variable. 56 |

    57 |
  2. 58 | 59 |
  3. 60 |

    61 | Download the Win32 port of GDBM from 62 | Roth Consulting. You can FTP a ZIP archive of the sources directly 63 | from 64 | ftp://ftp.roth.net/pub/ntperl/gdbm/source/Win32_GDBM_Source.zip. 65 |

    66 |
  4. 67 | 68 |
  5. 69 |

    Make a directory and unpack the Win32 port of GDBM.

    70 |
     71 | mkdir roth
     72 | cd roth
     73 | unzip ../Win32_GDBM_Source.zip
     74 | 
    75 |
  6. 76 | 77 |
  7. 78 |

    Manually build the GDBM library as follows:

    79 |
     80 | i386-mingw32-gcc -DWIN32=1 -O2 -c *.c
     81 | i386-mingw32-ar cr libgdbm.a *.o
     82 | i386-mingw32-ranlib libgdbm.a
     83 | cd ..
     84 | 
    85 |
  8. 86 | 87 |
  9. 88 |

    89 | Download the SQLite tarball from 90 | 91 | http://www.hwaci.com/sw/sqlite/sqlite.tar.gz. 92 | Unpack the tarball and create a separate directory in which 93 | to build the executable and library. 94 |

    95 |
     96 | tar xzf sqlite.tar.gz
     97 | mkdir sqlite-bld
     98 | cd sqlite-bld
     99 | 
    100 |
  10. 101 | 102 |
  11. 103 |

    104 | Create a "hints" file that will tell the SQLite configuration script 105 | to use the MinGW cross-compiler rather than the native linux compiler. 106 | The hints file should looks something like this:

    107 |
    108 | cat >mingw.hints <<\END
    109 |   config_TARGET_CC=i386-mingw32-gcc
    110 |   config_TARGET_CFLAGS='-O2'
    111 |   config_TARGET_GDBM_LIBS=../roth/libgdbm.a
    112 |   config_TARGET_GDBM_INC=-I../roth
    113 |   config_TARGET_AR='i386-mingw32-ar cr'
    114 |   config_TARGET_RANLIB=i386-mingw32-ranlib
    115 |   config_TARGET_EXEEXT='.exe'
    116 | END
    117 | 
    118 |
  12. 119 | 120 |
  13. 121 |

    Configure and build SQLite:

    122 |
    123 | ../sqlite/configure --with-hints=./mingw.hints
    124 | make
    125 | 
    126 |
  14. 127 |
128 | 129 | 130 |

Targetting Windows95/98 instead of WindowsNT

131 | 132 |

A small amount of additional work is needed to get SQLite running 133 | under Windows95/98. The first problem is that the LockFile() and 134 | UnlockFile() API that the Roth GDBM port uses does not work under 135 | Windows95. The easiest workaround is to just disable file locking 136 | in the GDBM library. You can do so by appending a few lines of code 137 | to the end of one of the GDBM source files and compiling the library 138 | using a special command-line option. Replace step (4) above as 139 | follows:

140 | 141 |
    142 |
  1. 143 | Append text to the systems.h source file as follows:

    144 | 145 |
    146 | cat >>systems.h <<\END
    147 | #ifdef NO_LOCKS
    148 | #undef  UNLOCK_FILE
    149 | #define UNLOCK_FILE(x)
    150 | #undef  READLOCK_FILE
    151 | #define READLOCK_FILE(x)  lock_val=0;
    152 | #undef  WRITELOCK_FILE
    153 | #define WRITELOCK_FILE(x) lock_val=0;
    154 | #endif
    155 | END
    156 | 
    157 | 158 |

    Then manually build the GDBM library with the extra 159 | "NO_LOCKS" define as follows:

    160 |
    161 | i386-mingw32-gcc -DWIN32=1 -DNO_LOCKS -O2 -c *.c
    162 | i386-mingw32-ar cr libgdbm.a *.o
    163 | i386-mingw32-ranlib libgdbm.a
    164 | cd ..
    165 | 
    166 |

  2. 167 |
168 | 169 |

Note that the locking problem has been reported and may actually 170 | be fixed in the Roth GDBM distribution by the time you read this. 171 | You should probably check before you make the above changes.

172 | 173 |

The above is all you have to do to get SQLite to work on Windows95. 174 | But one more step is required to get it to work well. It 175 | turns out that SQLite make heavy use of malloc() and 176 | free() and the implementation of this functions 177 | on Windows95 is particular poor. Large database queries will run 178 | more than 10 times faster if you substitute a better memory allocator 179 | such as the one by 180 | Doug Lea. 181 | A copy of Doug's allocator is included in the contrib 182 | directory of the source tree. Speed improvements are also reported 183 | on WindowsNT when alternative memory allocators are used, though 184 | the speedup is not as dramatic as it is with WIndows95.

185 | 186 | } 187 | puts { 188 |


189 |

190 | Back to the SQLite Home Page 191 |

192 | 193 | } 194 | -------------------------------------------------------------------------------- /www/download.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Run this TCL script to generate HTML for the download.html file. 3 | # 4 | set rcsid {$Id: download.tcl,v 1.5 2002/03/30 14:15:52 drh Exp $} 5 | 6 | puts { 7 | SQLite Download Page 8 | 9 |

SQLite Download Page

} 10 | #

} 11 | #puts "This page was last modified on [lrange $rcsid 3 4] UTC
" 12 | #set vers [lindex $argv 0] 13 | #puts "The latest SQLite version is $vers" 14 | #puts " created on [exec cat last_change] UTC" 15 | #puts {

} 16 | 17 | puts {

Precompiled Binaries For Linux

} 18 | 19 | proc Product {file desc} { 20 | if {![file exists $file]} return 21 | set size [file size $file] 22 | puts [subst { 23 | 24 | 25 | 28 | 29 | 30 |
26 | $file
($size bytes) 27 |
[string trim $desc]
}] 31 | } 32 | 33 | Product sqlite.bin.gz { 34 | A command-line program for accessing and modifing SQLite databases. 35 | See the documentation for additional information. 36 | } 37 | 38 | Product tclsqlite.so.gz { 39 | Bindings for TCL. You can import this shared library into either 40 | tclsh or wish to get SQLite database access from Tcl/Tk. 41 | See the documentation for details. 42 | } 43 | 44 | Product sqlite.so.gz { 45 | A precompiled shared-library for Linux. This is the same as 46 | tclsqlite.so.gz but without the TCL bindings. 47 | } 48 | 49 | foreach name [lsort -dict [glob -nocomplain sqlite-*.i386.rpm]] { 50 | if {[regexp -- -devel- $name]} { 51 | Product $name { 52 | RPM containing documentation, header files, and static library. 53 | } 54 | } else { 55 | Product $name { 56 | RPM containing shared libraries and the sqlite command-line 57 | program. 58 | } 59 | } 60 | } 61 | 62 | puts {

Precompiled Binaries For Windows

} 63 | 64 | Product sqlite.zip { 65 | A command-line program for accessing and modifing SQLite databases. 66 | See the documentation for additional information. 67 | } 68 | Product tclsqlite.zip { 69 | Bindings for TCL. You can import this shared library into either 70 | tclsh or wish to get SQLite database access from Tcl/Tk. 71 | See the documentation for details. 72 | } 73 | Product sqlitedll.zip { 74 | This is a DLL of the SQLite library without the TCL bindings. 75 | The only external dependency is MSVCRT.DLL. 76 | } 77 | 78 | puts {

Source Code

} 79 | 80 | Product {sqlite_source.zip} { 81 | This ZIP archive contains pure C source code for the SQLite library. 82 | Unlike the tarballs below, all of the preprocessing has already been 83 | done on these C source code, so you can just hand the files directly to 84 | your favorite C compiler. This file is provided as a service to 85 | MS-Windows users who lack the build support infrastructure of Unix. 86 | } 87 | 88 | foreach name [lsort -dict [glob -nocomplain sqlite-*.src.rpm]] { 89 | Product $name "RPM containing complete source code" 90 | } 91 | 92 | foreach name [lsort -dict -decreasing [glob -nocomplain sqlite-*.tar.gz]] { 93 | regexp {sqlite-(.*)\.tar\.gz} $name match vers 94 | Product $name " 95 | Version $vers of the source tree including all documentation. 96 | " 97 | } 98 | 99 | puts { 100 |


101 |

102 | 103 | Back to the SQLite home page 104 |

105 | 106 | } 107 | -------------------------------------------------------------------------------- /www/dynload.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Run this Tcl script to generate the dynload.html file. 3 | # 4 | set rcsid {$Id: dynload.tcl,v 1.1 2001/02/11 16:58:22 drh Exp $} 5 | 6 | puts { 7 | 8 | How to build a dynamically loaded Tcl extension for SQLite 9 | 10 | 11 |

12 | How To Build A Dynamically Loaded Tcl Extension 13 |

} 14 | puts {

15 | This note was contributed by 16 | Bill Saunders. Thanks, Bill! 17 | 18 |

19 | To compile the SQLite Tcl extension into a dynamically loaded module 20 | I did the following: 21 |

22 | 23 |
    24 |
  1. Do a standard compile 25 | (I had a dir called bld at the same level as sqlite ie 26 | /root/bld 27 | /root/sqlite 28 | I followed the directions and did a standard build in the bld 29 | directory)

  2. 30 | 31 |
  3. 32 | Now do the following in the bld directory 33 |

    34 | gcc -shared -I. -lgdbm ../sqlite/src/tclsqlite.c libsqlite.a -o sqlite.so
    35 | 

  4. 36 | 37 |
  5. 38 | This should produce the file sqlite.so in the bld directory

  6. 39 | 40 |
  7. 41 | Create a pkgIndex.tcl file that contains this line 42 | 43 |

    44 | package ifneeded sqlite 1.0 [list load [file join $dir sqlite.so]]
    45 | 

  8. 46 | 47 |
  9. 48 | To use this put sqlite.so and pkgIndex.tcl in the same directory

  10. 49 | 50 |
  11. 51 | From that directory start wish

  12. 52 | 53 |
  13. 54 | Execute the following tcl command (tells tcl where to fine loadable 55 | modules) 56 |

    57 | lappend auto_path [exec pwd]
    58 | 

  14. 59 | 60 |
  15. 61 | Load the package 62 |

    63 | package require sqlite
    64 | 

  16. 65 | 66 |
  17. 67 | Have fun....

  18. 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /www/formatchng.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Run this Tcl script to generate the formatchng.html file. 3 | # 4 | set rcsid {$Id: formatchng.tcl,v 1.4 2002/03/11 02:06:14 drh Exp $ } 5 | 6 | puts { 7 | 8 | File Format Changes in SQLite 9 | 10 | 11 |

    12 | File Format Changes in SQLite 13 |

    } 14 | puts "

    15 | (This page was last modified on [lrange $rcsid 3 4] UTC) 16 |

    " 17 | 18 | puts { 19 |

    20 | From time to time, enhancements or bug fixes require a change to 21 | the underlying file format for SQLite. When this happens and you 22 | want to upgrade your library, you must convert the contents of your 23 | databases into a portable ASCII representation using the old version 24 | of the library then reload the data using the new version of the 25 | library. 26 |

    27 | 28 |

    29 | You can tell if you should reload your databases by comparing the 30 | version numbers of the old and new libraries. If either of the 31 | first two digits in the version number change, then a reload is 32 | either required or recommended. For example, upgrading from 33 | version 1.0.32 to 2.0.0 requires a reload. So does going from 34 | version 2.0.8 to 2.1.0. 35 |

    36 | 37 |

    38 | The following table summarizes the SQLite file format changes that have 39 | occurred since version 1.0.0: 40 |

    41 | 42 |
    43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 | 67 | 68 | 69 | 70 | 71 | 84 | 85 | 86 | 87 | 93 | 94 | 95 | 96 | 97 | 107 | 108 |
    Version ChangeApprox. DateDescription Of File Format Change
    1.0.32 to 2.0.02001-Sep-20Version 1.0.X of SQLite used the GDBM library as its backend 53 | interface to the disk. Beginning in version 2.0.0, GDBM was replaced 54 | by a custom B-Tree library written especially for SQLite. The new 55 | B-Tree backend is twice as fast as GDBM, supports atomic commits and 56 | rollback, and stores an entire database in a single disk file instead 57 | using a separate file for each table as GDBM does. The two 58 | file formats are not even remotely similar.
    2.0.8 to 2.1.02001-Nov-12The same basic B-Tree format is used but the details of the 64 | index keys were changed in order to provide better query 65 | optimization opportunities. Some of the headers were also changed in order 66 | to increase the maximum size of a row from 64KB to 24MB.
    2.1.7 to 2.2.02001-Dec-21Beginning with version 2.2.0, SQLite no longer builds an index for 72 | an INTEGER PRIMARY KEY column. Instead, it uses that column as the actual 73 | B-Tree key for the main table.

    Version 2.2.0 and later of the library 74 | will automatically detect when it is reading a 2.1.x database and will 75 | disable the new INTEGER PRIMARY KEY feature. In other words, version 76 | 2.2.x is backwards compatible to version 2.1.x. But version 2.1.x is not 77 | forward compatible with version 2.2.x. If you try to open 78 | a 2.2.x database with an older 2.1.x library and that database contains 79 | an INTEGER PRIMARY KEY, you will likely get a coredump. If the database 80 | schema does not contain any INTEGER PRIMARY KEYs, then the version 2.1.x 81 | and version 2.2.x database files will be identical and completely 82 | interchangeable.

    83 |
    2.2.5 to 2.3.02002-Jan-30Beginning with version 2.3.0, SQLite supports some additional syntax 88 | (the "ON CONFLICT" clause) in the CREATE TABLE and CREATE INDEX statements 89 | that are stored in the SQLITE_MASTER table. If you create a database that 90 | contains this new syntax, then try to read that database using version 2.2.5 91 | or earlier, the parser will not understand the new syntax and you will get 92 | an error. Otherwise, databases for 2.2.x and 2.3.x are interchangeable.
    2.3.3 to 2.4.02002-Mar-10Beginning with version 2.4.0, SQLite added support for views. 98 | Information about views is stored in the SQLITE_MASTER table. If an older 99 | version of SQLite attempts to read a database that contains VIEW information 100 | in the SQLITE_MASTER table, the parser will not understand the new syntax 101 | and you will get an error. Also, the 102 | way SQLite keeps track of unused disk blocks in the database file 103 | changed slightly. 104 | If an older version of SQLite attempts to write a database that 105 | was previously written by version 2.4.0 or later, then it may leak disk 106 | blocks.
    109 |
    110 | 111 |

    112 | To perform a database reload, have ready versions of the 113 | sqlite command-line utility for both the old and new 114 | version of SQLite. Call these two executables "sqlite-old" 115 | and "sqlite-new". Suppose the name of your old database 116 | is "old.db" and you want to create a new database with 117 | the same information named "new.db". The command to do 118 | this is as follows: 119 |

    120 | 121 |
    122 | echo .dump | sqlite-old old.db | sqlite-new new.db 123 |
    124 | } 125 | 126 | puts { 127 |


    128 |

    129 | Back to the SQLite Home Page 130 |

    131 | 132 | } 133 | -------------------------------------------------------------------------------- /www/mingw.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Run this Tcl script to generate the crosscompile.html file. 3 | # 4 | set rcsid {$Id: mingw.tcl,v 1.3 2001/11/24 13:23:05 drh Exp $} 5 | 6 | puts { 7 | 8 | Notes On How To Build MinGW As A Cross-Compiler 9 | 10 | 11 |

    12 | Notes On How To Build MinGW As A Cross-Compiler 13 |

    } 14 | puts "

    15 | (This page was last modified on [lrange $rcsid 3 4] UTC) 16 |

    " 17 | 18 | puts { 19 |

    MinGW or 20 | Minimalist GNU For Windows 21 | is a version of the popular GCC compiler that builds Win95/Win98/WinNT 22 | binaries. See the website for details.

    23 | 24 |

    This page describes how you can build MinGW 25 | from sources as a cross-compiler 26 | running under Linux. Doing so will allow you to construct 27 | WinNT binaries from the comfort and convenience of your 28 | Unix desktop.

    29 | } 30 | 31 | proc Link {path {file {}}} { 32 | if {$file!=""} { 33 | set path $path/$file 34 | } else { 35 | set file $path 36 | } 37 | puts "$file" 38 | } 39 | 40 | puts { 41 |

    Here are the steps:

    42 | 43 |
      44 |
    1. 45 |

      Get a copy of source code. You will need the binutils, the 46 | compiler, and the MinGW runtime. Each are available separately. 47 | As of this writing, Mumit Khan has collected everything you need 48 | together in one FTP site: 49 | } 50 | set ftpsite \ 51 | ftp://ftp.nanotech.wisc.edu/pub/khan/gnu-win32/mingw32/snapshots/gcc-2.95.2-1 52 | Link $ftpsite 53 | puts { 54 | The three files you will need are:

      55 |
        56 |
      • } 57 | Link $ftpsite binutils-19990818-1-src.tar.gz 58 | puts
      • 59 | Link $ftpsite gcc-2.95.2-1-src.tar.gz 60 | puts
      • 61 | Link $ftpsite mingw-20000203.zip 62 | puts {
      • 63 |
      64 | 65 |

      Put all the downloads in a directory out of the way. The sequel 66 | will assume all downloads are in a directory named 67 | ~/mingw/download.

      68 |
    2. 69 | 70 |
    3. 71 |

      72 | Create a directory in which to install the new compiler suite and make 73 | the new directory writable. 74 | Depending on what directory you choose, you might need to become 75 | root. The example shell commands that follow 76 | will assume the installation directory is 77 | /opt/mingw and that your user ID is drh.

      78 |
       79 | su
       80 | mkdir /opt/mingw
       81 | chown drh /opt/mingw
       82 | exit
       83 | 
      84 |
    4. 85 | 86 |
    5. 87 |

      Unpack the source tarballs into a separate directory.

      88 |
       89 | mkdir ~/mingw/src
       90 | cd ~/mingw/src
       91 | tar xzf ../download/binutils-*.tar.gz
       92 | tar xzf ../download/gcc-*.tar.gz
       93 | unzip ../download/mingw-*.zip
       94 | 
      95 |
    6. 96 | 97 |
    7. 98 |

      Create a directory in which to put all the build products.

      99 |
      100 | mkdir ~/mingw/bld
      101 | 
      102 |
    8. 103 | 104 |
    9. 105 |

      Configure and build binutils and add the results to your PATH.

      106 |
      107 | mkdir ~/mingw/bld/binutils
      108 | cd ~/mingw/bld/binutils
      109 | ../../src/binutils/configure --prefix=/opt/mingw --target=i386-mingw32 -v
      110 | make 2>&1 | tee make.out
      111 | make install 2>&1 | tee make-install.out
      112 | export PATH=$PATH:/opt/mingw/bin
      113 | 
      114 |
    10. 115 | 116 |
    11. 117 |

      Manually copy the runtime include files into the installation directory 118 | before trying to build the compiler.

      119 |
      120 | mkdir /opt/mingw/i386-mingw32/include
      121 | cd ~/mingw/src/mingw-runtime*/mingw/include
      122 | cp -r * /opt/mingw/i386-mingw32/include
      123 | 
      124 |
    12. 125 | 126 |
    13. 127 |

      Configure and build the compiler

      128 |
      129 | mkdir ~/mingw/bld/gcc
      130 | cd ~/mingw/bld/gcc
      131 | ../../src/gcc-*/configure --prefix=/opt/mingw --target=i386-mingw32 -v
      132 | cd gcc
      133 | make installdirs
      134 | cd ..
      135 | make 2>&1 | tee make.out
      136 | make install
      137 | 
      138 |
    14. 139 | 140 |
    15. 141 |

      Configure and build the MinGW runtime

      142 |
      143 | mkdir ~/mingw/bld/runtime
      144 | cd ~/mingw/bld/runtime
      145 | ../../src/mingw-runtime*/configure --prefix=/opt/mingw --target=i386-mingw32 -v
      146 | make install-target-w32api
      147 | make install
      148 | 
      149 |
    16. 150 |
    151 | 152 |

    And you are done...

    153 | } 154 | puts { 155 |


    156 |

    157 | Back to the SQLite Home Page 158 |

    159 | 160 | } 161 | --------------------------------------------------------------------------------