[Asterisk-cvs] asterisk-addons/res_sqlite3/sqlite/test all.test, NONE, 1.1 attach.test, NONE, 1.1 attach2.test, NONE, 1.1 attach3.test, NONE, 1.1 auth.test, NONE, 1.1 bigfile.test, NONE, 1.1 bigrow.test, NONE, 1.1 bind.test, NONE, 1.1 blob.test, NONE, 1.1 btree.test, NONE, 1.1 btree2.test, NONE, 1.1 btree4.test, NONE, 1.1 btree5.test, NONE, 1.1 btree6.test, NONE, 1.1 btree7.test, NONE, 1.1 capi2.test, NONE, 1.1 capi3.test, NONE, 1.1 capi3b.test, NONE, 1.1 collate1.test, NONE, 1.1 collate2.test, NONE, 1.1 collate3.test, NONE, 1.1 collate4.test, NONE, 1.1 collate5.test, NONE, 1.1 collate6.test, NONE, 1.1 conflict.test, NONE, 1.1 corrupt.test, NONE, 1.1 crash.test, NONE, 1.1 crashtest1.c, NONE, 1.1 date.test, NONE, 1.1 delete.test, NONE, 1.1 delete2.test, NONE, 1.1 enc.test, NONE, 1.1 enc2.test, NONE, 1.1 enc3.test, NONE, 1.1 expr.test, NONE, 1.1 fkey1.test, NONE, 1.1 func.test, NONE, 1.1 hook.test, NONE, 1.1 in.test, NONE, 1.1 index.test, NONE, 1.1 insert.test, NONE, 1.1 insert2.test, NONE, 1.1 interrupt.test, NONE, 1.1 intpkey.test, NONE, 1.1 ioerr.test, NONE, 1.1 join.test, NONE, 1.1 join2.test, NONE, 1.1 join3.test, NONE, 1.1 join4.test, NONE, 1.1 lastinsert.test, NONE, 1.1 laststmtchanges.test, NONE, 1.1 limit.test, NONE, 1.1 lock.test, NONE, 1.1 lock2.test, NONE, 1.1 main.test, NONE, 1.1 malloc.test, NONE, 1.1 memdb.test, NONE, 1.1 memleak.test, NONE, 1.1 minmax.test, NONE, 1.1 misc1.test, NONE, 1.1 misc2.test, NONE, 1.1 misc3.test, NONE, 1.1 misc4.test, NONE, 1.1 misuse.test, NONE, 1.1 notnull.test, NONE, 1.1 null.test, NONE, 1.1 pager.test, NONE, 1.1 pager2.test, NONE, 1.1 pager3.test, NONE, 1.1 pagesize.test, NONE, 1.1 pragma.test, NONE, 1.1 printf.test, NONE, 1.1 progress.test, NONE, 1.1 quick.test, NONE, 1.1 quote.test, NONE, 1.1 rollback.test, NONE, 1.1 rowid.test, NONE, 1.1 select1.test, NONE, 1.1 select2.test, NONE, 1.1 select3.test, NONE, 1.1 select4.test, NONE, 1.1 select5.test, NONE, 1.1 select6.test, NONE, 1.1 select7.test, NONE, 1.1 sort.test, NONE, 1.1 subselect.test, NONE, 1.1 table.test, NONE, 1.1 tableapi.test, NONE, 1.1 tclsqlite.test, NONE, 1.1 temptable.test, NONE, 1.1 tester.tcl, NONE, 1.1 thread1.test, NONE, 1.1 threadtest1.c, NONE, 1.1 threadtest2.c, NONE, 1.1 trace.test, NONE, 1.1 trans.test, NONE, 1.1 trigger1.test, NONE, 1.1 trigger2.test, NONE, 1.1 trigger3.test, NONE, 1.1 trigger4.test, NONE, 1.1 trigger5.test, NONE, 1.1 types.test, NONE, 1.1 types2.test, NONE, 1.1 unique.test, NONE, 1.1 update.test, NONE, 1.1 utf16.test, NONE, 1.1 vacuum.test, NONE, 1.1 varint.test, NONE, 1.1 view.test, NONE, 1.1 where.test, NONE, 1.1

anthm at lists.digium.com anthm at lists.digium.com
Mon Nov 15 09:41:24 CST 2004


Update of /usr/cvsroot/asterisk-addons/res_sqlite3/sqlite/test
In directory mongoose.digium.com:/tmp/cvs-serv9113/res_sqlite3/sqlite/test

Added Files:
	all.test attach.test attach2.test attach3.test auth.test 
	bigfile.test bigrow.test bind.test blob.test btree.test 
	btree2.test btree4.test btree5.test btree6.test btree7.test 
	capi2.test capi3.test capi3b.test collate1.test collate2.test 
	collate3.test collate4.test collate5.test collate6.test 
	conflict.test corrupt.test crash.test crashtest1.c date.test 
	delete.test delete2.test enc.test enc2.test enc3.test 
	expr.test fkey1.test func.test hook.test in.test index.test 
	insert.test insert2.test interrupt.test intpkey.test 
	ioerr.test join.test join2.test join3.test join4.test 
	lastinsert.test laststmtchanges.test limit.test lock.test 
	lock2.test main.test malloc.test memdb.test memleak.test 
	minmax.test misc1.test misc2.test misc3.test misc4.test 
	misuse.test notnull.test null.test pager.test pager2.test 
	pager3.test pagesize.test pragma.test printf.test 
	progress.test quick.test quote.test rollback.test rowid.test 
	select1.test select2.test select3.test select4.test 
	select5.test select6.test select7.test sort.test 
	subselect.test table.test tableapi.test tclsqlite.test 
	temptable.test tester.tcl thread1.test threadtest1.c 
	threadtest2.c trace.test trans.test trigger1.test 
	trigger2.test trigger3.test trigger4.test trigger5.test 
	types.test types2.test unique.test update.test utf16.test 
	vacuum.test varint.test view.test where.test 
Log Message:
check in res_sqlite3

--- NEW FILE: all.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {memleak_check}

if {[file exists ./sqlite_test_count]} {
  set COUNT [exec cat ./sqlite_test_count]
} else {
  set COUNT 3
}

if {[llength $argv]>0} {
  foreach {name value} $argv {
    switch -- $name {
      -count {
         set COUNT $value
      }
      -quick {
         set ISQUICK $value
      }
      default {
         puts stderr "Unknown option: $name"
         exit
      }
    }
  }
}
set argv {}

# LeakList will hold a list of the number of unfreed mallocs after
# each round of the test.  This number should be constant.  If it
# grows, it may mean there is a memory leak in the library.
#
set LeakList {}

set EXCLUDE {
  all.test
  crash.test
  quick.test
  malloc.test
  misuse.test
  memleak.test
  corrupt.test
}
#  btree2.test

for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} {
  if {$Counter%2} {
    set ::SETUP_SQL {PRAGMA default_synchronous=off;}
  } else {
    catch {unset ::SETUP_SQL}
  }
  foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
    set tail [file tail $testfile]
    if {[lsearch -exact $EXCLUDE $tail]>=0} continue
    source $testfile
    catch {db close}
    if {$sqlite_open_file_count>0} {
      puts "$tail did not close all files: $sqlite_open_file_count"
      incr nErr
      lappend ::failList $tail
    }
  }
  if {[info exists Leak]} {
    lappend LeakList $Leak
  }
}

# Do one last test to look for a memory leak in the library.  This will
# only work if SQLite is compiled with the -DMEMORY_DEBUG=1 flag.
#
if {$LeakList!=""} {
  puts -nonewline memory-leak-test...
  incr ::nTest
  foreach x $LeakList {
    if {$x!=[lindex $LeakList 0]} {
       puts " failed!"
       puts "Expected: all values to be the same"
       puts "     Got: $LeakList"
       incr ::nErr
       lappend ::failList memory-leak-test
       break
    }
  }
  puts " Ok"
}

# Run the crashtest only on unix and only once.
#
if {$tcl_platform(platform)=="unix"} {
  source $testdir/crash.test
}

# Run the malloc tests and the misuse test after memory leak detection.
# Both tests leak memory. Currently, misuse.test also leaks a handful of
# file descriptors. This is not considered a problem, but can cause tests
# in malloc.test to fail. So set the open-file count to zero before running
# malloc.test to get around this.
#
catch {source $testdir/misuse.test}
set sqlite_open_file_count 0
catch {source $testdir/malloc.test}

catch {db close}
set sqlite_open_file_count 0
really_finish_test

--- NEW FILE: attach.test ---
# 2003 April 4
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
  file delete -force test$i.db-journal
}

set btree_trace 0
do_test attach-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(3,4);
    SELECT * FROM t1;
  }
} {1 2 3 4}
do_test attach-1.2 {
  sqlite3 db2 test2.db
  execsql {
    CREATE TABLE t2(x,y);
    INSERT INTO t2 VALUES(1,'x');
    INSERT INTO t2 VALUES(2,'y');
    SELECT * FROM t2;
  } db2
} {1 x 2 y}
do_test attach-1.3 {
  execsql {
    ATTACH DATABASE 'test2.db' AS two;
    SELECT * FROM two.t2;
  }
} {1 x 2 y}
do_test attach-1.4 {
  execsql {
    SELECT * FROM t2;
  }
} {1 x 2 y}
do_test attach-1.5 {
  execsql {
    DETACH DATABASE two;
    SELECT * FROM t1;
  }
} {1 2 3 4}
do_test attach-1.6 {
  catchsql {
    SELECT * FROM t2;
  }
} {1 {no such table: t2}}
do_test attach-1.7 {
  catchsql {
    SELECT * FROM two.t2;
  }
} {1 {no such table: two.t2}}
do_test attach-1.8 {
  catchsql {
    ATTACH DATABASE 'test3.db' AS three;
  }
} {0 {}}
do_test attach-1.9 {
  catchsql {
    SELECT * FROM three.sqlite_master;
  }
} {0 {}}
do_test attach-1.10 {
  catchsql {
    DETACH DATABASE three;
  }
} {0 {}}
do_test attach-1.11 {
  execsql {
    ATTACH 'test.db' AS db2;
    ATTACH 'test.db' AS db3;
    ATTACH 'test.db' AS db4;
    ATTACH 'test.db' AS db5;
    ATTACH 'test.db' AS db6;
    ATTACH 'test.db' AS db7;
    ATTACH 'test.db' AS db8;
    ATTACH 'test.db' AS db9;
  }
} {}
proc db_list {db} {
  set list {}
  foreach {idx name file} [execsql {PRAGMA database_list} $db] {
    lappend list $idx $name
  }
  return $list
}
do_test attach-1.11b {
  db_list db
} {0 main 2 db2 3 db3 4 db4 5 db5 6 db6 7 db7 8 db8 9 db9}
do_test attach-1.12 {
  catchsql {
    ATTACH 'test.db' as db2;
  }
} {1 {database db2 is already in use}}
do_test attach-1.13 {
  catchsql {
    ATTACH 'test.db' as db5;
  }
} {1 {database db5 is already in use}}
do_test attach-1.14 {
  catchsql {
    ATTACH 'test.db' as db9;
  }
} {1 {database db9 is already in use}}
do_test attach-1.15 {
  catchsql {
    ATTACH 'test.db' as main;
  }
} {1 {database main is already in use}}
do_test attach-1.16 {
  catchsql {
    ATTACH 'test.db' as temp;
  }
} {1 {database temp is already in use}}
do_test attach-1.17 {
  catchsql {
    ATTACH 'test.db' as MAIN;
  }
} {1 {database MAIN is already in use}}
do_test attach-1.18 {
  catchsql {
    ATTACH 'test.db' as db10;
    ATTACH 'test.db' as db11;
  }
} {0 {}}
do_test attach-1.19 {
  catchsql {
    ATTACH 'test.db' as db12;
  }
} {1 {too many attached databases - max 10}}
do_test attach-1.20.1 {
  execsql {
    DETACH db5;
  }
  db_list db
} {0 main 2 db2 3 db3 4 db4 5 db6 6 db7 7 db8 8 db9 9 db10 10 db11}
integrity_check attach-1.20.2
do_test attach-1.21 {
  catchsql {
    ATTACH 'test.db' as db12;
  }
} {0 {}}
do_test attach-1.22 {
  catchsql {
    ATTACH 'test.db' as db13;
  }
} {1 {too many attached databases - max 10}}
do_test attach-1.23 {
  catchsql {
    DETACH db14;
  }
} {1 {no such database: db14}}
do_test attach-1.24 {
  catchsql {
    DETACH db12;
  }
} {0 {}}
do_test attach-1.25 {
  catchsql {
    DETACH db12;
  }
} {1 {no such database: db12}}
do_test attach-1.26 {
  catchsql {
    DETACH main;
  }
} {1 {cannot detach database main}}
do_test attach-1.27 {
  catchsql {
    DETACH Temp;
  }
} {1 {cannot detach database Temp}}
do_test attach-1.28 {
  catchsql {
    DETACH db11;
    DETACH db10;
    DETACH db9;
    DETACH db8;
    DETACH db7;
    DETACH db6;
    DETACH db4;
    DETACH db3;
    DETACH db2;
  }
} {0 {}}
do_test attach-1.29 {
  db_list db
} {0 main 1 temp}

do_test attach-2.1 {
  execsql {
    CREATE TABLE tx(x1,x2,y1,y2);
    CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
      INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
    END;
    SELECT * FROM tx;
  } db2;
} {}
do_test attach-2.2 {
  execsql {
    UPDATE t2 SET x=x+10;
    SELECT * FROM tx;
  } db2;
} {1 11 x x 2 12 y y}
do_test attach-2.3 {
  execsql {
    CREATE TABLE tx(x1,x2,y1,y2);
    SELECT * FROM tx;
  }
} {}
do_test attach-2.4 {
  execsql {
    ATTACH 'test2.db' AS db2;
  }
} {}
do_test attach-2.5 {
  execsql {
    UPDATE db2.t2 SET x=x+10;
    SELECT * FROM db2.tx;
  }
} {1 11 x x 2 12 y y 11 21 x x 12 22 y y}
do_test attach-2.6 {
  execsql {
    SELECT * FROM main.tx;
  }
} {}
do_test attach-2.7 {
  execsql {
    SELECT type, name, tbl_name FROM db2.sqlite_master;
  }
} {table t2 t2 table tx tx trigger r1 t2}
do_test attach-2.8 {
  db_list db
} {0 main 1 temp 2 db2}
do_test attach-2.9 {
  execsql {
    CREATE INDEX i2 ON t2(x);
    SELECT * FROM t2 WHERE x>5;
  } db2
} {21 x 22 y}
do_test attach-2.10 {
  execsql {
    SELECT type, name, tbl_name FROM sqlite_master;
  } db2
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
#do_test attach-2.11 {
#  catchsql { 
#    SELECT * FROM t2 WHERE x>5;
#  }
#} {1 {database schema has changed}}
do_test attach-2.12 {
  db_list db
} {0 main 1 temp 2 db2}
do_test attach-2.13 {
  catchsql {
    SELECT * FROM t2 WHERE x>5;
  }
} {0 {21 x 22 y}}
do_test attach-2.14 {
  execsql {
    SELECT type, name, tbl_name FROM sqlite_master;
  }
} {table t1 t1 table tx tx}
do_test attach-2.15 {
  execsql {
    SELECT type, name, tbl_name FROM db2.sqlite_master;
  }
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
do_test attach-2.16 {
  db close
  sqlite3 db test.db
  execsql {
    ATTACH 'test2.db' AS db2;
    SELECT type, name, tbl_name FROM db2.sqlite_master;
  }
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}

do_test attach-3.1 {
  db close
  db2 close
  sqlite3 db test.db
  sqlite3 db2 test2.db
  execsql {
    SELECT * FROM t1
  }
} {1 2 3 4}
do_test attach-3.2 {
  catchsql {
    SELECT * FROM t2
  }
} {1 {no such table: t2}}
do_test attach-3.3 {
  catchsql {
    ATTACH DATABASE 'test2.db' AS db2;
    SELECT * FROM t2
  }
} {0 {21 x 22 y}}

# Even though 'db' has started a transaction, it should not yet have
# a lock on test2.db so 'db2' should be readable.
do_test attach-3.4 {
  execsql BEGIN
  catchsql {
    SELECT * FROM t2;
  } db2;
} {0 {21 x 22 y}}

# Reading from test2.db from db within a transaction should not
# prevent test2.db from being read by db2.
do_test attach-3.5 {
  execsql {SELECT * FROM t2}
  catchsql {
    SELECT * FROM t2;
  } db2;
} {0 {21 x 22 y}}

# Making a change to test2.db through db  causes test2.db to get
# a reserved lock.  It should still be accessible through db2.
do_test attach-3.6 {
  execsql {
    UPDATE t2 SET x=x+1 WHERE x=50;
  }
  catchsql {
    SELECT * FROM t2;
  } db2;
} {0 {21 x 22 y}}

do_test attach-3.7 {
  execsql ROLLBACK
  execsql {SELECT * FROM t2} db2
} {21 x 22 y}

# Start transactions on both db and db2.  Once again, just because
# we make a change to test2.db using db2, only a RESERVED lock is
# obtained, so test2.db should still be readable using db.
#
do_test attach-3.8 {
  execsql BEGIN
  execsql BEGIN db2
  execsql {UPDATE t2 SET x=0 WHERE 0} db2
  catchsql {SELECT * FROM t2}
} {0 {21 x 22 y}}

# It is also still accessible from db2.
do_test attach-3.9 {
  catchsql {SELECT * FROM t2} db2
} {0 {21 x 22 y}}

do_test attach-3.10 {
  execsql {SELECT * FROM t1}
} {1 2 3 4}

do_test attach-3.11 {
  catchsql {UPDATE t1 SET a=a+1}
} {0 {}}
do_test attach-3.12 {
  execsql {SELECT * FROM t1}
} {2 2 4 4}

# db2 has a RESERVED lock on test2.db, so db cannot write to any tables
# in test2.db.
do_test attach-3.13 {
  catchsql {UPDATE t2 SET x=x+1 WHERE x=50}
} {1 {database is locked}}

# Change for version 3. Transaction is no longer rolled back
# for a locked database.
execsql {ROLLBACK}

# db is able to reread its schema because db2 still only holds a
# reserved lock.
do_test attach-3.14 {
  catchsql {SELECT * FROM t1}
} {0 {1 2 3 4}}
do_test attach-3.15 {
  execsql COMMIT db2
  execsql {SELECT * FROM t1}
} {1 2 3 4}

#set btree_trace 1

# Ticket #323
do_test attach-4.1 {
  execsql {DETACH db2}
  db2 close
  sqlite3 db2 test2.db
  execsql {
    CREATE TABLE t3(x,y);
    CREATE UNIQUE INDEX t3i1 ON t3(x);
    INSERT INTO t3 VALUES(1,2);
    SELECT * FROM t3;
  } db2;
} {1 2}
do_test attach-4.2 {
  execsql {
    CREATE TABLE t3(a,b);
    CREATE UNIQUE INDEX t3i1b ON t3(a);
    INSERT INTO t3 VALUES(9,10);
    SELECT * FROM t3;
  }
} {9 10}
do_test attach-4.3 {
  execsql {
    ATTACH DATABASE 'test2.db' AS db2;
    SELECT * FROM db2.t3;
  }
} {1 2}
do_test attach-4.4 {
  execsql {
    SELECT * FROM main.t3;
  }
} {9 10}
do_test attach-4.5 {
  execsql {
    INSERT INTO db2.t3 VALUES(9,10);
    SELECT * FROM db2.t3;
  }
} {1 2 9 10}
do_test attach-4.6 {
  execsql {
    DETACH db2;
  }
  execsql {
    CREATE TABLE t4(x);
    CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
      INSERT INTO t4 VALUES('db2.' || NEW.x);
    END;
    INSERT INTO t3 VALUES(6,7);
    SELECT * FROM t4;
  } db2
} {db2.6}
do_test attach-4.7 {
  execsql {
    CREATE TABLE t4(y);
    CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
      INSERT INTO t4 VALUES('main.' || NEW.a);
    END;
    INSERT INTO main.t3 VALUES(11,12);
    SELECT * FROM main.t4;
  }
} {main.11}

# This one is tricky.  On the UNION ALL select, we have to make sure
# the schema for both main and db2 is valid before starting to execute
# the first query of the UNION ALL.  If we wait to test the validity of
# the schema for main until after the first query has run, that test will
# fail and the query will abort but we will have already output some
# results.  When the query is retried, the results will be repeated.
#
do_test attach-4.8 {
  execsql {
    ATTACH DATABASE 'test2.db' AS db2;
    INSERT INTO db2.t3 VALUES(13,14);
    SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
  }
} {db2.6 db2.13 main.11}

do_test attach-4.9 {
  execsql {
    INSERT INTO main.t3 VALUES(15,16);
    SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
  }
} {db2.6 db2.13 main.11 main.15}
do_test attach-4.10 {
  execsql {
    DETACH DATABASE db2;
  }
  execsql {
    CREATE VIEW v3 AS SELECT x*100+y FROM t3;
    SELECT * FROM v3;
  } db2
} {102 910 607 1314}
do_test attach-4.11 {
  execsql {
    CREATE VIEW v3 AS SELECT a*100+b FROM t3;
    SELECT * FROM v3;
  }
} {910 1112 1516}
do_test attach-4.12 {
  execsql {
    ATTACH DATABASE 'test2.db' AS db2;
    SELECT * FROM db2.v3;
  }
} {102 910 607 1314}
do_test attach-4.13 {
  execsql {
    SELECT * FROM main.v3;
  }
} {910 1112 1516}

# Tests for the sqliteFix...() routines in attach.c
#
do_test attach-5.1 {
  db close
  sqlite3 db test.db
  db2 close
  file delete -force test2.db
  sqlite3 db2 test2.db
  catchsql {
    ATTACH DATABASE 'test.db' AS orig;
    CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN;
      SELECT 'no-op';
    END;
  } db2
} {1 {trigger r1 cannot reference objects in database orig}}
do_test attach-5.2 {
  catchsql {
    CREATE TABLE t5(x,y);
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op';
    END;
  } db2
} {0 {}}
do_test attach-5.3 {
  catchsql {
    DROP TRIGGER r5;
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM orig.t1;
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database orig}}
do_test attach-5.4 {
  catchsql {
    CREATE TEMP TABLE t6(p,q,r);
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM temp.t6;
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.5 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' || (SELECT * FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.6 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.7 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT 'no-op' FROM t1 GROUP BY 1 HAVING x<(SELECT min(x) FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.7 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      SELECT max(1,x,(SELECT min(x) FROM temp.t6)) FROM t1;
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.8 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      INSERT INTO t1 VALUES((SELECT min(x) FROM temp.t6),5);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}
do_test attach-5.9 {
  catchsql {
    CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
      DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
    END;
  } db2
} {1 {trigger r5 cannot reference objects in database temp}}

# Check to make sure we get a sensible error if unable to open
# the file that we are trying to attach.
#
do_test attach-6.1 {
  catchsql {
    ATTACH DATABASE 'no-such-file' AS nosuch;
  }
} {0 {}}
if {$tcl_platform(platform)=="unix"} {
  do_test attach-6.2 {
    sqlite3 dbx cannot-read
    dbx eval {CREATE TABLE t1(a,b,c)}
    dbx close
    file attributes cannot-read -permission 0000
    catchsql {
      ATTACH DATABASE 'cannot-read' AS noread;
    }
  } {1 {unable to open database: cannot-read}}
  file delete -force cannot-read
}

for {set i 2} {$i<=15} {incr i} {
  catch {db$i close}
}
db close
file delete -force test2.db
file delete -force no-such-file


finish_test

--- NEW FILE: attach2.test ---
# 2003 July 1
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# Ticket #354
#
# Databases test.db and test2.db contain identical schemas.  Make
# sure we can attach test2.db from test.db.
#
do_test attach2-1.1 {
  db eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX x1 ON t1(a);
  }
  file delete -force test2.db
  file delete -force test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX x1 ON t1(a);
  }
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {0 {}}

# Ticket #514
#
proc db_list {db} {
  set list {}
  foreach {idx name file} [execsql {PRAGMA database_list} $db] {
    lappend list $idx $name
  }
  return $list
}
db eval {DETACH t2}
do_test attach2-2.1 {
  # lock test2.db then try to attach it.  This is no longer an error because
  # db2 just RESERVES the database.  It does not obtain a write-lock until
  # we COMMIT.
  db2 eval {BEGIN}
  db2 eval {UPDATE t1 SET a = 0 WHERE 0}
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {0 {}}
do_test attach2-2.2 {
  # make sure test2.db did get attached.
  db_list db
} {0 main 2 t2}
db2 eval {COMMIT}

do_test attach2-2.5 {
  # Make sure we can read test2.db from db
  catchsql {
    SELECT name FROM t2.sqlite_master;
  }
} {0 {t1 x1}}
do_test attach2-2.6 {
  # lock test2.db and try to read from it.  This should still work because
  # the lock is only a RESERVED lock which does not prevent reading.
  #
  db2 eval BEGIN
  db2 eval {UPDATE t1 SET a = 0 WHERE 0}
  catchsql {
    SELECT name FROM t2.sqlite_master;
  }
} {0 {t1 x1}}
do_test attach2-2.7 {
  # but we can still read from test1.db even though test2.db is locked.
  catchsql {
    SELECT name FROM main.sqlite_master;
  }
} {0 {t1 x1}}
do_test attach2-2.8 {
  # start a transaction on test.db even though test2.db is locked.
  catchsql {
    BEGIN;
    INSERT INTO t1 VALUES(8,9);
  }
} {0 {}}
do_test attach2-2.9 {
  execsql {
    SELECT * FROM t1
  }
} {8 9}
do_test attach2-2.10 {
  # now try to write to test2.db.  the write should fail
  catchsql {
    INSERT INTO t2.t1 VALUES(1,2);
  }
} {1 {database is locked}}
do_test attach2-2.11 {
  # when the write failed in the previous test, the transaction should
  # have rolled back.
  # 
  # Update for version 3: A transaction is no longer rolled back if a
  #                       database is found to be busy.
  execsql {rollback}
  db2 eval ROLLBACK
  execsql {
    SELECT * FROM t1
  }
} {}
do_test attach2-2.12 {
  catchsql {
    COMMIT
  }
} {1 {cannot commit - no transaction is active}}

# Ticket #574:  Make sure it works using the non-callback API
#
do_test attach2-3.1 {
  db close
  set DB [sqlite3 db test.db]
  set rc [catch {sqlite3_prepare $DB "ATTACH 'test2.db' AS t2" -1 TAIL} VM]
  if {$rc} {lappend rc $VM}
  sqlite3_finalize $VM
  set rc
} {0}
do_test attach2-3.2 {
  set rc [catch {sqlite3_prepare $DB "DETACH t2" -1 TAIL} VM]
  if {$rc} {lappend rc $VM}
  sqlite3_finalize $VM
  set rc
} {0}

db close
for {set i 2} {$i<=15} {incr i} {
  catch {db$i close}
}

# A procedure to verify the status of locks on a database.
#
proc lock_status {testnum db expected_result} {
  do_test attach2-$testnum [subst {
    execsql {PRAGMA lock_status} $db
  }] $expected_result
}
set sqlite_os_trace 0

# Tests attach2-4.* test that read-locks work correctly with attached
# databases.
do_test attach2-4.1 {
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql {ATTACH 'test2.db' as file2}
  execsql {ATTACH 'test2.db' as file2} db2
} {}

lock_status 4.1.1 db {main unlocked temp closed file2 unlocked}
lock_status 4.1.2 db2 {main unlocked temp closed file2 unlocked}

do_test attach2-4.2 {
  # Handle 'db' read-locks test.db
  execsql {BEGIN}
  execsql {SELECT * FROM t1}
  # Lock status:
  #    db  - shared(main)
  #    db2 -
} {}

lock_status 4.2.1 db {main shared temp closed file2 unlocked}
lock_status 4.2.2 db2 {main unlocked temp closed file2 unlocked}

do_test attach2-4.3 {
  # The read lock held by db does not prevent db2 from reading test.db
  execsql {SELECT * FROM t1} db2
} {}

lock_status 4.3.1 db {main shared temp closed file2 unlocked}
lock_status 4.3.2 db2 {main unlocked temp closed file2 unlocked}

do_test attach2-4.4 {
  # db is holding a read lock on test.db, so we should not be able
  # to commit a write to test.db from db2
  catchsql {
    INSERT INTO t1 VALUES(1, 2)
  } db2 
} {1 {database is locked}}

lock_status 4.4.1 db {main shared temp closed file2 unlocked}
lock_status 4.4.2 db2 {main unlocked temp closed file2 unlocked}

do_test attach2-4.5 {
  # Handle 'db2' reserves file2.
  execsql {BEGIN} db2
  execsql {INSERT INTO file2.t1 VALUES(1, 2)} db2
  # Lock status:
  #    db  - shared(main)
  #    db2 - reserved(file2)
} {}

lock_status 4.5.1 db {main shared temp closed file2 unlocked}
lock_status 4.5.2 db2 {main unlocked temp closed file2 reserved}

do_test attach2-4.6.1 {
  # Reads are allowed against a reserved database.
  catchsql {
    SELECT * FROM file2.t1;
  }
  # Lock status:
  #    db  - shared(main), shared(file2)
  #    db2 - reserved(file2)
} {0 {}}

lock_status 4.6.1.1 db {main shared temp closed file2 shared}
lock_status 4.6.1.2 db2 {main unlocked temp closed file2 reserved}

do_test attach2-4.6.2 {
  # Writes against a reserved database are not allowed.
  catchsql {
    UPDATE file2.t1 SET a=0;
  }
} {1 {database is locked}}

lock_status 4.6.2.1 db {main shared temp closed file2 shared}
lock_status 4.6.2.2 db2 {main unlocked temp closed file2 reserved}

do_test attach2-4.7 {
  # Ensure handle 'db' retains the lock on the main file after
  # failing to obtain a write-lock on file2.
  catchsql {
    INSERT INTO t1 VALUES(1, 2)
  } db2 
} {0 {}}

lock_status 4.7.1 db {main shared temp closed file2 shared}
lock_status 4.7.2 db2 {main reserved temp closed file2 reserved}

do_test attach2-4.8 {
  # We should still be able to read test.db from db2
  execsql {SELECT * FROM t1} db2
} {1 2}

lock_status 4.8.1 db {main shared temp closed file2 shared}
lock_status 4.8.2 db2 {main reserved temp closed file2 reserved}

do_test attach2-4.9 {
  # Try to upgrade the handle 'db' lock.
  catchsql {
    INSERT INTO t1 VALUES(1, 2)
  }
} {1 {database is locked}}

lock_status 4.9.1 db {main shared temp closed file2 shared}
lock_status 4.9.2 db2 {main reserved temp closed file2 reserved}

do_test attach2-4.10 {
  # We cannot commit db2 while db is holding a read-lock
  catchsql {COMMIT} db2
} {1 {database is locked}}

lock_status 4.10.1 db {main shared temp closed file2 shared}
lock_status 4.10.2 db2 {main pending temp closed file2 reserved}

set sqlite_os_trace 0
do_test attach2-4.11 {
  # db is able to commit.
  catchsql {COMMIT}
} {0 {}}

lock_status 4.11.1 db {main unlocked temp closed file2 unlocked}
lock_status 4.11.2 db2 {main pending temp closed file2 reserved}

do_test attach2-4.12 {
  # Now we can commit db2
  catchsql {COMMIT} db2
} {0 {}}

lock_status 4.12.1 db {main unlocked temp closed file2 unlocked}
lock_status 4.12.2 db2 {main unlocked temp closed file2 unlocked}

do_test attach2-4.13 {
  execsql {SELECT * FROM file2.t1}
} {1 2}
do_test attach2-4.14 {
  execsql {INSERT INTO t1 VALUES(1, 2)}
} {}
do_test attach2-4.15 {
  execsql {SELECT * FROM t1} db2
} {1 2 1 2}

db close
db2 close
file delete -force test2.db

# These tests - attach2-5.* - check that the master journal file is deleted
# correctly when a multi-file transaction is committed or rolled back.
#
# Update: It's not actually created if a rollback occurs, so that test
# doesn't really prove too much.
foreach f [glob test.db*] {file delete -force $f}
do_test attach2-5.1 {
  sqlite3 db test.db
  execsql {
    ATTACH 'test.db2' AS aux;
  }
} {}
do_test attach2-5.2 {
  execsql {
    BEGIN;
    CREATE TABLE tbl(a, b, c);
    CREATE TABLE aux.tbl(a, b, c);
    COMMIT;
  }
} {}
do_test attach2-5.3 {
  glob test.db*
} {test.db test.db2}
do_test attach2-5.4 {
  execsql {
    BEGIN;
    DROP TABLE aux.tbl;
    DROP TABLE tbl;
    ROLLBACK;
  }
} {}
do_test attach2-5.5 {
  glob test.db*
} {test.db test.db2}

# Check that a database cannot be ATTACHed or DETACHed during a transaction.
do_test attach2-6.1 {
  execsql {
    BEGIN;
  }
} {}
do_test attach2-6.2 {
  catchsql {
    ATTACH 'test3.db' as aux2;
  }
} {1 {cannot ATTACH database within transaction}}

do_test attach2-6.3 {
  catchsql {
    DETACH aux;
  }
} {1 {cannot DETACH database within transaction}}
do_test attach2-6.4 {
  execsql {
    COMMIT;
    DETACH aux;
  }
} {}

db close

finish_test

--- NEW FILE: attach3.test ---
# 2003 July 1
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and schema changes to attached databases.
#
# $Id: attach3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create tables t1 and t2 in the main database
execsql {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
}

# Create tables t1 and t2 in database file test2.db
file delete -force test2.db
sqlite3 db2 test2.db
execsql {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
} db2
db2 close

# Create a table in the auxilary database.
do_test attach3-1.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
  }
} {}
do_test attach3-1.2 {
  execsql {
    CREATE TABLE aux.t3(e, f);
  }
} {}
do_test attach3-1.3 {
  execsql {
    SELECT * FROM sqlite_master WHERE name = 't3';
  }
} {}
do_test attach3-1.4 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 't3';
  }
} {table t3 t3 4 {CREATE TABLE t3(e, f)}}
do_test attach3-1.5 {
  execsql {
    INSERT INTO t3 VALUES(1, 2);
    SELECT * FROM t3;
  }
} {1 2}

# Create an index on the auxilary database table.
do_test attach3-2.1 {
  execsql {
    CREATE INDEX aux.i1 on t3(e);
  }
} {}
execsql {
  pragma vdbe_trace = off;
}
do_test attach3-2.2 {
  execsql {
    SELECT * FROM sqlite_master WHERE name = 'i1';
  }
} {}
do_test attach3-2.3 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {index i1 t3 5 {CREATE INDEX i1 on t3(e)}}

# Drop the index on the aux database table.
do_test attach3-3.1 {
  execsql {
    DROP INDEX aux.i1;
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {}
do_test attach3-3.2 {
  execsql {
    CREATE INDEX aux.i1 on t3(e);
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {index i1 t3 5 {CREATE INDEX i1 on t3(e)}}
do_test attach3-3.3 {
  execsql {
    DROP INDEX i1;
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {}

# Drop tables t1 and t2 in the auxilary database.
do_test attach3-4.1 {
  execsql {
    DROP TABLE aux.t1;
    SELECT name FROM aux.sqlite_master;
  }
} {t2 t3}
do_test attach3-4.2 {
  # This will drop main.t2
  execsql {
    DROP TABLE t2;
    SELECT name FROM aux.sqlite_master;
  }
} {t2 t3}
do_test attach3-4.3 {
  execsql {
    DROP TABLE t2;
    SELECT name FROM aux.sqlite_master;
  }
} {t3}

# Create a view in the auxilary database.
do_test attach3-5.1 {
  execsql {
    CREATE VIEW aux.v1 AS SELECT * FROM t3;
  }
} {}
do_test attach3-5.2 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'v1';
  }
} {view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t3}}
do_test attach3-5.3 {
  execsql {
    INSERT INTO aux.t3 VALUES('hello', 'world');
    SELECT * FROM v1;
  }
} {1 2 hello world}

# Drop the view 
do_test attach3-6.1 {
  execsql {
    DROP VIEW aux.v1;
  }
} {}
do_test attach3-6.2 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'v1';
  }
} {}

# Create a trigger in the auxilary database.
do_test attach3-7.1 {
  execsql {
    CREATE TRIGGER aux.tr1 AFTER INSERT ON t3 BEGIN
      INSERT INTO t3 VALUES(new.e*2, new.f*2);
    END;
  }
} {}
do_test attach3-7.2 {
  execsql {
    DELETE FROM t3;
    INSERT INTO t3 VALUES(10, 20);
    SELECT * FROM t3;
  }
} {10 20 20 40}
do_test attach3-5.3 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'tr1';
  }
} {trigger tr1 t3 0 {CREATE TRIGGER tr1 AFTER INSERT ON t3 BEGIN
      INSERT INTO t3 VALUES(new.e*2, new.f*2);
    END}}

# Drop the trigger 
do_test attach3-8.1 {
  execsql {
    DROP TRIGGER aux.tr1;
  }
} {}
do_test attach3-8.2 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'tr1';
  }
} {}

# Try to trick SQLite into dropping the wrong temp trigger.
do_test attach3-9.0 {
  execsql {
    CREATE TABLE main.t4(a, b, c);
    CREATE TABLE aux.t4(a, b, c);
    CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN 
      SELECT 'hello world';
    END;
    SELECT count(*) FROM sqlite_temp_master;
  }
} {1}
do_test attach3-9.1 {
  execsql {
    DROP TABLE main.t4;
    SELECT count(*) FROM sqlite_temp_master;
  }
} {1}
do_test attach3-9.2 {
  execsql {
    DROP TABLE aux.t4;
    SELECT count(*) FROM sqlite_temp_master;
  }
} {0}

# Make sure the aux.sqlite_master table is read-only
do_test attach3-10.0 {
  catchsql {
    INSERT INTO aux.sqlite_master VALUES(1, 2, 3, 4, 5);
  }
} {1 {table sqlite_master may not be modified}}

# Failure to attach leaves us in a workable state.
# Ticket #811
#
do_test attach3-11.0 {
  catchsql {
    ATTACH DATABASE '/nodir/nofile.x' AS notadb;
  }
} {1 {unable to open database: /nodir/nofile.x}}
do_test attach3-11.1 {
  catchsql {
    ATTACH DATABASE ':memory:' AS notadb;
  }
} {0 {}}
do_test attach3-11.2 {
  catchsql {
    DETACH DATABASE notadb;
  }
} {0 {}}

finish_test

--- NEW FILE: auth.test ---
# 2003 April 4
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: auth.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
[...1824 lines suppressed...]
    END;
    SELECT * FROM v1;
  }
} {115 117}
do_test auth-4.5 {
  set authargs {}
  execsql {
    DELETE FROM v1 WHERE x=117
  }
  set authargs
} [list \
  SQLITE_DELETE v1     {} main {} \
  SQLITE_READ   v1     x  main {} \
  SQLITE_SELECT {}     {} {}   v1 \
  SQLITE_READ   t2     a  main v1 \
  SQLITE_READ   t2     b  main v1 \
  SQLITE_INSERT v1chng {} main r3 \
  SQLITE_READ   v1     x  main r3]

finish_test

--- NEW FILE: bigfile.test ---
# 2002 November 30
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the ability of SQLite to handle database
# files larger than 4GB.
#
# $Id: bigfile.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# These tests only work for Tcl version 8.4 and later.  Prior to 8.4,
# Tcl was unable to handle large files.
#
scan $::tcl_version %f vx
if {$vx<8.4} return

# Mac OS X does not handle large files efficiently.  So skip this test
# on that platform.
if {$tcl_platform(os)=="Darwin"} return

# This is the md5 checksum of all the data in table t1 as created
# by the first test.  We will use this number to make sure that data
# never changes.
#
set MAGIC_SUM {593f1efcfdbe698c28b4b1b693f7e4cf}

do_test bigfile-1.1 {
  execsql {
    BEGIN;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES('abcdefghijklmnopqrstuvwxyz');
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
    COMMIT;
  }
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM

# Try to create a large file - a file that is larger than 2^32 bytes.
# If this fails, it means that the system being tested does not support
# large files.  So skip all of the remaining tests in this file.
#
db close
if {[catch {fake_big_file 4096 test.db}]} {
  puts "**** Unable to create a file larger than 4096 MB. *****"
  finish_test
  return
}

do_test bigfile-1.2 {
  sqlite3 db test.db
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM


# The previous test may fail on some systems because they are unable
# to handle large files.  If that is so, then skip all of the following
# tests.  We will know the above test failed because the "db" command
# does not exist.
#
if {[llength [info command db]]>0} {

do_test bigfile-1.3 {
  execsql {
    CREATE TABLE t2 AS SELECT * FROM t1;
    SELECT md5sum(x) FROM t2;
  }
} $::MAGIC_SUM
do_test bigfile-1.4 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM
do_test bigfile-1.5 {
  execsql {
    SELECT md5sum(x) FROM t2;
  }
} $::MAGIC_SUM

db close
if {[catch {fake_big_file 8192 test.db}]} {
  puts "**** Unable to create a file larger than 8192 MB. *****"
  finish_test
  return
}

do_test bigfile-1.6 {
  sqlite3 db test.db
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM
do_test bigfile-1.7 {
  execsql {
    CREATE TABLE t3 AS SELECT * FROM t1;
    SELECT md5sum(x) FROM t3;
  }
} $::MAGIC_SUM
do_test bigfile-1.8 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM
do_test bigfile-1.9 {
  execsql {
    SELECT md5sum(x) FROM t2;
  }
} $::MAGIC_SUM
do_test bigfile-1.10 {
  execsql {
    SELECT md5sum(x) FROM t3;
  }
} $::MAGIC_SUM

db close
if {[catch {fake_big_file 16384 test.db}]} {
  puts "**** Unable to create a file larger than 16384 MB. *****"
  finish_test
  return
}

do_test bigfile-1.11 {
  sqlite3 db test.db
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM
do_test bigfile-1.12 {
  execsql {
    CREATE TABLE t4 AS SELECT * FROM t1;
    SELECT md5sum(x) FROM t4;
  }
} $::MAGIC_SUM
do_test bigfile-1.13 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT md5sum(x) FROM t1;
  }
} $::MAGIC_SUM
do_test bigfile-1.14 {
  execsql {
    SELECT md5sum(x) FROM t2;
  }
} $::MAGIC_SUM
do_test bigfile-1.15 {
  execsql {
    SELECT md5sum(x) FROM t3;
  }
} $::MAGIC_SUM
do_test bigfile-1.16 {
  execsql {
    SELECT md5sum(x) FROM t3;
  }
} $::MAGIC_SUM

} ;# End of the "if( db command exists )"

finish_test

--- NEW FILE: bigrow.test ---
# 2001 September 23
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is stressing the library by putting large amounts
# of data in a single row of a table.
#
# $Id: bigrow.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Make a big string that we can use for test data
#
do_test bigrow-1.0 {
  set ::bigstr {}
  for {set i 1} {$i<=9999} {incr i} {
    set sep [string index "abcdefghijklmnopqrstuvwxyz" [expr {$i%26}]]
    append ::bigstr "$sep [format %04d $i] "
  }
  string length $::bigstr
} {69993}

# Make a table into which we can insert some but records.
#
do_test bigrow-1.1 {
  execsql {
    CREATE TABLE t1(a text, b text, c text);
    SELECT name FROM sqlite_master
      WHERE type='table' OR type='index'
      ORDER BY name
  }
} {t1}

do_test bigrow-1.2 {
  set ::big1 [string range $::bigstr 0 65519]
  set sql "INSERT INTO t1 VALUES('abc',"
  append sql "'$::big1', 'xyz');"
  execsql $sql
  execsql {SELECT a, c FROM t1}
} {abc xyz}
do_test bigrow-1.3 {
  execsql {SELECT b FROM t1}
} [list $::big1]
do_test bigrow-1.4 {
  set ::big2 [string range $::bigstr 0 65520]
  set sql "INSERT INTO t1 VALUES('abc2',"
  append sql "'$::big2', 'xyz2');"
  set r [catch {execsql $sql} msg]
  lappend r $msg
} {0 {}}
do_test bigrow-1.4.1 {
  execsql {SELECT b FROM t1 ORDER BY c}
} [list $::big1 $::big2]
do_test bigrow-1.4.2 {
  execsql {SELECT c FROM t1 ORDER BY c}
} {xyz xyz2}
do_test bigrow-1.4.3 {
  execsql {DELETE FROM t1 WHERE a='abc2'}
  execsql {SELECT c FROM t1}
} {xyz}

do_test bigrow-1.5 {
  execsql {
    UPDATE t1 SET a=b, b=a;
    SELECT b,c FROM t1
  }
} {abc xyz}
do_test bigrow-1.6 {
  execsql {
    SELECT * FROM t1
  }
} [list $::big1 abc xyz]
do_test bigrow-1.7 {
  execsql {
    INSERT INTO t1 VALUES('1','2','3');
    INSERT INTO t1 VALUES('A','B','C');
    SELECT b FROM t1 WHERE a=='1';
  }
} {2}
do_test bigrow-1.8 {
  execsql "SELECT b FROM t1 WHERE a=='$::big1'"
} {abc}
do_test bigrow-1.9 {
  execsql "SELECT b FROM t1 WHERE a!='$::big1' ORDER BY a"
} {2 B}

# Try doing some indexing on big columns
#
do_test bigrow-2.1 {
  execsql {
    CREATE INDEX i1 ON t1(a)
  }
  execsql "SELECT b FROM t1 WHERE a=='$::big1'"
} {abc}
do_test bigrow-2.2 {
  execsql {
    UPDATE t1 SET a=b, b=a
  }
  execsql "SELECT b FROM t1 WHERE a=='abc'"
} [list $::big1]
do_test bigrow-2.3 {
  execsql {
    UPDATE t1 SET a=b, b=a
  }
  execsql "SELECT b FROM t1 WHERE a=='$::big1'"
} {abc}
catch {unset ::bigstr}
catch {unset ::big1}
catch {unset ::big2}

# Mosts of the tests above were created back when rows were limited in
# size to 64K.  Now rows can be much bigger.  Test that logic.  Also
# make sure things work correctly at the transition boundries between
# row sizes of 256 to 257 bytes and from 65536 to 65537 bytes.
#
# We begin by testing the 256..257 transition.
#
do_test bigrow-3.1 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi');
  }
  execsql {SELECT a,length(b),c FROM t1}
} {one 30 hi}
do_test bigrow-3.2 {
  execsql {
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
  }
  execsql {SELECT a,length(b),c FROM t1}
} {one 240 hi}
for {set i 1} {$i<10} {incr i} {
  do_test bigrow-3.3.$i {
    execsql "UPDATE t1 SET b=b||'$i'"
    execsql {SELECT a,length(b),c FROM t1}
  } "one [expr {240+$i}] hi"
}

# Now test the 65536..65537 row-size transition.
#
do_test bigrow-4.1 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi');
  }
  execsql {SELECT a,length(b),c FROM t1}
} {one 30 hi}
do_test bigrow-4.2 {
  execsql {
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
  }
  execsql {SELECT a,length(b),c FROM t1}
} {one 122880 hi}
do_test bigrow-4.3 {
  execsql {
    UPDATE t1 SET b=substr(b,1,65515)
  }
  execsql {SELECT a,length(b),c FROM t1}
} {one 65515 hi}
for {set i 1} {$i<10} {incr i} {
  do_test bigrow-4.4.$i {
    execsql "UPDATE t1 SET b=b||'$i'"
    execsql {SELECT a,length(b),c FROM t1}
  } "one [expr {65515+$i}] hi"
}

# Check to make sure the library recovers safely if a row contains
# too much data.
#
do_test bigrow-5.1 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi');
  }
  execsql {SELECT a,length(b),c FROM t1}
} {one 30 hi}
set i 1
for {set sz 60} {$sz<1048560} {incr sz $sz} {
  do_test bigrow-5.2.$i {
    execsql {
      UPDATE t1 SET b=b||b;
      SELECT a,length(b),c FROM t1;
    }
  } "one $sz hi"
  incr i
}
do_test bigrow-5.3 {
  catchsql {UPDATE t1 SET b=b||b}
} {0 {}}
do_test bigrow-5.4 {
  execsql {SELECT length(b) FROM t1}
} 1966080
do_test bigrow-5.5 {
  catchsql {UPDATE t1 SET b=b||b}
} {0 {}}
do_test bigrow-5.6 {
  execsql {SELECT length(b) FROM t1}
} 3932160
do_test bigrow-5.99 {
  execsql {DROP TABLE t1}
} {}

finish_test

--- NEW FILE: bind.test ---
# 2003 September 6
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the sqlite_bind API.
#
# $Id: bind.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc sqlite_step {stmt N VALS COLS} {
  upvar VALS vals
  upvar COLS cols
  set vals [list]
  set cols [list]

  set rc [sqlite3_step $stmt]
  for {set i 0} {$i < [sqlite3_column_count $stmt]} {incr i} {
    lappend cols [sqlite3_column_name $stmt $i]
  }
  for {set i 0} {$i < [sqlite3_data_count $stmt]} {incr i} {
    lappend vals [sqlite3_column_text $stmt $i]
  }

  return $rc
}

do_test bind-1.1 {
  db close
  set DB [sqlite3 db test.db]
  execsql {CREATE TABLE t1(a,b,c);}
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(:1,?,:abc)} -1 TAIL]
  set TAIL
} {}
do_test bind-1.1.1 {
  sqlite3_bind_parameter_count $VM
} 3
do_test bind-1.1.2 {
  sqlite3_bind_parameter_name $VM 1
} {:1}
do_test bind-1.1.3 {
  sqlite3_bind_parameter_name $VM 2
} {}
do_test bind-1.1.4 {
  sqlite3_bind_parameter_name $VM 3
} {:abc}
do_test bind-1.2 {
  sqlite_step $VM N VALUES COLNAMES
} {SQLITE_DONE}
do_test bind-1.3 {
  execsql {SELECT rowid, * FROM t1}
} {1 {} {} {}}
do_test bind-1.4 {
  sqlite3_reset $VM
  sqlite_bind $VM 1 {test value 1} normal
  sqlite_step $VM N VALUES COLNAMES
} SQLITE_DONE
do_test bind-1.5 {
  execsql {SELECT rowid, * FROM t1}
} {1 {} {} {} 2 {test value 1} {} {}}
do_test bind-1.6 {
  sqlite3_reset $VM
  sqlite_bind $VM 3 {'test value 2'} normal
  sqlite_step $VM N VALUES COLNAMES
} SQLITE_DONE
do_test bind-1.7 {
  execsql {SELECT rowid, * FROM t1}
} {1 {} {} {} 2 {test value 1} {} {} 3 {test value 1} {} {'test value 2'}}
do_test bind-1.8 {
  sqlite3_reset $VM
  set sqlite_static_bind_value 123
  sqlite_bind $VM 1 {} static
  sqlite_bind $VM 2 {abcdefg} normal
  sqlite_bind $VM 3 {} null
  execsql {DELETE FROM t1}
  sqlite_step $VM N VALUES COLNAMES
  execsql {SELECT rowid, * FROM t1}
} {1 123 abcdefg {}}
do_test bind-1.9 {
  sqlite3_reset $VM
  sqlite_bind $VM 1 {456} normal
  sqlite_step $VM N VALUES COLNAMES
  execsql {SELECT rowid, * FROM t1}
} {1 123 abcdefg {} 2 456 abcdefg {}}

do_test bind-1.99 {
  sqlite3_finalize $VM
} SQLITE_OK

do_test bind-2.1 {
  execsql {
    DELETE FROM t1;
  }
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES($one,$::two,${x})} -1 TAIL]
  set TAIL
} {}
do_test bind-2.1.1 {
  sqlite3_bind_parameter_count $VM
} 3
do_test bind-2.1.2 {
  sqlite3_bind_parameter_name $VM 1
} {$one}
do_test bind-2.1.3 {
  sqlite3_bind_parameter_name $VM 2
} {$::two}
do_test bind-2.1.4 {
  sqlite3_bind_parameter_name $VM 3
} {${x}}
do_test bind-2.1.5 {
  sqlite3_bind_parameter_index $VM {$one}
} 1
do_test bind-2.1.6 {
  sqlite3_bind_parameter_index $VM {$::two}
} 2
do_test bind-2.1.7 {
  sqlite3_bind_parameter_index $VM {${x}}
} 3
do_test bind-2.1.8 {
  sqlite3_bind_parameter_index $VM {:hi}
} 0

# 32 bit Integers
do_test bind-2.2 {
  sqlite3_bind_int $VM 1 123
  sqlite3_bind_int $VM 2 456
  sqlite3_bind_int $VM 3 789
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 123 456 789}
do_test bind-2.3 {
  sqlite3_bind_int $VM 2 -2000000000
  sqlite3_bind_int $VM 3 2000000000
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 123 456 789 2 123 -2000000000 2000000000}
do_test bind-2.4 {
  execsql {SELECT typeof(a), typeof(b), typeof(c) FROM t1}
} {integer integer integer integer integer integer}
do_test bind-2.5 {
  execsql {
    DELETE FROM t1;
  }
} {}

# 64 bit Integers
do_test bind-3.1 {
  sqlite3_bind_int64 $VM 1 32
  sqlite3_bind_int64 $VM 2 -2000000000000
  sqlite3_bind_int64 $VM 3 2000000000000
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 32 -2000000000000 2000000000000}
do_test bind-3.2 {
  execsql {SELECT typeof(a), typeof(b), typeof(c) FROM t1}
} {integer integer integer}
do_test bind-3.3 {
  execsql {
    DELETE FROM t1;
  }
} {}

# Doubles
do_test bind-4.1 {
  sqlite3_bind_double $VM 1 1234.1234
  sqlite3_bind_double $VM 2 0.00001
  sqlite3_bind_double $VM 3 123456789
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 1234.1234 1e-05 123456789.0}
do_test bind-4.2 {
  execsql {SELECT typeof(a), typeof(b), typeof(c) FROM t1}
} {real real real}
do_test bind-4.3 {
  execsql {
    DELETE FROM t1;
  }
} {}

# NULL
do_test bind-5.1 {
  sqlite3_bind_null $VM 1
  sqlite3_bind_null $VM 2
  sqlite3_bind_null $VM 3 
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 {} {} {}}
do_test bind-5.2 {
  execsql {SELECT typeof(a), typeof(b), typeof(c) FROM t1}
} {null null null}
do_test bind-5.3 {
  execsql {
    DELETE FROM t1;
  }
} {}

# UTF-8 text
do_test bind-6.1 {
  sqlite3_bind_text $VM 1 hellothere 5
  sqlite3_bind_text $VM 2 ".." 1
  sqlite3_bind_text $VM 3 world -1
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 hello . world}
do_test bind-6.2 {
  execsql {SELECT typeof(a), typeof(b), typeof(c) FROM t1}
} {text text text}
do_test bind-6.3 {
  execsql {
    DELETE FROM t1;
  }
} {}

# UTF-16 text
do_test bind-7.1 {
  sqlite3_bind_text16 $VM 1 [encoding convertto unicode hellothere] 10
  sqlite3_bind_text16 $VM 2 [encoding convertto unicode ""] 0
  sqlite3_bind_text16 $VM 3 [encoding convertto unicode world] 10
  sqlite_step $VM N VALUES COLNAMES
  sqlite3_reset $VM
  execsql {SELECT rowid, * FROM t1}
} {1 hello {} world}
do_test bind-7.2 {
  execsql {SELECT typeof(a), typeof(b), typeof(c) FROM t1}
} {text text text}
do_test bind-7.3 {
  execsql {
    DELETE FROM t1;
  }
} {}

# Test that the 'out of range' error works.
do_test bind-8.1 {
  catch { sqlite3_bind_null $VM 0 }
} {1}
do_test bind-8.2 {
  sqlite3_errmsg $DB
} {bind index out of range}
do_test bind-8.3 {
  encoding convertfrom unicode [sqlite3_errmsg16 $DB]
} {bind index out of range}
do_test bind-8.4 {
  sqlite3_bind_null $VM 1 
  sqlite3_errmsg $DB
} {not an error}
do_test bind-8.5 {
  catch { sqlite3_bind_null $VM 4 }
} {1}
do_test bind-8.6 {
  sqlite3_errmsg $DB
} {bind index out of range}
do_test bind-8.7 {
  encoding convertfrom unicode [sqlite3_errmsg16 $DB]
} {bind index out of range}

do_test bind-8.8 {
  catch { sqlite3_bind_blob $VM 0 "abc" 3 }
} {1}
do_test bind-8.9 {
  catch { sqlite3_bind_blob $VM 4 "abc" 3 }
} {1}
do_test bind-8.10 {
  catch { sqlite3_bind_text $VM 0 "abc" 3 }
} {1}
do_test bind-8.11 {
  catch { sqlite3_bind_text16 $VM 4 "abc" 2 }
} {1}
do_test bind-8.12 {
  catch { sqlite3_bind_int $VM 0 5 }
} {1}
do_test bind-8.13 {
  catch { sqlite3_bind_int $VM 4 5 }
} {1}
do_test bind-8.14 {
  catch { sqlite3_bind_double $VM 0 5.0 }
} {1}
do_test bind-8.15 {
  catch { sqlite3_bind_double $VM 4 6.0 }
} {1}

do_test bind-8.99 {
  sqlite3_finalize $VM
} SQLITE_OK

do_test bind-9.1 {
  execsql {
    CREATE TABLE t2(a,b,c,d,e,f);
  }
  set rc [catch {
    sqlite3_prepare $DB {
      INSERT INTO t2(a) VALUES(?0)
    } -1 TAIL
  } msg]
  lappend rc $msg
} {1 {(1) variable number must be between ?1 and ?999}}
do_test bind-9.2 {
  set rc [catch {
    sqlite3_prepare $DB {
      INSERT INTO t2(a) VALUES(?1000)
    } -1 TAIL
  } msg]
  lappend rc $msg
} {1 {(1) variable number must be between ?1 and ?999}}
do_test bind-9.3 {
  set VM [
    sqlite3_prepare $DB {
      INSERT INTO t2(a,b) VALUES(?1,?999)
    } -1 TAIL
  ]
  sqlite3_bind_parameter_count $VM
} {999}
catch {sqlite3_finalize $VM}
do_test bind-9.4 {
  set VM [
    sqlite3_prepare $DB {
      INSERT INTO t2(a,b,c,d) VALUES(?1,?999,?,?)
    } -1 TAIL
  ]
  sqlite3_bind_parameter_count $VM
} {1001}
do_test bind-9.5 {
  sqlite3_bind_int $VM 1 1
  sqlite3_bind_int $VM 999 999
  sqlite3_bind_int $VM 1000 1000
  sqlite3_bind_int $VM 1001 1001
  sqlite3_step $VM
} SQLITE_DONE
do_test bind-9.6 {
  sqlite3_finalize $VM
} SQLITE_OK
do_test bind-9.7 {
  execsql {SELECT * FROM t2}
} {1 999 1000 1001 {} {}}

do_test bind-10.1 {
  catch {sqlite3_finalize $VM}
  set VM [
    sqlite3_prepare $DB {
      INSERT INTO t2(a,b,c,d,e,f) VALUES(:abc,$abc,:abc,$ab,$abc,:abc)
    } -1 TAIL
  ]
  sqlite3_bind_parameter_count $VM
} 3
do_test bind-10.2 {
  sqlite3_bind_parameter_index $VM :abc
} 1
do_test bind-10.3 {
  sqlite3_bind_parameter_index $VM {$abc}
} 2
do_test bind-10.4 {
  sqlite3_bind_parameter_index $VM {$ab}
} 3
do_test bind-10.5 {
  sqlite3_bind_parameter_name $VM 1
} :abc
do_test bind-10.6 {
  sqlite3_bind_parameter_name $VM 2
} {$abc}
do_test bind-10.7 {
  sqlite3_bind_parameter_name $VM 3
} {$ab}
do_test bind-10.8 {
  sqlite3_bind_int $VM 1 1
  sqlite3_bind_int $VM 2 2
  sqlite3_bind_int $VM 3 3
  sqlite3_step $VM
} SQLITE_DONE
do_test bind-10.9 {
  sqlite3_finalize $VM
} SQLITE_OK
do_test bind-10.10 {
  execsql {SELECT * FROM t2}
} {1 999 1000 1001 {} {} 1 2 1 3 2 1}

finish_test

--- NEW FILE: blob.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: blob.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc bin_to_hex {blob} {
  set bytes {}
  binary scan $blob \c* bytes
  set bytes2 [list]
  foreach b $bytes {lappend bytes2 [format %02X [expr $b & 0xFF]]}
  join $bytes2 {}
}

# Simplest possible case. Specify a blob literal
do_test blob-1.0 {
  set blob [execsql {SELECT X'01020304'}]
  bin_to_hex [lindex $blob 0]
} {01020304}
do_test blob-1.1 {
  set blob [execsql {SELECT x'ABCDEF'}]
  bin_to_hex [lindex $blob 0]
} {ABCDEF}
do_test blob-1.2 {
  set blob [execsql {SELECT x''}]
  bin_to_hex [lindex $blob 0]
} {}
do_test blob-1.3 {
  set blob [execsql {SELECT x'abcdEF12'}]
  bin_to_hex [lindex $blob 0]
} {ABCDEF12}

# Try some syntax errors in blob literals.
do_test blob-1.4 {
  catchsql {SELECT X'01020k304', 100}
} {1 {unrecognized token: "X'01020"}}
do_test blob-1.5 {
  catchsql {SELECT X'01020, 100}
} {1 {unrecognized token: "X'01020"}}
do_test blob-1.6 {
  catchsql {SELECT X'01020 100'}
} {1 {unrecognized token: "X'01020"}}
do_test blob-1.7 {
  catchsql {SELECT X'01001'}
} {1 {unrecognized token: "X'01001'"}}

# Insert a blob into a table and retrieve it.
do_test blob-2.0 {
  execsql {
    CREATE TABLE t1(a BLOB, b BLOB);
    INSERT INTO t1 VALUES(X'123456', x'7890ab');
    INSERT INTO t1 VALUES(X'CDEF12', x'345678');
  }
  set blobs [execsql {SELECT * FROM t1}]
  set blobs2 [list]
  foreach b $blobs {lappend blobs2 [bin_to_hex $b]}
  set blobs2
} {123456 7890AB CDEF12 345678}

# An index on a blob column
do_test blob-2.1 {
  execsql {
    CREATE INDEX i1 ON t1(a);
  }
  set blobs [execsql {SELECT * FROM t1}]
  set blobs2 [list]
  foreach b $blobs {lappend blobs2 [bin_to_hex $b]}
  set blobs2
} {123456 7890AB CDEF12 345678}
do_test blob-2.2 {
  set blobs [execsql {SELECT * FROM t1 where a = X'123456'}]
  set blobs2 [list]
  foreach b $blobs {lappend blobs2 [bin_to_hex $b]}
  set blobs2
} {123456 7890AB}
do_test blob-2.3 {
  set blobs [execsql {SELECT * FROM t1 where a = X'CDEF12'}]
  set blobs2 [list]
  foreach b $blobs {lappend blobs2 [bin_to_hex $b]}
  set blobs2
} {CDEF12 345678}
do_test blob-2.4 {
  set blobs [execsql {SELECT * FROM t1 where a = X'CD12'}]
  set blobs2 [list]
  foreach b $blobs {lappend blobs2 [bin_to_hex $b]}
  set blobs2
} {}

# Try to bind a blob value to a prepared statement.
do_test blob-3.0 {
  set DB [sqlite3 db2 test.db]
  set STMT [sqlite3_prepare $DB "DELETE FROM t1 WHERE a = ?" -1 DUMMY]
  sqlite3_bind_blob $STMT 1 "\x12\x34\x56" 3
  sqlite3_step $STMT
} {SQLITE_DONE}
do_test blob-3.1 {
  sqlite3_finalize $STMT
  db2 close
} {}
do_test blob-2.3 {
  set blobs [execsql {SELECT * FROM t1}]
  set blobs2 [list]
  foreach b $blobs {lappend blobs2 [bin_to_hex $b]}
  set blobs2
} {CDEF12 345678}

finish_test



--- NEW FILE: btree.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend
#
# $Id: btree.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

[...996 lines suppressed...]
#   4.  Implement btree_sanity and put it throughout this script
#

do_test btree-15.98 {
  btree_close_cursor $::c1
  lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-15.99 {
  btree_rollback $::b1
  lindex [btree_pager_stats $::b1] 1
} {0}
btree_pager_ref_dump $::b1

do_test btree-99.1 {
  btree_close $::b1
} {}
catch {unset data}
catch {unset key}

finish_test

--- NEW FILE: btree2.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend
#
# $Id: btree2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

if {[info commands btree_open]!=""} {

# Create a new database file containing no entries.  The database should
# contain 5 tables:
#
#     2   The descriptor table
#     3   The foreground table
#     4   The background table
#     5   The long key table
#     6   The long data table
#
# An explanation for what all these tables are used for is provided below.
#
do_test btree2-1.1 {
  expr srand(1)
  file delete -force test2.bt
  file delete -force test2.bt-journal
  set ::b [btree_open test2.bt 2000 0]
  btree_begin_transaction $::b
  btree_create_table $::b 0
} {2}
do_test btree2-1.2 {
  btree_create_table $::b 0
} {3}
do_test btree2-1.3 {
  btree_create_table $::b 0
} {4}
do_test btree2-1.4 {
  btree_create_table $::b 0
} {5}
do_test btree2-1.5 {
  btree_create_table $::b 0
} {6}
do_test btree2-1.6 {
  set ::c2 [btree_cursor $::b 2 1]
  btree_insert $::c2 {one} {1}
  btree_move_to $::c2 {one}
  btree_delete $::c2
  btree_close_cursor $::c2
  btree_commit $::b
  btree_integrity_check $::b 1 2 3 4 5 6
} {}

# This test module works by making lots of pseudo-random changes to a
# database while simultaneously maintaining an invariant on that database.
# Periodically, the script does a sanity check on the database and verifies
# that the invariant is satisfied.
#
# The invariant is as follows:
#
#   1.  The descriptor table always contains 2 enters.  An entry keyed by
#       "N" is the number of elements in the foreground and background tables
#       combined.  The entry keyed by "L" is the number of digits in the keys
#       for foreground and background tables.
#
#   2.  The union of the foreground an background tables consists of N entries
#       where each entry has an L-digit key. (Actually, some keys can be longer 
#       than L characters, but they always start with L digits.)  The keys
#       cover all integers between 1 and N.  Whenever an entry is added to
#       the foreground it is removed form the background and vice versa.
#
#   3.  Some entries in the foreground and background tables have keys that
#       begin with an L-digit number but are followed by additional characters.
#       For each such entry there is a corresponding entry in the long key
#       table.  The long key table entry has a key which is just the L-digit
#       number and data which is the length of the key in the foreground and
#       background tables.
#
#   4.  The data for both foreground and background entries is usually a
#       short string.  But some entries have long data strings.  For each
#       such entries there is an entry in the long data type.  The key to
#       long data table is an L-digit number.  (The extension on long keys
#       is omitted.)  The data is the number of charaters in the data of the
#       foreground or background entry.
#
# The following function builds a database that satisfies all of the above
# invariants.
#
proc build_db {N L} {
  for {set i 2} {$i<=6} {incr i} {
    catch {btree_close_cursor [set ::c$i]}
    btree_clear_table $::b $i
    set ::c$i [btree_cursor $::b $i 1]
  }
  btree_insert $::c2 N $N
  btree_insert $::c2 L $L
  set format %0${L}d
  for {set i 1} {$i<=$N} {incr i} { 
    set key [format $format $i]
    set data $key
    btree_insert $::c3 $key $data
  }
}

# Given a base key number and a length, construct the full text of the key
# or data.
#
proc make_payload {keynum L len} {
  set key [format %0${L}d $keynum]
  set r $key
  set i 1
  while {[string length $r]<$len} {
    append r " ($i) $key"
    incr i
  }
  return [string range $r 0 [expr {$len-1}]]
}

# Verify the invariants on the database.  Return an empty string on 
# success or an error message if something is amiss.
#
proc check_invariants {} {
  set ck [btree_integrity_check $::b 1 2 3 4 5 6]
  if {$ck!=""} {
    puts "\n*** SANITY:\n$ck"
    exit
    return $ck
  }
  btree_move_to $::c3 {}
  btree_move_to $::c4 {}
  btree_move_to $::c2 N
  set N [btree_data $::c2]
  btree_move_to $::c2 L
  set L [btree_data $::c2]
  set LM1 [expr {$L-1}]
  for {set i 1} {$i<=$N} {incr i} {
    set key [btree_key $::c3]
    if {[scan $key %d k]<1} {set k 0}
    if {$k!=$i} {
      set key [btree_key $::c4]
      if {[scan $key %d k]<1} {set k 0}
      if {$k!=$i} {
        return "Key $i is missing from both foreground and background"
      }
      set data [btree_data $::c4]
      btree_next $::c4
    } else {
      set data [btree_data $::c3]
      btree_next $::c3
    }
    set skey [string range $key 0 $LM1]
    if {[btree_move_to $::c5 $skey]==0} {
      set keylen [btree_data $::c5]
    } else {
      set keylen $L
    }
    if {[string length $key]!=$keylen} {
      return "Key $i is the wrong size.\
              Is \"$key\" but should be \"[make_payload $k $L $keylen]\""
    }
    if {[make_payload $k $L $keylen]!=$key} {
      return "Key $i has an invalid extension"
    }
    if {[btree_move_to $::c6 $skey]==0} {
      set datalen [btree_data $::c6]
    } else {
      set datalen $L
    }
    if {[string length $data]!=$datalen} {
      return "Data for $i is the wrong size.\
              Is [string length $data] but should be $datalen"
    }
    if {[make_payload $k $L $datalen]!=$data} {
      return "Entry $i has an incorrect data"
    }
  }
}

# Look at all elements in both the foreground and background tables.
# Make sure the key is always the same as the prefix of the data.
#
# This routine was used for hunting bugs.  It is not a part of standard
# tests.
#
proc check_data {n key} {
  global c3 c4
  incr n -1
  foreach c [list $c3 $c4] {
    btree_first $c  ;# move_to $c $key
    set cnt 0
    while {![btree_eof $c]} {
      set key [btree_key $c]
      set data [btree_data $c]
      if {[string range $key 0 $n] ne [string range $data 0 $n]} {
        puts "key=[list $key] data=[list $data] n=$n"
        puts "cursor info = [btree_cursor_info $c]"
        btree_page_dump $::b [lindex [btree_cursor_info $c] 0]
        exit
      }
      btree_next $c
    }
  }
}

# Make random changes to the database such that each change preserves
# the invariants.  The number of changes is $n*N where N is the parameter
# from the descriptor table.  Each changes begins with a random key.
# the entry with that key is put in the foreground table with probability
# $I and it is put in background with probability (1.0-$I).  It gets
# a long key with probability $K and long data with probability $D.  
# 
set chngcnt 0
proc random_changes {n I K D} {
  global chngcnt
  btree_move_to $::c2 N
  set N [btree_data $::c2]
  btree_move_to $::c2 L
  set L [btree_data $::c2]
  set LM1 [expr {$L-1}]
  set total [expr {int($N*$n)}]
  set format %0${L}d
  for {set i 0} {$i<$total} {incr i} {
    set k [expr {int(rand()*$N)+1}]
    set insert [expr {rand()<=$I}]
    set longkey [expr {rand()<=$K}]
    set longdata [expr {rand()<=$D}]
    if {$longkey} {
      set x [expr {rand()}]
      set keylen [expr {int($x*$x*$x*$x*3000)+10}]
    } else {
      set keylen $L
    }
    set key [make_payload $k $L $keylen]
    if {$longdata} {
      set x [expr {rand()}]
      set datalen [expr {int($x*$x*$x*$x*3000)+10}]
    } else {
      set datalen $L
    }
    set data [make_payload $k $L $datalen]
    set basekey [format $format $k]
    if {[set c [btree_move_to $::c3 $basekey]]==0} {
      btree_delete $::c3
    } else {
      if {$c<0} {btree_next $::c3}
      if {[string match $basekey* [btree_key $::c3]]} {
        btree_delete $::c3
      }
    }
    if {[set c [btree_move_to $::c4 $basekey]]==0} {
      btree_delete $::c4
    } else {
      if {$c<0} {btree_next $::c4}
      if {[string match $basekey* [btree_key $::c4]]} {
        btree_delete $::c4
      }
    }
    if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
    if {$kx==$k} {
      btree_delete $::c4
    }
    # For debugging - change the "0" to "1" to integrity check after
    # every change.
    if 0 {
      incr chngcnt
      puts check----$chngcnt
      set ck [btree_integrity_check $::b 1 2 3 4 5 6]
      if {$ck!=""} {
         puts "\nSANITY CHECK FAILED!\n$ck"
         exit
       }
    }
    if {$insert} {
      btree_insert $::c3 $key $data
    } else {
      btree_insert $::c4 $key $data
    }
    if {$longkey} {
      btree_insert $::c5 $basekey $keylen
    } elseif {[btree_move_to $::c5 $basekey]==0} {
      btree_delete $::c5
    }
    if {$longdata} {
      btree_insert $::c6 $basekey $datalen
    } elseif {[btree_move_to $::c6 $basekey]==0} {
      btree_delete $::c6
    }
    # For debugging - change the "0" to "1" to integrity check after
    # every change.
    if 0 {
      incr chngcnt
      puts check----$chngcnt
      set ck [btree_integrity_check $::b 1 2 3 4 5 6]
      if {$ck!=""} {
         puts "\nSANITY CHECK FAILED!\n$ck"
         exit
       }
    }
  }
}
set btree_trace 0

# Repeat this test sequence on database of various sizes
#
set testno 2
foreach {N L} {
  10 2
  50 2
  200 3
  2000 5
} {
  puts "**** N=$N L=$L ****"
  set hash [md5file test2.bt]
  do_test btree2-$testno.1 [subst -nocommands {
    set ::c2 [btree_cursor $::b 2 1]
    set ::c3 [btree_cursor $::b 3 1]
    set ::c4 [btree_cursor $::b 4 1]
    set ::c5 [btree_cursor $::b 5 1]
    set ::c6 [btree_cursor $::b 6 1]
    btree_begin_transaction $::b
    build_db $N $L
    check_invariants
  }] {}
  do_test btree2-$testno.2 {
    btree_close_cursor $::c2
    btree_close_cursor $::c3
    btree_close_cursor $::c4
    btree_close_cursor $::c5
    btree_close_cursor $::c6
    btree_rollback $::b
    md5file test2.bt
  } $hash
  do_test btree2-$testno.3 [subst -nocommands {
    btree_begin_transaction $::b
    set ::c2 [btree_cursor $::b 2 1]
    set ::c3 [btree_cursor $::b 3 1]
    set ::c4 [btree_cursor $::b 4 1]
    set ::c5 [btree_cursor $::b 5 1]
    set ::c6 [btree_cursor $::b 6 1]
    build_db $N $L
    check_invariants
  }] {}
  do_test btree2-$testno.4 {
    btree_commit $::b
    check_invariants
  } {}
  do_test btree2-$testno.5  {
    lindex [btree_pager_stats $::b] 1
  } {6}
  do_test btree2-$testno.6  {
    btree_close_cursor $::c2
    btree_close_cursor $::c3
    btree_close_cursor $::c4
    btree_close_cursor $::c5
    btree_close_cursor $::c6
    lindex [btree_pager_stats $::b] 1
  } {0}
  do_test btree2-$testno.7 {
    btree_close $::b
  } {}

  # For each database size, run various changes tests.
  #
  set num2 1
  foreach {n I K D} {
    0.5 0.5 0.1 0.1
    1.0 0.2 0.1 0.1
    1.0 0.8 0.1 0.1
    2.0 0.0 0.1 0.1
    2.0 1.0 0.1 0.1
    2.0 0.0 0.0 0.0
    2.0 1.0 0.0 0.0
  } {
    set testid btree2-$testno.8.$num2
    set hash [md5file test2.bt]
    do_test $testid.0 {
      set ::b [btree_open test2.bt 2000 0]
      set ::c2 [btree_cursor $::b 2 1]
      set ::c3 [btree_cursor $::b 3 1]
      set ::c4 [btree_cursor $::b 4 1]
      set ::c5 [btree_cursor $::b 5 1]
      set ::c6 [btree_cursor $::b 6 1]
      check_invariants
    } {}
    set cnt 6
    for {set i 2} {$i<=6} {incr i} {
      if {[lindex [btree_cursor_info [set ::c$i]] 0]!=$i} {incr cnt}
    }
    do_test $testid.1 {
      btree_begin_transaction $::b
      lindex [btree_pager_stats $::b] 1
    } $cnt
    do_test $testid.2 [subst {
      random_changes $n $I $K $D
    }] {}
    do_test $testid.3 {
      check_invariants
    } {}
    do_test $testid.4 {
      btree_close_cursor $::c2
      btree_close_cursor $::c3
      btree_close_cursor $::c4
      btree_close_cursor $::c5
      btree_close_cursor $::c6
      btree_rollback $::b
      md5file test2.bt
    } $hash
    btree_begin_transaction $::b
    set ::c2 [btree_cursor $::b 2 1]
    set ::c3 [btree_cursor $::b 3 1]
    set ::c4 [btree_cursor $::b 4 1]
    set ::c5 [btree_cursor $::b 5 1]
    set ::c6 [btree_cursor $::b 6 1]
    do_test $testid.5 [subst {
      random_changes $n $I $K $D
    }] {}
    do_test $testid.6 {
      check_invariants
    } {}
    do_test $testid.7 {
      btree_commit $::b
      check_invariants
    } {}
    set hash [md5file test2.bt]
    do_test $testid.8 {
      btree_close_cursor $::c2
      btree_close_cursor $::c3
      btree_close_cursor $::c4
      btree_close_cursor $::c5
      btree_close_cursor $::c6
      lindex [btree_pager_stats $::b] 1
    } {0}
    do_test $testid.9 {
      btree_close $::b
      set ::b [btree_open test2.bt 2000 0]
      set ::c2 [btree_cursor $::b 2 1]
      set ::c3 [btree_cursor $::b 3 1]
      set ::c4 [btree_cursor $::b 4 1]
      set ::c5 [btree_cursor $::b 5 1]
      set ::c6 [btree_cursor $::b 6 1]
      check_invariants
    } {}
    do_test $testid.10 {
      btree_close_cursor $::c2
      btree_close_cursor $::c3
      btree_close_cursor $::c4
      btree_close_cursor $::c5
      btree_close_cursor $::c6
      lindex [btree_pager_stats $::b] 1
    } {0}
    do_test $testid.11 {
      btree_close $::b
    } {}
    incr num2
  }
  incr testno
  set ::b [btree_open test2.bt 2000 0]
}  

# Testing is complete.  Shut everything down.
#
do_test btree-999.1 {
  lindex [btree_pager_stats $::b] 1
} {0}
do_test btree-999.2 {
  btree_close $::b
} {}
do_test btree-999.3 {
  file delete -force test2.bt
  file exists test2.bt-journal
} {0}

} ;# end if( not mem: and has pager_open command );

finish_test

--- NEW FILE: btree4.test ---
# 2002 December 03
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend
#
# This file focuses on testing the sqliteBtreeNext() and 
# sqliteBtreePrevious() procedures and making sure they are able
# to step through an entire table from either direction.
#
# $Id: btree4.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

if {[info commands btree_open]!=""} {

# Open a test database.
#
file delete -force test1.bt
file delete -force test1.bt-journal
set b1 [btree_open test1.bt 2000 0]
btree_begin_transaction $b1
do_test btree4-0.1 {
  btree_create_table $b1 0
} 2

set data {abcdefghijklmnopqrstuvwxyz0123456789}
append data $data
append data $data
append data $data
append data $data

foreach N {10 100 1000} {
  btree_clear_table $::b1 2
  set ::c1 [btree_cursor $::b1 2 1]
  do_test btree4-$N.1 {
    for {set i 1} {$i<=$N} {incr i} {
      btree_insert $::c1 [format k-%05d $i] $::data-$i
    }
    btree_first $::c1
    btree_key $::c1
  } {k-00001}
  do_test btree4-$N.2 {
    btree_data $::c1
  } $::data-1
  for {set i 2} {$i<=$N} {incr i} {
    do_test btree-$N.3.$i.1 {
      btree_next $::c1
    } 0
    do_test btree-$N.3.$i.2 {
      btree_key $::c1
    } [format k-%05d $i]
    do_test btree-$N.3.$i.3 {
      btree_data $::c1
    } $::data-$i
  }
  do_test btree4-$N.4 {
    btree_next $::c1
  } 1
  do_test btree4-$N.5 {
    btree_last $::c1
  } 0
  do_test btree4-$N.6 {
    btree_key $::c1
  } [format k-%05d $N]
  do_test btree4-$N.7 {
    btree_data $::c1
  } $::data-$N
  for {set i [expr {$N-1}]} {$i>=1} {incr i -1} {
    do_test btree4-$N.8.$i.1 {
      btree_prev $::c1
    } 0
    do_test btree4-$N.8.$i.2 {
      btree_key $::c1
    } [format k-%05d $i]
    do_test btree4-$N.8.$i.3 {
      btree_data $::c1
    } $::data-$i
  }
  do_test btree4-$N.9 {
    btree_prev $::c1
  } 1
  btree_close_cursor $::c1
}

btree_rollback $::b1    
btree_pager_ref_dump $::b1
btree_close $::b1

} ;# end if( not mem: and has pager_open command );

finish_test

--- NEW FILE: btree5.test ---
# 2004 May 10
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend
#
# $Id: btree5.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Attempting to read table 1 of an empty file gives an SQLITE_EMPTY
# error.
#
do_test btree5-1.1 {
  file delete -force test1.bt
  file delete -force test1.bt-journal
  set rc [catch {btree_open test1.bt 2000 0} ::b1]
} {0}
do_test btree5-1.2 {
  set rc [catch {btree_cursor $::b1 1 0} ::c1]
} {1}
do_test btree5-1.3 {
  set ::c1
} {SQLITE_EMPTY}
do_test btree5-1.4 {
  set rc [catch {btree_cursor $::b1 1 1} ::c1]
} {1}
do_test btree5-1.5 {
  set ::c1
} {SQLITE_EMPTY}

# Starting a transaction initializes the first page of the database
# and the error goes away.
#
do_test btree5-1.6 {
  btree_begin_transaction $b1
  set rc [catch {btree_cursor $b1 1 0} c1]
} {0}
do_test btree5-1.7 {
  btree_first $c1
} {1}
do_test btree5-1.8 {
  btree_close_cursor $c1
  btree_rollback $b1
  set rc [catch {btree_cursor $b1 1 0} c1]
} {1}
do_test btree5-1.9 {
  set c1
} {SQLITE_EMPTY}
do_test btree5-1.10 {
  btree_begin_transaction $b1
  set rc [catch {btree_cursor $b1 1 0} c1]
} {0}
do_test btree5-1.11 {
  btree_first $c1
} {1}
do_test btree5-1.12 {
  btree_close_cursor $c1
  btree_commit $b1
  set rc [catch {btree_cursor $b1 1 0} c1]
} {0}
do_test btree5-1.13 {
  btree_first $c1
} {1}
do_test btree5-1.14 {
  btree_close_cursor $c1
  btree_integrity_check $b1 1
} {}

# Insert many entries into table 1.  This is designed to test the
# virtual-root logic that comes into play for page one.  It is also
# a good test of INTKEY tables.
#
# Stagger the inserts.  After the inserts complete, go back and do
# deletes.  Stagger the deletes too.  Repeat this several times.
#

# Do N inserts into table 1 using random keys between 0 and 1000000
#
proc random_inserts {N} {
  global c1
  while {$N>0} {
    set k [expr {int(rand()*1000000)}]
    if {[btree_move_to $c1 $k]==0} continue;  # entry already exists
    btree_insert $c1 $k data-for-$k
    incr N -1
  }
}

# Do N delete from table 1
#
proc random_deletes {N} {
  global c1
  while {$N>0} {
    set k [expr {int(rand()*1000000)}]
    btree_move_to $c1 $k
    btree_delete $c1
    incr N -1
  }
}

# Make sure the table has exactly N entries.  Make sure the data for
# each entry agrees with its key.
#
proc check_table {N} {
  global c1
  btree_first $c1
  set cnt 0
  while {![btree_eof $c1]} {
    if {[set data [btree_data $c1]] ne "data-for-[btree_key $c1]"} {
      return "wrong data for entry $cnt"
    }
    set n [string length $data]
    set fdata1 [btree_fetch_data $c1 $n]
    set fdata2 [btree_fetch_data $c1 -1]
    if {$fdata1 ne "" && $fdata1 ne $data} {
      return "DataFetch returned the wrong value with amt=$n"
    }
    if {$fdata1 ne $fdata2} {
      return "DataFetch returned the wrong value when amt=-1"
    }
    if {$n>10} {
      set fdata3 [btree_fetch_data $c1 10]
      if {$fdata3 ne [string range $data 0 9]} {
        return "DataFetch returned the wrong value when amt=10"
      }
    }
    incr cnt
    btree_next $c1
  }
  if {$cnt!=$N} {
    return "wrong number of entries"
  }
  return {}
}

# Initialize the database
#
btree_begin_transaction $b1
set c1 [btree_cursor $b1 1 1]
set btree_trace 0

# Do the tests.
#
set cnt 0
for {set i 1} {$i<=100} {incr i} {
  do_test btree5-2.$i.1 {
    random_inserts 200
    incr cnt 200
    check_table $cnt
  } {}
  do_test btree5-2.$i.2 {
    btree_integrity_check $b1 1
  } {}
  do_test btree5-2.$i.3 {
    random_deletes 190
    incr cnt -190
    check_table $cnt
  } {}
  do_test btree5-2.$i.4 {
    btree_integrity_check $b1 1
  } {}
}

#btree_tree_dump $b1 1
btree_close_cursor $c1
btree_commit $b1
btree_begin_transaction $b1

# This procedure converts an integer into a variable-length text key.
# The conversion is reversible.
#
# The first two characters of the string are alphabetics derived from
# the least significant bits of the number.  Because they are derived
# from least significant bits, the sort order of the resulting string
# is different from numeric order.  After the alphabetic prefix comes
# the original number.  A variable-length suffix follows.  The length
# of the suffix is based on a hash of the original number.
# 
proc num_to_key {n} {
  global charset ncharset suffix
  set c1 [string index $charset [expr {$n%$ncharset}]]
  set c2 [string index $charset [expr {($n/$ncharset)%$ncharset}]]
  set nsuf [expr {($n*211)%593}]
  return $c1$c2-$n-[string range $suffix 0 $nsuf]
}
set charset {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
set ncharset [string length $charset]
set suffix $charset$charset
while {[string length $suffix]<1000} {append suffix $suffix}

# This procedures extracts the original integer used to create
# a key by num_to_key
#
proc key_to_num {key} {
  regexp {^..-([0-9]+)} $key all n
  return $n
}

# Insert into table $tab keys corresponding to all values between
# $start and $end, inclusive.
#
proc insert_range {tab start end} {
  for {set i $start} {$i<=$end} {incr i} {
    btree_insert $tab [num_to_key $i] {}
  }
}

# Delete from table $tab keys corresponding to all values between
# $start and $end, inclusive.
#
proc delete_range {tab start end} {
  for {set i $start} {$i<=$end} {incr i} {
    if {[btree_move_to $tab [num_to_key $i]]==0} {
      btree_delete $tab
    }
  }
}

# Make sure table $tab contains exactly those keys corresponding
# to values between $start and $end
#
proc check_range {tab start end} {
  btree_first $tab
  while {![btree_eof $tab]} {
    set key [btree_key $tab]
    set i [key_to_num $key]
    if {[num_to_key $i] ne $key} {
      return "malformed key: $key"
    }
    set got($i) 1
    btree_next $tab
  }
  set all [lsort -integer [array names got]]
  if {[llength $all]!=$end+1-$start} {
    return "table contains wrong number of values"
  }
  if {[lindex $all 0]!=$start} {
    return "wrong starting value"
  }
  if {[lindex $all end]!=$end} {
    return "wrong ending value"
  }
  return {}
}

# Create a zero-data table and test it out.
#
do_test btree5-3.1 {
  set rc [catch {btree_create_table $b1 2} t2]
} {0}
do_test btree5-3.2 {
  set rc [catch {btree_cursor $b1 $t2 1} c2]
} {0}
set start 1
set end 100
for {set i 1} {$i<=100} {incr i} {
  do_test btree5-3.3.$i.1 {
    insert_range $c2 $start $end
    btree_integrity_check $b1 1 $t2
  } {}
  do_test btree5-3.3.$i.2 {
    check_range $c2 $start $end
  } {}
  set nstart $start
  incr nstart 89
  do_test btree5-3.3.$i.3 {
    delete_range $c2 $start $nstart
    btree_integrity_check $b1 1 $t2
  } {}
  incr start 90
  do_test btree5-3.3.$i.4 {
    check_range $c2 $start $end
  } {}
  incr end 100
}


btree_close_cursor $c2
btree_commit $b1
btree_close $b1

finish_test

--- NEW FILE: btree6.test ---
# 2004 May 10
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend - specifically
# the B+tree tables.  B+trees store all data on the leaves rather
# that storing data with keys on interior nodes.
#
# $Id: btree6.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl


# Insert many entries into the table that cursor $cur points to.
# The table should be an INTKEY table.
#
# Stagger the inserts.  After the inserts complete, go back and do
# deletes.  Stagger the deletes too.  Repeat this several times.
#

# Do N inserts into table $tab using random keys between 0 and 1000000
#
proc random_inserts {cur N} {
  global inscnt
  while {$N>0} {
    set k [expr {int(rand()*1000000)}]
    if {[btree_move_to $cur $k]==0} {
      continue;  # entry already exists
    }
    incr inscnt
    btree_insert $cur $k data-for-$k
    incr N -1
  }
}
set inscnt 0

# Do N delete from the table that $cur points to.
#
proc random_deletes {cur N} {
  while {$N>0} {
    set k [expr {int(rand()*1000000)}]
    btree_move_to $cur $k
    btree_delete $cur
    incr N -1
  }
}

# Make sure the table that $cur points to has exactly N entries.  
# Make sure the data for each entry agrees with its key.
#
proc check_table {cur N} {
  btree_first $cur
  set cnt 0
  while {![btree_eof $cur]} {
    if {[set data [btree_data $cur]] ne "data-for-[btree_key $cur]"} {
      return "wrong data for entry $cnt"
    }
    set n [string length $data]
    set fdata1 [btree_fetch_data $cur $n]
    set fdata2 [btree_fetch_data $cur -1]
    if {$fdata1 ne "" && $fdata1 ne $data} {
      return "DataFetch returned the wrong value with amt=$n"
    }
    if {$fdata1 ne $fdata2} {
      return "DataFetch returned the wrong value when amt=-1"
    }
    if {$n>10} {
      set fdata3 [btree_fetch_data $cur 10]
      if {$fdata3 ne [string range $data 0 9]} {
        return "DataFetch returned the wrong value when amt=10"
      }
    }
    incr cnt
    btree_next $cur
  }
  if {$cnt!=$N} {
    return "wrong number of entries.  Got $cnt.  Looking for $N"
  }
  return {}
}

# Initialize the database
#
file delete -force test1.bt
file delete -force test1.bt-journal
set b1 [btree_open test1.bt 2000 0]
btree_begin_transaction $b1
set tab [btree_create_table $b1 5]
set cur [btree_cursor $b1 $tab 1]
set btree_trace 0
expr srand(1)

# Do the tests.
#
set cnt 0
for {set i 1} {$i<=40} {incr i} {
  do_test btree6-1.$i.1 {
    random_inserts $cur 200
    incr cnt 200
    check_table $cur $cnt
  } {}
  do_test btree6-1.$i.2 {
    btree_integrity_check $b1 1 $tab
  } {}
  do_test btree6-1.$i.3 {
    random_deletes $cur 90
    incr cnt -90
    check_table $cur $cnt
  } {}
  do_test btree6-1.$i.4 {
    btree_integrity_check $b1 1 $tab
  } {}
}

btree_close_cursor $cur
btree_commit $b1
btree_close $b1

finish_test

--- NEW FILE: btree7.test ---
# 2004 Jun 4	
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend.
#
# $Id: btree7.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Stress the balance routine by trying to create situations where
# 3 neighboring nodes split into 5.
#
set bigdata _123456789    ;#  10
append bigdata $bigdata   ;#  20
append bigdata $bigdata   ;#  40
append bigdata $bigdata   ;#  80
append bigdata $bigdata   ;# 160
append bigdata $bigdata   ;# 320
append bigdata $bigdata   ;# 640
set data450 [string range $bigdata 0 449]
do_test btree7-1.1 {
  execsql "
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y TEXT);
    INSERT INTO t1 VALUES(1, '$bigdata');
    INSERT INTO t1 VALUES(2, '$bigdata');
    INSERT INTO t1 VALUES(3, '$data450');
    INSERT INTO t1 VALUES(5, '$data450');
    INSERT INTO t1 VALUES(8, '$bigdata');
    INSERT INTO t1 VALUES(9, '$bigdata');
  "
} {}
#puts [execsql {select * from sqlite_master}]
#set bt [btree_open test.db 2000 0]
#btree_tree_dump $bt 2
do_test btree7-1.2 {
  execsql {PRAGMA integrity_check}
} {ok}
do_test btree7-1.3 {
  execsql "
    INSERT INTO t1 VALUES(4, '$bigdata');
  "
} {}
#btree_tree_dump $bt 2
do_test btree7-1.4 {
  execsql {PRAGMA integrity_check}
} {ok}

finish_test

--- NEW FILE: capi2.test ---
# 2003 January 29
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Return the text values from the current row pointed at by STMT as a list.
proc get_row_values {STMT} {
  set VALUES [list]
  for {set i 0} {$i < [sqlite3_data_count $STMT]} {incr i} {
    lappend VALUES [sqlite3_column_text $STMT $i]
  }
  return $VALUES
}

# Return the column names followed by declaration types for the result set
# of the SQL statement STMT.
#
# i.e. for:
# CREATE TABLE abc(a text, b integer); 
# SELECT * FROM abc;
#
# The result is {a b text integer}
proc get_column_names {STMT} {
  set VALUES [list]
  for {set i 0} {$i < [sqlite3_column_count $STMT]} {incr i} {
    lappend VALUES [sqlite3_column_name $STMT $i]
  }
  for {set i 0} {$i < [sqlite3_column_count $STMT]} {incr i} {
    lappend VALUES [sqlite3_column_decltype $STMT $i]
  }
  return $VALUES
}

# Check basic functionality
#
do_test capi2-1.1 {
  db close
  set DB [sqlite3 db test.db]
  execsql {CREATE TABLE t1(a,b,c)}
  set VM [sqlite3_prepare $DB {SELECT name, rowid FROM sqlite_master} -1 TAIL]
  set TAIL
} {}
do_test capi2-1.2 {
  sqlite3_step $VM
} {SQLITE_ROW}
do_test capi2-1.3 {
  sqlite3_data_count $VM
} {2}
do_test capi2-1.4 {
  get_row_values $VM
} {t1 1}
do_test capi2-1.5 {
  get_column_names $VM
} {name rowid text INTEGER}
do_test capi2-1.6 {
  sqlite3_step $VM 
} {SQLITE_DONE}
do_test capi2-1.7 {
  list [sqlite3_column_count $VM] [get_row_values $VM] [get_column_names $VM]
} {2 {} {name rowid text INTEGER}}
do_test capi2-1.8 {
  sqlite3_step $VM
} {SQLITE_MISUSE}

# Update: In v2, once SQLITE_MISUSE is returned the statement handle cannot
# be interrogated for more information. However in v3, since the column
# count, names and types are determined at compile time, these are still
# accessible after an SQLITE_MISUSE error.
do_test capi2-1.9 {
  list [sqlite3_column_count $VM] [get_row_values $VM] [get_column_names $VM]
} {2 {} {name rowid text INTEGER}}
do_test capi2-1.10 {
  sqlite3_data_count $VM
} {0}

do_test capi2-1.11 {
  sqlite3_finalize $VM
} {SQLITE_OK}

# Check to make sure that the "tail" of a multi-statement SQL script
# is returned by sqlite3_prepare.
#
do_test capi2-2.1 {
  set SQL {
    SELECT name, rowid FROM sqlite_master;
    SELECT name, rowid FROM sqlite_temp_master;
    -- A comment at the end
  }
  set VM [sqlite3_prepare $DB $SQL -1 SQL]
  set SQL
} {
    SELECT name, rowid FROM sqlite_temp_master;
    -- A comment at the end
  }
do_test capi2-2.2 {
  set r [sqlite3_step $VM]
  lappend r [sqlite3_column_count $VM] \
            [get_row_values $VM] \
            [get_column_names $VM]
} {SQLITE_ROW 2 {t1 1} {name rowid text INTEGER}}
do_test capi2-2.3 {
  set r [sqlite3_step $VM]
  lappend r [sqlite3_column_count $VM] \
            [get_row_values $VM] \
            [get_column_names $VM]
} {SQLITE_DONE 2 {} {name rowid text INTEGER}}
do_test capi2-2.4 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-2.5 {
  set VM [sqlite3_prepare $DB $SQL -1 SQL]
  set SQL
} {
    -- A comment at the end
  }
do_test capi2-2.6 {
  set r [sqlite3_step $VM]
  lappend r [sqlite3_column_count $VM] \
            [get_row_values $VM] \
            [get_column_names $VM]
} {SQLITE_DONE 2 {} {name rowid text INTEGER}}
do_test capi2-2.7 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-2.8 {
  set VM [sqlite3_prepare $DB $SQL -1 SQL]
  list $SQL $VM
} {{} {}}

# Check the error handling.
#
do_test capi2-3.1 {
  set rc [catch {
      sqlite3_prepare $DB {select bogus from sqlite_master} -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {}}
do_test capi2-3.2 {
  set rc [catch {
      sqlite3_prepare $DB {select bogus from } -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) near " ": syntax error} {}}
do_test capi2-3.3 {
  set rc [catch {
      sqlite3_prepare $DB {;;;;select bogus from sqlite_master} -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {}}
do_test capi2-3.4 {
  set rc [catch {
      sqlite3_prepare $DB {select bogus from sqlite_master;x;} -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {x;}}
do_test capi2-3.5 {
  set rc [catch {
      sqlite3_prepare $DB {select bogus from sqlite_master;;;x;} -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {;;x;}}
do_test capi2-3.6 {
  set rc [catch {
      sqlite3_prepare $DB {select 5/0} -1 TAIL
  } VM]
  lappend rc $TAIL
} {0 {}}
do_test capi2-3.7 {
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_ROW 1 {{}} {5/0 {}}}
do_test capi2-3.8 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-3.9 {
  execsql {CREATE UNIQUE INDEX i1 ON t1(a)}
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,2,3)} -1 TAIL]
  set TAIL
} {}
do_test capi2-3.9b {db changes} {0}
do_test capi2-3.10 {
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_DONE 0 {} {}}

# Update for v3 - the change has not actually happened until the query is
# finalized. Is this going to cause trouble for anyone? Lee Nelson maybe?
# (Later:) The change now happens just before SQLITE_DONE is returned.
do_test capi2-3.10b {db changes} {1}
do_test capi2-3.11 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-3.11b {db changes} {1}
do_test capi2-3.12 {
  sqlite3_finalize $VM
} {SQLITE_MISUSE}
do_test capi2-3.13 {
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL]
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_ERROR 0 {} {}}

# Update for v3: Preparing a statement does not affect the change counter.
# (Test result changes from 0 to 1).  (Later:) change counter updates occur
# when sqlite3_step returns, not at finalize time.
do_test capi2-3.13b {db changes} {0}

do_test capi2-3.14 {
  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]
} {SQLITE_CONSTRAINT {column a is not unique}}
do_test capi2-3.15 {
  set VM [sqlite3_prepare $DB {CREATE TABLE t2(a NOT NULL, b)} -1 TAIL]
  set TAIL
} {}
do_test capi2-3.16 {
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_DONE 0 {} {}}
do_test capi2-3.17 {
  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]
} {SQLITE_OK {not an error}}
do_test capi2-3.18 {
  set VM [sqlite3_prepare $DB {INSERT INTO t2 VALUES(NULL,2)} -1 TAIL]
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_ERROR 0 {} {}}
do_test capi2-3.19 {
  list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]
} {SQLITE_CONSTRAINT {t2.a may not be NULL}}

# Two or more virtual machines exists at the same time.
#
do_test capi2-4.1 {
  set VM1 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(1,2)} -1 TAIL]
  set TAIL
} {}
do_test capi2-4.2 {
  set VM2 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(2,3)} -1 TAIL]
  set TAIL
} {}
do_test capi2-4.3 {
  set VM3 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(3,4)} -1 TAIL]
  set TAIL
} {}
do_test capi2-4.4 {
  list [sqlite3_step $VM2] \
       [sqlite3_column_count $VM2] \
       [get_row_values $VM2] \
       [get_column_names $VM2]
} {SQLITE_DONE 0 {} {}}
do_test capi2-4.5 {
  execsql {SELECT * FROM t2 ORDER BY a}
} {2 3}
do_test capi2-4.6 {
  sqlite3_finalize $VM2
} {SQLITE_OK}
do_test capi2-4.7 {
  list [sqlite3_step $VM3] \
       [sqlite3_column_count $VM3] \
       [get_row_values $VM3] \
       [get_column_names $VM3]
} {SQLITE_DONE 0 {} {}}
do_test capi2-4.8 {
  execsql {SELECT * FROM t2 ORDER BY a}
} {2 3 3 4}
do_test capi2-4.9 {
  sqlite3_finalize $VM3
} {SQLITE_OK}
do_test capi2-4.10 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_DONE 0 {} {}}
do_test capi2-4.11 {
  execsql {SELECT * FROM t2 ORDER BY a}
} {1 2 2 3 3 4}
do_test capi2-4.12 {
  sqlite3_finalize $VM1
} {SQLITE_OK}

# Interleaved SELECTs
#
do_test capi2-5.1 {
  set VM1 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL]
  set VM2 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL]
  set VM3 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL]
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 2 {2 3} {a b {} {}}}
do_test capi2-5.2 {
  list [sqlite3_step $VM2] \
       [sqlite3_column_count $VM2] \
       [get_row_values $VM2] \
       [get_column_names $VM2]
} {SQLITE_ROW 2 {2 3} {a b {} {}}}
do_test capi2-5.3 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 2 {3 4} {a b {} {}}}
do_test capi2-5.4 {
  list [sqlite3_step $VM3] \
       [sqlite3_column_count $VM3] \
       [get_row_values $VM3] \
       [get_column_names $VM3]
} {SQLITE_ROW 2 {2 3} {a b {} {}}}
do_test capi2-5.5 {
  list [sqlite3_step $VM3] \
       [sqlite3_column_count $VM3] \
       [get_row_values $VM3] \
       [get_column_names $VM3]
} {SQLITE_ROW 2 {3 4} {a b {} {}}}
do_test capi2-5.6 {
  list [sqlite3_step $VM3] \
       [sqlite3_column_count $VM3] \
       [get_row_values $VM3] \
       [get_column_names $VM3]
} {SQLITE_ROW 2 {1 2} {a b {} {}}}
do_test capi2-5.7 {
  list [sqlite3_step $VM3] \
       [sqlite3_column_count $VM3] \
       [get_row_values $VM3] \
       [get_column_names $VM3]
} {SQLITE_DONE 2 {} {a b {} {}}}
do_test capi2-5.8 {
  sqlite3_finalize $VM3
} {SQLITE_OK}
do_test capi2-5.9 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 2 {1 2} {a b {} {}}}
do_test capi2-5.10 {
  sqlite3_finalize $VM1
} {SQLITE_OK}
do_test capi2-5.11 {
  list [sqlite3_step $VM2] \
       [sqlite3_column_count $VM2] \
       [get_row_values $VM2] \
       [get_column_names $VM2]
} {SQLITE_ROW 2 {3 4} {a b {} {}}}
do_test capi2-5.12 {
  list [sqlite3_step $VM2] \
       [sqlite3_column_count $VM2] \
       [get_row_values $VM2] \
       [get_column_names $VM2]
} {SQLITE_ROW 2 {1 2} {a b {} {}}}
do_test capi2-5.11 {
  sqlite3_finalize $VM2
} {SQLITE_OK}

# Check for proper SQLITE_BUSY returns.
#
do_test capi2-6.1 {
  execsql {
    BEGIN;
    CREATE TABLE t3(x counter);
    INSERT INTO t3 VALUES(1);
    INSERT INTO t3 VALUES(2);
    INSERT INTO t3 SELECT x+2 FROM t3;
    INSERT INTO t3 SELECT x+4 FROM t3;
    INSERT INTO t3 SELECT x+8 FROM t3;
    COMMIT;
  }
  set VM1 [sqlite3_prepare $DB {SELECT * FROM t3} -1 TAIL]
  sqlite3 db2 test.db
  execsql {BEGIN} db2
} {}
# Update for v3: BEGIN doesn't write-lock the database. It is quite
# difficult to get v3 to write-lock the database, which causes a few
# problems for test scripts.
#
# do_test capi2-6.2 {
#   list [sqlite3_step $VM1] \
#        [sqlite3_column_count $VM1] \
#        [get_row_values $VM1] \
#        [get_column_names $VM1]
# } {SQLITE_BUSY 0 {} {}}
do_test capi2-6.3 {
  execsql {COMMIT} db2
} {}
do_test capi2-6.4 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 1 {x counter}}
do_test capi2-6.5 {
  catchsql {INSERT INTO t3 VALUES(10);} db2
} {1 {database is locked}}
do_test capi2-6.6 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 2 {x counter}}
do_test capi2-6.7 {
  execsql {SELECT * FROM t2} db2
} {2 3 3 4 1 2}
do_test capi2-6.8 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 3 {x counter}}
do_test capi2-6.9 {
  execsql {SELECT * FROM t2} 
} {2 3 3 4 1 2}
do_test capi2-6.10 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 4 {x counter}}
do_test capi2-6.11 {
  execsql {BEGIN}
} {}
do_test capi2-6.12 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 5 {x counter}}
do_test capi2-6.13 {
  catchsql {UPDATE t3 SET x=x+1}
} {1 {database table is locked}}
do_test capi2-6.14 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 6 {x counter}}
do_test capi2-6.15 {
  execsql {SELECT * FROM t1}
} {1 2 3}
do_test capi2-6.16 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 7 {x counter}}
do_test capi2-6.17 {
  catchsql {UPDATE t1 SET b=b+1}
} {0 {}}
do_test capi2-6.18 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 8 {x counter}}
do_test capi2-6.19 {
  execsql {SELECT * FROM t1}
} {1 3 3}
do_test capi2-6.20 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 9 {x counter}}
#do_test capi2-6.21 {
#  execsql {ROLLBACK; SELECT * FROM t1}
#} {1 2 3}
do_test capi2-6.22 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 10 {x counter}}
#do_test capi2-6.23 {
#  execsql {BEGIN TRANSACTION;}
#} {}
do_test capi2-6.24 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 11 {x counter}}
do_test capi2-6.25 {
  execsql {
    INSERT INTO t1 VALUES(2,3,4);
    SELECT * FROM t1;
  }
} {1 3 3 2 3 4}
do_test capi2-6.26 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 12 {x counter}}
do_test capi2-6.27 {
  catchsql {
    INSERT INTO t1 VALUES(2,4,5);
    SELECT * FROM t1;
  }
} {1 {column a is not unique}}
do_test capi2-6.28 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 13 {x counter}}
do_test capi2-6.99 {
  sqlite3_finalize $VM1
} {SQLITE_OK}
catchsql {ROLLBACK}

do_test capi2-7.1 {
  stepsql $DB {
    SELECT * FROM t1
  }
} {0 1 2 3}
do_test capi2-7.2 {
  stepsql $DB {
    PRAGMA count_changes=on
  }
} {0}
do_test capi2-7.3 {
  stepsql $DB {
    UPDATE t1 SET a=a+10;
  }
} {0 1}
do_test capi2-7.4 {
  stepsql $DB {
    INSERT INTO t1 SELECT a+1,b+1,c+1 FROM t1;
  }
} {0 1}
do_test capi2-7.4b {sqlite3_changes $DB} {1}
do_test capi2-7.5 {
  stepsql $DB {
    UPDATE t1 SET a=a+10;
  }
} {0 2}
do_test capi2-7.5b {sqlite3_changes $DB} {2}
do_test capi2-7.6 {
  stepsql $DB {
    SELECT * FROM t1;
  }
} {0 21 2 3 22 3 4}
do_test capi2-7.7 {
  stepsql $DB {
    INSERT INTO t1 SELECT a+2,b+2,c+2 FROM t1;
  }
} {0 2}
do_test capi2-7.8 {
  sqlite3_changes $DB
} {2}
do_test capi2-7.9 {
  stepsql $DB {
    SELECT * FROM t1;
  }
} {0 21 2 3 22 3 4 23 4 5 24 5 6}
do_test capi2-7.10 {
  stepsql $DB {
    UPDATE t1 SET a=a-20;
    SELECT * FROM t1;
  }
} {0 4 1 2 3 2 3 4 3 4 5 4 5 6}

# Update for version 3: A SELECT statement no longer resets the change
# counter (Test result changes from 0 to 4).
do_test capi2-7.11 {
  sqlite3_changes $DB
} {4}
do_test capi2-7.11a {
  execsql {SELECT count(*) FROM t1}
} {4}

do_test capi2-7.12 {
  set x [stepsql $DB {EXPLAIN SELECT * FROM t1}]
  lindex $x 0
} {0}

# Ticket #261 - make sure we can finalize before the end of a query.
#
do_test capi2-8.1 {
  set VM1 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL]
  sqlite3_finalize $VM1
} {SQLITE_OK}
  
# Tickets #384 and #385 - make sure the TAIL argument to sqlite3_prepare
# and all of the return pointers in sqlite_step can be null.
#
do_test capi2-9.1 {
  set VM1 [sqlite3_prepare $DB {SELECT * FROM t2} -1 DUMMY]
  sqlite3_step $VM1
  sqlite3_finalize $VM1
} {SQLITE_OK}

db2 close

finish_test

--- NEW FILE: capi3.test ---
# 2003 January 29
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.
proc utf16 {str {nt 1}} {
  set r [encoding convertto unicode $str]
  if {$nt} {
    append r "\x00\x00"
  }
  return $r
}

# Return the UTF-8 representation of the supplied UTF-16 string $str. 
proc utf8 {str} {
  # If $str ends in two 0x00 0x00 bytes, knock these off before
  # converting to UTF-8 using TCL.
  binary scan $str \c* vals
  if {[lindex $vals end]==0 && [lindex $vals end-1]==0} {
    set str [binary format \c* [lrange $vals 0 end-2]]
  }

  set r [encoding convertfrom unicode $str]
  return $r
}

# These tests complement those in capi2.test. They are organized
# as follows:
#
# capi3-1.*: Test sqlite3_prepare 
# capi3-2.*: Test sqlite3_prepare16
# capi3-3.*: Test sqlite3_open
# capi3-4.*: Test sqlite3_open16
# capi3-5.*: Test the various sqlite3_result_* APIs
# capi3-6.*: Test that sqlite3_close fails if there are outstanding VMs.
#

db close
set DB [sqlite3 db test.db]

do_test capi3-1.1 {
  set STMT [sqlite3_prepare $DB {SELECT name FROM sqlite_master} -1 TAIL]
  sqlite3_finalize $STMT
  set TAIL
} {}
do_test capi3-1.2 {
  sqlite3_errcode $DB
} {SQLITE_OK}
do_test capi3-1.3 {
  sqlite3_errmsg $DB
} {not an error}
do_test capi3-1.4 {
  set sql {SELECT name FROM sqlite_master;SELECT 10}
  set STMT [sqlite3_prepare $DB $sql -1 TAIL]
  sqlite3_finalize $STMT
  set TAIL
} {SELECT 10}
do_test capi3-1.5 {
  set sql {SELECT namex FROM sqlite_master}
  catch {
    set STMT [sqlite3_prepare $DB $sql -1 TAIL]
  }
} {1}
do_test capi3-1.6 {
  sqlite3_errcode $DB
} {SQLITE_ERROR}
do_test capi3-1.7 {
  sqlite3_errmsg $DB
} {no such column: namex}

do_test capi3-2.1 {
  set sql16 [utf16 {SELECT name FROM sqlite_master}]
  set STMT [sqlite3_prepare16 $DB $sql16 -1 ::TAIL]
  sqlite3_finalize $STMT
  utf8 $::TAIL
} {}
do_test capi3-2.2 {
  set sql [utf16 {SELECT name FROM sqlite_master;SELECT 10}]
  set STMT [sqlite3_prepare16 $DB $sql -1 TAIL]
  sqlite3_finalize $STMT
  utf8 $TAIL
} {SELECT 10}
do_test capi3-2.3 {
  set sql [utf16 {SELECT namex FROM sqlite_master}]
  catch {
    set STMT [sqlite3_prepare16 $DB $sql -1 TAIL]
  }
} {1}
do_test capi3-2.4 {
  sqlite3_errcode $DB
} {SQLITE_ERROR}
do_test capi3-2.5 {
  sqlite3_errmsg $DB
} {no such column: namex}

# rename sqlite3_open sqlite3_open_old
# proc sqlite3_open {fname options} {sqlite3_open_new $fname $options}

do_test capi3-3.1 {
  set db2 [sqlite3_open test.db {}]
  sqlite3_errcode $db2
} {SQLITE_OK}
# FIX ME: Should test the db handle works.
do_test capi3-3.2 {
  sqlite3_close $db2
} {SQLITE_OK}
do_test capi3-3.3 {
  catch {
    set db2 [sqlite3_open /bogus/path/test.db {}]
  }
  sqlite3_errcode $db2
} {SQLITE_CANTOPEN}
do_test capi3-3.4 {
  sqlite3_errmsg $db2
} {unable to open database file}
do_test capi3-3.5 {
  sqlite3_close $db2
} {SQLITE_OK}
do_test capi3-3.6 {
  sqlite3_close $db2
} {SQLITE_MISUSE}
do_test capi3-3.6 {
  sqlite3_errmsg $db2
} {library routine called out of sequence}
do_test capi3-3.6 {
  utf8 [sqlite3_errmsg16 $db2]
} {library routine called out of sequence}

# rename sqlite3_open ""
# rename sqlite3_open_old sqlite3_open

do_test capi3-4.1 {
  set db2 [sqlite3_open16 [utf16 test.db] {}]
  sqlite3_errcode $db2
} {SQLITE_OK}
# FIX ME: Should test the db handle works.
do_test capi3-4.2 {
  sqlite3_close $db2
} {SQLITE_OK}
do_test capi3-4.3 {
  catch {
    set db2 [sqlite3_open16 [utf16 /bogus/path/test.db] {}]
  }
  sqlite3_errcode $db2
} {SQLITE_CANTOPEN}
do_test capi3-4.4 {
  utf8 [sqlite3_errmsg16 $db2]
} {unable to open database file}
do_test capi3-4.5 {
  sqlite3_close $db2
} {SQLITE_OK}

# This proc is used to test the following API calls:
#
# sqlite3_column_count
# sqlite3_column_name
# sqlite3_column_name16
# sqlite3_column_decltype
# sqlite3_column_decltype16
#
# $STMT is a compiled SQL statement. $test is a prefix
# to use for test names within this proc. $names is a list
# of the column names that should be returned by $STMT.
# $decltypes is a list of column declaration types for $STMT.
#
# Example:
#
# set STMT [sqlite3_prepare "SELECT 1, 2, 2;" -1 DUMMY]
# check_header test1.1 {1 2 3} {"" "" ""}
#
proc check_header {STMT test names decltypes} {

  # Use the return value of sqlite3_column_count() to build
  # a list of column indexes. i.e. If sqlite3_column_count
  # is 3, build the list {0 1 2}.
  set ::idxlist [list]
  set ::numcols [sqlite3_column_count $STMT]
  for {set i 0} {$i < $::numcols} {incr i} {lappend ::idxlist $i}

  # Column names in UTF-8
  do_test $test.1 {
    set cnamelist [list]
    foreach i $idxlist {lappend cnamelist [sqlite3_column_name $STMT $i]} 
    set cnamelist
  } $names

  # Column names in UTF-16
  do_test $test.2 {
    set cnamelist [list]
    foreach i $idxlist {
      lappend cnamelist [utf8 [sqlite3_column_name16 $STMT $i]]
    }
    set cnamelist
  } $names

  # Column names in UTF-8
  do_test $test.3 {
    set cnamelist [list]
    foreach i $idxlist {lappend cnamelist [sqlite3_column_name $STMT $i]} 
    set cnamelist
  } $names

  # Column names in UTF-16
  do_test $test.4 {
    set cnamelist [list]
    foreach i $idxlist {
      lappend cnamelist [utf8 [sqlite3_column_name16 $STMT $i]]
    }
    set cnamelist
  } $names

  # Column names in UTF-8
  do_test $test.5 {
    set cnamelist [list]
    foreach i $idxlist {lappend cnamelist [sqlite3_column_decltype $STMT $i]} 
    set cnamelist
  } $decltypes

  # Column declaration types in UTF-16
  do_test $test.6 {
    set cnamelist [list]
    foreach i $idxlist {
      lappend cnamelist [utf8 [sqlite3_column_decltype16 $STMT $i]]
    }
    set cnamelist
  } $decltypes


  # Test some out of range conditions:
  do_test $test.7 {
    list \
      [sqlite3_column_name $STMT -1] \
      [sqlite3_column_name16 $STMT -1] \
      [sqlite3_column_decltype $STMT -1] \
      [sqlite3_column_decltype16 $STMT -1] \
      [sqlite3_column_name $STMT $numcols] \
      [sqlite3_column_name16 $STMT $numcols] \
      [sqlite3_column_decltype $STMT $numcols] \
      [sqlite3_column_decltype16 $STMT $numcols]
  } {{} {} {} {} {} {} {} {}}

} 

# This proc is used to test the following APIs:
#
# sqlite3_data_count
# sqlite3_column_type
# sqlite3_column_int
# sqlite3_column_text
# sqlite3_column_text16
# sqlite3_column_double
#
# $STMT is a compiled SQL statement for which the previous call 
# to sqlite3_step returned SQLITE_ROW. $test is a prefix to use 
# for test names within this proc. $types is a list of the 
# manifest types for the current row. $ints, $doubles and $strings
# are lists of the integer, real and string representations of
# the values in the current row.
#
# Example:
#
# set STMT [sqlite3_prepare "SELECT 'hello', 1.1, NULL" -1 DUMMY]
# sqlite3_step $STMT
# check_data test1.2 {TEXT REAL NULL} {0 1 0} {0 1.1 0} {hello 1.1 {}}
#
proc check_data {STMT test types ints doubles strings} {

  # Use the return value of sqlite3_column_count() to build
  # a list of column indexes. i.e. If sqlite3_column_count
  # is 3, build the list {0 1 2}.
  set ::idxlist [list]
  set numcols [sqlite3_data_count $STMT]
  for {set i 0} {$i < $numcols} {incr i} {lappend ::idxlist $i}

# types
do_test $test.1 {
  set types [list]
  foreach i $idxlist {lappend types [sqlite3_column_type $STMT $i]}
  set types
} $types

# Integers
do_test $test.2 {
  set ints [list]
  foreach i $idxlist {lappend ints [sqlite3_column_int64 $STMT $i]}
  set ints
} $ints

# bytes
set lens [list]
foreach i $::idxlist {
  lappend lens [string length [lindex $strings $i]]
}
do_test $test.3 {
  set bytes [list]
  set lens [list]
  foreach i $idxlist {
    lappend bytes [sqlite3_column_bytes $STMT $i]
  }
  set bytes
} $lens

# bytes16
set lens [list]
foreach i $::idxlist {
  lappend lens [expr 2 * [string length [lindex $strings $i]]]
}
do_test $test.4 {
  set bytes [list]
  set lens [list]
  foreach i $idxlist {
    lappend bytes [sqlite3_column_bytes16 $STMT $i]
  }
  set bytes
} $lens

# Blob
do_test $test.5 {
  set utf8 [list]
  foreach i $idxlist {lappend utf8 [sqlite3_column_blob $STMT $i]}
  set utf8
} $strings

# UTF-8
do_test $test.6 {
  set utf8 [list]
  foreach i $idxlist {lappend utf8 [sqlite3_column_text $STMT $i]}
  set utf8
} $strings

# Floats
do_test $test.7 {
  set utf8 [list]
  foreach i $idxlist {lappend utf8 [sqlite3_column_double $STMT $i]}
  set utf8
} $doubles

# UTF-16
do_test $test.8 {
  set utf8 [list]
  foreach i $idxlist {lappend utf8 [utf8 [sqlite3_column_text16 $STMT $i]]}
  set utf8
} $strings

# Integers
do_test $test.9 {
  set ints [list]
  foreach i $idxlist {lappend ints [sqlite3_column_int $STMT $i]}
  set ints
} $ints

# Floats
do_test $test.10 {
  set utf8 [list]
  foreach i $idxlist {lappend utf8 [sqlite3_column_double $STMT $i]}
  set utf8
} $doubles

# UTF-8
do_test $test.11 {
  set utf8 [list]
  foreach i $idxlist {lappend utf8 [sqlite3_column_text $STMT $i]}
  set utf8
} $strings

# Types
do_test $test.12 {
  set types [list]
  foreach i $idxlist {lappend types [sqlite3_column_type $STMT $i]}
  set types
} $types

# Test that an out of range request returns the equivalent of NULL
do_test $test.13 {
  sqlite3_column_int $STMT -1
} {0}
do_test $test.13 {
  sqlite3_column_text $STMT -1
} {}

}

do_test capi3-5.0 {
  execsql {
    CREATE TABLE t1(a VARINT, b BLOB, c VARCHAR(16));
    INSERT INTO t1 VALUES(1, 2, 3);
    INSERT INTO t1 VALUES('one', 'two', NULL);
    INSERT INTO t1 VALUES(1.2, 1.3, 1.4);
  }
  set sql "SELECT * FROM t1"
  set STMT [sqlite3_prepare $DB $sql -1 TAIL]
  sqlite3_column_count $STMT
} 3

check_header $STMT capi3-5.1 {a b c} {VARINT BLOB VARCHAR(16)}
do_test capi3-5.2 {
  sqlite3_step $STMT
} SQLITE_ROW

check_header $STMT capi3-5.3 {a b c} {VARINT BLOB VARCHAR(16)}
check_data $STMT capi3-5.4 {INTEGER INTEGER TEXT} {1 2 3} {1.0 2.0 3.0} {1 2 3}

do_test capi3-5.5 {
  sqlite3_step $STMT
} SQLITE_ROW

check_header $STMT capi3-5.6 {a b c} {VARINT BLOB VARCHAR(16)}
check_data $STMT capi3-5.7 {TEXT TEXT NULL} {0 0 0} {0.0 0.0 0.0} {one two {}}

do_test capi3-5.8 {
  sqlite3_step $STMT
} SQLITE_ROW

check_header $STMT capi3-5.9 {a b c} {VARINT BLOB VARCHAR(16)}
check_data $STMT capi3-5.10 {FLOAT FLOAT TEXT} {1 1 1} {1.2 1.3 1.4} {1.2 1.3 1.4}

do_test capi3-5.11 {
  sqlite3_step $STMT
} SQLITE_DONE

do_test capi3-5.12 {
  sqlite3_finalize $STMT
} SQLITE_OK

set ::ENC [execsql {pragma encoding}]
db close

do_test capi3-6.0 {
  set DB [sqlite3_open test.db]
  sqlite3_key $DB xyzzy
  set sql {SELECT a FROM t1 order by rowid}
  set STMT [sqlite3_prepare $DB $sql -1 TAIL]
  expr 0
} {0}
do_test capi3-6.1 {
  sqlite3_close $DB
} {SQLITE_BUSY}
do_test capi3-6.2 {
  sqlite3_step $STMT
} {SQLITE_ROW}
check_data $STMT capi3-6.3 {INTEGER} {1} {1.0} {1}
do_test capi3-6.3 {
  sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-6.4 {
  sqlite3_close $DB
} {SQLITE_OK}

if {![sqlite3 -has-codec]} {
  # Test what happens when the library encounters a newer file format.
  # Do this by updating the file format via the btree layer.
  do_test capi3-7.1 {
    set ::bt [btree_open test.db 10 0]
    btree_begin_transaction $::bt
    set meta [btree_get_meta $::bt]
    lset meta 2 2
    eval [concat btree_update_meta $::bt [lrange $meta 0 end]]
    btree_commit $::bt
    btree_close $::bt
  } {}
  do_test capi3-7.2 {
    sqlite3 db test.db
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {unsupported file format}}
  db close
}

if {![sqlite3 -has-codec]} {
  # Now test that the library correctly handles bogus entries in the
  # sqlite_master table (schema corruption).
  do_test capi3-8.1 {
    file delete -force test.db
    file delete -force test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
    }
    db close
  } {}
  do_test capi3-8.2 {
    set ::bt [btree_open test.db 10 0]
    btree_begin_transaction $::bt
    set ::bc [btree_cursor $::bt 1 1]

    # Build a 5-field row record consisting of 5 null records. This is
    # officially black magic.
    catch {unset data}
    set data [binary format c6 {6 0 0 0 0 0}]
    btree_insert $::bc 5 $data

    btree_close_cursor $::bc
    btree_commit $::bt
    btree_close $::bt
  } {}
  do_test capi3-8.3 {
    sqlite3 db test.db
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema}}
  do_test capi3-8.4 {
    set ::bt [btree_open test.db 10 0]
    btree_begin_transaction $::bt
    set ::bc [btree_cursor $::bt 1 1]
  
    # Build a 5-field row record. The first field is a string 'table', and
    # subsequent fields are all NULL. Replace the other broken record with
    # this one and try to read the schema again. The broken record uses
    # either UTF-8 or native UTF-16 (if this file is being run by
    # utf16.test).
    if { [string match UTF-16* $::ENC] } {
      set data [binary format c6a10 {6 33 0 0 0 0} [utf16 table]]
    } else {
      set data [binary format c6a5 {6 23 0 0 0 0} table]
    }
    btree_insert $::bc 5 $data
  
    btree_close_cursor $::bc
    btree_commit $::bt
    btree_close $::bt
  } {};
  do_test capi3-8.5 {
    db close 
    sqlite3 db test.db
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema}}
  db close
}
file delete -force test.db
file delete -force test.db-journal


# Test the english language string equivalents for sqlite error codes
set code2english [list \
SQLITE_OK         {not an error} \
SQLITE_ERROR      {SQL logic error or missing database} \
SQLITE_INTERNAL   {internal SQLite implementation flaw} \
SQLITE_PERM       {access permission denied} \
SQLITE_ABORT      {callback requested query abort} \
SQLITE_BUSY       {database is locked} \
SQLITE_LOCKED     {database table is locked} \
SQLITE_NOMEM      {out of memory} \
SQLITE_READONLY   {attempt to write a readonly database} \
SQLITE_INTERRUPT  {interrupted} \
SQLITE_IOERR      {disk I/O error} \
SQLITE_CORRUPT    {database disk image is malformed} \
SQLITE_NOTFOUND   {table or record not found} \
SQLITE_FULL       {database is full} \
SQLITE_CANTOPEN   {unable to open database file} \
SQLITE_PROTOCOL   {database locking protocol failure} \
SQLITE_EMPTY      {table contains no data} \
SQLITE_SCHEMA     {database schema has changed} \
SQLITE_TOOBIG     {too much data for one table row} \
SQLITE_CONSTRAINT {constraint failed} \
SQLITE_MISMATCH   {datatype mismatch} \
SQLITE_MISUSE     {library routine called out of sequence} \
SQLITE_NOLFS      {kernel lacks large file support} \
SQLITE_AUTH       {authorization denied} \
SQLITE_FORMAT     {auxiliary database format error} \
SQLITE_RANGE      {bind index out of range} \
SQLITE_NOTADB     {file is encrypted or is not a database} \
unknownerror      {unknown error} \
]

set test_number 1
foreach {code english} $code2english {
  do_test capi3-9.$test_number "sqlite3_test_errstr $code" $english
  incr test_number
}

# Test the error message when a "real" out of memory occurs.
if {[info command sqlite_malloc_stat]!=""} {
set sqlite_malloc_fail 1
do_test capi3-10-1 {
  set ::DB [sqlite3 db test.db]
  sqlite_malloc_fail 1
  catchsql {
    select * from sqlite_master;
  }
} {1 {out of memory}}
do_test capi3-10-2 {
  sqlite3_errmsg $::DB
} {out of memory}
do_test capi3-10-3 {
  utf8 [sqlite3_errmsg16 $::DB]
} {out of memory}
db close
sqlite_malloc_fail 0
}

# The following tests - capi3-11.* - test that a COMMIT or ROLLBACK
# statement issued while there are still outstanding VMs that are part of
# the transaction fails.
set DB [sqlite3 db test.db]
sqlite_register_test_function $DB func
do_test capi3-11.1 {
  execsql {
    BEGIN;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 'int');
    INSERT INTO t1 VALUES(2, 'notatype');
  }
} {}
do_test capi3-11.2 {
  set STMT [sqlite3_prepare $DB "SELECT func(b, a) FROM t1" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.3 {
  catchsql {
    COMMIT;
  }
} {1 {cannot commit transaction - SQL statements in progress}}
do_test capi3-11.4 {
  sqlite3_step $STMT
} {SQLITE_ERROR}
do_test capi3-11.5 {
  sqlite3_finalize $STMT
} {SQLITE_ERROR}
do_test capi3-11.6 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 int 2 notatype}}
do_test capi3-11.7 {
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.8 {
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
    BEGIN;
    INSERT INTO t2 VALUES(3);
  }
} {}
do_test capi3-11.9 {
  set STMT [sqlite3_prepare $DB "SELECT a FROM t2" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.3 {
  catchsql {
    ROLLBACK;
  }
} {1 {cannot rollback transaction - SQL statements in progress}}
do_test capi3-11.10 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.11 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.12 {
  sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3-11.13 {
  sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-11.14 {
  execsql {
    SELECT a FROM t2;
  }
} {1 2 3}
do_test capi3-11.15 {
  catchsql {
    ROLLBACK;
  }
} {0 {}}
do_test capi3-11.16 {
  execsql {
    SELECT a FROM t2;
  }
} {1 2}

# Sanity check on the definition of 'outstanding VM'. This means any VM
# that has had sqlite3_step() called more recently than sqlite3_finalize() or
# sqlite3_reset(). So a VM that has just been prepared or reset does not
# count as an active VM.
do_test capi3-11.17 {
  execsql {
    BEGIN;
  }
} {}
do_test capi3-11.18 {
  set STMT [sqlite3_prepare $DB "SELECT a FROM t1" -1 TAIL]
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.19 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.20 {
  catchsql {
    BEGIN;
    COMMIT;
  }
} {1 {cannot commit transaction - SQL statements in progress}}
do_test capi3-11.20 {
  sqlite3_reset $STMT
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.21 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

# The following tests - capi3-12.* - check that it's Ok to start a
# transaction while other VMs are active, and that it's Ok to execute
# atomic updates in the same situation (so long as they are on a different
# table).
do_test capi3-12.1 {
  set STMT [sqlite3_prepare $DB "SELECT a FROM t2" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-12.2 {
  catchsql {
    INSERT INTO t1 VALUES(3, NULL);
  }
} {0 {}}
do_test capi3-12.3 {
  catchsql {
    INSERT INTO t2 VALUES(4);
  }
} {1 {database table is locked}}
do_test capi3-12.4 {
  catchsql {
    BEGIN;
    INSERT INTO t1 VALUES(4, NULL);
  }
} {0 {}}
do_test capi3-12.5 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-12.6 {
  sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3-12.7 {
  sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-12.8 {
  execsql {
    COMMIT;
    SELECT a FROM t1;
  }
} {1 2 3 4}


finish_test

--- NEW FILE: capi3b.test ---
# 2004 September 2
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the callback-free C/C++ API and in
# particular the behavior of sqlite3_step() when trying to commit
# with lock contention.
#
# $Id: capi3b.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl


db close
set DB [sqlite3 db test.db]
set DB2 [sqlite3 db2 test.db]

# Create some data in the database
#
do_test capi3b-1.1 {
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    SELECT * FROM t1
  }
} {1 2}

# Make sure the second database connection can see the data
#
do_test capi3b-1.2 {
  execsql {
    SELECT * FROM t1
  } db2
} {1 2}

# First database connection acquires a shared lock
#
do_test capi3b-1.3 {
  execsql {
    BEGIN;
    SELECT * FROM t1;
  }
} {1 2}

# Second database connection tries to write.  The sqlite3_step()
# function returns SQLITE_BUSY because it cannot commit.
#
do_test capi3b-1.4 {
  set VM [sqlite3_prepare $DB2 {INSERT INTO t1 VALUES(3)} -1 TAIL]
  sqlite3_step $VM
} SQLITE_BUSY

# The sqlite3_step call can be repeated multiple times.
#
do_test capi3b-1.5.1 {
  sqlite3_step $VM
} SQLITE_BUSY
do_test capi3b-1.5.2 {
  sqlite3_step $VM
} SQLITE_BUSY

# The first connection closes its transaction.  This allows the second
# connections sqlite3_step to succeed.
#
do_test capi3b-1.6 {
  execsql COMMIT
  sqlite3_step $VM
} SQLITE_DONE
do_test capi3b-1.7 {
  sqlite3_finalize $VM
} SQLITE_OK
do_test capi3b-1.8 {
  execsql {SELECT * FROM t1} db2
} {1 2 3}
do_test capi3b-1.9 {
  execsql {SELECT * FROM t1}
} {1 2 3}

# Start doing a SELECT with one connection.  This gets a SHARED lock.
# Then do an INSERT with the other connection.  The INSERT should
# not be able to complete until the SELECT finishes.
#
do_test capi3b-2.1 {
  set VM1 [sqlite3_prepare $DB {SELECT * FROM t1} -1 TAIL]
  sqlite3_step $VM1
} SQLITE_ROW
do_test capi3b-2.2 {
  sqlite3_column_text $VM1 0
} 1
do_test capi3b-2.3 {
  set VM2 [sqlite3_prepare $DB2 {INSERT INTO t1 VALUES(4)} -1 TAIL]
  sqlite3_step $VM2
} SQLITE_BUSY
do_test capi3b-2.4 {
  sqlite3_step $VM1
} SQLITE_ROW
do_test capi3b-2.5 {
  sqlite3_column_text $VM1 0
} 2
do_test capi3b-2.6 {
  sqlite3_step $VM2
} SQLITE_BUSY
do_test capi3b-2.7 {
  sqlite3_step $VM1
} SQLITE_ROW
do_test capi3b-2.8 {
  sqlite3_column_text $VM1 0
} 3
do_test capi3b-2.9 {
  sqlite3_step $VM2
} SQLITE_BUSY
do_test capi3b-2.10 {
  sqlite3_step $VM1
} SQLITE_DONE
do_test capi3b-2.11 {
  sqlite3_step $VM2
} SQLITE_DONE
do_test capi3b-2.12 {
  sqlite3_finalize $VM1
  sqlite3_finalize $VM2
  execsql {SELECT * FROM t1}
} {1 2 3 4}

catch {db2 close}
finish_test

--- NEW FILE: collate1.test ---
#
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: collate1.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

#
# Tests are roughly organised as follows:
#
# collate1-1.* - Single-field ORDER BY with an explicit COLLATE clause.
# collate1-2.* - Multi-field ORDER BY with an explicit COLLATE clause.
# collate1-3.* - ORDER BY using a default collation type. Also that an 
#                explict collate type overrides a default collate type.
# collate1-4.* - ORDER BY using a data type.
#

#
# Collation type 'HEX'. If an argument can be interpreted as a hexadecimal
# number, then it is converted to one before the comparison is performed. 
# Numbers are less than other strings. If neither argument is a number, 
# [string compare] is used.
#
db collate HEX hex_collate
proc hex_collate {lhs rhs} {
  set lhs_ishex [regexp {^(0x|)[1234567890abcdefABCDEF]+$} $lhs]
  set rhs_ishex [regexp {^(0x|)[1234567890abcdefABCDEF]+$} $rhs]
  if {$lhs_ishex && $rhs_ishex} { 
    set lhsx [scan $lhs %x]
    set rhsx [scan $rhs %x]
    if {$lhs < $rhs} {return -1}
    if {$lhs == $rhs} {return 0}
    if {$lhs > $rhs} {return 1}
  }
  if {$lhs_ishex} {
    return -1;
  }
  if {$rhs_ishex} {
    return 1;
  }
  return [string compare $lhs $rhs]
}
db function hex {format 0x%X}

# Mimic the SQLite 2 collation type NUMERIC.
db collate numeric numeric_collate
proc numeric_collate {lhs rhs} {
  if {$lhs == $rhs} {return 0} 
  return [expr ($lhs>$rhs)?1:-1]
}

do_test collate1-1.0 {
  execsql {
    CREATE TABLE collate1t1(c1, c2);
    INSERT INTO collate1t1 VALUES(45, hex(45));
    INSERT INTO collate1t1 VALUES(NULL, NULL);
    INSERT INTO collate1t1 VALUES(281, hex(281));
  }
} {}
do_test collate1-1.1 {
  execsql {
    SELECT c2 FROM collate1t1 ORDER BY 1;
  }
} {{} 0x119 0x2D}
do_test collate1-1.2 {
  execsql {
    SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex;
  }
} {{} 0x2D 0x119}
do_test collate1-1.3 {
  execsql {
    SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex DESC;
  }
} {0x119 0x2D {}}
do_test collate1-1.4 {
  execsql {
   SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex ASC;
  }
} {{} 0x2D 0x119}
do_test collate1-1.5 {
  execsql {
    DROP TABLE collate1t1;
  }
} {}

do_test collate1-2.0 {
  execsql {
    CREATE TABLE collate1t1(c1, c2);
    INSERT INTO collate1t1 VALUES('5', '0x11');
    INSERT INTO collate1t1 VALUES('5', '0xA');
    INSERT INTO collate1t1 VALUES(NULL, NULL);
    INSERT INTO collate1t1 VALUES('7', '0xA');
    INSERT INTO collate1t1 VALUES('11', '0x11');
    INSERT INTO collate1t1 VALUES('11', '0x101');
  }
} {}
do_test collate1-2.2 {
  execsql {
    SELECT c1, c2 FROM collate1t1 ORDER BY 1 COLLATE numeric, 2 COLLATE hex;
  }
} {{} {} 5 0xA 5 0x11 7 0xA 11 0x11 11 0x101}
do_test collate1-2.3 {
  execsql {
    SELECT c1, c2 FROM collate1t1 ORDER BY 1 COLLATE binary, 2 COLLATE hex;
  }
} {{} {} 11 0x11 11 0x101 5 0xA 5 0x11 7 0xA}
do_test collate1-2.4 {
  execsql {
    SELECT c1, c2 FROM collate1t1 ORDER BY 1 COLLATE binary DESC, 2 COLLATE hex;
  }
} {7 0xA 5 0xA 5 0x11 11 0x11 11 0x101 {} {}}
do_test collate1-2.5 {
  execsql {
    SELECT c1, c2 FROM collate1t1 
        ORDER BY 1 COLLATE binary DESC, 2 COLLATE hex DESC;
  }
} {7 0xA 5 0x11 5 0xA 11 0x101 11 0x11 {} {}}
do_test collate1-2.6 {
  execsql {
    SELECT c1, c2 FROM collate1t1 
        ORDER BY 1 COLLATE binary ASC, 2 COLLATE hex ASC;
  }
} {{} {} 11 0x11 11 0x101 5 0xA 5 0x11 7 0xA}
do_test collate1-2.7 {
  execsql {
    DROP TABLE collate1t1;
  }
} {}

#
# These tests ensure that the default collation type for a column is used 
# by an ORDER BY clause correctly. The focus is all the different ways
# the column can be referenced. i.e. a, collate2t1.a, main.collate2t1.a etc.
#
do_test collate1-3.0 {
  execsql {
    CREATE TABLE collate1t1(a COLLATE hex, b);
    INSERT INTO collate1t1 VALUES( '0x5', 5 );
    INSERT INTO collate1t1 VALUES( '1', 1 );
    INSERT INTO collate1t1 VALUES( '0x45', 69 );
    INSERT INTO collate1t1 VALUES( NULL, NULL );
    SELECT * FROM collate1t1 ORDER BY a;
  }
} {{} {} 1 1 0x5 5 0x45 69}

do_test collate1-3.1 {
  execsql {
    SELECT * FROM collate1t1 ORDER BY 1;
  }
} {{} {} 1 1 0x5 5 0x45 69}
do_test collate1-3.2 {
  execsql {
    SELECT * FROM collate1t1 ORDER BY collate1t1.a;
  }
} {{} {} 1 1 0x5 5 0x45 69}
do_test collate1-3.3 {
  execsql {
    SELECT * FROM collate1t1 ORDER BY main.collate1t1.a;
  }
} {{} {} 1 1 0x5 5 0x45 69}
do_test collate1-3.4 {
  execsql {
    SELECT a as c1, b as c2 FROM collate1t1 ORDER BY c1;
  }
} {{} {} 1 1 0x5 5 0x45 69}
do_test collate1-3.5 {
  execsql {
    SELECT a as c1, b as c2 FROM collate1t1 ORDER BY c1 COLLATE binary;
  }
} {{} {} 0x45 69 0x5 5 1 1}
do_test collate1-3.6 {
  execsql {
    DROP TABLE collate1t1;
  }
} {}

# Update for SQLite version 3. The collate1-4.* test cases were written
# before manifest types were introduced. The following test cases still
# work, due to the 'affinity' mechanism, but they don't prove anything
# about collation sequences.
#
do_test collate1-4.0 {
  execsql {
    CREATE TABLE collate1t1(c1 numeric, c2 text);
    INSERT INTO collate1t1 VALUES(1, 1);
    INSERT INTO collate1t1 VALUES(12, 12);
    INSERT INTO collate1t1 VALUES(NULL, NULL);
    INSERT INTO collate1t1 VALUES(101, 101);
  }
} {}
do_test collate1-4.1 {
  execsql {
    SELECT c1 FROM collate1t1 ORDER BY 1;
  }
} {{} 1 12 101}
do_test collate1-4.2 {
  execsql {
    SELECT c2 FROM collate1t1 ORDER BY 1;
  }
} {{} 1 101 12}
do_test collate1-4.3 {
  execsql {
    SELECT c2+0 FROM collate1t1 ORDER BY 1;
  }
} {{} 1.0 12.0 101.0}
do_test collate1-4.4 {
  execsql {
    SELECT c1||'' FROM collate1t1 ORDER BY 1;
  }
} {{} 1 101 12}
do_test collate1-4.5 {
  execsql {
    DROP TABLE collate1t1;
  }
} {}

finish_test

--- NEW FILE: collate2.test ---
#
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: collate2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

#
# Tests are organised as follows:
#
# collate2-1.* WHERE <expr> expressions (sqliteExprIfTrue).
# collate2-2.* WHERE NOT <expr> expressions (sqliteExprIfFalse).
# collate2-3.* SELECT <expr> expressions (sqliteExprCode).
# collate2-4.* Precedence of collation/data types in binary comparisons
# collate2-5.* JOIN syntax.
#

# Create a collation type BACKWARDS for use in testing. This collation type
# is similar to the built-in TEXT collation type except the order of
# characters in each string is reversed before the comparison is performed.
db collate BACKWARDS backwards_collate
proc backwards_collate {a b} {
  set ra {};
  set rb {}
  foreach c [split $a {}] { set ra $c$ra }
  foreach c [split $b {}] { set rb $c$rb }
  return [string compare $ra $rb]
}

# The following values are used in these tests:
# NULL   aa ab ba bb   aA aB bA bB   Aa Ab Ba Bb   AA AB BA BB 
#
# The collation orders for each of the tested collation types are:
#
# BINARY:    NULL  AA AB Aa Ab  BA BB Ba Bb  aA aB aa ab  bA bB ba bb 
# NOCASE:    NULL  aa aA Aa AA  ab aB Ab AB  ba bA Ba BA  bb bB Bb BB 
# BACKWARDS: NULL  AA BA aA bA  AB BB aB bB  Aa Ba aa ba  Ab Bb ab bb 
#
# These tests verify that the default collation type for a column is used
# for comparison operators (<, >, <=, >=, =) involving that column and 
# an expression that is not a column with a default collation type.
# 
# The collation sequences BINARY and NOCASE are built-in, the BACKWARDS
# collation sequence is implemented by the TCL proc backwards_collate
# above.
#
do_test collate2-1.0 {
  execsql {
    CREATE TABLE collate2t1(
      a COLLATE BINARY, 
      b COLLATE NOCASE, 
      c COLLATE BACKWARDS
    );
    INSERT INTO collate2t1 VALUES( NULL, NULL, NULL );

    INSERT INTO collate2t1 VALUES( 'aa', 'aa', 'aa' );
    INSERT INTO collate2t1 VALUES( 'ab', 'ab', 'ab' );
    INSERT INTO collate2t1 VALUES( 'ba', 'ba', 'ba' );
    INSERT INTO collate2t1 VALUES( 'bb', 'bb', 'bb' );

    INSERT INTO collate2t1 VALUES( 'aA', 'aA', 'aA' );
    INSERT INTO collate2t1 VALUES( 'aB', 'aB', 'aB' );
    INSERT INTO collate2t1 VALUES( 'bA', 'bA', 'bA' );
    INSERT INTO collate2t1 VALUES( 'bB', 'bB', 'bB' );

    INSERT INTO collate2t1 VALUES( 'Aa', 'Aa', 'Aa' );
    INSERT INTO collate2t1 VALUES( 'Ab', 'Ab', 'Ab' );
    INSERT INTO collate2t1 VALUES( 'Ba', 'Ba', 'Ba' );
    INSERT INTO collate2t1 VALUES( 'Bb', 'Bb', 'Bb' );

    INSERT INTO collate2t1 VALUES( 'AA', 'AA', 'AA' );
    INSERT INTO collate2t1 VALUES( 'AB', 'AB', 'AB' );
    INSERT INTO collate2t1 VALUES( 'BA', 'BA', 'BA' );
    INSERT INTO collate2t1 VALUES( 'BB', 'BB', 'BB' );
  }
  if {[info exists collate_test_use_index]} { 
    execsql {
      CREATE INDEX collate2t1_i1 ON collate2t1(a);
      CREATE INDEX collate2t1_i2 ON collate2t1(b);
      CREATE INDEX collate2t1_i3 ON collate2t1(c);
    }
  }
} {}
do_test collate2-1.1 {
  execsql {
    SELECT a FROM collate2t1 WHERE a > 'aa' ORDER BY 1;
  }
} {ab bA bB ba bb}
do_test collate2-1.2 {
  execsql {
    SELECT b FROM collate2t1 WHERE b > 'aa' ORDER BY 1, oid;
  }
} {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
do_test collate2-1.3 {
  execsql {
    SELECT c FROM collate2t1 WHERE c > 'aa' ORDER BY 1;
  }
} {ba Ab Bb ab bb}
do_test collate2-1.4 {
  execsql {
    SELECT a FROM collate2t1 WHERE a < 'aa' ORDER BY 1;
  }
} {AA AB Aa Ab BA BB Ba Bb aA aB}
do_test collate2-1.5 {
  execsql {
    SELECT b FROM collate2t1 WHERE b < 'aa' ORDER BY 1, oid;
  }
} {}
do_test collate2-1.6 {
  execsql {
    SELECT c FROM collate2t1 WHERE c < 'aa' ORDER BY 1;
  }
} {AA BA aA bA AB BB aB bB Aa Ba}
do_test collate2-1.7 {
  execsql {
    SELECT a FROM collate2t1 WHERE a = 'aa';
  }
} {aa}
do_test collate2-1.8 {
  execsql {
    SELECT b FROM collate2t1 WHERE b = 'aa' ORDER BY oid;
  }
} {aa aA Aa AA}
do_test collate2-1.9 {
  execsql {
    SELECT c FROM collate2t1 WHERE c = 'aa';
  }
} {aa}
do_test collate2-1.10 {
  execsql {
    SELECT a FROM collate2t1 WHERE a >= 'aa' ORDER BY 1;
  }
} {aa ab bA bB ba bb}
do_test collate2-1.11 {
  execsql {
    SELECT b FROM collate2t1 WHERE b >= 'aa' ORDER BY 1, oid;
  }
} {aa aA Aa AA ab aB Ab AB ba bA Ba BA bb bB Bb BB}
do_test collate2-1.12 {
  execsql {
    SELECT c FROM collate2t1 WHERE c >= 'aa' ORDER BY 1;
  }
} {aa ba Ab Bb ab bb}
do_test collate2-1.13 {
  execsql {
    SELECT a FROM collate2t1 WHERE a <= 'aa' ORDER BY 1;
  }
} {AA AB Aa Ab BA BB Ba Bb aA aB aa}
do_test collate2-1.14 {
  execsql {
    SELECT b FROM collate2t1 WHERE b <= 'aa' ORDER BY 1, oid;
  }
} {aa aA Aa AA}
do_test collate2-1.15 {
  execsql {
    SELECT c FROM collate2t1 WHERE c <= 'aa' ORDER BY 1;
  }
} {AA BA aA bA AB BB aB bB Aa Ba aa}
do_test collate2-1.16 {
  execsql {
    SELECT a FROM collate2t1 WHERE a BETWEEN 'Aa' AND 'Bb' ORDER BY 1;
  }
} {Aa Ab BA BB Ba Bb}
do_test collate2-1.17 {
  execsql {
    SELECT b FROM collate2t1 WHERE b BETWEEN 'Aa' AND 'Bb' ORDER BY 1, oid;
  }
} {aa aA Aa AA ab aB Ab AB ba bA Ba BA bb bB Bb BB}
do_test collate2-1.18 {
  execsql {
    SELECT c FROM collate2t1 WHERE c BETWEEN 'Aa' AND 'Bb' ORDER BY 1;
  }
} {Aa Ba aa ba Ab Bb}
do_test collate2-1.19 {
  execsql {
    SELECT a FROM collate2t1 WHERE 
      CASE a WHEN 'aa' THEN 1 ELSE 0 END
        ORDER BY 1, oid;
  }
} {aa}
do_test collate2-1.20 {
  execsql {
    SELECT b FROM collate2t1 WHERE 
      CASE b WHEN 'aa' THEN 1 ELSE 0 END
        ORDER BY 1, oid;
  }
} {aa aA Aa AA}
do_test collate2-1.21 {
  execsql {
    SELECT c FROM collate2t1 WHERE 
      CASE c WHEN 'aa' THEN 1 ELSE 0 END
        ORDER BY 1, oid;
  }
} {aa}
do_test collate2-1.22 {
  execsql {
    SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb') ORDER BY 1, oid;
  }
} {aa bb}
do_test collate2-1.23 {
  execsql {
    SELECT b FROM collate2t1 WHERE b IN ('aa', 'bb') ORDER BY 1, oid;
  }
} {aa aA Aa AA bb bB Bb BB}
do_test collate2-1.24 {
  execsql {
    SELECT c FROM collate2t1 WHERE c IN ('aa', 'bb') ORDER BY 1, oid;
  }
} {aa bb}
do_test collate2-1.25 {
  execsql {
    SELECT a FROM collate2t1 
      WHERE a IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb'));
  }
} {aa bb}
do_test collate2-1.26 {
  execsql {
    SELECT b FROM collate2t1 
      WHERE b IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb'));
  }
} {aa bb aA bB Aa Bb AA BB}
do_test collate2-1.27 {
  execsql {
    SELECT c FROM collate2t1 
      WHERE c IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb'));
  }
} {aa bb}

do_test collate2-2.1 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT a > 'aa' ORDER BY 1;
  }
} {AA AB Aa Ab BA BB Ba Bb aA aB aa}
do_test collate2-2.2 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT b > 'aa' ORDER BY 1, oid;
  }
} {aa aA Aa AA}
do_test collate2-2.3 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT c > 'aa' ORDER BY 1;
  }
} {AA BA aA bA AB BB aB bB Aa Ba aa}
do_test collate2-2.4 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT a < 'aa' ORDER BY 1;
  }
} {aa ab bA bB ba bb}
do_test collate2-2.5 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT b < 'aa' ORDER BY 1, oid;
  }
} {aa aA Aa AA ab aB Ab AB ba bA Ba BA bb bB Bb BB}
do_test collate2-2.6 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT c < 'aa' ORDER BY 1;
  }
} {aa ba Ab Bb ab bb}
do_test collate2-2.7 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT a = 'aa';
  }
} {ab ba bb aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.8 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT b = 'aa';
  }
} {ab ba bb aB bA bB Ab Ba Bb AB BA BB}
do_test collate2-2.9 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT c = 'aa';
  }
} {ab ba bb aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.10 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT a >= 'aa' ORDER BY 1;
  }
} {AA AB Aa Ab BA BB Ba Bb aA aB}
do_test collate2-2.11 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT b >= 'aa' ORDER BY 1, oid;
  }
} {}
do_test collate2-2.12 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT c >= 'aa' ORDER BY 1;
  }
} {AA BA aA bA AB BB aB bB Aa Ba}
do_test collate2-2.13 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT a <= 'aa' ORDER BY 1;
  }
} {ab bA bB ba bb}
do_test collate2-2.14 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT b <= 'aa' ORDER BY 1, oid;
  }
} {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
do_test collate2-2.15 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT c <= 'aa' ORDER BY 1;
  }
} {ba Ab Bb ab bb}
do_test collate2-2.16 {
  execsql {
    SELECT a FROM collate2t1 WHERE a NOT BETWEEN 'Aa' AND 'Bb' ORDER BY 1;
  }
} {AA AB aA aB aa ab bA bB ba bb}
do_test collate2-2.17 {
  execsql {
    SELECT b FROM collate2t1 WHERE b NOT BETWEEN 'Aa' AND 'Bb' ORDER BY 1, oid;
  }
} {}
do_test collate2-2.18 {
  execsql {
    SELECT c FROM collate2t1 WHERE c NOT BETWEEN 'Aa' AND 'Bb' ORDER BY 1;
  }
} {AA BA aA bA AB BB aB bB ab bb}
do_test collate2-2.19 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT CASE a WHEN 'aa' THEN 1 ELSE 0 END;
  }
} {{} ab ba bb aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.20 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT CASE b WHEN 'aa' THEN 1 ELSE 0 END;
  }
} {{} ab ba bb aB bA bB Ab Ba Bb AB BA BB}
do_test collate2-2.21 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT CASE c WHEN 'aa' THEN 1 ELSE 0 END;
  }
} {{} ab ba bb aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.22 {
  execsql {
    SELECT a FROM collate2t1 WHERE NOT a IN ('aa', 'bb');
  }
} {ab ba aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.23 {
  execsql {
    SELECT b FROM collate2t1 WHERE NOT b IN ('aa', 'bb');
  }
} {ab ba aB bA Ab Ba AB BA}
do_test collate2-2.24 {
  execsql {
    SELECT c FROM collate2t1 WHERE NOT c IN ('aa', 'bb');
  }
} {ab ba aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.25 {
  execsql {
    SELECT a FROM collate2t1 
      WHERE NOT a IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb'));
  }
} {ab ba aA aB bA bB Aa Ab Ba Bb AA AB BA BB}
do_test collate2-2.26 {
  execsql {
    SELECT b FROM collate2t1 
      WHERE NOT b IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb'));
  }
} {ab ba aB bA Ab Ba AB BA}
do_test collate2-2.27 {
  execsql {
    SELECT c FROM collate2t1 
      WHERE NOT c IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb'));
  }
} {ab ba aA aB bA bB Aa Ab Ba Bb AA AB BA BB}

do_test collate2-3.1 {
  execsql {
    SELECT a > 'aa' FROM collate2t1;
  }
} {{} 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0}
do_test collate2-3.2 {
  execsql {
    SELECT b > 'aa' FROM collate2t1;
  }
} {{} 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1}
do_test collate2-3.3 {
  execsql {
    SELECT c > 'aa' FROM collate2t1;
  }
} {{} 0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0}
do_test collate2-3.4 {
  execsql {
    SELECT a < 'aa' FROM collate2t1;
  }
} {{} 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1}
do_test collate2-3.5 {
  execsql {
    SELECT b < 'aa' FROM collate2t1;
  }
} {{} 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.6 {
  execsql {
    SELECT c < 'aa' FROM collate2t1;
  }
} {{} 0 0 0 0 1 1 1 1 1 0 1 0 1 1 1 1}
do_test collate2-3.7 {
  execsql {
    SELECT a = 'aa' FROM collate2t1;
  }
} {{} 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.8 {
  execsql {
    SELECT b = 'aa' FROM collate2t1;
  }
} {{} 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0}
do_test collate2-3.9 {
  execsql {
    SELECT c = 'aa' FROM collate2t1;
  }
} {{} 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.10 {
  execsql {
    SELECT a <= 'aa' FROM collate2t1;
  }
} {{} 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1}
do_test collate2-3.11 {
  execsql {
    SELECT b <= 'aa' FROM collate2t1;
  }
} {{} 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0}
do_test collate2-3.12 {
  execsql {
    SELECT c <= 'aa' FROM collate2t1;
  }
} {{} 1 0 0 0 1 1 1 1 1 0 1 0 1 1 1 1}
do_test collate2-3.13 {
  execsql {
    SELECT a >= 'aa' FROM collate2t1;
  }
} {{} 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0}
do_test collate2-3.14 {
  execsql {
    SELECT b >= 'aa' FROM collate2t1;
  }
} {{} 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}
do_test collate2-3.15 {
  execsql {
    SELECT c >= 'aa' FROM collate2t1;
  }
} {{} 1 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0}
do_test collate2-3.16 {
  execsql {
    SELECT a BETWEEN 'Aa' AND 'Bb' FROM collate2t1;
  }
} {{} 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1}
do_test collate2-3.17 {
  execsql {
    SELECT b BETWEEN 'Aa' AND 'Bb' FROM collate2t1;
  }
} {{} 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}
do_test collate2-3.18 {
  execsql {
    SELECT c BETWEEN 'Aa' AND 'Bb' FROM collate2t1;
  }
} {{} 1 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0}
do_test collate2-3.19 {
  execsql {
    SELECT CASE a WHEN 'aa' THEN 1 ELSE 0 END FROM collate2t1;
  }
} {0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.20 {
  execsql {
    SELECT CASE b WHEN 'aa' THEN 1 ELSE 0 END FROM collate2t1;
  }
} {0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0}
do_test collate2-3.21 {
  execsql {
    SELECT CASE c WHEN 'aa' THEN 1 ELSE 0 END FROM collate2t1;
  }
} {0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.22 {
  execsql {
    SELECT a IN ('aa', 'bb') FROM collate2t1;
  }
} {{} 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.23 {
  execsql {
    SELECT b IN ('aa', 'bb') FROM collate2t1;
  }
} {{} 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1}
do_test collate2-3.24 {
  execsql {
    SELECT c IN ('aa', 'bb') FROM collate2t1;
  }
} {{} 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.25 {
  execsql {
    SELECT a IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb')) 
      FROM collate2t1;
  }
} {{} 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0}
do_test collate2-3.26 {
  execsql {
    SELECT b IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb')) 
      FROM collate2t1;
  }
} {{} 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1}
do_test collate2-3.27 {
  execsql {
    SELECT c IN (SELECT a FROM collate2t1 WHERE a IN ('aa', 'bb')) 
      FROM collate2t1;
  }
} {{} 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0}

do_test collate2-4.0 {
  execsql {
    CREATE TABLE collate2t2(b COLLATE binary);
    CREATE TABLE collate2t3(b text);
    INSERT INTO collate2t2 VALUES('aa');
    INSERT INTO collate2t3 VALUES('aa');
  }
} {}

# Test that when both sides of a binary comparison operator have
# default collation types, the collate type for the leftmost term
# is used.
do_test collate2-4.1 {
  execsql {
    SELECT collate2t1.a FROM collate2t1, collate2t2 
      WHERE collate2t1.b = collate2t2.b;
  }
} {aa aA Aa AA}
do_test collate2-4.2 {
  execsql {
    SELECT collate2t1.a FROM collate2t1, collate2t2 
      WHERE collate2t2.b = collate2t1.b;
  }
} {aa}

# Test that when one side has a default collation type and the other
# does not, the collation type is used.
do_test collate2-4.3 {
  execsql {
    SELECT collate2t1.a FROM collate2t1, collate2t3 
      WHERE collate2t1.b = collate2t3.b||'';
  }
} {aa aA Aa AA}
do_test collate2-4.4 {
  execsql {
    SELECT collate2t1.a FROM collate2t1, collate2t3 
      WHERE collate2t3.b||'' = collate2t1.b;
  }
} {aa aA Aa AA}

do_test collate2-4.5 {
  execsql {
    DROP TABLE collate2t3;
  }
} {}

#
# Test that the default collation types are used when the JOIN syntax
# is used in place of a WHERE clause.
#
# SQLite transforms the JOIN syntax into a WHERE clause internally, so
# the focus of these tests is to ensure that the table on the left-hand-side
# of the join determines the collation type used. 
#
do_test collate2-5.0 {
  execsql {
    SELECT collate2t1.b FROM collate2t1 JOIN collate2t2 USING (b);
  }
} {aa aA Aa AA}
do_test collate2-5.1 {
  execsql {
    SELECT collate2t1.b FROM collate2t2 JOIN collate2t1 USING (b);
  }
} {aa}
do_test collate2-5.2 {
  execsql {
    SELECT collate2t1.b FROM collate2t1 NATURAL JOIN collate2t2;
  }
} {aa aA Aa AA}
do_test collate2-5.3 {
  execsql {
    SELECT collate2t1.b FROM collate2t2 NATURAL JOIN collate2t1;
  }
} {aa}
do_test collate2-5.4 {
  execsql {
    SELECT collate2t2.b FROM collate2t1 LEFT OUTER JOIN collate2t2 USING (b) order by collate2t1.oid;
  }
} {{} aa {} {} {} aa {} {} {} aa {} {} {} aa {} {} {}}
do_test collate2-5.5 {
  execsql {
    SELECT collate2t1.b, collate2t2.b FROM collate2t2 LEFT OUTER JOIN collate2t1 USING (b);
  }
} {aa aa}

finish_test





--- NEW FILE: collate3.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: collate3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

#
# Tests are organised as follows:
#
# collate3.1.* - Errors related to unknown collation sequences.
# collate3.2.* - Errors related to undefined collation sequences.
# collate3.3.* - Writing to a table that has an index with an undefined c.s.
# collate3.4.* - Misc errors.
# collate3.5.* - Collation factory.
#

#
# These tests ensure that when a user executes a statement with an 
# unknown collation sequence an error is returned.
#
do_test collate3-1.0 {
  execsql {
    CREATE TABLE collate3t1(c1);
  }
} {}
do_test collate3-1.1 {
  catchsql {
    SELECT * FROM collate3t1 ORDER BY 1 collate garbage;
  }
} {1 {no such collation sequence: garbage}}
do_test collate3-1.2 {
  catchsql {
    CREATE TABLE collate3t2(c1 collate garbage);
  }
} {1 {no such collation sequence: garbage}}
do_test collate3-1.3 {
  catchsql {
    CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage);
  }
} {1 {no such collation sequence: garbage}}

execsql {
  DROP TABLE collate3t1;
}

#
# Create a table with a default collation sequence, then close
# and re-open the database without re-registering the collation
# sequence. Then make sure the library stops us from using
# the collation sequence in:
# * an explicitly collated ORDER BY
# * an ORDER BY that uses the default collation sequence
# * an expression (=)
# * a CREATE TABLE statement
# * a CREATE INDEX statement that uses a default collation sequence
# * a GROUP BY that uses the default collation sequence
# * a SELECT DISTINCT that uses the default collation sequence
# * Compound SELECTs that uses the default collation sequence
# * An ORDER BY on a compound SELECT with an explicit ORDER BY.
#
do_test collate3-2.0 {
  db collate string_compare {string compare}
  execsql {
    CREATE TABLE collate3t1(c1 COLLATE string_compare, c2);
  }
  db close
  sqlite3 db test.db
  expr 0
} 0
do_test collate3-2.1 {
  catchsql {
    SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.2 {
  catchsql {
    SELECT * FROM collate3t1 ORDER BY c1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.3 {
  catchsql {
    SELECT * FROM collate3t1 WHERE c1 = 'xxx';
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.4 {
  catchsql {
    CREATE TABLE collate3t2(c1 COLLATE string_compare);
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.5 {
  catchsql {
    CREATE INDEX collate3t1_i1 ON collate3t1(c1);
  }
} {1 {no such collation sequence: string_compare}}
do_test collate3-2.6 {
  catchsql {
    SELECT * FROM collate3t1;
  }
} {0 {}}
do_test collate3-2.7 {
  catchsql {
    SELECT * FROM collate3t1 GROUP BY c1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.8 {
  catchsql {
    SELECT DISTINCT c1 FROM collate3t1;
  }
} {1 {no such collation sequence: string_compare}} 

do_test collate3-2.9 {
  catchsql {
    SELECT c1 FROM collate3t1 UNION SELECT c1 FROM collate3t1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.10 {
  catchsql {
    SELECT c1 FROM collate3t1 EXCEPT SELECT c1 FROM collate3t1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.11 {
  catchsql {
    SELECT c1 FROM collate3t1 INTERSECT SELECT c1 FROM collate3t1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.12 {
  catchsql {
    SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1;
  }
} {0 {}}
do_test collate3-2.13 {
  catchsql {
    SELECT 10 UNION ALL SELECT 20 ORDER BY 1 COLLATE string_compare;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.14 {
  catchsql {
    SELECT 10 INTERSECT SELECT 20 ORDER BY 1 COLLATE string_compare;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.15 {
  catchsql {
    SELECT 10 EXCEPT SELECT 20 ORDER BY 1 COLLATE string_compare;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.16 {
  catchsql {
    SELECT 10 UNION SELECT 20 ORDER BY 1 COLLATE string_compare;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-2.17 {
  catchsql {
    SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1 ORDER BY 1;
  }
} {1 {no such collation sequence: string_compare}} 

#
# Create an index that uses a collation sequence then close and
# re-open the database without re-registering the collation
# sequence. Then check that for the table with the index 
# * An INSERT fails,
# * An UPDATE on the column with the index fails,
# * An UPDATE on a different column succeeds.
# * A DELETE with a WHERE clause fails
# * A DELETE without a WHERE clause succeeds
#
# Also, ensure that the restrictions tested by collate3-2.* still
# apply after the index has been created.
#
do_test collate3-3.0 {
  db collate string_compare {string compare}
  execsql {
    CREATE INDEX collate3t1_i1 ON collate3t1(c1);
    INSERT INTO collate3t1 VALUES('xxx', 'yyy');
  }
  db close
  sqlite3 db test.db
  expr 0
} 0
db eval {select * from collate3t1}
breakpoint
do_test collate3-3.1 {
  catchsql {
    INSERT INTO collate3t1 VALUES('xxx', 0);
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.2 {
  catchsql {
    UPDATE collate3t1 SET c1 = 'xxx';
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.3 {
  catchsql {
    UPDATE collate3t1 SET c2 = 'xxx';
  }
} {0 {}}
do_test collate3-3.4 {
  catchsql {
    DELETE FROM collate3t1 WHERE 1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.5 {
  catchsql {
    SELECT * FROM collate3t1;
  }
} {0 {xxx xxx}}
do_test collate3-3.6 {
  catchsql {
    DELETE FROM collate3t1;
  }
} {0 {}}
do_test collate3-3.8 {
  catchsql {
    PRAGMA integrity_check
  }
} {1 {no such collation sequence: string_compare}}
do_test collate3-3.9 {
  catchsql {
    SELECT * FROM collate3t1;
  }
} {0 {}}
do_test collate3-3.10 {
  catchsql {
    SELECT * FROM collate3t1 ORDER BY 1 COLLATE string_compare;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.11 {
  catchsql {
    SELECT * FROM collate3t1 ORDER BY c1;
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.12 {
  catchsql {
    SELECT * FROM collate3t1 WHERE c1 = 'xxx';
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.13 {
  catchsql {
    CREATE TABLE collate3t2(c1 COLLATE string_compare);
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.14 {
  catchsql {
    CREATE INDEX collate3t1_i2 ON collate3t1(c1);
  }
} {1 {no such collation sequence: string_compare}} 
do_test collate3-3.15 {
  execsql {
    DROP TABLE collate3t1;
  }
} {}

# Check we can create an index that uses an explicit collation 
# sequence and then close and re-open the database.
do_test collate3-4.6 {
  db collate user_defined "string compare"
  execsql {
    CREATE TABLE collate3t1(a, b);
    INSERT INTO collate3t1 VALUES('hello', NULL);
    CREATE INDEX collate3i1 ON collate3t1(a COLLATE user_defined);
  }
} {}
do_test collate3-4.7 {
  db close
  sqlite3 db test.db
  catchsql {
    SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
  }
} {1 {no such collation sequence: user_defined}}
do_test collate3-4.8 {
  db collate user_defined "string compare"
  catchsql {
    SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
  }
} {0 {hello {}}}
do_test collate3-4.8 {
  db close
  lindex [catch {
    sqlite3 db test.db
  }] 0
} {0}
do_test collate3-4.8 {
  execsql {
    DROP TABLE collate3t1;
  }
} {}

# Compare strings as numbers.
proc numeric_compare {lhs rhs} {
  if {$rhs > $lhs} {
    set res -1
  } else {
    set res [expr ($lhs > $rhs)?1:0]
  }
  return $res
}

# Check we can create a view that uses an explicit collation 
# sequence and then close and re-open the database.
do_test collate3-4.9 {
  db collate user_defined numeric_compare
  execsql {
    CREATE TABLE collate3t1(a, b);
    INSERT INTO collate3t1 VALUES('2', NULL);
    INSERT INTO collate3t1 VALUES('101', NULL);
    INSERT INTO collate3t1 VALUES('12', NULL);
    CREATE VIEW collate3v1 AS SELECT * FROM collate3t1 
        ORDER BY 1 COLLATE user_defined;
    SELECT * FROM collate3v1;
  }
} {2 {} 12 {} 101 {}}
do_test collate3-4.10 {
  db close
  sqlite3 db test.db
  catchsql {
    SELECT * FROM collate3v1;
  }
} {1 {no such collation sequence: user_defined}}
do_test collate3-4.11 {
  db collate user_defined numeric_compare
  catchsql {
    SELECT * FROM collate3v1;
  }
} {0 {2 {} 12 {} 101 {}}}
do_test collate3-4.12 {
  execsql {
    DROP TABLE collate3t1;
  }
} {}

#
# Test the collation factory. In the code, the "no such collation sequence"
# message is only generated in two places. So these tests just test that
# the collation factory can be called once from each of those points.
#
do_test collate3-5.0 {
  catchsql {
    CREATE TABLE collate3t1(a);
    INSERT INTO collate3t1 VALUES(10);
    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
  }
} {1 {no such collation sequence: unk}}
do_test collate3-5.1 {
  set ::cfact_cnt 0
  proc cfact {nm} {
    db collate $nm {string compare}
    incr ::cfact_cnt
  }
  db collation_needed cfact
} {}
do_test collate3-5.2 {
  catchsql {
    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
  }
} {0 10}
do_test collate3-5.3 {
  set ::cfact_cnt
} {1}
do_test collate3-5.4 {
  catchsql {
    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
  }
} {0 10}
do_test collate3-5.5 {
  set ::cfact_cnt
} {1}
do_test collate3-5.6 {
  catchsql {
    SELECT a FROM collate3t1 ORDER BY 1 COLLATE unk;
  }
} {0 10}
do_test collate3-5.7 {
  execsql {
    DROP TABLE collate3t1;
    CREATE TABLE collate3t1(a COLLATE unk);
  }
  db close
  sqlite3 db test.db
  catchsql {
    SELECT a FROM collate3t1 ORDER BY 1;
  }
} {1 {no such collation sequence: unk}}
do_test collate3-5.8 {
  set ::cfact_cnt 0
  proc cfact {nm} {
    db collate $nm {string compare}
    incr ::cfact_cnt
  }
  db collation_needed cfact
  catchsql {
    SELECT a FROM collate3t1 ORDER BY 1;
  }
} {0 {}}

do_test collate3-5.9 {
  execsql {
    DROP TABLE collate3t1;
  }
} {}

finish_test

--- NEW FILE: collate4.test ---
#
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: collate4.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

db collate TEXT text_collate
proc text_collate {a b} {
  return [string compare $a $b]
}

# Do an SQL statement.  Append the search count to the end of the result.
#
proc count sql {
  set ::sqlite_search_count 0
  return [concat [execsql $sql] $::sqlite_search_count]
}

# This procedure executes the SQL.  Then it checks the generated program
# for the SQL and appends a "nosort" to the result if the program contains the
# SortCallback opcode.  If the program does not contain the SortCallback
# opcode it appends "sort"
#
proc cksort {sql} {
  set data [execsql $sql]
  set prog [execsql "EXPLAIN $sql"]
  if {[regexp Sort $prog]} {set x sort} {set x nosort}
  lappend data $x
  return $data
}

# 
# Test cases are organized roughly as follows:
#
# collate4-1.*      ORDER BY.
# collate4-2.*      WHERE clauses.
# collate4-3.*      constraints (primary key, unique).
# collate4-4.*      simple min() or max() queries.
# collate4-5.*      REINDEX command
# collate4-6.*      INTEGER PRIMARY KEY indices.
#

#
# These tests - collate4-1.* - check that indices are correctly
# selected or not selected to implement ORDER BY clauses when 
# user defined collation sequences are involved. 
#
# Because these tests also exercise all the different ways indices 
# can be created, they also serve to verify that indices are correctly 
# initialised with user-defined collation sequences when they are
# created.
#
# Tests named collate4-1.1.* use indices with a single column. Tests
# collate4-1.2.* use indices with two columns.
#
do_test collate4-1.1.0 {
  execsql {
    CREATE TABLE collate4t1(a COLLATE NOCASE, b COLLATE TEXT);
    INSERT INTO collate4t1 VALUES( 'a', 'a' );
    INSERT INTO collate4t1 VALUES( 'b', 'b' );
    INSERT INTO collate4t1 VALUES( NULL, NULL );
    INSERT INTO collate4t1 VALUES( 'B', 'B' );
    INSERT INTO collate4t1 VALUES( 'A', 'A' );
    CREATE INDEX collate4i1 ON collate4t1(a);
    CREATE INDEX collate4i2 ON collate4t1(b);
  }
} {}
do_test collate4-1.1.1 {
  cksort {SELECT a FROM collate4t1 ORDER BY a}
} {{} a A b B nosort}
do_test collate4-1.1.2 {
  cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE NOCASE}
} {{} a A b B nosort}
do_test collate4-1.1.3 {
  cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE TEXT}
} {{} A B a b sort}
do_test collate4-1.1.4 {
  cksort {SELECT b FROM collate4t1 ORDER BY b}
} {{} A B a b nosort}
do_test collate4-1.1.5 {
  cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE TEXT}
} {{} A B a b nosort}
do_test collate4-1.1.6 {
  cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE NOCASE}
} {{} A a B b sort}

do_test collate4-1.1.7 {
  execsql {
    CREATE TABLE collate4t2(
      a PRIMARY KEY COLLATE NOCASE, 
      b UNIQUE COLLATE TEXT
    );
    INSERT INTO collate4t2 VALUES( 'a', 'a' );
    INSERT INTO collate4t2 VALUES( NULL, NULL );
    INSERT INTO collate4t2 VALUES( 'B', 'B' );
  }
} {}
do_test collate4-1.1.8 {
  cksort {SELECT a FROM collate4t2 ORDER BY a}
} {{} a B nosort}
do_test collate4-1.1.9 {
  cksort {SELECT a FROM collate4t2 ORDER BY a COLLATE NOCASE}
} {{} a B nosort}
do_test collate4-1.1.10 {
  cksort {SELECT a FROM collate4t2 ORDER BY a COLLATE TEXT}
} {{} B a sort}
do_test collate4-1.1.11 {
  cksort {SELECT b FROM collate4t2 ORDER BY b}
} {{} B a nosort}
do_test collate4-1.1.12 {
  cksort {SELECT b FROM collate4t2 ORDER BY b COLLATE TEXT}
} {{} B a nosort}
do_test collate4-1.1.13 {
  cksort {SELECT b FROM collate4t2 ORDER BY b COLLATE NOCASE}
} {{} a B sort}

do_test collate4-1.1.14 {
  execsql {
    CREATE TABLE collate4t3(
      b COLLATE TEXT,  
      a COLLATE NOCASE, 
      UNIQUE(a), PRIMARY KEY(b)
    );
    INSERT INTO collate4t3 VALUES( 'a', 'a' );
    INSERT INTO collate4t3 VALUES( NULL, NULL );
    INSERT INTO collate4t3 VALUES( 'B', 'B' );
  }
} {}
do_test collate4-1.1.15 {
  cksort {SELECT a FROM collate4t3 ORDER BY a}
} {{} a B nosort}
do_test collate4-1.1.16 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE NOCASE}
} {{} a B nosort}
do_test collate4-1.1.17 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE TEXT}
} {{} B a sort}
do_test collate4-1.1.18 {
  cksort {SELECT b FROM collate4t3 ORDER BY b}
} {{} B a nosort}
do_test collate4-1.1.19 {
  cksort {SELECT b FROM collate4t3 ORDER BY b COLLATE TEXT}
} {{} B a nosort}
do_test collate4-1.1.20 {
  cksort {SELECT b FROM collate4t3 ORDER BY b COLLATE NOCASE}
} {{} a B sort}

do_test collate4-1.1.21 {
  execsql {
    CREATE TABLE collate4t4(a COLLATE NOCASE, b COLLATE TEXT);
    INSERT INTO collate4t4 VALUES( 'a', 'a' );
    INSERT INTO collate4t4 VALUES( 'b', 'b' );
    INSERT INTO collate4t4 VALUES( NULL, NULL );
    INSERT INTO collate4t4 VALUES( 'B', 'B' );
    INSERT INTO collate4t4 VALUES( 'A', 'A' );
    CREATE INDEX collate4i3 ON collate4t4(a COLLATE TEXT);
    CREATE INDEX collate4i4 ON collate4t4(b COLLATE NOCASE);
  }
} {}
do_test collate4-1.1.22 {
  cksort {SELECT a FROM collate4t4 ORDER BY a}
} {{} A a B b sort}
do_test collate4-1.1.23 {
  cksort {SELECT a FROM collate4t4 ORDER BY a COLLATE NOCASE}
} {{} A a B b sort}
do_test collate4-1.1.24 {
  cksort {SELECT a FROM collate4t4 ORDER BY a COLLATE TEXT}
} {{} A B a b nosort}
do_test collate4-1.1.25 {
  cksort {SELECT b FROM collate4t4 ORDER BY b}
} {{} A B a b sort}
do_test collate4-1.1.26 {
  cksort {SELECT b FROM collate4t4 ORDER BY b COLLATE TEXT}
} {{} A B a b sort}
do_test collate4-1.1.27 {
  cksort {SELECT b FROM collate4t4 ORDER BY b COLLATE NOCASE}
} {{} a A b B nosort}

do_test collate4-1.1.30 {
  execsql {
    DROP TABLE collate4t1;
    DROP TABLE collate4t2;
    DROP TABLE collate4t3;
    DROP TABLE collate4t4;
  }
} {}

do_test collate4-1.2.0 {
  execsql {
    CREATE TABLE collate4t1(a COLLATE NOCASE, b COLLATE TEXT);
    INSERT INTO collate4t1 VALUES( 'a', 'a' );
    INSERT INTO collate4t1 VALUES( 'b', 'b' );
    INSERT INTO collate4t1 VALUES( NULL, NULL );
    INSERT INTO collate4t1 VALUES( 'B', 'B' );
    INSERT INTO collate4t1 VALUES( 'A', 'A' );
    CREATE INDEX collate4i1 ON collate4t1(a, b);
  }
} {}
do_test collate4-1.2.1 {
  cksort {SELECT a FROM collate4t1 ORDER BY a}
} {{} A a B b nosort}
do_test collate4-1.2.2 {
  cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE nocase}
} {{} A a B b nosort}
do_test collate4-1.2.3 {
  cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE text}
} {{} A B a b sort}
do_test collate4-1.2.4 {
  cksort {SELECT a FROM collate4t1 ORDER BY a, b}
} {{} A a B b nosort}
do_test collate4-1.2.5 {
  cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE nocase}
} {{} A a B b sort}
do_test collate4-1.2.6 {
  cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE text}
} {{} A a B b nosort}

do_test collate4-1.2.7 {
  execsql {
    CREATE TABLE collate4t2(
      a COLLATE NOCASE, 
      b COLLATE TEXT, 
      PRIMARY KEY(a, b)
    );
    INSERT INTO collate4t2 VALUES( 'a', 'a' );
    INSERT INTO collate4t2 VALUES( NULL, NULL );
    INSERT INTO collate4t2 VALUES( 'B', 'B' );
  }
} {}
do_test collate4-1.2.8 {
  cksort {SELECT a FROM collate4t2 ORDER BY a}
} {{} a B nosort}
do_test collate4-1.2.9 {
  cksort {SELECT a FROM collate4t2 ORDER BY a COLLATE nocase}
} {{} a B nosort}
do_test collate4-1.2.10 {
  cksort {SELECT a FROM collate4t2 ORDER BY a COLLATE text}
} {{} B a sort}
do_test collate4-1.2.11 {
  cksort {SELECT a FROM collate4t2 ORDER BY a, b}
} {{} a B nosort}
do_test collate4-1.2.12 {
  cksort {SELECT a FROM collate4t2 ORDER BY a, b COLLATE nocase}
} {{} a B sort}
do_test collate4-1.2.13 {
  cksort {SELECT a FROM collate4t2 ORDER BY a, b COLLATE text}
} {{} a B nosort}

do_test collate4-1.2.14 {
  execsql {
    CREATE TABLE collate4t3(a COLLATE NOCASE, b COLLATE TEXT);
    INSERT INTO collate4t3 VALUES( 'a', 'a' );
    INSERT INTO collate4t3 VALUES( 'b', 'b' );
    INSERT INTO collate4t3 VALUES( NULL, NULL );
    INSERT INTO collate4t3 VALUES( 'B', 'B' );
    INSERT INTO collate4t3 VALUES( 'A', 'A' );
    CREATE INDEX collate4i2 ON collate4t3(a COLLATE TEXT, b COLLATE NOCASE);
  }
} {}
do_test collate4-1.2.15 {
  cksort {SELECT a FROM collate4t3 ORDER BY a}
} {{} A a B b sort}
do_test collate4-1.2.16 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE nocase}
} {{} A a B b sort}
do_test collate4-1.2.17 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text}
} {{} A B a b nosort}
do_test collate4-1.2.18 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text, b}
} {{} A B a b sort}
do_test collate4-1.2.19 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text, b COLLATE nocase}
} {{} A B a b nosort}
do_test collate4-1.2.20 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text, b COLLATE text}
} {{} A B a b sort}
do_test collate4-1.2.21 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text DESC}
} {b a B A {} nosort}
do_test collate4-1.2.22 {
  cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text DESC, b}
} {b a B A {} sort}
do_test collate4-1.2.23 {
  cksort {SELECT a FROM collate4t3 
            ORDER BY a COLLATE text DESC, b COLLATE nocase}
} {b a B A {} sort}
do_test collate4-1.2.24 {
  cksort {SELECT a FROM collate4t3 
            ORDER BY a COLLATE text DESC, b COLLATE nocase DESC}
} {b a B A {} nosort}

do_test collate4-1.2.25 {
  execsql {
    DROP TABLE collate4t1;
    DROP TABLE collate4t2;
    DROP TABLE collate4t3;
  }
} {}

#
# These tests - collate4-2.* - check that indices are correctly
# selected or not selected to implement WHERE clauses when user 
# defined collation sequences are involved. 
#
# Indices may optimise WHERE clauses using <, >, <=, >=, = or IN
# operators.
#
do_test collate4-2.1.0 {
  execsql {
    CREATE TABLE collate4t1(a COLLATE NOCASE);
    CREATE TABLE collate4t2(b COLLATE TEXT);

    INSERT INTO collate4t1 VALUES('a');
    INSERT INTO collate4t1 VALUES('A');
    INSERT INTO collate4t1 VALUES('b');
    INSERT INTO collate4t1 VALUES('B');
    INSERT INTO collate4t1 VALUES('c');
    INSERT INTO collate4t1 VALUES('C');
    INSERT INTO collate4t1 VALUES('d');
    INSERT INTO collate4t1 VALUES('D');
    INSERT INTO collate4t1 VALUES('e');
    INSERT INTO collate4t1 VALUES('D');

    INSERT INTO collate4t2 VALUES('A');
    INSERT INTO collate4t2 VALUES('Z');
  }
} {}
do_test collate4-2.1.1 {
  count {
    SELECT * FROM collate4t2, collate4t1 WHERE a = b;
  }
} {A a A A 19}
do_test collate4-2.1.2 {
  execsql {
    CREATE INDEX collate4i1 ON collate4t1(a);
  }
  count {
    SELECT * FROM collate4t2, collate4t1 WHERE a = b;
  }
} {A a A A 7}
do_test collate4-2.1.3 {
  count {
    SELECT * FROM collate4t2, collate4t1 WHERE b = a;
  }
} {A A 19}
do_test collate4-2.1.4 {
  execsql {
    DROP INDEX collate4i1;
    CREATE INDEX collate4i1 ON collate4t1(a COLLATE TEXT);
  }
  count {
    SELECT * FROM collate4t2, collate4t1 WHERE a = b;
  }
} {A a A A 19}
do_test collate4-2.1.5 {
  count {
    SELECT * FROM collate4t2, collate4t1 WHERE b = a;
  }
} {A A 5}
do_test collate4-2.1.6 {
  count {
    SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2);
  }
} {a A 10}
do_test collate4-2.1.7 {
  execsql {
    DROP INDEX collate4i1;
    CREATE INDEX collate4i1 ON collate4t1(a);
  }
  count {
    SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2);
  }
} {a A 8}
do_test collate4-2.1.8 {
  count {
    SELECT a FROM collate4t1 WHERE a IN ('z', 'a');
  }
} {a A 7}
do_test collate4-2.1.9 {
  execsql {
    DROP INDEX collate4i1;
    CREATE INDEX collate4i1 ON collate4t1(a COLLATE TEXT);
  }
  count {
    SELECT a FROM collate4t1 WHERE a IN ('z', 'a');
  }
} {a A 9}
do_test collate4-2.1.10 {
  execsql {
    DROP TABLE collate4t1;
    DROP TABLE collate4t2;
  }
} {}

do_test collate4-2.2.0 {
  execsql {
    CREATE TABLE collate4t1(a COLLATE nocase, b COLLATE text, c);
    CREATE TABLE collate4t2(a COLLATE nocase, b COLLATE text, c COLLATE TEXT);

    INSERT INTO collate4t1 VALUES('0', '0', '0');
    INSERT INTO collate4t1 VALUES('0', '0', '1');
    INSERT INTO collate4t1 VALUES('0', '1', '0');
    INSERT INTO collate4t1 VALUES('0', '1', '1');
    INSERT INTO collate4t1 VALUES('1', '0', '0');
    INSERT INTO collate4t1 VALUES('1', '0', '1');
    INSERT INTO collate4t1 VALUES('1', '1', '0');
    INSERT INTO collate4t1 VALUES('1', '1', '1');
    insert into collate4t2 SELECT * FROM collate4t1;
  }
} {}
do_test collate4-2.2.1 {
  count {
    SELECT * FROM collate4t2 NATURAL JOIN collate4t1;
  }
} {0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 63}
do_test collate4-2.2.1 {
  execsql {
    CREATE INDEX collate4i1 ON collate4t1(a, b, c);
  }
  count {
    SELECT * FROM collate4t2 NATURAL JOIN collate4t1;
  }
} {0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 45}
do_test collate4-2.2.2 {
  execsql {
    DROP INDEX collate4i1;
    CREATE INDEX collate4i1 ON collate4t1(a, b, c COLLATE text);
  }
  count {
    SELECT * FROM collate4t2 NATURAL JOIN collate4t1;
  }
} {0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 22}

do_test collate4-2.2.10 {
  execsql {
    DROP TABLE collate4t1;
    DROP TABLE collate4t2;
  }
} {}

#
# These tests - collate4-3.* verify that indices that implement
# UNIQUE and PRIMARY KEY constraints operate correctly with user
# defined collation sequences.
#
do_test collate4-3.0 {
  execsql {
    CREATE TABLE collate4t1(a PRIMARY KEY COLLATE NOCASE);
  }
} {}
do_test collate4-3.1 {
  catchsql {
    INSERT INTO collate4t1 VALUES('abc');
    INSERT INTO collate4t1 VALUES('ABC');
  }
} {1 {column a is not unique}}
do_test collate4-3.2 {
  execsql {
    SELECT * FROM collate4t1;
  }
} {abc}
do_test collate4-3.3 {
  catchsql {
    INSERT INTO collate4t1 SELECT upper(a) FROM collate4t1;
  }
} {1 {column a is not unique}}
do_test collate4-3.4 {
  catchsql {
    INSERT INTO collate4t1 VALUES(1);
    UPDATE collate4t1 SET a = 'abc';
  }
} {1 {column a is not unique}}
do_test collate4-3.5 {
  execsql {
    DROP TABLE collate4t1;
    CREATE TABLE collate4t1(a COLLATE NOCASE UNIQUE);
  }
} {}
do_test collate4-3.6 {
  catchsql {
    INSERT INTO collate4t1 VALUES('abc');
    INSERT INTO collate4t1 VALUES('ABC');
  }
} {1 {column a is not unique}}
do_test collate4-3.7 {
  execsql {
    SELECT * FROM collate4t1;
  }
} {abc}
do_test collate4-3.8 {
  catchsql {
    INSERT INTO collate4t1 SELECT upper(a) FROM collate4t1;
  }
} {1 {column a is not unique}}
do_test collate4-3.9 {
  catchsql {
    INSERT INTO collate4t1 VALUES(1);
    UPDATE collate4t1 SET a = 'abc';
  }
} {1 {column a is not unique}}
do_test collate4-3.10 {
  execsql {
    DROP TABLE collate4t1;
    CREATE TABLE collate4t1(a);
    CREATE UNIQUE INDEX collate4i1 ON collate4t1(a COLLATE NOCASE);
  }
} {}
do_test collate4-3.11 {
  catchsql {
    INSERT INTO collate4t1 VALUES('abc');
    INSERT INTO collate4t1 VALUES('ABC');
  }
} {1 {column a is not unique}}
do_test collate4-3.12 {
  execsql {
    SELECT * FROM collate4t1;
  }
} {abc}
do_test collate4-3.13 {
  catchsql {
    INSERT INTO collate4t1 SELECT upper(a) FROM collate4t1;
  }
} {1 {column a is not unique}}
do_test collate4-3.14 {
  catchsql {
    INSERT INTO collate4t1 VALUES(1);
    UPDATE collate4t1 SET a = 'abc';
  }
} {1 {column a is not unique}}

do_test collate4-3.15 {
  execsql {
    DROP TABLE collate4t1;
  }
} {}

# Mimic the SQLite 2 collation type NUMERIC.
db collate numeric numeric_collate
proc numeric_collate {lhs rhs} {
  if {$lhs == $rhs} {return 0} 
  return [expr ($lhs>$rhs)?1:-1]
}

#
# These tests - collate4-4.* check that min() and max() only ever 
# use indices constructed with built-in collation type numeric.
#
# CHANGED:  min() and max() now use the collation type. If there
# is an indice that can be used, it is used.
#
do_test collate4-4.0 {
  execsql {
    CREATE TABLE collate4t1(a COLLATE TEXT);
    INSERT INTO collate4t1 VALUES('2');
    INSERT INTO collate4t1 VALUES('10');
    INSERT INTO collate4t1 VALUES('20');
    INSERT INTO collate4t1 VALUES('104');
  }
} {}
do_test collate4-4.1 {
  count {
    SELECT max(a) FROM collate4t1
  }
} {20 3}
do_test collate4-4.2 {
  count {
    SELECT min(a) FROM collate4t1
  }
} {10 3}
do_test collate4-4.3 {
  # Test that the index with collation type TEXT is used.
  execsql {
    CREATE INDEX collate4i1 ON collate4t1(a);
  }
  count {
    SELECT min(a) FROM collate4t1;
  }
} {10 2}
do_test collate4-4.4 {
  count {
    SELECT max(a) FROM collate4t1;
  }
} {20 1}
do_test collate4-4.5 {
  # Test that the index with collation type NUMERIC is not used.
  execsql {
    DROP INDEX collate4i1;
    CREATE INDEX collate4i1 ON collate4t1(a COLLATE NUMERIC);
  }
  count {
    SELECT min(a) FROM collate4t1;
  }
} {10 3}
do_test collate4-4.6 {
  count {
    SELECT max(a) FROM collate4t1;
  }
} {20 3}
do_test collate4-4.7 {
  execsql {
    DROP TABLE collate4t1;
  }
} {}

# Also test the scalar min() and max() functions.
#
do_test collate4-4.8 {
  execsql {
    CREATE TABLE collate4t1(a COLLATE TEXT, b COLLATE NUMERIC);
    INSERT INTO collate4t1 VALUES('11', '101');
    INSERT INTO collate4t1 VALUES('101', '11')
  }
} {}
do_test collate4-4.9 {
  execsql {
    SELECT max(a, b) FROM collate4t1;
  }
} {11 11}
do_test collate4-4.10 {
  execsql {
    SELECT max(b, a) FROM collate4t1;
  }
} {101 101}
do_test collate4-4.11 {
  execsql {
    SELECT max(a, '101') FROM collate4t1;
  }
} {11 101}
do_test collate4-4.12 {
  execsql {
    SELECT max('101', a) FROM collate4t1;
  }
} {11 101}
do_test collate4-4.13 {
  execsql {
    SELECT max(b, '101') FROM collate4t1;
  }
} {101 101}
do_test collate4-4.14 {
  execsql {
    SELECT max('101', b) FROM collate4t1;
  }
} {101 101}

do_test collate4-4.15 {
  execsql {
    DROP TABLE collate4t1;
  }
} {}

#
# These tests - collate4.6.* - ensure that implict INTEGER PRIMARY KEY 
# indices do not confuse collation sequences. 
#
# These indices are never used for sorting in SQLite. And you can't
# create another index on an INTEGER PRIMARY KEY column, so we don't have 
# to test that.
#
do_test collate4-6.0 {
  execsql {
    CREATE TABLE collate4t1(a INTEGER PRIMARY KEY);
    INSERT INTO collate4t1 VALUES(101);
    INSERT INTO collate4t1 VALUES(10);
    INSERT INTO collate4t1 VALUES(15);
  }
} {}
do_test collate4-6.1 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY 1;
  }
} {10 15 101 sort}
do_test collate4-6.2 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY oid;
  }
} {10 15 101 sort}
do_test collate4-6.3 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY oid||'' COLLATE TEXT;
  }
} {10 101 15 sort}

finish_test

--- NEW FILE: collate5.test ---
#
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing DISTINCT, UNION, INTERSECT and EXCEPT
# SELECT statements that use user-defined collation sequences. Also
# GROUP BY clauses that use user-defined collation sequences.
#
# $Id: collate5.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl


#
# Tests are organised as follows:
# collate5-1.* - DISTINCT
# collate5-2.* - Compound SELECT
# collate5-3.* - ORDER BY on compound SELECT
# collate5-4.* - GROUP BY

# Create the collation sequence 'TEXT', purely for asthetic reasons. The
# test cases in this script could just as easily use BINARY.
db collate TEXT [list string compare]

# Mimic the SQLite 2 collation type NUMERIC.
db collate numeric numeric_collate
proc numeric_collate {lhs rhs} {
  if {$lhs == $rhs} {return 0} 
  return [expr ($lhs>$rhs)?1:-1]
}

#
# These tests - collate5-1.* - focus on the DISTINCT keyword.
#
do_test collate5-1.0 {
  execsql {
    CREATE TABLE collate5t1(a COLLATE nocase, b COLLATE text);

    INSERT INTO collate5t1 VALUES('a', 'apple');
    INSERT INTO collate5t1 VALUES('A', 'Apple');
    INSERT INTO collate5t1 VALUES('b', 'banana');
    INSERT INTO collate5t1 VALUES('B', 'banana');
    INSERT INTO collate5t1 VALUES('n', NULL);
    INSERT INTO collate5t1 VALUES('N', NULL);
  } 
} {}
do_test collate5-1.1 {
  execsql {
    SELECT DISTINCT a FROM collate5t1;
  }
} {a b n}
do_test collate5-1.2 {
  execsql {
    SELECT DISTINCT b FROM collate5t1;
  }
} {apple Apple banana {}}
do_test collate5-1.3 {
  execsql {
    SELECT DISTINCT a, b FROM collate5t1;
  }
} {a apple A Apple b banana n {}}


#
# Tests named collate5-2.* focus on UNION, EXCEPT and INTERSECT
# queries that use user-defined collation sequences.
#
# collate5-2.1.* - UNION
# collate5-2.2.* - INTERSECT
# collate5-2.3.* - EXCEPT
#
do_test collate5-2.0 {
  execsql {
    CREATE TABLE collate5t2(a COLLATE text, b COLLATE nocase);

    INSERT INTO collate5t2 VALUES('a', 'apple');
    INSERT INTO collate5t2 VALUES('A', 'apple');
    INSERT INTO collate5t2 VALUES('b', 'banana');
    INSERT INTO collate5t2 VALUES('B', 'Banana');
  } 
} {}

do_test collate5-2.1.1 {
  execsql {
    SELECT a FROM collate5t1 UNION select a FROM collate5t2;
  }
} {A B N}
do_test collate5-2.1.2 {
  execsql {
    SELECT a FROM collate5t2 UNION select a FROM collate5t1;
  }
} {A B N a b n}
do_test collate5-2.1.3 {
  execsql {
    SELECT a, b FROM collate5t1 UNION select a, b FROM collate5t2;
  }
} {A Apple A apple B Banana b banana N {}}
do_test collate5-2.1.4 {
  execsql {
    SELECT a, b FROM collate5t2 UNION select a, b FROM collate5t1;
  }
} {A Apple B banana N {} a apple b banana n {}}

do_test collate5-2.2.1 {
  execsql {
    SELECT a FROM collate5t1 EXCEPT select a FROM collate5t2;
  }
} {N}
do_test collate5-2.2.2 {
  execsql {
    SELECT a FROM collate5t2 EXCEPT select a FROM collate5t1 WHERE a != 'a';
  }
} {A a}
do_test collate5-2.2.3 {
  execsql {
    SELECT a, b FROM collate5t1 EXCEPT select a, b FROM collate5t2;
  }
} {A Apple N {}}
do_test collate5-2.2.4 {
  execsql {
    SELECT a, b FROM collate5t2 EXCEPT select a, b FROM collate5t1 
      where a != 'a';
  }
} {A apple a apple}

do_test collate5-2.3.1 {
  execsql {
    SELECT a FROM collate5t1 INTERSECT select a FROM collate5t2;
  }
} {A B}
do_test collate5-2.3.2 {
  execsql {
    SELECT a FROM collate5t2 INTERSECT select a FROM collate5t1 WHERE a != 'a';
  }
} {B b}
do_test collate5-2.3.3 {
  execsql {
    SELECT a, b FROM collate5t1 INTERSECT select a, b FROM collate5t2;
  }
} {a apple B banana}
do_test collate5-2.3.4 {
  execsql {
    SELECT a, b FROM collate5t2 INTERSECT select a, b FROM collate5t1;
  }
} {A apple B Banana a apple b banana}

#
# This test ensures performs a UNION operation with a bunch of different
# length records. The goal is to test that the logic that compares records
# for the compound SELECT operators works with record lengths that lie
# either side of the troublesome 256 and 65536 byte marks.
#
set ::lens [list \
  0 1 2 3 4 5 6 7 8 9 \
  240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 \
  257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 \
  65520 65521 65522 65523 65524 65525 65526 65527 65528 65529 65530 \
  65531 65532 65533 65534 65535 65536 65537 65538 65539 65540 65541 \
  65542 65543 65544 65545 65546 65547 65548 65549 65550 65551 ]
do_test collate5-2.4.0 {
  execsql {
    BEGIN;
    CREATE TABLE collate5t3(a, b);
  }
  foreach ii $::lens { 
    execsql "INSERT INTO collate5t3 VALUES($ii, '[string repeat a $ii]');"
  }
  execsql {
    COMMIT;
    SELECT count(*) FROM 
        (SELECT * FROM collate5t3 UNION SELECT * FROM collate5t3);
  }
} [llength $::lens]
do_test collate5-2.4.1 {
  execsql {DROP TABLE collate5t3;}
} {}
unset ::lens

#
# These tests - collate5-3.* - focus on compound SELECT queries that 
# feature ORDER BY clauses.
#
do_test collate5-3.0 {
  execsql {
    SELECT a FROM collate5t1 UNION ALL SELECT a FROM collate5t2 ORDER BY 1;
  }
} {A a A a B b B b N n}
do_test collate5-3.1 {
  execsql {
    SELECT a FROM collate5t2 UNION ALL SELECT a FROM collate5t1 ORDER BY 1;
  }
} {A A B B N a a b b n}
do_test collate5-3.2 {
  execsql {
    SELECT a FROM collate5t1 UNION ALL SELECT a FROM collate5t2 
      ORDER BY 1 COLLATE TEXT;
  }
} {A A B B N a a b b n}

do_test collate5-3.3 {
  execsql {
    CREATE TABLE collate5t_cn(a COLLATE NUMERIC);
    CREATE TABLE collate5t_ct(a COLLATE TEXT);
    INSERT INTO collate5t_cn VALUES('1');
    INSERT INTO collate5t_cn VALUES('11');
    INSERT INTO collate5t_cn VALUES('101');
    INSERT INTO collate5t_ct SELECT * FROM collate5t_cn;
  }
} {}
do_test collate5-3.4 {
  execsql {
    SELECT a FROM collate5t_cn INTERSECT SELECT a FROM collate5t_ct ORDER BY 1;
  }
} {1 11 101}
do_test collate5-3.5 {
  execsql {
    SELECT a FROM collate5t_ct INTERSECT SELECT a FROM collate5t_cn ORDER BY 1;
  }
} {1 101 11}

do_test collate5-3.20 {
  execsql {
    DROP TABLE collate5t_cn;
    DROP TABLE collate5t_ct;
    DROP TABLE collate5t1;
    DROP TABLE collate5t2;
  }
} {}

do_test collate5-4.0 {
  execsql {
    CREATE TABLE collate5t1(a COLLATE NOCASE, b COLLATE NUMERIC); 
    INSERT INTO collate5t1 VALUES('a', '1');
    INSERT INTO collate5t1 VALUES('A', '1.0');
    INSERT INTO collate5t1 VALUES('b', '2');
    INSERT INTO collate5t1 VALUES('B', '3');
  }
} {}
do_test collate5-4.1 {
  execsql {
    SELECT a, count(*) FROM collate5t1 GROUP BY a;
  }
} {a 2 b 2}
do_test collate5-4.2 {
  execsql {
    SELECT a, b, count(*) FROM collate5t1 GROUP BY a, b;
  }
} {a 1 2 b 2 1 B 3 1}
do_test collate5-4.3 {
  execsql {
    DROP TABLE collate5t1;
  }
} {}

finish_test

--- NEW FILE: collate6.test ---
#
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is collation sequences in concert with triggers.
#
# $Id: collate6.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a case-insensitive collation type NOCASE for use in testing. 
# Normally, capital letters are less than their lower-case counterparts.
db collate NOCASE nocase_collate
proc nocase_collate {a b} {
  return [string compare -nocase $a $b]
}

#
# Tests are organized as follows:
# collate6-1.* - triggers.
#

do_test collate6-1.0 {
  execsql {
    CREATE TABLE collate6log(a, b);
    CREATE TABLE collate6tab(a COLLATE NOCASE, b COLLATE BINARY);
  }
} {}

# Test that the default collation sequence applies to new.* references 
# in WHEN clauses.
do_test collate6-1.1 {
  execsql {
    CREATE TRIGGER collate6trig BEFORE INSERT ON collate6tab 
      WHEN new.a = 'a' BEGIN
        INSERT INTO collate6log VALUES(new.a, new.b);
    END;
  }
} {}
do_test collate6-1.2 {
  execsql {
    INSERT INTO collate6tab VALUES('a', 'b');
    SELECT * FROM collate6log;
  }
} {a b}
do_test collate6-1.3 {
  execsql {
    INSERT INTO collate6tab VALUES('A', 'B');
    SELECT * FROM collate6log;
  }
} {a b A B}
do_test collate6-1.4 {
  execsql {
    DROP TRIGGER collate6trig;
    DELETE FROM collate6log;
  } 
} {}

# Test that the default collation sequence applies to new.* references 
# in the body of triggers.
do_test collate6-1.5 {
  execsql {
    CREATE TRIGGER collate6trig BEFORE INSERT ON collate6tab BEGIN
      INSERT INTO collate6log VALUES(new.a='a', new.b='b');
    END;
  }
} {}
do_test collate6-1.6 {
  execsql {
    INSERT INTO collate6tab VALUES('a', 'b');
    SELECT * FROM collate6log;
  }
} {1 1}
do_test collate6-1.7 {
  execsql {
    INSERT INTO collate6tab VALUES('A', 'B');
    SELECT * FROM collate6log;
  }
} {1 1 1 0}
do_test collate6-1.8 {
  execsql {
    DROP TRIGGER collate6trig;
    DELETE FROM collate6log;
  } 
} {}

do_test collate6-1.9 {
  execsql {
    DROP TABLE collate6tab;
  }
} {}


finish_test




--- NEW FILE: conflict.test ---
# 2002 January 29
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create tables for the first group of tests.
#
do_test conflict-1.0 {
  execsql {
    CREATE TABLE t1(a, b, c, UNIQUE(a,b));
    CREATE TABLE t2(x);
    SELECT c FROM t1 ORDER BY c;
  }
} {}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf   The conflict resolution algorithm on the BEGIN statement
#   cmd    An INSERT or REPLACE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "c" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t2
#
foreach {i conf cmd t0 t1 t2} {
  1 {}       INSERT                  1 {}  1
  2 {}       {INSERT OR IGNORE}      0 3   1
  3 {}       {INSERT OR REPLACE}     0 4   1
  4 {}       REPLACE                 0 4   1
  5 {}       {INSERT OR FAIL}        1 {}  1
  6 {}       {INSERT OR ABORT}       1 {}  1
  7 {}       {INSERT OR ROLLBACK}    1 {}  {}
} {
  if { $conf=={} } {

  do_test conflict-1.$i {
    if {$conf!=""} {set conf "ON CONFLICT $conf"}
    set r0 [catch {execsql [subst {
      DELETE FROM t1;
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);
      BEGIN $conf;
      INSERT INTO t2 VALUES(1); 
      $cmd INTO t1 VALUES(1,2,4);
    }]} r1]
    catch {execsql {COMMIT}}
    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
    set r2 [execsql {SELECT x FROM t2}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]

  }
}

# Create tables for the first group of tests.
#
do_test conflict-2.0 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(a,b));
    CREATE TABLE t2(x);
    SELECT c FROM t1 ORDER BY c;
  }
} {}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf   The conflict resolution algorithm on the BEGIN statement
#   cmd    An INSERT or REPLACE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "c" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t2
#
foreach {i conf cmd t0 t1 t2} {
  1 {}       INSERT                  1 {}  1
  2 {}       {INSERT OR IGNORE}      0 3   1
  3 {}       {INSERT OR REPLACE}     0 4   1
  4 {}       REPLACE                 0 4   1
  5 {}       {INSERT OR FAIL}        1 {}  1
  6 {}       {INSERT OR ABORT}       1 {}  1
  7 {}       {INSERT OR ROLLBACK}    1 {}  {}
} {
  do_test conflict-2.$i {
    if {$conf!=""} {set conf "ON CONFLICT $conf"}
    set r0 [catch {execsql [subst {
      DELETE FROM t1;
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);
      BEGIN $conf;
      INSERT INTO t2 VALUES(1); 
      $cmd INTO t1 VALUES(1,2,4);
    }]} r1]
    catch {execsql {COMMIT}}
    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
    set r2 [execsql {SELECT x FROM t2}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

# Create tables for the first group of tests.
#
do_test conflict-3.0 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    CREATE TABLE t1(a, b, c INTEGER, PRIMARY KEY(c), UNIQUE(a,b));
    CREATE TABLE t2(x);
    SELECT c FROM t1 ORDER BY c;
  }
} {}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf   The conflict resolution algorithm on the BEGIN statement
#   cmd    An INSERT or REPLACE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "c" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t2
#
foreach {i conf cmd t0 t1 t2} {
  1 {}       INSERT                  1 {}  1
  2 {}       {INSERT OR IGNORE}      0 3   1
  3 {}       {INSERT OR REPLACE}     0 4   1
  4 {}       REPLACE                 0 4   1
  5 {}       {INSERT OR FAIL}        1 {}  1
  6 {}       {INSERT OR ABORT}       1 {}  1
  7 {}       {INSERT OR ROLLBACK}    1 {}  {}
} {
  do_test conflict-3.$i {
    if {$conf!=""} {set conf "ON CONFLICT $conf"}
    set r0 [catch {execsql [subst {
      DELETE FROM t1;
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);
      BEGIN $conf;
      INSERT INTO t2 VALUES(1); 
      $cmd INTO t1 VALUES(1,2,4);
    }]} r1]
    catch {execsql {COMMIT}}
    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
    set r2 [execsql {SELECT x FROM t2}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

do_test conflict-4.0 {
  execsql {
    DROP TABLE t2;
    CREATE TABLE t2(x);
    SELECT x FROM t2;
  }
} {}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf1  The conflict resolution algorithm on the UNIQUE constraint
#   conf2  The conflict resolution algorithm on the BEGIN statement
#   cmd    An INSERT or REPLACE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "c" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t2
#
foreach {i conf1 conf2 cmd t0 t1 t2} {
  1 {}       {}       INSERT                  1 {}  1
  2 REPLACE  {}       INSERT                  0 4   1
  3 IGNORE   {}       INSERT                  0 3   1
  4 FAIL     {}       INSERT                  1 {}  1
  5 ABORT    {}       INSERT                  1 {}  1
  6 ROLLBACK {}       INSERT                  1 {}  {}
  7 REPLACE  {}       {INSERT OR IGNORE}      0 3   1
  8 IGNORE   {}       {INSERT OR REPLACE}     0 4   1
  9 FAIL     {}       {INSERT OR IGNORE}      0 3   1
 10 ABORT    {}       {INSERT OR REPLACE}     0 4   1
 11 ROLLBACK {}       {INSERT OR IGNORE }     0 3   1
} {
  do_test conflict-4.$i {
    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
    if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
      CREATE TABLE t1(a,b,c,UNIQUE(a,b) $conf1);
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);
      BEGIN $conf2;
      INSERT INTO t2 VALUES(1); 
      $cmd INTO t1 VALUES(1,2,4);
    }]} r1]
    catch {execsql {COMMIT}}
    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
    set r2 [execsql {SELECT x FROM t2}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

do_test conflict-5.0 {
  execsql {
    DROP TABLE t2;
    CREATE TABLE t2(x);
    SELECT x FROM t2;
  }
} {}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf1  The conflict resolution algorithm on the NOT NULL constraint
#   conf2  The conflict resolution algorithm on the BEGIN statement
#   cmd    An INSERT or REPLACE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "c" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t2
#
foreach {i conf1 conf2 cmd t0 t1 t2} {
  1 {}       {}       INSERT                  1 {}  1
  2 REPLACE  {}       INSERT                  0 5   1
  3 IGNORE   {}       INSERT                  0 {}  1
  4 FAIL     {}       INSERT                  1 {}  1
  5 ABORT    {}       INSERT                  1 {}  1
  6 ROLLBACK {}       INSERT                  1 {}  {}
  7 REPLACE  {}       {INSERT OR IGNORE}      0 {}  1
  8 IGNORE   {}       {INSERT OR REPLACE}     0 5   1
  9 FAIL     {}       {INSERT OR IGNORE}      0 {}  1
 10 ABORT    {}       {INSERT OR REPLACE}     0 5   1
 11 ROLLBACK {}       {INSERT OR IGNORE}      0 {}  1
 12 {}       {}       {INSERT OR IGNORE}      0 {}  1
 13 {}       {}       {INSERT OR REPLACE}     0 5   1
 14 {}       {}       {INSERT OR FAIL}        1 {}  1
 15 {}       {}       {INSERT OR ABORT}       1 {}  1
 16 {}       {}       {INSERT OR ROLLBACK}    1 {}  {}
} {
  if {$t0} {set t1 {t1.c may not be NULL}}
  do_test conflict-5.$i {
    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
    if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
      CREATE TABLE t1(a,b,c NOT NULL $conf1 DEFAULT 5);
      DELETE FROM t2;
      BEGIN $conf2;
      INSERT INTO t2 VALUES(1); 
      $cmd INTO t1 VALUES(1,2,NULL);
    }]} r1]
    catch {execsql {COMMIT}}
    if {!$r0} {set r1 [execsql {SELECT c FROM t1}]}
    set r2 [execsql {SELECT x FROM t2}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

do_test conflict-6.0 {
  execsql {
    DROP TABLE t2;
    CREATE TABLE t2(a,b,c);
    INSERT INTO t2 VALUES(1,2,1);
    INSERT INTO t2 VALUES(2,3,2);
    INSERT INTO t2 VALUES(3,4,1);
    INSERT INTO t2 VALUES(4,5,4);
    SELECT c FROM t2 ORDER BY b;
    CREATE TABLE t3(x);
    INSERT INTO t3 VALUES(1);
  }
} {1 2 1 4}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf1  The conflict resolution algorithm on the UNIQUE constraint
#   conf2  The conflict resolution algorithm on the BEGIN statement
#   cmd    An UPDATE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "b" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t3
#
foreach {i conf1 conf2 cmd t0 t1 t2} {
  1 {}       {}       UPDATE                  1 {6 7 8 9}  1
  2 REPLACE  {}       UPDATE                  0 {7 6 9}    1
  3 IGNORE   {}       UPDATE                  0 {6 7 3 9}  1
  4 FAIL     {}       UPDATE                  1 {6 7 3 4}  1
  5 ABORT    {}       UPDATE                  1 {1 2 3 4}  1
  6 ROLLBACK {}       UPDATE                  1 {1 2 3 4}  0
  7 REPLACE  {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
  8 IGNORE   {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
  9 FAIL     {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
 10 ABORT    {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 11 ROLLBACK {}       {UPDATE OR IGNORE}      0 {6 7 3 9}   1
 12 {}       {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
 13 {}       {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 14 {}       {}       {UPDATE OR FAIL}        1 {6 7 3 4}  1
 15 {}       {}       {UPDATE OR ABORT}       1 {1 2 3 4}  1
 16 {}       {}       {UPDATE OR ROLLBACK}    1 {1 2 3 4}  0
} {
  if {$t0} {set t1 {column a is not unique}}
  do_test conflict-6.$i {
    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
    if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
      CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
      INSERT INTO t1 SELECT * FROM t2;
      UPDATE t3 SET x=0;
      BEGIN $conf2;
      $cmd t3 SET x=1;
      $cmd t1 SET b=b*2;
      $cmd t1 SET a=c+5;
    }]} r1]
    catch {execsql {COMMIT}}
    if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
    set r2 [execsql {SELECT x FROM t3}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

# Test to make sure a lot of IGNOREs don't cause a stack overflow
#
do_test conflict-7.1 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    DROP TABLE t3;
    CREATE TABLE t1(a unique, b);
  }
  for {set i 1} {$i<=50} {incr i} {
    execsql "INSERT into t1 values($i,[expr {$i+1}]);"
  }
  execsql {
    SELECT count(*), min(a), max(b) FROM t1;
  }
} {50 1 51}
do_test conflict-7.2 {
  execsql {
    PRAGMA count_changes=on;
    UPDATE OR IGNORE t1 SET a=1000;
  }
} {1}
do_test conflict-7.2.1 {
  db changes
} {1}
do_test conflict-7.3 {
  execsql {
    SELECT b FROM t1 WHERE a=1000;
  }
} {2}
do_test conflict-7.4 {
  execsql {
    SELECT count(*) FROM t1;
  }
} {50}
do_test conflict-7.5 {
  execsql {
    PRAGMA count_changes=on;
    UPDATE OR REPLACE t1 SET a=1001;
  }
} {50}
do_test conflict-7.5.1 {
  db changes
} {50}
do_test conflict-7.6 {
  execsql {
    SELECT b FROM t1 WHERE a=1001;
  }
} {51}
do_test conflict-7.7 {
  execsql {
    SELECT count(*) FROM t1;
  }
} {1}

# Update for version 3: A SELECT statement no longer resets the change
# counter (Test result changes from 0 to 50).
do_test conflict-7.7.1 {
  db changes
} {50}

# Make sure the row count is right for rows that are ignored on
# an insert.
#
do_test conflict-8.1 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2);
  }
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,3);
  }
} {1}
do_test conflict-8.1.1 {
  db changes
} {1}
do_test conflict-8.2 {
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,4);
  }
} {0}
do_test conflict-8.2.1 {
  db changes
} {0}
do_test conflict-8.3 {
  execsql {
    INSERT OR REPLACE INTO t1 VALUES(2,4);
  }
} {1}
do_test conflict-8.3.1 {
  db changes
} {1}
do_test conflict-8.4 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT * FROM t1;
  }
} {0}
do_test conflict-8.4.1 {
  db changes
} {0}
do_test conflict-8.5 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
  }
} {2}
do_test conflict-8.5.1 {
  db changes
} {2}
do_test conflict-8.6 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
  }
} {3}
do_test conflict-8.6.1 {
  db changes
} {3}

integrity_check conflict-8.99

do_test conflict-9.1 {
  execsql {
    PRAGMA count_changes=0;
    CREATE TABLE t2(
      a INTEGER UNIQUE ON CONFLICT IGNORE,
      b INTEGER UNIQUE ON CONFLICT FAIL,
      c INTEGER UNIQUE ON CONFLICT REPLACE,
      d INTEGER UNIQUE ON CONFLICT ABORT,
      e INTEGER UNIQUE ON CONFLICT ROLLBACK
    );
    CREATE TABLE t3(x);
    INSERT INTO t3 VALUES(1);
    SELECT * FROM t3;
  }
} {1}
do_test conflict-9.2 {
  catchsql {
    INSERT INTO t2 VALUES(1,1,1,1,1);
    INSERT INTO t2 VALUES(2,2,2,2,2);
    SELECT * FROM t2;
  }
} {0 {1 1 1 1 1 2 2 2 2 2}}
do_test conflict-9.3 {
  catchsql {
    INSERT INTO t2 VALUES(1,3,3,3,3);
    SELECT * FROM t2;
  }
} {0 {1 1 1 1 1 2 2 2 2 2}}
do_test conflict-9.4 {
  catchsql {
    UPDATE t2 SET a=a+1 WHERE a=1;
    SELECT * FROM t2;
  }
} {0 {1 1 1 1 1 2 2 2 2 2}}
do_test conflict-9.5 {
  catchsql {
    INSERT INTO t2 VALUES(3,1,3,3,3);
    SELECT * FROM t2;
  }
} {1 {column b is not unique}}
do_test conflict-9.6 {
  catchsql {
    UPDATE t2 SET b=b+1 WHERE b=1;
    SELECT * FROM t2;
  }
} {1 {column b is not unique}}
do_test conflict-9.7 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    INSERT INTO t2 VALUES(3,1,3,3,3);
    SELECT * FROM t2;
  }
} {1 {column b is not unique}}
do_test conflict-9.8 {
  execsql {COMMIT}
  execsql {SELECT * FROM t3}
} {2}
do_test conflict-9.9 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    UPDATE t2 SET b=b+1 WHERE b=1;
    SELECT * FROM t2;
  }
} {1 {column b is not unique}}
do_test conflict-9.10 {
  execsql {COMMIT}
  execsql {SELECT * FROM t3}
} {3}
do_test conflict-9.11 {
  catchsql {
    INSERT INTO t2 VALUES(3,3,3,1,3);
    SELECT * FROM t2;
  }
} {1 {column d is not unique}}
do_test conflict-9.12 {
  catchsql {
    UPDATE t2 SET d=d+1 WHERE d=1;
    SELECT * FROM t2;
  }
} {1 {column d is not unique}}
do_test conflict-9.13 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    INSERT INTO t2 VALUES(3,3,3,1,3);
    SELECT * FROM t2;
  }
} {1 {column d is not unique}}
do_test conflict-9.14 {
  execsql {COMMIT}
  execsql {SELECT * FROM t3}
} {4}
do_test conflict-9.15 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    UPDATE t2 SET d=d+1 WHERE d=1;
    SELECT * FROM t2;
  }
} {1 {column d is not unique}}
do_test conflict-9.16 {
  execsql {COMMIT}
  execsql {SELECT * FROM t3}
} {5}
do_test conflict-9.17 {
  catchsql {
    INSERT INTO t2 VALUES(3,3,3,3,1);
    SELECT * FROM t2;
  }
} {1 {column e is not unique}}
do_test conflict-9.18 {
  catchsql {
    UPDATE t2 SET e=e+1 WHERE e=1;
    SELECT * FROM t2;
  }
} {1 {column e is not unique}}
do_test conflict-9.19 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    INSERT INTO t2 VALUES(3,3,3,3,1);
    SELECT * FROM t2;
  }
} {1 {column e is not unique}}
do_test conflict-9.20 {
  catch {execsql {COMMIT}}
  execsql {SELECT * FROM t3}
} {5}
do_test conflict-9.21 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    UPDATE t2 SET e=e+1 WHERE e=1;
    SELECT * FROM t2;
  }
} {1 {column e is not unique}}
do_test conflict-9.22 {
  catch {execsql {COMMIT}}
  execsql {SELECT * FROM t3}
} {5}
do_test conflict-9.23 {
  catchsql {
    INSERT INTO t2 VALUES(3,3,1,3,3);
    SELECT * FROM t2;
  }
} {0 {2 2 2 2 2 3 3 1 3 3}}
do_test conflict-9.24 {
  catchsql {
    UPDATE t2 SET c=c-1 WHERE c=2;
    SELECT * FROM t2;
  }
} {0 {2 2 1 2 2}}
do_test conflict-9.25 {
  catchsql {
    BEGIN;
    UPDATE t3 SET x=x+1;
    INSERT INTO t2 VALUES(3,3,1,3,3);
    SELECT * FROM t2;
  }
} {0 {3 3 1 3 3}}
do_test conflict-9.26 {
  catch {execsql {COMMIT}}
  execsql {SELECT * FROM t3}
} {6}

do_test conflict-10.1 {
  catchsql {
    DELETE FROM t1;
    BEGIN;
    INSERT OR ROLLBACK INTO t1 VALUES(1,2);
    INSERT OR ROLLBACK INTO t1 VALUES(1,3);
    COMMIT;
  }
  execsql {SELECT * FROM t1}
} {}
do_test conflict-10.2 {
  catchsql {
    CREATE TABLE t4(x);
    CREATE UNIQUE INDEX t4x ON t4(x);
    BEGIN;
    INSERT OR ROLLBACK INTO t4 VALUES(1);
    INSERT OR ROLLBACK INTO t4 VALUES(1);
    COMMIT;
  }
  execsql {SELECT * FROM t4}
} {}

integrity_check conflict-99.0

finish_test

--- NEW FILE: corrupt.test ---
# 2004 August 30
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Construct a large database for testing.
#
do_test corrupt-1.1 {
  execsql {
    BEGIN;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randstr(10,100));
    INSERT INTO t1 VALUES(randstr(10,100));
    INSERT INTO t1 VALUES(randstr(10,100));
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 VALUES(randstr(2100,3000));
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    INSERT INTO t1 SELECT x || randstr(5,10) FROM t1;
    CREATE INDEX t1i1 ON t1(x);
    CREATE TABLE t2 AS SELECT * FROM t1;
    DELETE FROM t2 WHERE rowid%5!=0;
    COMMIT;
    PRAGMA integrity_check;
  }
} {ok}

# Copy a file 
#
proc copy_file {from to} {
  set f [open $from]
  fconfigure $f -translation binary
  set t [open $to w]
  fconfigure $t -translation binary
  puts -nonewline $t [read $f [file size $from]]
  close $t
  close $f
}

# Setup for the tests.
copy_file test.db test.bu
set fsize [file size test.db]
set junk "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while {[string length $junk]<256} {append junk $junk}
set junk [string range $junk 0 255]


for {set i [expr {1*256}]} {$i<$fsize-256} {incr i 256} {
  set tn [expr {$i/256}]
  db close
  copy_file test.bu test.db
  set fd [open test.db r+]
  fconfigure $fd -translation binary
  seek $fd $i
  puts -nonewline $fd $junk
  close $fd
  sqlite3 db test.db
  do_test corrupt-2.$tn.1 {
    sqlite3 db test.db
    catchsql {SELECT count(*) FROM sqlite_master}
    set x {}
  } {}
  do_test corrupt-2.$tn.2 {
    catchsql {SELECT count(*) FROM t1}
    set x {}
  } {}
  do_test corrupt-2.$tn.3 {
    catchsql {SELECT count(*) FROM t1 WHERE x>'abcdef'}
    set x {}
  } {}
  do_test corrupt-2.$tn.4 {
    catchsql {SELECT count(*) FROM t2}
    set x {}
  } {}
  do_test corrupt-2.$tn.5 {
    catchsql {CREATE TABLE t3 AS SELECT * FROM t1}
    set x {}
  } {}
  do_test corrupt-2.$tn.6 {
    catchsql {DROP TABLE t1}
    set x {}
  } {}
if {$tn==724} btree_breakpoint
  do_test corrupt-2.$tn.7 {
    catchsql {PRAGMA integrity_check}
    set x {}
  } {}
}  

finish_test

--- NEW FILE: crash.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# The focus of this file is testing the ability of the database to
# uses its rollback journal to recover intact (no database corruption)
# from a power failure during the middle of a COMMIT.  The special test
# module "crashtest" compiled with the special "os_test.c" backend is used.
# The os_test.c simulates the kind of file corruption that can occur
# when writes are happening at the moment of power loss.
# 
# The special crash-test module with its os_test.c backend only works
# on Unix.
#
# $Id: crash.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# set repeats 100
set repeats 10

# This proc execs a seperate process that crashes midway through executing
# the SQL script $sql on database test.db.
#
# The crash occurs during a sync() of file $crashfile. When the crash
# occurs a random subset of all unsynced writes made by the process are
# written into the files on disk. Argument $crashdelay indicates the
# number of file syncs to wait before crashing.
#
# The return value is a list of two elements. The first element is a
# boolean, indicating whether or not the process actually crashed or
# reported some other error. The second element in the returned list is the
# error message. This is "child process exited abnormally" if the crash
# occured.
proc crashsql {crashdelay crashfile sql} {
  set cfile [file join [pwd] $crashfile]

  set f [open crash.tcl w]
  puts $f "sqlite3_crashparams $crashdelay $cfile"
  puts $f "sqlite3 db test.db"
  puts $f "db eval {pragma cache_size = 10}"
  puts $f "db eval {"
  puts $f   "$sql"
  puts $f "}"
  close $f

  set r [catch {
    exec [file join . crashtest] crash.tcl >@stdout
  } msg]
  lappend r $msg
}

# The following procedure computes a "signature" for table "abc".  If
# abc changes in any way, the signature should change.  
proc signature {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}]
}
proc signature2 {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc2}]
}

#--------------------------------------------------------------------------
# Simple crash test:
#
# crash-1.1: Create a database with a table with two rows.
# crash-1.2: Run a 'DELETE FROM abc WHERE a = 1' that crashes during
#            the first journal-sync.
# crash-1.3: Ensure the database is in the same state as after crash-1.1.
# crash-1.4: Run a 'DELETE FROM abc WHERE a = 1' that crashes during
#            the first database-sync.
# crash-1.5: Ensure the database is in the same state as after crash-1.1.
# crash-1.6: Run a 'DELETE FROM abc WHERE a = 1' that crashes during
#            the second journal-sync.
# crash-1.7: Ensure the database is in the same state as after crash-1.1.
#
# Tests 1.8 through 1.11 test for crashes on the third journal sync and
# second database sync.  Neither of these is required in such a small test
# case, so these tests are just to verify that the test infrastructure
# operates as expected.
#
do_test crash-1.1 {
  execsql {
    CREATE TABLE abc(a, b, c);
    INSERT INTO abc VALUES(1, 2, 3);
    INSERT INTO abc VALUES(4, 5, 6);
  }
  set ::sig [signature]
  expr 0
} {0}
do_test crash-1.2 {
  crashsql 1 test.db-journal {
    DELETE FROM abc WHERE a = 1;
  }
} {1 {child process exited abnormally}}
do_test crash-1.3 {
  signature
} $::sig
do_test crash-1.4 {
  crashsql 1 test.db {
    DELETE FROM abc WHERE a = 1;
  }
} {1 {child process exited abnormally}}
do_test crash-1.5 {
  signature
} $::sig
do_test crash-1.6 {
  crashsql 2 test.db-journal {
    DELETE FROM abc WHERE a = 1;
  }
} {1 {child process exited abnormally}}
do_test crash-1.7 {
  catchsql {
    SELECT * FROM abc;
  }
} {0 {1 2 3 4 5 6}}

do_test crash-1.8 {
  crashsql 3 test.db-journal {
    DELETE FROM abc WHERE a = 1;
  }
} {0 {}}
do_test crash-1.9 {
  catchsql {
    SELECT * FROM abc;
  }
} {0 {4 5 6}}
do_test crash-1.10 {
  crashsql 2 test.db {
    DELETE FROM abc WHERE a = 4;
  }
} {0 {}}
do_test crash-1.11 {
  catchsql {
    SELECT * FROM abc;
  }
} {0 {}}

#--------------------------------------------------------------------------
# The following tests test recovery when both the database file and the the
# journal file contain corrupt data. This can happen after pages are
# written to the database file before a transaction is committed due to
# cache-pressure.
#
# crash-2.1: Insert 18 pages of data into the database.
# crash-2.2: Check the database file size looks ok.
# crash-2.3: Delete 15 or so pages (with a 10 page page-cache), then crash.
# crash-2.4: Ensure the database is in the same state as after crash-2.1.
#
# Test cases crash-2.5 and crash-2.6 check that the database is OK if the 
# crash occurs during the main database file sync. But this isn't really
# different from the crash-1.* cases.
#
do_test crash-2.1 {
  execsql { BEGIN }
  for {set n 0} {$n < 1000} {incr n} {
    execsql "INSERT INTO abc VALUES($n, [expr 2*$n], [expr 3*$n])"
  }
  execsql { COMMIT }
  set ::sig [signature]
  execsql { SELECT sum(a), sum(b), sum(c) from abc }
} {499500.0 999000.0 1498500.0}
do_test crash-2.2 {
  expr [file size test.db] / 1024
} {19}
do_test crash-2.3 {
  crashsql 2 test.db-journal {
    DELETE FROM abc WHERE a < 800;
  }
} {1 {child process exited abnormally}}
do_test crash-2.4 {
  signature
} $sig
do_test crash-2.5 {
  crashsql 1 test.db {
    DELETE FROM abc WHERE a<800;
  }
} {1 {child process exited abnormally}}
do_test crash-2.6 {
  signature
} $sig

#--------------------------------------------------------------------------
# The crash-3.* test cases are essentially the same test as test case
# crash-2.*, but with a more complicated data set. 
#
# The test is repeated a few times with different seeds for the random
# number generator in the crashing executable. Because there is no way to
# seed the random number generator directly, some SQL is added to the test
# case to 'use up' a different quantity random numbers before the test SQL
# is executed.
#

# Make sure the file is much bigger than the pager-cache (10 pages). This
# ensures that cache-spills happen regularly.
do_test crash-3.0 {
  execsql {
    INSERT INTO abc SELECT * FROM abc;
    INSERT INTO abc SELECT * FROM abc;
    INSERT INTO abc SELECT * FROM abc;
    INSERT INTO abc SELECT * FROM abc;
    INSERT INTO abc SELECT * FROM abc;
  }
  expr [file size test.db] / 1024
} {554}
for {set i 1} {$i < $repeats} {incr i} {
  set sig [signature]
  do_test crash-3.$i.1 {
     crashsql [expr $i%5 + 1] test.db-journal "
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc WHERE random()%10!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}
  do_test crash-3.$i.2 {
    signature
  } $sig
} 

#--------------------------------------------------------------------------
# The following test cases - crash-4.* - test the correct recovery of the
# database when a crash occurs during a multi-file transaction.
#
# crash-4.1.*: Test recovery when crash occurs during sync() of the 
#              main database journal file.
# crash-4.2.*: Test recovery when crash occurs during sync() of an 
#              attached database journal file.
# crash-4.3.*: Test recovery when crash occurs during sync() of the master
#              journal file. 
#
do_test crash-4.0 {
  file delete -force test2.db
  file delete -force test2.db-journal
  execsql {
    ATTACH 'test2.db' AS aux;
    PRAGMA aux.default_cache_size = 10;
    CREATE TABLE aux.abc2 AS SELECT 2*a as a, 2*b as b, 2*c as c FROM abc;
  }
  expr [file size test2.db] / 1024
} {559}

for {set i 1} {$i<$repeats} {incr i} {
  set sig [signature]
  set sig2 [signature2]
  do_test crash-4.1.$i.1 {
     set c [crashsql $i test.db-journal "
       ATTACH 'test2.db' AS aux;
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc WHERE random()%10!=0;
       INSERT INTO abc2 VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc2 WHERE random()%10!=0;
       COMMIT;
     "]
     set c
  } {1 {child process exited abnormally}}
  do_test crash-4.1.$i.2 {
    signature
  } $sig
  do_test crash-4.1.$i.3 {
    signature2
  } $sig2
} 
set i 0
while {[incr i]} {
  set sig [signature]
  set sig2 [signature2]
  set ::fin 0
  do_test crash-4.2.$i.1 {
     set c [crashsql $i test2.db-journal "
       ATTACH 'test2.db' AS aux;
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc WHERE random()%10!=0;
       INSERT INTO abc2 VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc2 WHERE random()%10!=0;
       COMMIT;
     "]
     if { $c == {0 {}} } {
       set ::fin 1
       set c {1 {child process exited abnormally}}
     }
     set c
  } {1 {child process exited abnormally}}
  if { $::fin } break
  do_test crash-4.2.$i.2 {
    signature
  } $sig
  do_test crash-4.2.$i.3 {
    signature2
  } $sig2
} 
for {set i 1} {$i < 5} {incr i} {
  set sig [signature]
  set sig2 [signature2]
  do_test crash-4.3.$i.1 {
     crashsql 1 test.db-mj* "
       ATTACH 'test2.db' AS aux;
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc WHERE random()%10!=0;
       INSERT INTO abc2 VALUES(randstr(10,10), 0, 0);
       DELETE FROM abc2 WHERE random()%10!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}
  do_test crash-4.3.$i.2 {
    signature
  } $sig
  do_test crash-4.3.$i.3 {
    signature2
  } $sig2
}

--- NEW FILE: crashtest1.c ---
/*
** This program tests the ability of SQLite database to recover from a crash.
** This program runs under Unix only, but the results are applicable to all
** systems.
**
** The main process first constructs a test database, then starts creating
** subprocesses that write to that database.  Each subprocess is killed off,
** without a chance to clean up its database connection, after a random
** delay.  This killing of the subprocesses simulates a crash or power
** failure.  The next subprocess to open the database should rollback
** whatever operation was in process at the time of the simulated crash.
**
** If any problems are encountered, an error is reported and the test stops.
** If no problems are seen after a large number of tests, we assume that
** the rollback mechanism is working.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include "sqlite.h"

static void do_some_sql(int parent){
  char *zErr;
  int rc = SQLITE_OK;
  sqlite *db;
  int cnt = 0;
  static char zBig[] = 
    "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

  if( access("./test.db-journal",0)==0 ){
    /*printf("pid %d: journal exists.  rollback will be required\n",getpid());*/    unlink("test.db-saved");
    system("cp test.db test.db-saved");
    unlink("test.db-journal-saved");
    system("cp test.db-journal test.db-journal-saved");
  }
  db = sqlite_open("./test.db", 0, &zErr);
  if( db==0 ){
    printf("ERROR: %s\n", zErr);
    if( strcmp(zErr,"database disk image is malformed")==0 ){
      kill(parent, SIGKILL);
    }
    exit(1);
  }
  srand(getpid());
  while( rc==SQLITE_OK ){
    cnt++;
    rc = sqlite_exec_printf(db, 
       "INSERT INTO t1 VALUES(%d,'%d%s')", 0, 0, &zErr,
       rand(), rand(), zBig);
  }
  if( rc!=SQLITE_OK ){
    printf("ERROR #%d: %s\n", rc, zErr);
    if( rc==SQLITE_CORRUPT ){
      kill(parent, SIGKILL);
    }
  }
  printf("pid %d: cnt=%d\n", getpid(), cnt);
}


int main(int argc, char **argv){
  int i;
  sqlite *db;
  char *zErr;
  int status;
  int parent = getpid();

  unlink("test.db");
  unlink("test.db-journal");
  db = sqlite_open("test.db", 0, &zErr);
  if( db==0 ){
    printf("Cannot initialize: %s\n", zErr);
    return 1;
  }
  sqlite_exec(db, "CREATE TABLE t1(a,b)", 0, 0, 0);
  sqlite_close(db);
  for(i=0; i<10000; i++){
    int pid = fork();
    if( pid==0 ){
      sched_yield();
      do_some_sql(parent);
      return 0;
    }
    printf("test %d, pid=%d\n", i, pid);
    usleep(rand()%10000 + 1000);
    kill(pid, SIGKILL);
    waitpid(pid, &status, 0);
  }
  return 0;
}

--- NEW FILE: date.test ---
# 2003 October 31
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"
  }] [list $result]
}
set tcl_precision 15
datetest 1.1 julianday('2000-01-01') 2451544.5
datetest 1.2 julianday('1970-01-01') 2440587.5
datetest 1.3 julianday('1910-04-20') 2418781.5
datetest 1.4 julianday('1986-02-09') 2446470.5
datetest 1.5 julianday('12:00:00') 2451545.0
datetest 1.6 {julianday('2000-01-01 12:00:00')} 2451545.0
datetest 1.7 {julianday('2000-01-01 12:00')} 2451545.0
datetest 1.8 julianday('bogus') NULL
datetest 1.9 julianday('1999-12-31') 2451543.5
datetest 1.10 julianday('1999-12-32') NULL
datetest 1.11 julianday('1999-13-01') NULL
datetest 1.12 julianday('2003-02-31') 2452701.5
datetest 1.13 julianday('2003-03-03') 2452701.5
datetest 1.14 julianday('+2000-01-01') NULL
datetest 1.15 julianday('200-01-01') NULL
datetest 1.16 julianday('2000-1-01') NULL
datetest 1.17 julianday('2000-01-1') NULL
datetest 1.18 {julianday('2000-01-01     12:00:00')} 2451545.0
datetest 1.19 {julianday('2000-01-01 12:00:00.1')}   2451545.00000116
datetest 1.20 {julianday('2000-01-01 12:00:00.01')}  2451545.00000012
datetest 1.21 {julianday('2000-01-01 12:00:00.001')} 2451545.00000001
datetest 1.22 {julianday('2000-01-01 12:00:00.')} NULL
datetest 1.23 julianday(12345.6) 12345.6
datetest 1.24 {julianday('2001-01-01 12:00:00 bogus')} NULL
datetest 1.25 {julianday('2001-01-01 bogus')} NULL

datetest 2.1 datetime(0,'unixepoch') {1970-01-01 00:00:00}
datetest 2.2 datetime(946684800,'unixepoch') {2000-01-01 00:00:00}
datetest 2.3 {date('2003-10-22','weekday 0')} 2003-10-26
datetest 2.4 {date('2003-10-22','weekday 1')} 2003-10-27
datetest 2.5 {date('2003-10-22','weekday 2')} 2003-10-28
datetest 2.6 {date('2003-10-22','weekday 3')} 2003-10-22
datetest 2.7 {date('2003-10-22','weekday 4')} 2003-10-23
datetest 2.8 {date('2003-10-22','weekday 5')} 2003-10-24
datetest 2.9 {date('2003-10-22','weekday 6')} 2003-10-25
datetest 2.10 {date('2003-10-22','weekday 7')} NULL
datetest 2.11 {date('2003-10-22','weekday 5.5')} NULL
datetest 2.12 {datetime('2003-10-22 12:34','weekday 0')} {2003-10-26 12:34:00}
datetest 2.13 {datetime('2003-10-22 12:34','start of month')} \
   {2003-10-01 00:00:00}
datetest 2.14 {datetime('2003-10-22 12:34','start of year')} \
   {2003-01-01 00:00:00}
datetest 2.15 {datetime('2003-10-22 12:34','start of day')} \
   {2003-10-22 00:00:00}
datetest 2.16 time('12:34:56.43') 12:34:56
datetest 2.17 {datetime('2003-10-22 12:34','1 day')} {2003-10-23 12:34:00}
datetest 2.18 {datetime('2003-10-22 12:34','+1 day')} {2003-10-23 12:34:00}
datetest 2.19 {datetime('2003-10-22 12:34','+1.25 day')} {2003-10-23 18:34:00}
datetest 2.20 {datetime('2003-10-22 12:34','-1.0 day')} {2003-10-21 12:34:00}
datetest 2.21 {datetime('2003-10-22 12:34','1 month')} {2003-11-22 12:34:00}
datetest 2.22 {datetime('2003-10-22 12:34','11 month')} {2004-09-22 12:34:00}
datetest 2.23 {datetime('2003-10-22 12:34','-13 month')} {2002-09-22 12:34:00}
datetest 2.24 {datetime('2003-10-22 12:34','1.5 months')} {2003-12-07 12:34:00}
datetest 2.25 {datetime('2003-10-22 12:34','-5 years')} {1998-10-22 12:34:00}
datetest 2.26 {datetime('2003-10-22 12:34','+10.5 minutes')} \
  {2003-10-22 12:44:30}
datetest 2.27 {datetime('2003-10-22 12:34','-1.25 hours')} \
  {2003-10-22 11:19:00}
datetest 2.28 {datetime('2003-10-22 12:34','11.25 seconds')} \
  {2003-10-22 12:34:11}
datetest 2.29 {datetime('2003-10-22 12:24','+5 bogus')} NULL


datetest 3.1 {strftime('%d','2003-10-31 12:34:56.432')} 31
datetest 3.2 {strftime('%f','2003-10-31 12:34:56.432')} 56.432
datetest 3.3 {strftime('%H','2003-10-31 12:34:56.432')} 12
datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304
datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259
datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10
datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
datetest 3.8 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
datetest 3.9 {strftime('%S','2003-10-31 12:34:56.432')} 56
datetest 3.10 {strftime('%w','2003-10-31 12:34:56.432')} 5
datetest 3.11.1 {strftime('%W','2003-10-31 12:34:56.432')} 43
datetest 3.11.2 {strftime('%W','2004-01-01')} 00
datetest 3.11.3 {strftime('%W','2004-01-02')} 00
datetest 3.11.4 {strftime('%W','2004-01-03')} 00
datetest 3.11.5 {strftime('%W','2004-01-04')} 00
datetest 3.11.6 {strftime('%W','2004-01-05')} 01
datetest 3.11.7 {strftime('%W','2004-01-06')} 01
datetest 3.11.8 {strftime('%W','2004-01-07')} 01
datetest 3.11.9 {strftime('%W','2004-01-08')} 01
datetest 3.11.10 {strftime('%W','2004-01-09')} 01
datetest 3.11.11 {strftime('%W','2004-07-18')} 28
datetest 3.11.12 {strftime('%W','2004-12-31')} 52
datetest 3.11.13 {strftime('%W','2007-12-31')} 53
datetest 3.11.14 {strftime('%W','2007-01-01')} 01
datetest 3.12 {strftime('%Y','2003-10-31 12:34:56.432')} 2003
datetest 3.13 {strftime('%%','2003-10-31 12:34:56.432')} %
datetest 3.14 {strftime('%_','2003-10-31 12:34:56.432')} NULL
datetest 3.15 {strftime('%Y-%m-%d','2003-10-31')} 2003-10-31
proc repeat {n txt} {
  set x {} 
  while {$n>0} {
    append x $txt
    incr n -1
  }
  return $x
}
datetest 3.16 "strftime('[repeat 200 %Y]','2003-10-31')" [repeat 200 2003]
datetest 3.17 "strftime('[repeat 200 abc%m123]','2003-10-31')" \
    [repeat 200 abc10123]

set now [clock format [clock seconds] -format "%Y-%m-%d" -gmt 1]
datetest 4.1 {date('now')} $now

datetest 5.1 {datetime('1994-04-16 14:00:00 -05:00')} {1994-04-16 09:00:00}
datetest 5.2 {datetime('1994-04-16 14:00:00 +05:15')} {1994-04-16 19:15:00}
datetest 5.3 {datetime('1994-04-16 05:00:00 -08:30')} {1994-04-15 20:30:00}
datetest 5.4 {datetime('1994-04-16 14:00:00 +11:55')} {1994-04-17 01:55:00}

# localtime->utc and utc->localtime conversions.  These tests only work
# if the localtime is in the US Eastern Time (the time in Charlotte, NC
# and in New York.)
#
if {[clock scan [clock format 0 -format {%b %d, %Y %H:%M:%S}] -gmt 1]==-18000} {
  datetest 6.1 {datetime('2000-10-29 05:59:00','localtime')}\
      {2000-10-29 01:59:00}
  datetest 6.2 {datetime('2000-10-29 06:00:00','localtime')}\
      {2000-10-29 01:00:00}
  datetest 6.3 {datetime('2000-04-02 06:59:00','localtime')}\
      {2000-04-02 01:59:00}
  datetest 6.4 {datetime('2000-04-02 07:00:00','localtime')}\
      {2000-04-02 03:00:00}
  datetest 6.5 {datetime('2000-10-29 01:59:00','utc')} {2000-10-29 05:59:00}
  datetest 6.6 {datetime('2000-10-29 02:00:00','utc')} {2000-10-29 07:00:00}
  datetest 6.7 {datetime('2000-04-02 01:59:00','utc')} {2000-04-02 06:59:00}
  datetest 6.8 {datetime('2000-04-02 02:00:00','utc')} {2000-04-02 06:00:00}

  datetest 6.10 {datetime('2000-01-01 12:00:00','localtime')} \
      {2000-01-01 07:00:00}
  datetest 6.11 {datetime('1969-01-01 12:00:00','localtime')} \
      {1969-01-01 07:00:00}
  datetest 6.12 {datetime('2039-01-01 12:00:00','localtime')} \
      {2039-01-01 07:00:00}
  datetest 6.13 {datetime('2000-07-01 12:00:00','localtime')} \
      {2000-07-01 08:00:00}
  datetest 6.14 {datetime('1969-07-01 12:00:00','localtime')} \
      {1969-07-01 07:00:00}
  datetest 6.15 {datetime('2039-07-01 12:00:00','localtime')} \
      {2039-07-01 07:00:00}
  set sqlite_current_time \
     [db eval {SELECT strftime('%s','2000-07-01 12:34:56')}]
  datetest 6.16 {datetime('now','localtime')} {2000-07-01 08:34:56}
  set sqlite_current_time 0
}

# Date-time functions that contain NULL arguments return a NULL
# result.
#
datetest 7.1 {datetime(null)} NULL
datetest 7.2 {datetime('now',null)} NULL
datetest 7.3 {datetime('now','localtime',null)} NULL
datetest 7.4 {time(null)} NULL
datetest 7.5 {time('now',null)} NULL
datetest 7.6 {time('now','localtime',null)} NULL
datetest 7.7 {date(null)} NULL
datetest 7.8 {date('now',null)} NULL
datetest 7.9 {date('now','localtime',null)} NULL
datetest 7.10 {julianday(null)} NULL
datetest 7.11 {julianday('now',null)} NULL
datetest 7.12 {julianday('now','localtime',null)} NULL
datetest 7.13 {strftime(null,'now')} NULL
datetest 7.14 {strftime('%s',null)} NULL
datetest 7.15 {strftime('%s','now',null)} NULL
datetest 7.16 {strftime('%s','now','localtime',null)} NULL

# Test modifiers when the date begins as a julian day number - to
# make sure the HH:MM:SS is preserved.  Ticket #551.
#
set sqlite_current_time [db eval {SELECT strftime('%s','2003-10-22 12:34:00')}]
datetest 8.1 {datetime('now','weekday 0')} {2003-10-26 12:34:00}
datetest 8.2 {datetime('now','weekday 1')} {2003-10-27 12:34:00}
datetest 8.3 {datetime('now','weekday 2')} {2003-10-28 12:34:00}
datetest 8.4 {datetime('now','weekday 3')} {2003-10-22 12:34:00}
datetest 8.5 {datetime('now','start of month')} {2003-10-01 00:00:00}
datetest 8.6 {datetime('now','start of year')} {2003-01-01 00:00:00}
datetest 8.7 {datetime('now','start of day')} {2003-10-22 00:00:00}
datetest 8.8 {datetime('now','1 day')} {2003-10-23 12:34:00}
datetest 8.9 {datetime('now','+1 day')} {2003-10-23 12:34:00}
datetest 8.10 {datetime('now','+1.25 day')} {2003-10-23 18:34:00}
datetest 8.11 {datetime('now','-1.0 day')} {2003-10-21 12:34:00}
datetest 8.12 {datetime('now','1 month')} {2003-11-22 12:34:00}
datetest 8.13 {datetime('now','11 month')} {2004-09-22 12:34:00}
datetest 8.14 {datetime('now','-13 month')} {2002-09-22 12:34:00}
datetest 8.15 {datetime('now','1.5 months')} {2003-12-07 12:34:00}
datetest 8.16 {datetime('now','-5 years')} {1998-10-22 12:34:00}
datetest 8.17 {datetime('now','+10.5 minutes')} {2003-10-22 12:44:30}
datetest 8.18 {datetime('now','-1.25 hours')} {2003-10-22 11:19:00}
datetest 8.19 {datetime('now','11.25 seconds')} {2003-10-22 12:34:11}
set sqlite_current_time 0

# Negative years work.  Example:  '-4713-11-26' is JD 1.5.
#
datetest 9.1 {julianday('-4713-11-24 12:00:00')} {0.0}
datetest 9.2 {julianday(datetime(5))} {5.0}
datetest 9.3 {julianday(datetime(10))} {10.0}
datetest 9.4 {julianday(datetime(100))} {100.0}
datetest 9.5 {julianday(datetime(1000))} {1000.0}
datetest 9.6 {julianday(datetime(10000))} {10000.0}
datetest 9.7 {julianday(datetime(100000))} {100000.0}

# datetime() with just an HH:MM:SS correctly inserts the date 2000-01-01.
#
datetest 10.1 {datetime('01:02:03')}  {2000-01-01 01:02:03}
datetest 10.2 {date('01:02:03')}  {2000-01-01}
datetest 10.3 {strftime('%Y-%m-%d %H:%M','01:02:03')} {2000-01-01 01:02}

# Test the new HH:MM:SS modifier
#
datetest 11.1 {datetime('2004-02-28 20:00:00', '-01:20:30')} \
   {2004-02-28 18:39:30}
datetest 11.2 {datetime('2004-02-28 20:00:00', '+12:30:00')} \
   {2004-02-29 08:30:00}
datetest 11.3 {datetime('2004-02-28 20:00:00', '+12:30')} \
   {2004-02-29 08:30:00}
datetest 11.4 {datetime('2004-02-28 20:00:00', '12:30')} \
   {2004-02-29 08:30:00}
datetest 11.5 {datetime('2004-02-28 20:00:00', '-12:00')} \
   {2004-02-28 08:00:00}
datetest 11.6 {datetime('2004-02-28 20:00:00', '-12:01')} \
   {2004-02-28 07:59:00}
datetest 11.7 {datetime('2004-02-28 20:00:00', '-11:59')} \
   {2004-02-28 08:01:00}
datetest 11.8 {datetime('2004-02-28 20:00:00', '11:59')} \
   {2004-02-29 07:59:00}
datetest 11.9 {datetime('2004-02-28 20:00:00', '12:01')} \
   {2004-02-29 08:01:00}




finish_test

--- NEW FILE: delete.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the DELETE FROM statement.
#
# $Id: delete.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to delete from a non-existant table.
#
do_test delete-1.1 {
  set v [catch {execsql {DELETE FROM test1}} msg]
  lappend v $msg
} {1 {no such table: test1}}

# Try to delete from sqlite_master
#
do_test delete-2.1 {
  set v [catch {execsql {DELETE FROM sqlite_master}} msg]
  lappend v $msg
} {1 {table sqlite_master may not be modified}}

# Delete selected entries from a table with and without an index.
#
do_test delete-3.1.1 {
  execsql {CREATE TABLE table1(f1 int, f2 int)}
  execsql {INSERT INTO table1 VALUES(1,2)}
  execsql {INSERT INTO table1 VALUES(2,4)}
  execsql {INSERT INTO table1 VALUES(3,8)}
  execsql {INSERT INTO table1 VALUES(4,16)}
  execsql {SELECT * FROM table1 ORDER BY f1}
} {1 2 2 4 3 8 4 16}
do_test delete-3.1.2 {
  execsql {DELETE FROM table1 WHERE f1=3}
} {}
do_test delete-3.1.3 {
  execsql {SELECT * FROM table1 ORDER BY f1}
} {1 2 2 4 4 16}
do_test delete-3.1.4 {
  execsql {CREATE INDEX index1 ON table1(f1)}
  execsql {PRAGMA count_changes=on}
  execsql {DELETE FROM 'table1' WHERE f1=3}
} {0}
do_test delete-3.1.5 {
  execsql {SELECT * FROM table1 ORDER BY f1}
} {1 2 2 4 4 16}
do_test delete-3.1.6.1 {
  execsql {DELETE FROM table1 WHERE f1=2}
} {1}
do_test delete-3.1.6.2 {
  db changes
} 1
do_test delete-3.1.7 {
  execsql {SELECT * FROM table1 ORDER BY f1}
} {1 2 4 16}
integrity_check delete-3.2


# Semantic errors in the WHERE clause
#
do_test delete-4.1 {
  execsql {CREATE TABLE table2(f1 int, f2 int)}
  set v [catch {execsql {DELETE FROM table2 WHERE f3=5}} msg]
  lappend v $msg
} {1 {no such column: f3}}

do_test delete-4.2 {
  set v [catch {execsql {DELETE FROM table2 WHERE xyzzy(f1+4)}} msg]
  lappend v $msg
} {1 {no such function: xyzzy}}
integrity_check delete-4.3

# Lots of deletes
#
do_test delete-5.1.1 {
  execsql {DELETE FROM table1}
} {2}
do_test delete-5.1.2 {
  execsql {SELECT count(*) FROM table1}
} {0}
do_test delete-5.2.1 {
  execsql {BEGIN TRANSACTION}
  for {set i 1} {$i<=200} {incr i} {
     execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
  }
  execsql {COMMIT}
  execsql {SELECT count(*) FROM table1}
} {200}
do_test delete-5.2.2 {
  execsql {DELETE FROM table1}
} {200}
do_test delete-5.2.3 {
  execsql {BEGIN TRANSACTION}
  for {set i 1} {$i<=200} {incr i} {
     execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
  }
  execsql {COMMIT}
  execsql {SELECT count(*) FROM table1}
} {200}
do_test delete-5.2.4 {
  execsql {PRAGMA count_changes=off}
  execsql {DELETE FROM table1}
} {}
do_test delete-5.2.5 {
  execsql {SELECT count(*) FROM table1}
} {0}
do_test delete-5.2.6 {
  execsql {BEGIN TRANSACTION}
  for {set i 1} {$i<=200} {incr i} {
     execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
  }
  execsql {COMMIT}
  execsql {SELECT count(*) FROM table1}
} {200}
do_test delete-5.3 {
  for {set i 1} {$i<=200} {incr i 4} {
     execsql "DELETE FROM table1 WHERE f1==$i"
  }
  execsql {SELECT count(*) FROM table1}
} {150}
do_test delete-5.4.1 {
  execsql "DELETE FROM table1 WHERE f1>50"
  db changes
} [db one {SELECT count(*) FROM table1 WHERE f1>50}]
do_test delete-5.4.2 {
  execsql {SELECT count(*) FROM table1}
} {37}
do_test delete-5.5 {
  for {set i 1} {$i<=70} {incr i 3} {
     execsql "DELETE FROM table1 WHERE f1==$i"
  }
  execsql {SELECT f1 FROM table1 ORDER BY f1}
} {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}
do_test delete-5.6 {
  for {set i 1} {$i<40} {incr i} {
     execsql "DELETE FROM table1 WHERE f1==$i"
  }
  execsql {SELECT f1 FROM table1 ORDER BY f1}
} {42 44 47 48 50}
do_test delete-5.7 {
  execsql "DELETE FROM table1 WHERE f1!=48"
  execsql {SELECT f1 FROM table1 ORDER BY f1}
} {48}
integrity_check delete-5.8


# Delete large quantities of data.  We want to test the List overflow
# mechanism in the vdbe.
#
do_test delete-6.1 {
  execsql {BEGIN; DELETE FROM table1}
  for {set i 1} {$i<=3000} {incr i} {
    execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
  }
  execsql {DELETE FROM table2}
  for {set i 1} {$i<=3000} {incr i} {
    execsql "INSERT INTO table2 VALUES($i,[expr {$i*$i}])"
  }
  execsql {COMMIT}
  execsql {SELECT count(*) FROM table1}
} {3000}
do_test delete-6.2 {
  execsql {SELECT count(*) FROM table2}
} {3000}
do_test delete-6.3 {
  execsql {SELECT f1 FROM table1 WHERE f1<10 ORDER BY f1}
} {1 2 3 4 5 6 7 8 9}
do_test delete-6.4 {
  execsql {SELECT f1 FROM table2 WHERE f1<10 ORDER BY f1}
} {1 2 3 4 5 6 7 8 9}
do_test delete-6.5.1 {
  execsql {DELETE FROM table1 WHERE f1>7}
  db changes
} {2993}
do_test delete-6.5.2 {
  execsql {SELECT f1 FROM table1 ORDER BY f1}
} {1 2 3 4 5 6 7}
do_test delete-6.6 {
  execsql {DELETE FROM table2 WHERE f1>7}
  execsql {SELECT f1 FROM table2 ORDER BY f1}
} {1 2 3 4 5 6 7}
do_test delete-6.7 {
  execsql {DELETE FROM table1}
  execsql {SELECT f1 FROM table1}
} {}
do_test delete-6.8 {
  execsql {INSERT INTO table1 VALUES(2,3)}
  execsql {SELECT f1 FROM table1}
} {2}
do_test delete-6.9 {
  execsql {DELETE FROM table2}
  execsql {SELECT f1 FROM table2}
} {}
do_test delete-6.10 {
  execsql {INSERT INTO table2 VALUES(2,3)}
  execsql {SELECT f1 FROM table2}
} {2}
integrity_check delete-6.11

do_test delete-7.1 {
  execsql {
    CREATE TABLE t3(a);
    INSERT INTO t3 VALUES(1);
    INSERT INTO t3 SELECT a+1 FROM t3;
    INSERT INTO t3 SELECT a+2 FROM t3;
    SELECT * FROM t3;
  }
} {1 2 3 4}
do_test delete-7.2 {
  execsql {
    CREATE TABLE cnt(del);
    INSERT INTO cnt VALUES(0);
    CREATE TRIGGER r1 AFTER DELETE ON t3 FOR EACH ROW BEGIN
      UPDATE cnt SET del=del+1;
    END;
    DELETE FROM t3 WHERE a<2;
    SELECT * FROM t3;
  }
} {2 3 4}
do_test delete-7.3 {
  execsql {
    SELECT * FROM cnt;
  }
} {1}
do_test delete-7.4 {
  execsql {
    DELETE FROM t3;
    SELECT * FROM t3;
  }
} {}
do_test delete-7.5 {
  execsql {
    SELECT * FROM cnt;
  }
} {4}
do_test delete-7.6 {
  execsql {
    INSERT INTO t3 VALUES(1);
    INSERT INTO t3 SELECT a+1 FROM t3;
    INSERT INTO t3 SELECT a+2 FROM t3;
    CREATE TABLE t4 AS SELECT * FROM t3;
    PRAGMA count_changes=ON;
    DELETE FROM t3;
    DELETE FROM t4;
  }
} {4 4}
integrity_check delete-7.7

# Make sure error messages are consistent when attempting to delete
# from a read-only database.  Ticket #304.
#
do_test delete-8.0 {
  execsql {
    PRAGMA count_changes=OFF;
    INSERT INTO t3 VALUES(123);
    SELECT * FROM t3;
  }
} {123}
db close
catch {file attributes test.db -permissions 0444}
catch {file attributes test.db -readonly 1}
sqlite3 db test.db
do_test delete-8.1 {
  catchsql {
    DELETE FROM t3;
  }
} {1 {attempt to write a readonly database}}
do_test delete-8.2 {
  execsql {SELECT * FROM t3} 
} {123}
do_test delete-8.3 {
  catchsql {
    DELETE FROM t3 WHERE 1;
  }
} {1 {attempt to write a readonly database}}
do_test delete-8.4 {
  execsql {SELECT * FROM t3} 
} {123}

# Update for v3: In v2 the DELETE statement would succeed because no
# database writes actually occur. Version 3 refuses to open a transaction
# on a read-only file, so the statement fails.
do_test delete-8.5 {
  catchsql {
    DELETE FROM t3 WHERE a<100;
  }
# v2 result: {0 {}}
} {1 {attempt to write a readonly database}}
do_test delete-8.6 {
  execsql {SELECT * FROM t3}
} {123}
integrity_check delete-8.7

finish_test

--- NEW FILE: delete2.test ---
# 2003 September 6
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is a test to replicate the bug reported by
# ticket #842.
#
# Ticket #842 was a database corruption problem caused by a DELETE that
# removed an index entry by not the main table entry.  To recreate the
# problem do this:
#
#   (1) Create a table with an index.  Insert some data into that table.
#   (2) Start a query on the table but do not complete the query.
#   (3) Try to delete a single entry from the table.
#
# Step 3 will fail because there is still a read cursor on the table.
# But the database is corrupted by the DELETE.  It turns out that the
# index entry was deleted first, before the table entry.  And the index
# delete worked.  Thus an entry was deleted from the index but not from
# the table.
#
# The solution to the problem was to detect that the table is locked
# before the index entry is deleted.
#
# $Id: delete2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table that has an index.
#
do_test delete2-1.1 {
  db close
  set DB [sqlite3 db test.db]
  execsql {
    CREATE TABLE q(s string, id string, constraint pk_q primary key(id));
    BEGIN;
    INSERT INTO q(s,id) VALUES('hello','id.1');
    INSERT INTO q(s,id) VALUES('goodbye','id.2');
    INSERT INTO q(s,id) VALUES('again','id.3');
    END;
    SELECT * FROM q;
  }
} {hello id.1 goodbye id.2 again id.3}
do_test delete2-1.2 {
  execsql {
    SELECT * FROM q WHERE id='id.1';
  }
} {hello id.1}
do_test delete2-1.3 {
  execsql {
    PRAGMA integrity_check
  }
} ok

# Start a query on the table.  The query should not use the index.
# Do not complete the query, thus leaving the table locked.
#
do_test delete2-1.4 {
  set STMT [sqlite3_prepare $DB {SELECT * FROM q} -1 TAIL]
  sqlite3_step $STMT
} SQLITE_ROW
do_test delete2-1.5 {
  execsql {PRAGMA integrity_check}
} {ok}

# Try to delete a row from the table.  The delete should fail.
#
do_test delete2-1.6 {
  catchsql {
    DELETE FROM q WHERE rowid=1
  }
} {1 {database table is locked}}
do_test delete2-1.7 {
  execsql {PRAGMA integrity_check}
} {ok}
do_test delete2-1.8 {
  execsql {
    SELECT * FROM q;
  }
} {hello id.1 goodbye id.2 again id.3}

# Finalize the query, thus clearing the lock on the table.  Then
# retry the delete.  The delete should work this time.
#
do_test delete2-1.9 {
  sqlite3_finalize $STMT
  catchsql {
    DELETE FROM q WHERE rowid=1
  }
} {0 {}}
do_test delete2-1.10 {
  execsql {PRAGMA integrity_check}
} {ok}
do_test delete2-1.11 {
  execsql {
    SELECT * FROM q;
  }
} {goodbye id.2 again id.3}

finish_test

--- NEW FILE: enc.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The focus of
# this file is testing the SQLite routines used for converting between the
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
# UTF-16be).
#
# $Id: enc.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc do_bincmp_test {testname got expect} {
  binary scan $expect \c* expectvals
  binary scan $got \c* gotvals
  do_test $testname [list set dummy $gotvals] $expectvals
}

# $utf16 is a UTF-16 encoded string. Swap each pair of bytes around
# to change the byte-order of the string.
proc swap_byte_order {utf16} {
  binary scan $utf16 \c* ints

  foreach {a b} $ints {
    lappend ints2 $b
    lappend ints2 $a
  }

  return [binary format \c* $ints2]
}

#
# Test that the SQLite routines for converting between UTF encodings
# produce the same results as their TCL counterparts.
#
# $testname is the prefix to be used for the test names.
# $str is a string to use for testing (encoded in UTF-8, as normal for TCL).
#
# The test procedure is:
# 1. Convert the string from UTF-8 to UTF-16le and check that the TCL and
#    SQLite routines produce the same results.
#
# 2. Convert the string from UTF-8 to UTF-16be and check that the TCL and
#    SQLite routines produce the same results.
#
# 3. Use the SQLite routines to convert the native machine order UTF-16
#    representation back to the original UTF-8. Check that the result
#    matches the original representation.
#
# 4. Add a byte-order mark to each of the UTF-16 representations and
#    check that the SQLite routines can convert them back to UTF-8.  For
#    byte-order mark info, refer to section 3.10 of the unicode standard.
#
# 5. Take the byte-order marked UTF-16 strings from step 4 and ensure
#    that SQLite can convert them both to native byte order UTF-16 
#    strings, sans BOM.
#
# Coverage:
#
# sqlite_utf8to16be (step 2)
# sqlite_utf8to16le (step 1)
# sqlite_utf16to8 (steps 3, 4)
# sqlite_utf16to16le (step 5)
# sqlite_utf16to16be (step 5)
#
proc test_conversion {testname str} {
 
  # Step 1.
  set utf16le_sqlite3 [test_translate $str UTF8 UTF16LE]
  set utf16le_tcl [encoding convertto unicode $str]
  append utf16le_tcl "\x00\x00"
  if { $::tcl_platform(byteOrder)!="littleEndian" } {
    set utf16le_tcl [swap_byte_order $utf16le_tcl]
  }
  do_bincmp_test $testname.1 $utf16le_sqlite3 $utf16le_tcl
  set utf16le $utf16le_tcl

  # Step 2.
  set utf16be_sqlite3 [test_translate $str UTF8 UTF16BE]
  set utf16be_tcl [encoding convertto unicode $str]
  append utf16be_tcl "\x00\x00"
  if { $::tcl_platform(byteOrder)=="littleEndian" } {
    set utf16be_tcl [swap_byte_order $utf16be_tcl]
  }
  do_bincmp_test $testname.2 $utf16be_sqlite3 $utf16be_tcl
  set utf16be $utf16be_tcl
 
  # Step 3.
  if { $::tcl_platform(byteOrder)=="littleEndian" } {
    set utf16 $utf16le
  } else {
    set utf16 $utf16be
  }
  set utf8_sqlite3 [test_translate $utf16 UTF16 UTF8]
  do_bincmp_test $testname.3 $utf8_sqlite3 [binarize $str]

  # Step 4 (little endian).
  append utf16le_bom "\xFF\xFE" $utf16le
  set utf8_sqlite3 [test_translate $utf16le_bom UTF16 UTF8 1]
  do_bincmp_test $testname.4.le $utf8_sqlite3 [binarize $str]

  # Step 4 (big endian).
  append utf16be_bom "\xFE\xFF" $utf16be
  set utf8_sqlite3 [test_translate $utf16be_bom UTF16 UTF8]
  do_bincmp_test $testname.4.be $utf8_sqlite3 [binarize $str]

  # Step 5 (little endian to little endian).
  set utf16_sqlite3 [test_translate $utf16le_bom UTF16LE UTF16LE]
  do_bincmp_test $testname.5.le.le $utf16_sqlite3 $utf16le

  # Step 5 (big endian to big endian).
  set utf16_sqlite3 [test_translate $utf16be_bom UTF16 UTF16BE]
  do_bincmp_test $testname.5.be.be $utf16_sqlite3 $utf16be

  # Step 5 (big endian to little endian).
  set utf16_sqlite3 [test_translate $utf16be_bom UTF16 UTF16LE]
  do_bincmp_test $testname.5.be.le $utf16_sqlite3 $utf16le

  # Step 5 (little endian to big endian).
  set utf16_sqlite3 [test_translate $utf16le_bom UTF16 UTF16BE]
  do_bincmp_test $testname.5.le.be $utf16_sqlite3 $utf16be
}

translate_selftest

test_conversion enc-1 "hello world"
test_conversion enc-2 "sqlite"
test_conversion enc-3 ""
test_conversion enc-X "\u0100"
test_conversion enc-4 "\u1234"
test_conversion enc-5 "\u4321abc"
test_conversion enc-6 "\u4321\u1234"
test_conversion enc-7 [string repeat "abcde\u00EF\u00EE\uFFFCabc" 100]
test_conversion enc-8 [string repeat "\u007E\u007F\u0080\u0081" 100]
test_conversion enc-9 [string repeat "\u07FE\u07FF\u0800\u0801\uFFF0" 100]

finish_test




--- NEW FILE: enc2.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The focus of
# this file is testing the SQLite routines used for converting between the
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
# UTF-16be).
#
# $Id: enc2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# The rough organisation of tests in this file is:
#
# enc2.1.*: Simple tests with a UTF-8 db.
# enc2.2.*: Simple tests with a UTF-16LE db.
# enc2.3.*: Simple tests with a UTF-16BE db.
# enc2.4.*: Test that attached databases must have the same text encoding
#           as the main database.
# enc2.5.*: Test the behaviour of the library when a collation sequence is
#           not available for the most desirable text encoding.
# enc2.6.*: Similar test for user functions.
# enc2.7.*: Test that the VerifyCookie opcode protects against assuming the
#           wrong text encoding for the database.
# enc2.8.*: Test sqlite3_complete16()
#

db close

# Return the UTF-8 representation of the supplied UTF-16 string $str. 
proc utf8 {str} {
  # If $str ends in two 0x00 0x00 bytes, knock these off before
  # converting to UTF-8 using TCL.
  binary scan $str \c* vals
  if {[lindex $vals end]==0 && [lindex $vals end-1]==0} {
    set str [binary format \c* [lrange $vals 0 end-2]]
  }

  set r [encoding convertfrom unicode $str]
  return $r
}

#
# This proc contains all the tests in this file. It is run
# three times. Each time the file 'test.db' contains a database
# with the following contents:
set dbcontents {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES('one', 'I', 1);
}
# This proc tests that we can open and manipulate the test.db 
# database, and that it is possible to retreive values in
# various text encodings.
#
proc run_test_script {t enc} {

# Open the database and pull out a (the) row.
do_test $t.1 {
  set DB [sqlite3 db test.db]
  execsql {SELECT * FROM t1}
} {one I 1}

# Insert some data
do_test $t.2 {
  execsql {INSERT INTO t1 VALUES('two', 'II', 2);}
  execsql {SELECT * FROM t1}
} {one I 1 two II 2}

# Insert some data 
do_test $t.3 {
  execsql {
    INSERT INTO t1 VALUES('three','III',3);
    INSERT INTO t1 VALUES('four','IV',4);
    INSERT INTO t1 VALUES('five','V',5);
  }
  execsql {SELECT * FROM t1}
} {one I 1 two II 2 three III 3 four IV 4 five V 5}

# Use the index
do_test $t.4 {
  execsql {
    SELECT * FROM t1 WHERE a = 'one';
  }
} {one I 1}
do_test $t.5 {
  execsql {
    SELECT * FROM t1 WHERE a = 'four';
  }
} {four IV 4}
do_test $t.6 {
  execsql {
    SELECT * FROM t1 WHERE a IN ('one', 'two');
  }
} {one I 1 two II 2}

# Now check that we can retrieve data in both UTF-16 and UTF-8
do_test $t.7 {
  set STMT [sqlite3_prepare $DB "SELECT a FROM t1 WHERE c>3;" -1 TAIL]
  sqlite3_step $STMT
  sqlite3_column_text $STMT 0
} {four}

do_test $t.8 {
  sqlite3_step $STMT
  utf8 [sqlite3_column_text16 $STMT 0]
} {five}

do_test $t.9 {
  sqlite3_finalize $STMT
} SQLITE_OK

do_test $t.10 {
  db eval {PRAGMA encoding}
} $enc

}

# The three unicode encodings understood by SQLite.
set encodings [list UTF-8 UTF-16le UTF-16be]

set sqlite_os_trace 0
set i 1
foreach enc $encodings {
  file delete -force test.db
  sqlite3 db test.db
  db eval "PRAGMA encoding = \"$enc\""
  execsql $dbcontents
  db close
  run_test_script enc2-$i $enc
  db close
  incr i
}

# Test that it is an error to try to attach a database with a different
# encoding to the main database.
do_test enc2-4.1 {
  file delete -force test.db
  sqlite3 db test.db
  db eval "PRAGMA encoding = 'UTF-8'"
  db eval "CREATE TABLE abc(a, b, c);"
} {}
do_test enc2-4.2 {
  file delete -force test2.db
  sqlite3 db2 test2.db
  db2 eval "PRAGMA encoding = 'UTF-16'"
  db2 eval "CREATE TABLE abc(a, b, c);"
} {}
do_test enc2-4.3 {
  catchsql {
    ATTACH 'test2.db' as aux;
  }
} {1 {attached databases must use the same text encoding as main database}}

db2 close
db close

# The following tests - enc2-5.* - test that SQLite selects the correct
# collation sequence when more than one is available.

set ::values [list one two three four five]
set ::test_collate_enc INVALID
proc test_collate {enc lhs rhs} {
  set ::test_collate_enc $enc
  set l [lsearch -exact $::values $lhs]
  set r [lsearch -exact $::values $rhs]
  set res [expr $l - $r]
  return $res
}

file delete -force test.db
set DB [sqlite3 db test.db]
do_test enc2-5.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
    INSERT INTO t5 VALUES('five');
    INSERT INTO t5 VALUES('three');
    INSERT INTO t5 VALUES('four');
  }
} {}
do_test enc2-5.1 {
  add_test_collate $DB 1 1 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}
do_test enc2-5.2 {
  add_test_collate $DB 0 1 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16LE}
do_test enc2-5.3 {
  add_test_collate $DB 0 0 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}

db close
file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-5.4 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
    INSERT INTO t5 VALUES('five');
    INSERT INTO t5 VALUES('three');
    INSERT INTO t5 VALUES('four');
  }
} {}
do_test enc2-5.5 {
  add_test_collate $DB 1 1 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16LE}
do_test enc2-5.6 {
  add_test_collate $DB 1 0 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}
do_test enc2-5.7 {
  add_test_collate $DB 1 0 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}

db close
file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-5.8 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
    INSERT INTO t5 VALUES('five');
    INSERT INTO t5 VALUES('three');
    INSERT INTO t5 VALUES('four');
  }
} {}
do_test enc2-5.9 {
  add_test_collate $DB 1 1 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}
do_test enc2-5.10 {
  add_test_collate $DB 1 1 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16LE}
do_test enc2-5.11 {
  add_test_collate $DB 1 0 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}

# Also test that a UTF-16 collation factory works.
do_test enc2-5-12 {
  add_test_collate $DB 0 0 0
  catchsql {
    SELECT * FROM t5 ORDER BY 1 COLLATE test_collate
  }
} {1 {no such collation sequence: test_collate}}
do_test enc2-5.13 {
  add_test_collate_needed $DB 
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}

db close
file delete -force test.db

# The following tests - enc2-6.* - test that SQLite selects the correct
# user function when more than one is available.

proc test_function {enc arg} {
  return "$enc $arg"
}

file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-8'}
do_test enc2-6.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
  }
} {}
do_test enc2-6.1 {
  add_test_function $DB 1 1 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-8 sqlite}}
db close
set DB [sqlite3 db test.db]
do_test enc2-6.2 {
  add_test_function $DB 0 1 0
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
db close
set DB [sqlite3 db test.db]
do_test enc2-6.3 {
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-6.3 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }
} {}
do_test enc2-6.4 {
  add_test_function $DB 1 1 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
db close
set DB [sqlite3 db test.db]
do_test enc2-6.5 {
  add_test_function $DB 0 1 0
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
db close
set DB [sqlite3 db test.db]
do_test enc2-6.6 {
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-6.7 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }
} {}
do_test enc2-6.8 {
  add_test_function $DB 1 1 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}
db close
set DB [sqlite3 db test.db]
do_test enc2-6.9 {
  add_test_function $DB 0 1 0
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
db close
set DB [sqlite3 db test.db]
do_test enc2-6.10 {
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}


db close
file delete -force test.db

# The following tests - enc2-7.* - function as follows:
#
# 1: Open an empty database file assuming UTF-16 encoding.
# 2: Open the same database with a different handle assuming UTF-8. Create
#    a table using this handle.
# 3: Read the sqlite_master table from the first handle. 
# 4: Ensure the first handle recognises the database encoding is UTF-8.
#
do_test enc2-7.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA encoding = 'UTF-16';
    SELECT * FROM sqlite_master;
  }
} {}
do_test enc2-7.2 {
  set enc [execsql {
    PRAGMA encoding;
  }]
  string range $enc 0 end-2 ;# Chop off the "le" or "be"
} {UTF-16}
do_test enc2-7.3 {
  sqlite3 db2 test.db
  execsql {
    PRAGMA encoding = 'UTF-8';
    CREATE TABLE abc(a, b, c);
  } db2
} {}
do_test enc2-7.4 {
  execsql {
    SELECT * FROM sqlite_master;
  }
} {table abc abc 2 {CREATE TABLE abc(a, b, c)}}
do_test enc2-7.5 {
  execsql {
    PRAGMA encoding;
  }
} {UTF-8}

db close
db2 close

proc utf16 {utf8} {
  set utf16 [encoding convertto unicode $utf8]
  append utf16 "\x00\x00"
  return $utf16
}
do_test enc2-8.1 {
  sqlite3_complete16 [utf16 "SELECT * FROM t1;"]
} {1}
do_test enc2-8.2 {
  sqlite3_complete16 [utf16 "SELECT * FROM"]
} {0}

finish_test

--- NEW FILE: enc3.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. 
#
# The focus of this file is testing of the proper handling of conversions
# to the native text representation.
#
# $Id: enc3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test enc3-1.1 {
  execsql {
    PRAGMA encoding=utf16le;
    PRAGMA encoding;
  }
} {UTF-16le}
do_test enc3-1.2 {
  execsql {
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES('abc''123',5);
    SELECT * FROM t1
  }
} {abc'123 5}
do_test enc3-1.3 {
  execsql {
    SELECT quote(x) || ' ' || quote(y) FROM t1
  }
} {{'abc''123' 5}}
do_test enc3-1.4 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(x'616263646566',NULL);
    SELECT * FROM t1
  }
} {abcdef {}}
do_test enc3-1.5 {
  execsql {
    SELECT quote(x) || ' ' || quote(y) FROM t1
  }
} {{X'616263646566' NULL}}


finish_test

--- NEW FILE: expr.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing expressions.
#
# $Id: expr.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
execsql {INSERT INTO test1 VALUES(1,2,1.1,2.2,'hello','world')}
proc test_expr {name settings expr result} {
  do_test $name [format {
    execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
  } $settings $expr] $result
}

test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
test_expr expr-1.3 {i1=10, i2=20} {i1*i2} 200
# update for sqlite3 v3: Change 0.5 to 0 in expr1.4 due to manifest types.
test_expr expr-1.4 {i1=10, i2=20} {i1/i2} 0
test_expr expr-1.5 {i1=10, i2=20} {i2/i1} 2
test_expr expr-1.6 {i1=10, i2=20} {i2<i1} 0
test_expr expr-1.7 {i1=10, i2=20} {i2<=i1} 0
test_expr expr-1.8 {i1=10, i2=20} {i2>i1} 1
test_expr expr-1.9 {i1=10, i2=20} {i2>=i1} 1
test_expr expr-1.10 {i1=10, i2=20} {i2!=i1} 1
test_expr expr-1.11 {i1=10, i2=20} {i2=i1} 0
test_expr expr-1.12 {i1=10, i2=20} {i2<>i1} 1
test_expr expr-1.13 {i1=10, i2=20} {i2==i1} 0
test_expr expr-1.14 {i1=20, i2=20} {i2<i1} 0
test_expr expr-1.15 {i1=20, i2=20} {i2<=i1} 1
test_expr expr-1.16 {i1=20, i2=20} {i2>i1} 0
test_expr expr-1.17 {i1=20, i2=20} {i2>=i1} 1
test_expr expr-1.18 {i1=20, i2=20} {i2!=i1} 0
test_expr expr-1.19 {i1=20, i2=20} {i2=i1} 1
test_expr expr-1.20 {i1=20, i2=20} {i2<>i1} 0
test_expr expr-1.21 {i1=20, i2=20} {i2==i1} 1
test_expr expr-1.22 {i1=1, i2=2, r1=3.0} {i1+i2*r1} {7.0}
test_expr expr-1.23 {i1=1, i2=2, r1=3.0} {(i1+i2)*r1} {9.0}
test_expr expr-1.24 {i1=1, i2=2} {min(i1,i2,i1+i2,i1-i2)} {-1}
test_expr expr-1.25 {i1=1, i2=2} {max(i1,i2,i1+i2,i1-i2)} {3}
test_expr expr-1.26 {i1=1, i2=2} {max(i1,i2,i1+i2,i1-i2)} {3}
test_expr expr-1.27 {i1=1, i2=2} {i1==1 AND i2=2} {1}
test_expr expr-1.28 {i1=1, i2=2} {i1=2 AND i2=1} {0}
test_expr expr-1.29 {i1=1, i2=2} {i1=1 AND i2=1} {0}
test_expr expr-1.30 {i1=1, i2=2} {i1=2 AND i2=2} {0}
test_expr expr-1.31 {i1=1, i2=2} {i1==1 OR i2=2} {1}
test_expr expr-1.32 {i1=1, i2=2} {i1=2 OR i2=1} {0}
test_expr expr-1.33 {i1=1, i2=2} {i1=1 OR i2=1} {1}
test_expr expr-1.34 {i1=1, i2=2} {i1=2 OR i2=2} {1}
test_expr expr-1.35 {i1=1, i2=2} {i1-i2=-1} {1}
test_expr expr-1.36 {i1=1, i2=0} {not i1} {0}
test_expr expr-1.37 {i1=1, i2=0} {not i2} {1}
test_expr expr-1.38 {i1=1} {-i1} {-1}
test_expr expr-1.39 {i1=1} {+i1} {1}
test_expr expr-1.40 {i1=1, i2=2} {+(i2+i1)} {3}
test_expr expr-1.41 {i1=1, i2=2} {-(i2+i1)} {-3}
test_expr expr-1.42 {i1=1, i2=2} {i1|i2} {3}
test_expr expr-1.42b {i1=1, i2=2} {4|2} {6}
test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0}
test_expr expr-1.43b {i1=1, i2=2} {4&5} {4}
test_expr expr-1.44 {i1=1} {~i1} {-2}
test_expr expr-1.45 {i1=1, i2=3} {i1<<i2} {8}
test_expr expr-1.46 {i1=32, i2=3} {i1>>i2} {4}
test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1<i2} 0
test_expr expr-1.48 {i1=9999999999, i2=8888888888} {i1=i2} 0
test_expr expr-1.49 {i1=9999999999, i2=8888888888} {i1>i2} 1
test_expr expr-1.50 {i1=99999999999, i2=99999999998} {i1<i2} 0
test_expr expr-1.51 {i1=99999999999, i2=99999999998} {i1=i2} 0
test_expr expr-1.52 {i1=99999999999, i2=99999999998} {i1>i2} 1
test_expr expr-1.53 {i1=099999999999, i2=99999999999} {i1<i2} 0
test_expr expr-1.54 {i1=099999999999, i2=99999999999} {i1=i2} 1
test_expr expr-1.55 {i1=099999999999, i2=99999999999} {i1>i2} 0
test_expr expr-1.56 {i1=25, i2=11} {i1%i2} 3
test_expr expr-1.58 {i1=NULL, i2=1} {coalesce(i1+i2,99)} 99
test_expr expr-1.59 {i1=1, i2=NULL} {coalesce(i1+i2,99)} 99
test_expr expr-1.60 {i1=NULL, i2=NULL} {coalesce(i1+i2,99)} 99
test_expr expr-1.61 {i1=NULL, i2=1} {coalesce(i1-i2,99)} 99
test_expr expr-1.62 {i1=1, i2=NULL} {coalesce(i1-i2,99)} 99
test_expr expr-1.63 {i1=NULL, i2=NULL} {coalesce(i1-i2,99)} 99
test_expr expr-1.64 {i1=NULL, i2=1} {coalesce(i1*i2,99)} 99
test_expr expr-1.65 {i1=1, i2=NULL} {coalesce(i1*i2,99)} 99
test_expr expr-1.66 {i1=NULL, i2=NULL} {coalesce(i1*i2,99)} 99
test_expr expr-1.67 {i1=NULL, i2=1} {coalesce(i1/i2,99)} 99
test_expr expr-1.68 {i1=1, i2=NULL} {coalesce(i1/i2,99)} 99
test_expr expr-1.69 {i1=NULL, i2=NULL} {coalesce(i1/i2,99)} 99
test_expr expr-1.70 {i1=NULL, i2=1} {coalesce(i1<i2,99)} 99
test_expr expr-1.71 {i1=1, i2=NULL} {coalesce(i1>i2,99)} 99
test_expr expr-1.72 {i1=NULL, i2=NULL} {coalesce(i1<=i2,99)} 99
test_expr expr-1.73 {i1=NULL, i2=1} {coalesce(i1>=i2,99)} 99
test_expr expr-1.74 {i1=1, i2=NULL} {coalesce(i1!=i2,99)} 99
test_expr expr-1.75 {i1=NULL, i2=NULL} {coalesce(i1==i2,99)} 99
test_expr expr-1.76 {i1=NULL, i2=NULL} {coalesce(not i1,99)} 99
test_expr expr-1.77 {i1=NULL, i2=NULL} {coalesce(-i1,99)} 99
test_expr expr-1.78 {i1=NULL, i2=NULL} {coalesce(i1 IS NULL AND i2=5,99)} 99
test_expr expr-1.79 {i1=NULL, i2=NULL} {coalesce(i1 IS NULL OR i2=5,99)} 1
test_expr expr-1.80 {i1=NULL, i2=NULL} {coalesce(i1=5 AND i2 IS NULL,99)} 99
test_expr expr-1.81 {i1=NULL, i2=NULL} {coalesce(i1=5 OR i2 IS NULL,99)} 1
test_expr expr-1.82 {i1=NULL, i2=3} {coalesce(min(i1,i2,1),99)} 99
test_expr expr-1.83 {i1=NULL, i2=3} {coalesce(max(i1,i2,1),99)} 99
test_expr expr-1.84 {i1=3, i2=NULL} {coalesce(min(i1,i2,1),99)} 99
test_expr expr-1.85 {i1=3, i2=NULL} {coalesce(max(i1,i2,1),99)} 99
test_expr expr-1.86 {i1=3, i2=8} {5 between i1 and i2} 1
test_expr expr-1.87 {i1=3, i2=8} {5 not between i1 and i2} 0
test_expr expr-1.88 {i1=3, i2=8} {55 between i1 and i2} 0
test_expr expr-1.89 {i1=3, i2=8} {55 not between i1 and i2} 1
test_expr expr-1.90 {i1=3, i2=NULL} {5 between i1 and i2} {{}}
test_expr expr-1.91 {i1=3, i2=NULL} {5 not between i1 and i2} {{}}
test_expr expr-1.92 {i1=3, i2=NULL} {2 between i1 and i2} 0
test_expr expr-1.93 {i1=3, i2=NULL} {2 not between i1 and i2} 1
test_expr expr-1.94 {i1=NULL, i2=8} {2 between i1 and i2} {{}}
test_expr expr-1.95 {i1=NULL, i2=8} {2 not between i1 and i2} {{}}
test_expr expr-1.94 {i1=NULL, i2=8} {55 between i1 and i2} 0
test_expr expr-1.95 {i1=NULL, i2=8} {55 not between i1 and i2} 1
test_expr expr-1.96 {i1=NULL, i2=3} {coalesce(i1<<i2,99)} 99
test_expr expr-1.97 {i1=32, i2=NULL} {coalesce(i1>>i2,99)} 99
test_expr expr-1.98 {i1=NULL, i2=NULL} {coalesce(i1|i2,99)} 99
test_expr expr-1.99 {i1=32, i2=NULL} {coalesce(i1&i2,99)} 99
test_expr expr-1.100 {i1=1, i2=''} {i1=i2} 0
test_expr expr-1.101 {i1=0, i2=''} {i1=i2} 0

test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
set tcl_precision 15
test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024
test_expr expr-2.6 {r1=1.23, r2=2.34} {r2<r1} 0
test_expr expr-2.7 {r1=1.23, r2=2.34} {r2<=r1} 0
test_expr expr-2.8 {r1=1.23, r2=2.34} {r2>r1} 1
test_expr expr-2.9 {r1=1.23, r2=2.34} {r2>=r1} 1
test_expr expr-2.10 {r1=1.23, r2=2.34} {r2!=r1} 1
test_expr expr-2.11 {r1=1.23, r2=2.34} {r2=r1} 0
test_expr expr-2.12 {r1=1.23, r2=2.34} {r2<>r1} 1
test_expr expr-2.13 {r1=1.23, r2=2.34} {r2==r1} 0
test_expr expr-2.14 {r1=2.34, r2=2.34} {r2<r1} 0
test_expr expr-2.15 {r1=2.34, r2=2.34} {r2<=r1} 1
test_expr expr-2.16 {r1=2.34, r2=2.34} {r2>r1} 0
test_expr expr-2.17 {r1=2.34, r2=2.34} {r2>=r1} 1
test_expr expr-2.18 {r1=2.34, r2=2.34} {r2!=r1} 0
test_expr expr-2.19 {r1=2.34, r2=2.34} {r2=r1} 1
test_expr expr-2.20 {r1=2.34, r2=2.34} {r2<>r1} 0
test_expr expr-2.21 {r1=2.34, r2=2.34} {r2==r1} 1
test_expr expr-2.22 {r1=1.23, r2=2.34} {min(r1,r2,r1+r2,r1-r2)} {-1.11}
test_expr expr-2.23 {r1=1.23, r2=2.34} {max(r1,r2,r1+r2,r1-r2)} {3.57}
test_expr expr-2.24 {r1=25.0, r2=11.0} {r1%r2} 3.0
test_expr expr-2.25 {r1=1.23, r2=NULL} {coalesce(r1+r2,99.0)} 99.0

test_expr expr-3.1 {t1='abc', t2='xyz'} {t1<t2} 1
test_expr expr-3.2 {t1='xyz', t2='abc'} {t1<t2} 0
test_expr expr-3.3 {t1='abc', t2='abc'} {t1<t2} 0
test_expr expr-3.4 {t1='abc', t2='xyz'} {t1<=t2} 1
test_expr expr-3.5 {t1='xyz', t2='abc'} {t1<=t2} 0
test_expr expr-3.6 {t1='abc', t2='abc'} {t1<=t2} 1
test_expr expr-3.7 {t1='abc', t2='xyz'} {t1>t2} 0
test_expr expr-3.8 {t1='xyz', t2='abc'} {t1>t2} 1
test_expr expr-3.9 {t1='abc', t2='abc'} {t1>t2} 0
test_expr expr-3.10 {t1='abc', t2='xyz'} {t1>=t2} 0
test_expr expr-3.11 {t1='xyz', t2='abc'} {t1>=t2} 1
test_expr expr-3.12 {t1='abc', t2='abc'} {t1>=t2} 1
test_expr expr-3.13 {t1='abc', t2='xyz'} {t1=t2} 0
test_expr expr-3.14 {t1='xyz', t2='abc'} {t1=t2} 0
test_expr expr-3.15 {t1='abc', t2='abc'} {t1=t2} 1
test_expr expr-3.16 {t1='abc', t2='xyz'} {t1==t2} 0
test_expr expr-3.17 {t1='xyz', t2='abc'} {t1==t2} 0
test_expr expr-3.18 {t1='abc', t2='abc'} {t1==t2} 1
test_expr expr-3.19 {t1='abc', t2='xyz'} {t1<>t2} 1
test_expr expr-3.20 {t1='xyz', t2='abc'} {t1<>t2} 1
test_expr expr-3.21 {t1='abc', t2='abc'} {t1<>t2} 0
test_expr expr-3.22 {t1='abc', t2='xyz'} {t1!=t2} 1
test_expr expr-3.23 {t1='xyz', t2='abc'} {t1!=t2} 1
test_expr expr-3.24 {t1='abc', t2='abc'} {t1!=t2} 0
test_expr expr-3.25 {t1=NULL, t2='hi'} {t1 isnull} 1
test_expr expr-3.25b {t1=NULL, t2='hi'} {t1 is null} 1
test_expr expr-3.26 {t1=NULL, t2='hi'} {t2 isnull} 0
test_expr expr-3.27 {t1=NULL, t2='hi'} {t1 notnull} 0
test_expr expr-3.28 {t1=NULL, t2='hi'} {t2 notnull} 1
test_expr expr-3.28b {t1=NULL, t2='hi'} {t2 is not null} 1
test_expr expr-3.29 {t1='xyz', t2='abc'} {t1||t2} {xyzabc}
test_expr expr-3.30 {t1=NULL, t2='abc'} {t1||t2} {{}}
test_expr expr-3.31 {t1='xyz', t2=NULL} {t1||t2} {{}}
test_expr expr-3.32 {t1='xyz', t2='abc'} {t1||' hi '||t2} {{xyz hi abc}}
test_expr epxr-3.33 {t1='abc', t2=NULL} {coalesce(t1<t2,99)} 99
test_expr epxr-3.34 {t1='abc', t2=NULL} {coalesce(t2<t1,99)} 99
test_expr epxr-3.35 {t1='abc', t2=NULL} {coalesce(t1>t2,99)} 99
test_expr epxr-3.36 {t1='abc', t2=NULL} {coalesce(t2>t1,99)} 99
test_expr epxr-3.37 {t1='abc', t2=NULL} {coalesce(t1<=t2,99)} 99
test_expr epxr-3.38 {t1='abc', t2=NULL} {coalesce(t2<=t1,99)} 99
test_expr epxr-3.39 {t1='abc', t2=NULL} {coalesce(t1>=t2,99)} 99
test_expr epxr-3.40 {t1='abc', t2=NULL} {coalesce(t2>=t1,99)} 99
test_expr epxr-3.41 {t1='abc', t2=NULL} {coalesce(t1==t2,99)} 99
test_expr epxr-3.42 {t1='abc', t2=NULL} {coalesce(t2==t1,99)} 99
test_expr epxr-3.43 {t1='abc', t2=NULL} {coalesce(t1!=t2,99)} 99
test_expr epxr-3.44 {t1='abc', t2=NULL} {coalesce(t2!=t1,99)} 99


test_expr expr-4.1 {t1='abc', t2='Abc'} {t1<t2} 0
test_expr expr-4.2 {t1='abc', t2='Abc'} {t1>t2} 1
test_expr expr-4.3 {t1='abc', t2='Bbc'} {t1<t2} 0
test_expr expr-4.4 {t1='abc', t2='Bbc'} {t1>t2} 1
test_expr expr-4.5 {t1='0', t2='0.0'} {t1==t2} 0
test_expr expr-4.6 {t1='0.000', t2='0.0'} {t1==t2} 0
test_expr expr-4.7 {t1=' 0.000', t2=' 0.0'} {t1==t2} 0
test_expr expr-4.8 {t1='0.0', t2='abc'} {t1<t2} 1
test_expr expr-4.9 {t1='0.0', t2='abc'} {t1==t2} 0
test_expr expr-4.10 {r1='0.0', r2='abc'} {r1>r2} 0
test_expr expr-4.11 {r1='abc', r2='Abc'} {r1<r2} 0
test_expr expr-4.12 {r1='abc', r2='Abc'} {r1>r2} 1
test_expr expr-4.13 {r1='abc', r2='Bbc'} {r1<r2} 0
test_expr expr-4.14 {r1='abc', r2='Bbc'} {r1>r2} 1
test_expr expr-4.15 {r1='0', r2='0.0'} {r1==r2} 1
test_expr expr-4.16 {r1='0.000', r2='0.0'} {r1==r2} 1
test_expr expr-4.17 {r1=' 0.000', r2=' 0.0'} {r1==r2} 0
test_expr expr-4.18 {r1='0.0', r2='abc'} {r1<r2} 1
test_expr expr-4.19 {r1='0.0', r2='abc'} {r1==r2} 0
test_expr expr-4.20 {r1='0.0', r2='abc'} {r1>r2} 0

test_expr expr-5.1 {t1='abc', t2='xyz'} {t1 LIKE t2} 0
test_expr expr-5.2 {t1='abc', t2='ABC'} {t1 LIKE t2} 1
test_expr expr-5.3 {t1='abc', t2='A_C'} {t1 LIKE t2} 1
test_expr expr-5.4 {t1='abc', t2='abc_'} {t1 LIKE t2} 0
test_expr expr-5.5 {t1='abc', t2='A%C'} {t1 LIKE t2} 1
test_expr expr-5.5a {t1='abdc', t2='a%c'} {t1 LIKE t2} 1
test_expr expr-5.5b {t1='ac', t2='A%C'} {t1 LIKE t2} 1
test_expr expr-5.6 {t1='abxyzzyc', t2='A%C'} {t1 LIKE t2} 1
test_expr expr-5.7 {t1='abxyzzy', t2='A%C'} {t1 LIKE t2} 0
test_expr expr-5.8 {t1='abxyzzycx', t2='A%C'} {t1 LIKE t2} 0
test_expr expr-5.8b {t1='abxyzzycy', t2='A%CX'} {t1 LIKE t2} 0
test_expr expr-5.9 {t1='abc', t2='A%_C'} {t1 LIKE t2} 1
test_expr expr-5.9b {t1='ac', t2='A%_C'} {t1 LIKE t2} 0
test_expr expr-5.10 {t1='abxyzzyc', t2='A%_C'} {t1 LIKE t2} 1
test_expr expr-5.11 {t1='abc', t2='xyz'} {t1 NOT LIKE t2} 1
test_expr expr-5.12 {t1='abc', t2='ABC'} {t1 NOT LIKE t2} 0

# The following tests only work on versions of TCL that support Unicode
#
if {"\u1234"!="u1234"} {
  test_expr expr-5.13 "t1='a\u0080c', t2='A_C'" {t1 LIKE t2} 1
  test_expr expr-5.14 "t1='a\u07FFc', t2='A_C'" {t1 LIKE t2} 1
  test_expr expr-5.15 "t1='a\u0800c', t2='A_C'" {t1 LIKE t2} 1
  test_expr expr-5.16 "t1='a\uFFFFc', t2='A_C'" {t1 LIKE t2} 1
  test_expr expr-5.17 "t1='a\u0080', t2='A__'" {t1 LIKE t2} 0
  test_expr expr-5.18 "t1='a\u07FF', t2='A__'" {t1 LIKE t2} 0
  test_expr expr-5.19 "t1='a\u0800', t2='A__'" {t1 LIKE t2} 0
  test_expr expr-5.20 "t1='a\uFFFF', t2='A__'" {t1 LIKE t2} 0
  test_expr expr-5.21 "t1='ax\uABCD', t2='A_\uABCD'" {t1 LIKE t2} 1
  test_expr expr-5.22 "t1='ax\u1234', t2='A%\u1234'" {t1 LIKE t2} 1
  test_expr expr-5.23 "t1='ax\uFEDC', t2='A_%'" {t1 LIKE t2} 1
  test_expr expr-5.24 "t1='ax\uFEDCy\uFEDC', t2='A%\uFEDC'" {t1 LIKE t2} 1
}

test_expr expr-5.54 {t1='abc', t2=NULL} {t1 LIKE t2} {{}}
test_expr expr-5.55 {t1='abc', t2=NULL} {t1 NOT LIKE t2} {{}}
test_expr expr-5.56 {t1='abc', t2=NULL} {t2 LIKE t1} {{}}
test_expr expr-5.57 {t1='abc', t2=NULL} {t2 NOT LIKE t1} {{}}


test_expr expr-6.1 {t1='abc', t2='xyz'} {t1 GLOB t2} 0
test_expr expr-6.2 {t1='abc', t2='ABC'} {t1 GLOB t2} 0
test_expr expr-6.3 {t1='abc', t2='A?C'} {t1 GLOB t2} 0
test_expr expr-6.4 {t1='abc', t2='a?c'} {t1 GLOB t2} 1
test_expr expr-6.5 {t1='abc', t2='abc?'} {t1 GLOB t2} 0
test_expr expr-6.6 {t1='abc', t2='A*C'} {t1 GLOB t2} 0
test_expr expr-6.7 {t1='abc', t2='a*c'} {t1 GLOB t2} 1
test_expr expr-6.8 {t1='abxyzzyc', t2='a*c'} {t1 GLOB t2} 1
test_expr expr-6.9 {t1='abxyzzy', t2='a*c'} {t1 GLOB t2} 0
test_expr expr-6.10 {t1='abxyzzycx', t2='a*c'} {t1 GLOB t2} 0
test_expr expr-6.11 {t1='abc', t2='xyz'} {t1 NOT GLOB t2} 1
test_expr expr-6.12 {t1='abc', t2='abc'} {t1 NOT GLOB t2} 0
test_expr expr-6.13 {t1='abc', t2='a[bx]c'} {t1 GLOB t2} 1
test_expr expr-6.14 {t1='abc', t2='a[cx]c'} {t1 GLOB t2} 0
test_expr expr-6.15 {t1='abc', t2='a[a-d]c'} {t1 GLOB t2} 1
test_expr expr-6.16 {t1='abc', t2='a[^a-d]c'} {t1 GLOB t2} 0
test_expr expr-6.17 {t1='abc', t2='a[A-Dc]c'} {t1 GLOB t2} 0
test_expr expr-6.18 {t1='abc', t2='a[^A-Dc]c'} {t1 GLOB t2} 1
test_expr expr-6.19 {t1='abc', t2='a[]b]c'} {t1 GLOB t2} 1
test_expr expr-6.20 {t1='abc', t2='a[^]b]c'} {t1 GLOB t2} 0
test_expr expr-6.21a {t1='abcdefg', t2='a*[de]g'} {t1 GLOB t2} 0
test_expr expr-6.21b {t1='abcdefg', t2='a*[df]g'} {t1 GLOB t2} 1
test_expr expr-6.21c {t1='abcdefg', t2='a*[d-h]g'} {t1 GLOB t2} 1
test_expr expr-6.21d {t1='abcdefg', t2='a*[b-e]g'} {t1 GLOB t2} 0
test_expr expr-6.22a {t1='abcdefg', t2='a*[^de]g'} {t1 GLOB t2} 1
test_expr expr-6.22b {t1='abcdefg', t2='a*[^def]g'} {t1 GLOB t2} 0
test_expr expr-6.23 {t1='abcdefg', t2='a*?g'} {t1 GLOB t2} 1
test_expr expr-6.24 {t1='ac', t2='a*c'} {t1 GLOB t2} 1
test_expr expr-6.25 {t1='ac', t2='a*?c'} {t1 GLOB t2} 0


# These tests only work on versions of TCL that support Unicode
#
if {"\u1234"!="u1234"} {
  test_expr expr-6.26 "t1='a\u0080c', t2='a?c'" {t1 GLOB t2} 1
  test_expr expr-6.27 "t1='a\u07ffc', t2='a?c'" {t1 GLOB t2} 1
  test_expr expr-6.28 "t1='a\u0800c', t2='a?c'" {t1 GLOB t2} 1
  test_expr expr-6.29 "t1='a\uffffc', t2='a?c'" {t1 GLOB t2} 1
  test_expr expr-6.30 "t1='a\u1234', t2='a?'" {t1 GLOB t2} 1
  test_expr expr-6.31 "t1='a\u1234', t2='a??'" {t1 GLOB t2} 0
  test_expr expr-6.32 "t1='ax\u1234', t2='a?\u1234'" {t1 GLOB t2} 1
  test_expr expr-6.33 "t1='ax\u1234', t2='a*\u1234'" {t1 GLOB t2} 1
  test_expr expr-6.34 "t1='ax\u1234y\u1234', t2='a*\u1234'" {t1 GLOB t2} 1
  test_expr expr-6.35 "t1='a\u1234b', t2='a\[x\u1234y\]b'" {t1 GLOB t2} 1
  test_expr expr-6.36 "t1='a\u1234b', t2='a\[\u1233-\u1235\]b'" {t1 GLOB t2} 1
  test_expr expr-6.37 "t1='a\u1234b', t2='a\[\u1234-\u124f\]b'" {t1 GLOB t2} 1
  test_expr expr-6.38 "t1='a\u1234b', t2='a\[\u1235-\u124f\]b'" {t1 GLOB t2} 0
  test_expr expr-6.39 "t1='a\u1234b', t2='a\[a-\u1235\]b'" {t1 GLOB t2} 1
  test_expr expr-6.40 "t1='a\u1234b', t2='a\[a-\u1234\]b'" {t1 GLOB t2} 1
  test_expr expr-6.41 "t1='a\u1234b', t2='a\[a-\u1233\]b'" {t1 GLOB t2} 0
}

test_expr expr-6.51 {t1='ABC', t2='xyz'} {t1 GLOB t2} 0
test_expr expr-6.52 {t1='ABC', t2='abc'} {t1 GLOB t2} 0
test_expr expr-6.53 {t1='ABC', t2='a?c'} {t1 GLOB t2} 0
test_expr expr-6.54 {t1='ABC', t2='A?C'} {t1 GLOB t2} 1
test_expr expr-6.55 {t1='ABC', t2='abc?'} {t1 GLOB t2} 0
test_expr expr-6.56 {t1='ABC', t2='a*c'} {t1 GLOB t2} 0
test_expr expr-6.57 {t1='ABC', t2='A*C'} {t1 GLOB t2} 1
test_expr expr-6.58 {t1='ABxyzzyC', t2='A*C'} {t1 GLOB t2} 1
test_expr expr-6.59 {t1='ABxyzzy', t2='A*C'} {t1 GLOB t2} 0
test_expr expr-6.60 {t1='ABxyzzyCx', t2='A*C'} {t1 GLOB t2} 0
test_expr expr-6.61 {t1='ABC', t2='xyz'} {t1 NOT GLOB t2} 1
test_expr expr-6.62 {t1='ABC', t2='ABC'} {t1 NOT GLOB t2} 0
test_expr expr-6.63 {t1='ABC', t2='A[Bx]C'} {t1 GLOB t2} 1
test_expr expr-6.64 {t1='ABC', t2='A[Cx]C'} {t1 GLOB t2} 0
test_expr expr-6.65 {t1='ABC', t2='A[A-D]C'} {t1 GLOB t2} 1
test_expr expr-6.66 {t1='ABC', t2='A[^A-D]C'} {t1 GLOB t2} 0
test_expr expr-6.67 {t1='ABC', t2='A[a-dC]C'} {t1 GLOB t2} 0
test_expr expr-6.68 {t1='ABC', t2='A[^a-dC]C'} {t1 GLOB t2} 1
test_expr expr-6.69a {t1='ABC', t2='A[]B]C'} {t1 GLOB t2} 1
test_expr expr-6.69b {t1='A]C', t2='A[]B]C'} {t1 GLOB t2} 1
test_expr expr-6.70a {t1='ABC', t2='A[^]B]C'} {t1 GLOB t2} 0
test_expr expr-6.70b {t1='AxC', t2='A[^]B]C'} {t1 GLOB t2} 1
test_expr expr-6.70c {t1='A]C', t2='A[^]B]C'} {t1 GLOB t2} 0
test_expr expr-6.71 {t1='ABCDEFG', t2='A*[DE]G'} {t1 GLOB t2} 0
test_expr expr-6.72 {t1='ABCDEFG', t2='A*[^DE]G'} {t1 GLOB t2} 1
test_expr expr-6.73 {t1='ABCDEFG', t2='A*?G'} {t1 GLOB t2} 1
test_expr expr-6.74 {t1='AC', t2='A*C'} {t1 GLOB t2} 1
test_expr expr-6.75 {t1='AC', t2='A*?C'} {t1 GLOB t2} 0

test_expr expr-6.63 {t1=NULL, t2='a*?c'} {t1 GLOB t2} {{}}
test_expr expr-6.64 {t1='ac', t2=NULL} {t1 GLOB t2} {{}}
test_expr expr-6.65 {t1=NULL, t2='a*?c'} {t1 NOT GLOB t2} {{}}
test_expr expr-6.66 {t1='ac', t2=NULL} {t1 NOT GLOB t2} {{}}

test_expr expr-case.1 {i1=1, i2=2} \
	{CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
test_expr expr-case.2 {i1=2, i2=2} \
	{CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} eq
test_expr expr-case.3 {i1=NULL, i2=2} \
	{CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
test_expr expr-case.4 {i1=2, i2=NULL} \
	{CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
test_expr expr-case.5 {i1=2} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} two
test_expr expr-case.6 {i1=1} \
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} one
test_expr expr-case.7 {i1=2} \
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} error
test_expr expr-case.8 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} error
test_expr expr-case.9 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} error
test_expr expr-case.10 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' END} {{}}
test_expr expr-case.11 {i1=null} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 3 END} 3
test_expr expr-case.12 {i1=1} \
	{CASE i1 WHEN 1 THEN null WHEN 2 THEN 'two' ELSE 3 END} {{}}
test_expr expr-case.13 {i1=7} \
	{ CASE WHEN i1 < 5 THEN 'low' 
	       WHEN i1 < 10 THEN 'medium' 
               WHEN i1 < 15 THEN 'high' ELSE 'error' END} medium


# The sqliteExprIfFalse and sqliteExprIfTrue routines are only
# executed as part of a WHERE clause.  Create a table suitable
# for testing these functions.
#
execsql {DROP TABLE test1}
execsql {CREATE TABLE test1(a int, b int);}
for {set i 1} {$i<=20} {incr i} {
  execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
}
execsql "INSERT INTO test1 VALUES(NULL,0)"
do_test expr-7.1 {
  execsql {SELECT * FROM test1 ORDER BY a}
} {{} 0 1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024 11 2048 12 4096 13 8192 14 16384 15 32768 16 65536 17 131072 18 262144 19 524288 20 1048576}

proc test_expr2 {name expr result} {
  do_test $name [format {
    execsql {SELECT a FROM test1 WHERE %s ORDER BY a}
  } $expr] $result
}

test_expr2 expr-7.2  {a<10 AND a>8}                  {9}
test_expr2 expr-7.3  {a<=10 AND a>=8}                {8 9 10}
test_expr2 expr-7.4  {a>=8 AND a<=10}                {8 9 10}
test_expr2 expr-7.5  {a>=20 OR a<=1}                 {1 20}
test_expr2 expr-7.6  {b!=4 AND a<=3}                 {1 3}
test_expr2 expr-7.7  {b==8 OR b==16 OR b==32}        {3 4 5}
test_expr2 expr-7.8  {NOT b<>8 OR b==1024}           {3 10}
test_expr2 expr-7.9  {b LIKE '10%'}                  {10 20}
test_expr2 expr-7.10 {b LIKE '_4'}                   {6}
test_expr2 expr-7.11 {a GLOB '1?'}            {10 11 12 13 14 15 16 17 18 19}
test_expr2 expr-7.12 {b GLOB '1*4'}                  {10 14}
test_expr2 expr-7.13 {b GLOB '*1[456]'}              {4}
test_expr2 expr-7.14 {a ISNULL}                      {{}}
test_expr2 expr-7.15 {a NOTNULL AND a<3}             {1 2}
test_expr2 expr-7.16 {a AND a<3}                     {1 2}
test_expr2 expr-7.17 {NOT a}                         {}
test_expr2 expr-7.18 {a==11 OR (b>1000 AND b<2000)}  {10 11}
test_expr2 expr-7.19 {a<=1 OR a>=20}                 {1 20}
test_expr2 expr-7.20 {a<1 OR a>20}                   {}
test_expr2 expr-7.21 {a>19 OR a<1}                   {20}
test_expr2 expr-7.22 {a!=1 OR a=100} \
                         {2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
test_expr2 expr-7.23 {(a notnull AND a<4) OR a==8}   {1 2 3 8}
test_expr2 expr-7.24 {a LIKE '2_' OR a==8}           {8 20}
test_expr2 expr-7.25 {a GLOB '2?' OR a==8}           {8 20}
test_expr2 expr-7.26 {a isnull OR a=8}               {{} 8}
test_expr2 expr-7.27 {a notnull OR a=8} \
                          {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
test_expr2 expr-7.28 {a<0 OR b=0} {{}}
test_expr2 expr-7.29 {b=0 OR a<0} {{}}
test_expr2 expr-7.30 {a<0 AND b=0} {}
test_expr2 expr-7.31 {b=0 AND a<0} {}
test_expr2 expr-7.32 {a IS NULL AND (a<0 OR b=0)} {{}}
test_expr2 expr-7.33 {a IS NULL AND (b=0 OR a<0)} {{}}
test_expr2 expr-7.34 {a IS NULL AND (a<0 AND b=0)} {}
test_expr2 expr-7.35 {a IS NULL AND (b=0 AND a<0)} {}
test_expr2 expr-7.32 {(a<0 OR b=0) AND a IS NULL} {{}}
test_expr2 expr-7.33 {(b=0 OR a<0) AND a IS NULL} {{}}
test_expr2 expr-7.34 {(a<0 AND b=0) AND a IS NULL} {}
test_expr2 expr-7.35 {(b=0 AND a<0) AND a IS NULL} {}
test_expr2 expr-7.36 {a<2 OR (a<0 OR b=0)} {{} 1}
test_expr2 expr-7.37 {a<2 OR (b=0 OR a<0)} {{} 1}
test_expr2 expr-7.38 {a<2 OR (a<0 AND b=0)} {1}
test_expr2 expr-7.39 {a<2 OR (b=0 AND a<0)} {1}
test_expr2 expr-7.40 {((a<2 OR a IS NULL) AND b<3) OR b>1e10} {{} 1}
test_expr2 expr-7.41 {a BETWEEN -1 AND 1} {1}
test_expr2 expr-7.42 {a NOT BETWEEN 2 AND 100} {1}
test_expr2 expr-7.43 {(b+1234)||'this is a string that is at least 32 characters long' BETWEEN 1 AND 2} {}
test_expr2 expr-7.44 {123||'xabcdefghijklmnopqrstuvwyxz01234567890'||a BETWEEN '123a' AND '123b'} {}
test_expr2 expr-7.45 {((123||'xabcdefghijklmnopqrstuvwyxz01234567890'||a) BETWEEN '123a' AND '123b')<0} {}
test_expr2 expr-7.46 {((123||'xabcdefghijklmnopqrstuvwyxz01234567890'||a) BETWEEN '123a' AND '123z')>0} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}

test_expr2 expr-7.50 {((a between 1 and 2 OR 0) AND 1) OR 0} {1 2}
test_expr2 expr-7.51 {((a not between 3 and 100 OR 0) AND 1) OR 0} {1 2}
test_expr2 expr-7.52 {((a in (1,2) OR 0) AND 1) OR 0} {1 2}
test_expr2 expr-7.53 {((a not in (3,4,5,6,7,8,9,10) OR 0) AND a<11) OR 0} {1 2}
test_expr2 expr-7.54 {((a>0 OR 0) AND a<3) OR 0} {1 2}
test_expr2 expr-7.55 {((a in (1,2) OR 0) IS NULL AND 1) OR 0} {{}}
test_expr2 expr-7.56 {((a not in (3,4,5,6,7,8,9,10) IS NULL OR 0) AND 1) OR 0} \
   {{}}
test_expr2 expr-7.57 {((a>0 IS NULL OR 0) AND 1) OR 0} {{}}

test_expr2 expr-7.58  {(a||'')<='1'}                  {1}

test_expr2 expr-7.59 {LIKE('10%',b)}                  {10 20}
test_expr2 expr-7.60 {LIKE('_4',b)}                   {6}
test_expr2 expr-7.61 {GLOB('1?',a)}            {10 11 12 13 14 15 16 17 18 19}
test_expr2 expr-7.62 {GLOB('1*4',b)}                  {10 14}
test_expr2 expr-7.63 {GLOB('*1[456]',b)}              {4}


finish_test

--- NEW FILE: fkey1.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for foreign keys.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table and some data to work with.
#
do_test fkey1-1.0 {
  execsql {
    CREATE TABLE t1(
      a INTEGER PRIMARY KEY,
      b INTEGER
           REFERENCES t1 ON DELETE CASCADE
           REFERENCES t2,
      c TEXT,
      FOREIGN KEY (b,c) REFERENCES t2(x,y) ON UPDATE CASCADE
    );
  }
} {}
do_test fkey1-1.1 {
  execsql {
    CREATE TABLE t2(
      x INTEGER PRIMARY KEY,
      y TEXT
    );
  }
} {}
do_test fkey1-1.2 {
  execsql {
    CREATE TABLE t3(
      a INTEGER REFERENCES t2,
      b INTEGER REFERENCES t1,
      FOREIGN KEY (a,b) REFERENCES t2(x,y)
    );
  }
} {}
   


finish_test

--- NEW FILE: func.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
  execsql {CREATE TABLE tbl1(t1 text)}
  foreach word {this program is free software} {
    execsql "INSERT INTO tbl1 VALUES('$word')"
  }
  execsql {SELECT t1 FROM tbl1 ORDER BY t1}
} {free is program software this}
do_test func-0.1 {
  execsql {
     CREATE TABLE t2(a);
     INSERT INTO t2 VALUES(1);
     INSERT INTO t2 VALUES(NULL);
     INSERT INTO t2 VALUES(345);
     INSERT INTO t2 VALUES(NULL);
     INSERT INTO t2 VALUES(67890);
     SELECT * FROM t2;
  }
} {1 {} 345 {} 67890}

# Check out the length() function
#
do_test func-1.0 {
  execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
} {4 2 7 8 4}
do_test func-1.1 {
  set r [catch {execsql {SELECT length(*) FROM tbl1 ORDER BY t1}} msg]
  lappend r $msg
} {1 {wrong number of arguments to function length()}}
do_test func-1.2 {
  set r [catch {execsql {SELECT length(t1,5) FROM tbl1 ORDER BY t1}} msg]
  lappend r $msg
} {1 {wrong number of arguments to function length()}}
do_test func-1.3 {
  execsql {SELECT length(t1), count(*) FROM tbl1 GROUP BY length(t1)
           ORDER BY length(t1)}
} {2 1 4 2 7 1 8 1}
do_test func-1.4 {
  execsql {SELECT coalesce(length(a),-1) FROM t2}
} {1 -1 3 -1 5}

# Check out the substr() function
#
do_test func-2.0 {
  execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
} {fr is pr so th}
do_test func-2.1 {
  execsql {SELECT substr(t1,2,1) FROM tbl1 ORDER BY t1}
} {r s r o h}
do_test func-2.2 {
  execsql {SELECT substr(t1,3,3) FROM tbl1 ORDER BY t1}
} {ee {} ogr ftw is}
do_test func-2.3 {
  execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
} {e s m e s}
do_test func-2.4 {
  execsql {SELECT substr(t1,-1,2) FROM tbl1 ORDER BY t1}
} {e s m e s}
do_test func-2.5 {
  execsql {SELECT substr(t1,-2,1) FROM tbl1 ORDER BY t1}
} {e i a r i}
do_test func-2.6 {
  execsql {SELECT substr(t1,-2,2) FROM tbl1 ORDER BY t1}
} {ee is am re is}
do_test func-2.7 {
  execsql {SELECT substr(t1,-4,2) FROM tbl1 ORDER BY t1}
} {fr {} gr wa th}
do_test func-2.8 {
  execsql {SELECT t1 FROM tbl1 ORDER BY substr(t1,2,20)}
} {this software free program is}
do_test func-2.9 {
  execsql {SELECT substr(a,1,1) FROM t2}
} {1 {} 3 {} 6}
do_test func-2.10 {
  execsql {SELECT substr(a,2,2) FROM t2}
} {{} {} 45 {} 78}

# Only do the following tests if TCL has UTF-8 capabilities
#
if {"\u1234"!="u1234"} {

# Put some UTF-8 characters in the database
#
do_test func-3.0 {
  execsql {DELETE FROM tbl1}
  foreach word "contains UTF-8 characters hi\u1234ho" {
    execsql "INSERT INTO tbl1 VALUES('$word')"
  }
  execsql {SELECT t1 FROM tbl1 ORDER BY t1}
} "UTF-8 characters contains hi\u1234ho"
do_test func-3.1 {
  execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
} {5 10 8 5}
do_test func-3.2 {
  execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
} {UT ch co hi}
do_test func-3.3 {
  execsql {SELECT substr(t1,1,3) FROM tbl1 ORDER BY t1}
} "UTF cha con hi\u1234"
do_test func-3.4 {
  execsql {SELECT substr(t1,2,2) FROM tbl1 ORDER BY t1}
} "TF ha on i\u1234"
do_test func-3.5 {
  execsql {SELECT substr(t1,2,3) FROM tbl1 ORDER BY t1}
} "TF- har ont i\u1234h"
do_test func-3.6 {
  execsql {SELECT substr(t1,3,2) FROM tbl1 ORDER BY t1}
} "F- ar nt \u1234h"
do_test func-3.7 {
  execsql {SELECT substr(t1,4,2) FROM tbl1 ORDER BY t1}
} "-8 ra ta ho"
do_test func-3.8 {
  execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
} "8 s s o"
do_test func-3.9 {
  execsql {SELECT substr(t1,-3,2) FROM tbl1 ORDER BY t1}
} "F- er in \u1234h"
do_test func-3.10 {
  execsql {SELECT substr(t1,-4,3) FROM tbl1 ORDER BY t1}
} "TF- ter ain i\u1234h"
do_test func-3.99 {
  execsql {DELETE FROM tbl1}
  foreach word {this program is free software} {
    execsql "INSERT INTO tbl1 VALUES('$word')"
  }
  execsql {SELECT t1 FROM tbl1}
} {this program is free software}

} ;# End \u1234!=u1234

# Test the abs() and round() functions.
#
do_test func-4.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 VALUES(2,1.2345678901234,-12345.67890);
    INSERT INTO t1 VALUES(3,-2,-5);
  }
  catchsql {SELECT abs(a,b) FROM t1}
} {1 {wrong number of arguments to function abs()}}
do_test func-4.2 {
  catchsql {SELECT abs() FROM t1}
} {1 {wrong number of arguments to function abs()}}
do_test func-4.3 {
  catchsql {SELECT abs(b) FROM t1 ORDER BY a}
} {0 {2 1.2345678901234 2}}
do_test func-4.4 {
  catchsql {SELECT abs(c) FROM t1 ORDER BY a}
} {0 {3 12345.6789 5}}
do_test func-4.4.1 {
  execsql {SELECT abs(a) FROM t2}
} {1 {} 345 {} 67890}
do_test func-4.4.2 {
  execsql {SELECT abs(t1) FROM tbl1}
} {0.0 0.0 0.0 0.0 0.0}

do_test func-4.5 {
  catchsql {SELECT round(a,b,c) FROM t1}
} {1 {wrong number of arguments to function round()}}
do_test func-4.6 {
  catchsql {SELECT round(b,2) FROM t1 ORDER BY b}
} {0 {-2.00 1.23 2.00}}
do_test func-4.7 {
  catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
} {0 {2 1 -2}}
do_test func-4.8 {
  catchsql {SELECT round(c) FROM t1 ORDER BY a}
} {0 {3 -12346 -5}}
do_test func-4.9 {
  catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
} {0 {3.0 -12345.68 -5.000}}
do_test func-4.10 {
  catchsql {SELECT 'x' || round(c,a) || 'y' FROM t1 ORDER BY a}
} {0 {x3.0y x-12345.68y x-5.000y}}
do_test func-4.11 {
  catchsql {SELECT round() FROM t1 ORDER BY a}
} {1 {wrong number of arguments to function round()}}
do_test func-4.12 {
  execsql {SELECT coalesce(round(a,2),'nil') FROM t2}
} {1.00 nil 345.00 nil 67890.00}
do_test func-4.13 {
  execsql {SELECT round(t1,2) FROM tbl1}
} {0.00 0.00 0.00 0.00 0.00}

# Test the upper() and lower() functions
#
do_test func-5.1 {
  execsql {SELECT upper(t1) FROM tbl1}
} {THIS PROGRAM IS FREE SOFTWARE}
do_test func-5.2 {
  execsql {SELECT lower(upper(t1)) FROM tbl1}
} {this program is free software}
do_test func-5.3 {
  execsql {SELECT upper(a), lower(a) FROM t2}
} {1 1 {} {} 345 345 {} {} 67890 67890}
do_test func-5.4 {
  catchsql {SELECT upper(a,5) FROM t2}
} {1 {wrong number of arguments to function upper()}}
do_test func-5.5 {
  catchsql {SELECT upper(*) FROM t2}
} {1 {wrong number of arguments to function upper()}}

# Test the coalesce() and nullif() functions
#
do_test func-6.1 {
  execsql {SELECT coalesce(a,'xyz') FROM t2}
} {1 xyz 345 xyz 67890}
do_test func-6.2 {
  execsql {SELECT coalesce(upper(a),'nil') FROM t2}
} {1 nil 345 nil 67890}
do_test func-6.3 {
  execsql {SELECT coalesce(nullif(1,1),'nil')}
} {nil}
do_test func-6.4 {
  execsql {SELECT coalesce(nullif(1,2),'nil')}
} {1}
do_test func-6.5 {
  execsql {SELECT coalesce(nullif(1,NULL),'nil')}
} {1}


# Test the last_insert_rowid() function
#
do_test func-7.1 {
  execsql {SELECT last_insert_rowid()}
} [db last_insert_rowid]

# Tests for aggregate functions and how they handle NULLs.
#
do_test func-8.1 {
  execsql {
    SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
  }
} {68236.0 3 22745.33 1 67890 5}
do_test func-8.2 {
  execsql {
    SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
  }
} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
do_test func-8.3 {
  execsql {
    CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
    SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
  }
} {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
do_test func-8.4 {
  execsql {
    SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
  }
} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}

# How do you test the random() function in a meaningful, deterministic way?
#
do_test func-9.1 {
  execsql {
    SELECT random() is not null;
  }
} {1}

# Use the "sqlite_register_test_function" TCL command which is part of
# the text fixture in order to verify correct operation of some of
# the user-defined SQL function APIs that are not used by the built-in
# functions.
#
db close
set ::DB [sqlite3 db test.db]
sqlite_register_test_function $::DB testfunc
do_test func-10.1 {
  catchsql {
    SELECT testfunc(NULL,NULL);
  }
} {1 {first argument should be one of: int int64 string double null value}}
do_test func-10.2 {
  execsql {
    SELECT testfunc(
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'int', 1234
    );
  }
} {1234}
do_test func-10.3 {
  execsql {
    SELECT testfunc(
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'string', NULL
    );
  }
} {{}}
do_test func-10.4 {
  execsql {
    SELECT testfunc(
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'double', 1.234
    );
  }
} {1.234}
do_test func-10.5 {
  execsql {
    SELECT testfunc(
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'int', 1234,
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'string', NULL,
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'double', 1.234,
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'int', 1234,
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'string', NULL,
     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
     'double', 1.234
    );
  }
} {1.234}

# Test the built-in sqlite_version(*) SQL function.
#
do_test func-11.1 {
  execsql {
    SELECT sqlite_version(*);
  }
} [sqlite3 -version]

# Test that destructors passed to sqlite3 by calls to sqlite3_result_text()
# etc. are called. These tests use two special user-defined functions
# (implemented in func.c) only available in test builds. 
#
# Function test_destructor() takes one argument and returns a copy of the
# text form of that argument. A destructor is associated with the return
# value. Function test_destructor_count() returns the number of outstanding
# destructor calls for values returned by test_destructor().
#
do_test func-12.1 {
  execsql {
    SELECT test_destructor('hello world'), test_destructor_count();
  }
} {{hello world} 1}
do_test func-12.2 {
  execsql {
    SELECT test_destructor_count();
  }
} {0}
do_test func-12.3 {
  execsql {
    SELECT test_destructor('hello')||' world', test_destructor_count();
  }
} {{hello world} 0}
do_test func-12.4 {
  execsql {
    SELECT test_destructor_count();
  }
} {0}
do_test func-12.5 {
  execsql {
    CREATE TABLE t4(x);
    INSERT INTO t4 VALUES(test_destructor('hello'));
    INSERT INTO t4 VALUES(test_destructor('world'));
    SELECT min(test_destructor(x)), max(test_destructor(x)) FROM t4;
  }
} {hello world}
do_test func-12.6 {
  execsql {
    SELECT test_destructor_count();
  }
} {0}
do_test func-12.7 {
  execsql {
    DROP TABLE t4;
  }
} {}

# Test that the auxdata API for scalar functions works. This test uses
# a special user-defined function only available in test builds,
# test_auxdata(). Function test_auxdata() takes any number of arguments.
do_test func-13.1 {
  execsql {
    SELECT test_auxdata('hello world');
  }
} {0}

do_test func-13.2 {
  execsql {
    CREATE TABLE t4(a, b);
    INSERT INTO t4 VALUES('abc', 'def');
    INSERT INTO t4 VALUES('ghi', 'jkl');
  }
} {}
do_test func-13.3 {
  execsql {
    SELECT test_auxdata('hello world') FROM t4;
  }
} {0 1}
do_test func-13.4 {
  execsql {
    SELECT test_auxdata('hello world', 123) FROM t4;
  }
} {{0 0} {1 1}}
do_test func-13.5 {
  execsql {
    SELECT test_auxdata('hello world', a) FROM t4;
  }
} {{0 0} {1 0}}
do_test func-13.6 {
  execsql {
    SELECT test_auxdata('hello'||'world', a) FROM t4;
  }
} {{0 0} {1 0}}

# Test that auxilary data is preserved between calls for SQL variables.
do_test func-13.7 {
  db close
  set DB [sqlite3 db test.db]
  set sql "SELECT test_auxdata( ? , a ) FROM t4;"
  set STMT [sqlite3_prepare $DB $sql -1 TAIL]
  sqlite3_bind_text $STMT 1 hello -1
  set res [list]
  while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
    lappend res [sqlite3_column_text $STMT 0]
  }
  lappend res [sqlite3_finalize $STMT]
} {{0 0} {1 0} SQLITE_OK}

# Make sure that a function with a very long name is rejected
do_test func-14.1 {
  catch {
    db function [string repeat X 254] {return "hello"}
  } 
} {0}
do_test func-14.2 {
  catch {
    db function [string repeat X 256] {return "hello"}
  }
} {1}

finish_test

--- NEW FILE: hook.test ---
# 2004 Jan 14
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# The focus of the tests in this file is the  following interface:
#
#      sqlite_commit_hook
#
# $Id: hook.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test hook-1.2 {
  db commit_hook
} {}


do_test hook-3.1 {
  set commit_cnt 0
  proc commit_hook {} {
    incr ::commit_cnt
    return 0
  }
  db commit_hook ::commit_hook
  db commit_hook
} {::commit_hook}
do_test hook-3.2 {
  set commit_cnt
} {0}
do_test hook-3.3 {
  execsql {
    CREATE TABLE t2(a,b);
  }
  set commit_cnt
} {1}
do_test hook-3.4 {
  execsql {
    INSERT INTO t2 VALUES(1,2);
    INSERT INTO t2 SELECT a+1, b+1 FROM t2;
    INSERT INTO t2 SELECT a+2, b+2 FROM t2;
  }
  set commit_cnt
} {4}
do_test hook-3.5 {
  set commit_cnt {}
  proc commit_hook {} {
    set ::commit_cnt [execsql {SELECT * FROM t2}]
    return 0
  }
  execsql {
    INSERT INTO t2 VALUES(5,6);
  }
  set commit_cnt
} {1 2 2 3 3 4 4 5 5 6}
do_test hook-3.6 {
  set commit_cnt {}
  proc commit_hook {} {
    set ::commit_cnt [execsql {SELECT * FROM t2}] 
    return 1
  }
  catchsql {
    INSERT INTO t2 VALUES(6,7);
  }
} {1 {constraint failed}}
do_test hook-3.7 {
  set ::commit_cnt
} {1 2 2 3 3 4 4 5 5 6 6 7}
do_test hook-3.8 {
  execsql {SELECT * FROM t2}
} {1 2 2 3 3 4 4 5 5 6}

# Test turnning off the commit hook
#
do_test hook-3.9 {
  db commit_hook {}
  set ::commit_cnt {}
  execsql {
    INSERT INTO t2 VALUES(7,8);
  }
  set ::commit_cnt
} {}

finish_test

--- NEW FILE: in.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the IN and BETWEEN operator.
#
# $Id: in.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Generate the test data we will need for the first squences of tests.
#
do_test in-1.0 {
  execsql {
    BEGIN;
    CREATE TABLE t1(a int, b int);
  }
  for {set i 1} {$i<=10} {incr i} {
    execsql "INSERT INTO t1 VALUES($i,[expr {int(pow(2,$i))}])"
  }
  execsql {
    COMMIT;
    SELECT count(*) FROM t1;
  }
} {10}

# Do basic testing of BETWEEN.
#
do_test in-1.1 {
  execsql {SELECT a FROM t1 WHERE b BETWEEN 10 AND 50 ORDER BY a}
} {4 5}
do_test in-1.2 {
  execsql {SELECT a FROM t1 WHERE b NOT BETWEEN 10 AND 50 ORDER BY a}
} {1 2 3 6 7 8 9 10}
do_test in-1.3 {
  execsql {SELECT a FROM t1 WHERE b BETWEEN a AND a*5 ORDER BY a}
} {1 2 3 4}
do_test in-1.4 {
  execsql {SELECT a FROM t1 WHERE b NOT BETWEEN a AND a*5 ORDER BY a}
} {5 6 7 8 9 10}
do_test in-1.6 {
  execsql {SELECT a FROM t1 WHERE b BETWEEN a AND a*5 OR b=512 ORDER BY a}
} {1 2 3 4 9}
do_test in-1.7 {
  execsql {SELECT a+ 100*(a BETWEEN 1 and 3) FROM t1 ORDER BY b}
} {101 102 103 4 5 6 7 8 9 10}


# Testing of the IN operator using static lists on the right-hand side.
#
do_test in-2.1 {
  execsql {SELECT a FROM t1 WHERE b IN (8,12,16,24,32) ORDER BY a}
} {3 4 5}
do_test in-2.2 {
  execsql {SELECT a FROM t1 WHERE b NOT IN (8,12,16,24,32) ORDER BY a}
} {1 2 6 7 8 9 10}
do_test in-2.3 {
  execsql {SELECT a FROM t1 WHERE b IN (8,12,16,24,32) OR b=512 ORDER BY a}
} {3 4 5 9}
do_test in-2.4 {
  execsql {SELECT a FROM t1 WHERE b NOT IN (8,12,16,24,32) OR b=512 ORDER BY a}
} {1 2 6 7 8 9 10}
do_test in-2.5 {
  execsql {SELECT a+100*(b IN (8,16,24)) FROM t1 ORDER BY b}
} {1 2 103 104 5 6 7 8 9 10}

do_test in-2.6 {
  set v [catch {execsql {SELECT a FROM t1 WHERE b IN (b+10,20)}} msg]
  lappend v $msg
} {1 {right-hand side of IN operator must be constant}}
do_test in-2.7 {
  set v [catch {execsql {SELECT a FROM t1 WHERE b IN (max(5,10,b),20)}} msg]
  lappend v $msg
} {1 {right-hand side of IN operator must be constant}}
do_test in-2.8 {
  execsql {SELECT a FROM t1 WHERE b IN (8*2,64/2) ORDER BY b}
} {4 5}
do_test in-2.9 {
  set v [catch {execsql {SELECT a FROM t1 WHERE b IN (max(5,10),20)}} msg]
  lappend v $msg
} {1 {right-hand side of IN operator must be constant}}
do_test in-2.10 {
  set v [catch {execsql {SELECT a FROM t1 WHERE min(0,b IN (a,30))}} msg]
  lappend v $msg
} {1 {right-hand side of IN operator must be constant}}
do_test in-2.11 {
  set v [catch {execsql {SELECT a FROM t1 WHERE c IN (10,20)}} msg]
  lappend v $msg
} {1 {no such column: c}}

# Testing the IN operator where the right-hand side is a SELECT
#
do_test in-3.1 {
  execsql {
    SELECT a FROM t1
    WHERE b IN (SELECT b FROM t1 WHERE a<5)
    ORDER BY a
  }
} {1 2 3 4}
do_test in-3.2 {
  execsql {
    SELECT a FROM t1
    WHERE b IN (SELECT b FROM t1 WHERE a<5) OR b==512
    ORDER BY a
  }
} {1 2 3 4 9}
do_test in-3.3 {
  execsql {
    SELECT a + 100*(b IN (SELECT b FROM t1 WHERE a<5)) FROM t1 ORDER BY b
  }
} {101 102 103 104 5 6 7 8 9 10}

# Make sure the UPDATE and DELETE commands work with IN-SELECT
#
do_test in-4.1 {
  execsql {
    UPDATE t1 SET b=b*2 
    WHERE b IN (SELECT b FROM t1 WHERE a>8)
  }
  execsql {SELECT b FROM t1 ORDER BY b}
} {2 4 8 16 32 64 128 256 1024 2048}
do_test in-4.2 {
  execsql {
    DELETE FROM t1 WHERE b IN (SELECT b FROM t1 WHERE a>8)
  }
  execsql {SELECT a FROM t1 ORDER BY a}
} {1 2 3 4 5 6 7 8}
do_test in-4.3 {
  execsql {
    DELETE FROM t1 WHERE b NOT IN (SELECT b FROM t1 WHERE a>4)
  }
  execsql {SELECT a FROM t1 ORDER BY a}
} {5 6 7 8}

# Do an IN with a constant RHS but where the RHS has many, many
# elements.  We need to test that collisions in the hash table
# are resolved properly.
#
do_test in-5.1 {
  execsql {
    INSERT INTO t1 VALUES('hello', 'world');
    SELECT * FROM t1
    WHERE a IN (
       'Do','an','IN','with','a','constant','RHS','but','where','the',
       'has','many','elements','We','need','to','test','that',
       'collisions','hash','table','are','resolved','properly',
       'This','in-set','contains','thirty','one','entries','hello');
  }
} {hello world}

# Make sure the IN operator works with INTEGER PRIMARY KEY fields.
#
do_test in-6.1 {
  execsql {
    CREATE TABLE ta(a INTEGER PRIMARY KEY, b);
    INSERT INTO ta VALUES(1,1);
    INSERT INTO ta VALUES(2,2);
    INSERT INTO ta VALUES(3,3);
    INSERT INTO ta VALUES(4,4);
    INSERT INTO ta VALUES(6,6);
    INSERT INTO ta VALUES(8,8);
    INSERT INTO ta VALUES(10,
       'This is a key that is long enough to require a malloc in the VDBE');
    SELECT * FROM ta WHERE a<10;
  }
} {1 1 2 2 3 3 4 4 6 6 8 8}
do_test in-6.2 {
  execsql {
    CREATE TABLE tb(a INTEGER PRIMARY KEY, b);
    INSERT INTO tb VALUES(1,1);
    INSERT INTO tb VALUES(2,2);
    INSERT INTO tb VALUES(3,3);
    INSERT INTO tb VALUES(5,5);
    INSERT INTO tb VALUES(7,7);
    INSERT INTO tb VALUES(9,9);
    INSERT INTO tb VALUES(11,
       'This is a key that is long enough to require a malloc in the VDBE');
    SELECT * FROM tb WHERE a<10;
  }
} {1 1 2 2 3 3 5 5 7 7 9 9}
do_test in-6.3 {
  execsql {
    SELECT a FROM ta WHERE b IN (SELECT a FROM tb);
  }
} {1 2 3}
do_test in-6.4 {
  execsql {
    SELECT a FROM ta WHERE b NOT IN (SELECT a FROM tb);
  }
} {4 6 8 10}
do_test in-6.5 {
  execsql {
    SELECT a FROM ta WHERE b IN (SELECT b FROM tb);
  }
} {1 2 3 10}
do_test in-6.6 {
  execsql {
    SELECT a FROM ta WHERE b NOT IN (SELECT b FROM tb);
  }
} {4 6 8}
do_test in-6.7 {
  execsql {
    SELECT a FROM ta WHERE a IN (SELECT a FROM tb);
  }
} {1 2 3}
do_test in-6.8 {
  execsql {
    SELECT a FROM ta WHERE a NOT IN (SELECT a FROM tb);
  }
} {4 6 8 10}
do_test in-6.9 {
  execsql {
    SELECT a FROM ta WHERE a IN (SELECT b FROM tb);
  }
} {1 2 3}
do_test in-6.10 {
  execsql {
    SELECT a FROM ta WHERE a NOT IN (SELECT b FROM tb);
  }
} {4 6 8 10}

# Tests of IN operator against empty sets.  (Ticket #185)
#
do_test in-7.1 {
  execsql {
    SELECT a FROM t1 WHERE a IN ();
  }
} {}
do_test in-7.2 {
  execsql {
    SELECT a FROM t1 WHERE a IN (5);
  }
} {5}
do_test in-7.3 {
  execsql {
    SELECT a FROM t1 WHERE a NOT IN () ORDER BY a;
  }
} {5 6 7 8 hello}
do_test in-7.4 {
  execsql {
    SELECT a FROM t1 WHERE a IN (5) AND b IN ();
  }
} {}
do_test in-7.5 {
  execsql {
    SELECT a FROM t1 WHERE a IN (5) AND b NOT IN ();
  }
} {5}
do_test in-7.6 {
  execsql {
    SELECT a FROM ta WHERE a IN ();
  }
} {}
do_test in-7.7 {
  execsql {
    SELECT a FROM ta WHERE a NOT IN ();
  }
} {1 2 3 4 6 8 10}

do_test in-8.1 {
  execsql {
    SELECT b FROM t1 WHERE a IN ('hello','there')
  }
} {world}
do_test in-8.2 {
  execsql {
    SELECT b FROM t1 WHERE a IN ("hello",'there')
  }
} {world}

# Test constructs of the form:  expr IN tablename
#
do_test in-9.1 {
  execsql {
    CREATE TABLE t4 AS SELECT a FROM tb;
    SELECT * FROM t4;    
  }
} {1 2 3 5 7 9 11}
do_test in-9.2 {
  execsql {
    SELECT b FROM t1 WHERE a IN t4;
  }
} {32 128}
do_test in-9.3 {
  execsql {
    SELECT b FROM t1 WHERE a NOT IN t4;
  }
} {64 256 world}
do_test in-9.4 {
  catchsql {
    SELECT b FROM t1 WHERE a NOT IN tb;
  }
} {1 {only a single result allowed for a SELECT that is part of an expression}}

finish_test

--- NEW FILE: index.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE INDEX statement.
#
# $Id: index.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a basic index and verify it is added to sqlite_master
#
do_test index-1.1 {
  execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
  execsql {CREATE INDEX index1 ON test1(f1)}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {index1 test1}
do_test index-1.1b {
  execsql {SELECT name, sql, tbl_name, type FROM sqlite_master 
           WHERE name='index1'}
} {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
do_test index-1.1c {
  db close
  sqlite3 db test.db
  execsql {SELECT name, sql, tbl_name, type FROM sqlite_master 
           WHERE name='index1'}
} {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
do_test index-1.1d {
  db close
  sqlite3 db test.db
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {index1 test1}

# Verify that the index dies with the table
#
do_test index-1.2 {
  execsql {DROP TABLE test1}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {}

# Try adding an index to a table that does not exist
#
do_test index-2.1 {
  set v [catch {execsql {CREATE INDEX index1 ON test1(f1)}} msg]
  lappend v $msg
} {1 {no such table: main.test1}}

# Try adding an index on a column of a table where the table
# exists but the column does not.
#
do_test index-2.1 {
  execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
  set v [catch {execsql {CREATE INDEX index1 ON test1(f4)}} msg]
  lappend v $msg
} {1 {table test1 has no column named f4}}

# Try an index with some columns that match and others that do now.
#
do_test index-2.2 {
  set v [catch {execsql {CREATE INDEX index1 ON test1(f1, f2, f4, f3)}} msg]
  execsql {DROP TABLE test1}
  lappend v $msg
} {1 {table test1 has no column named f4}}

# Try creating a bunch of indices on the same table
#
set r {}
for {set i 1} {$i<100} {incr i} {
  lappend r [format index%02d $i]
}
do_test index-3.1 {
  execsql {CREATE TABLE test1(f1 int, f2 int, f3 int, f4 int, f5 int)}
  for {set i 1} {$i<100} {incr i} {
    set sql "CREATE INDEX [format index%02d $i] ON test1(f[expr {($i%5)+1}])"
    execsql $sql
  }
  execsql {SELECT name FROM sqlite_master 
           WHERE type='index' AND tbl_name='test1'
           ORDER BY name}
} $r


# Verify that all the indices go away when we drop the table.
#
do_test index-3.3 {
  execsql {DROP TABLE test1}
  execsql {SELECT name FROM sqlite_master 
           WHERE type='index' AND tbl_name='test1'
           ORDER BY name}
} {}

# Create a table and insert values into that table.  Then create
# an index on that table.  Verify that we can select values
# from the table correctly using the index.
#
# Note that the index names "index9" and "indext" are chosen because
# they both have the same hash.
#
do_test index-4.1 {
  execsql {CREATE TABLE test1(cnt int, power int)}
  for {set i 1} {$i<20} {incr i} {
    execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
  }
  execsql {CREATE INDEX index9 ON test1(cnt)}
  execsql {CREATE INDEX indext ON test1(power)}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {index9 indext test1}
do_test index-4.2 {
  execsql {SELECT cnt FROM test1 WHERE power=4}
} {2}
do_test index-4.3 {
  execsql {SELECT cnt FROM test1 WHERE power=1024}
} {10}
do_test index-4.4 {
  execsql {SELECT power FROM test1 WHERE cnt=6}
} {64}
do_test index-4.5 {
  execsql {DROP INDEX indext}
  execsql {SELECT power FROM test1 WHERE cnt=6}
} {64}
do_test index-4.6 {
  execsql {SELECT cnt FROM test1 WHERE power=1024}
} {10}
do_test index-4.7 {
  execsql {CREATE INDEX indext ON test1(cnt)}
  execsql {SELECT power FROM test1 WHERE cnt=6}
} {64}
do_test index-4.8 {
  execsql {SELECT cnt FROM test1 WHERE power=1024}
} {10}
do_test index-4.9 {
  execsql {DROP INDEX index9}
  execsql {SELECT power FROM test1 WHERE cnt=6}
} {64}
do_test index-4.10 {
  execsql {SELECT cnt FROM test1 WHERE power=1024}
} {10}
do_test index-4.11 {
  execsql {DROP INDEX indext}
  execsql {SELECT power FROM test1 WHERE cnt=6}
} {64}
do_test index-4.12 {
  execsql {SELECT cnt FROM test1 WHERE power=1024}
} {10}
do_test index-4.13 {
  execsql {DROP TABLE test1}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {}
integrity_check index-4.14

# Do not allow indices to be added to sqlite_master
#
do_test index-5.1 {
  set v [catch {execsql {CREATE INDEX index1 ON sqlite_master(name)}} msg]
  lappend v $msg
} {1 {table sqlite_master may not be indexed}}
do_test index-5.2 {
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Do not allow indices with duplicate names to be added
#
do_test index-6.1 {
  execsql {CREATE TABLE test1(f1 int, f2 int)}
  execsql {CREATE TABLE test2(g1 real, g2 real)}
  execsql {CREATE INDEX index1 ON test1(f1)}
  set v [catch {execsql {CREATE INDEX index1 ON test2(g1)}} msg]
  lappend v $msg
} {1 {index index1 already exists}}
do_test index-6.1b {
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {index1 test1 test2}
do_test index-6.2 {
  set v [catch {execsql {CREATE INDEX test1 ON test2(g1)}} msg]
  lappend v $msg
} {1 {there is already a table named test1}}
do_test index-6.2b {
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {index1 test1 test2}
do_test index-6.3 {
  execsql {DROP TABLE test1}
  execsql {DROP TABLE test2}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {}
do_test index-6.4 {
  execsql {
    CREATE TABLE test1(a,b);
    CREATE INDEX index1 ON test1(a);
    CREATE INDEX index2 ON test1(b);
    CREATE INDEX index3 ON test1(a,b);
    DROP TABLE test1;
    SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name;
  }
} {}
integrity_check index-6.5


# Create a primary key
#
do_test index-7.1 {
  execsql {CREATE TABLE test1(f1 int, f2 int primary key)}
  for {set i 1} {$i<20} {incr i} {
    execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
  }
  execsql {SELECT count(*) FROM test1}
} {19}
do_test index-7.2 {
  execsql {SELECT f1 FROM test1 WHERE f2=65536}
} {16}
do_test index-7.3 {
  execsql {
    SELECT name FROM sqlite_master 
    WHERE type='index' AND tbl_name='test1'
  }
} {sqlite_autoindex_test1_1}
do_test index-7.4 {
  execsql {DROP table test1}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}
integrity_check index-7.5

# Make sure we cannot drop a non-existant index.
#
do_test index-8.1 {
  set v [catch {execsql {DROP INDEX index1}} msg]
  lappend v $msg
} {1 {no such index: index1}}

# Make sure we don't actually create an index when the EXPLAIN keyword
# is used.
#
do_test index-9.1 {
  execsql {CREATE TABLE tab1(a int)}
  execsql {EXPLAIN CREATE INDEX idx1 ON tab1(a)}
  execsql {SELECT name FROM sqlite_master WHERE tbl_name='tab1'}
} {tab1}
do_test index-9.2 {
  execsql {CREATE INDEX idx1 ON tab1(a)}
  execsql {SELECT name FROM sqlite_master WHERE tbl_name='tab1' ORDER BY name}
} {idx1 tab1}
integrity_check index-9.3

# Allow more than one entry with the same key.
#
do_test index-10.0 {
  execsql {
    CREATE TABLE t1(a int, b int);
    CREATE INDEX i1 ON t1(a);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(2,4);
    INSERT INTO t1 VALUES(3,8);
    INSERT INTO t1 VALUES(1,12);
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {2 12}
do_test index-10.1 {
  execsql {
    SELECT b FROM t1 WHERE a=2 ORDER BY b;
  }
} {4}
do_test index-10.2 {
  execsql {
    DELETE FROM t1 WHERE b=12;
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {2}
do_test index-10.3 {
  execsql {
    DELETE FROM t1 WHERE b=2;
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {}
do_test index-10.4 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES (1,1);
    INSERT INTO t1 VALUES (1,2);
    INSERT INTO t1 VALUES (1,3);
    INSERT INTO t1 VALUES (1,4);
    INSERT INTO t1 VALUES (1,5);
    INSERT INTO t1 VALUES (1,6);
    INSERT INTO t1 VALUES (1,7);
    INSERT INTO t1 VALUES (1,8);
    INSERT INTO t1 VALUES (1,9);
    INSERT INTO t1 VALUES (2,0);
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {1 2 3 4 5 6 7 8 9}
do_test index-10.5 {
  execsql {
    DELETE FROM t1 WHERE b IN (2, 4, 6, 8);
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {1 3 5 7 9}
do_test index-10.6 {
  execsql {
    DELETE FROM t1 WHERE b>2;
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {1}
do_test index-10.7 {
  execsql {
    DELETE FROM t1 WHERE b=1;
    SELECT b FROM t1 WHERE a=1 ORDER BY b;
  }
} {}
do_test index-10.8 {
  execsql {
    SELECT b FROM t1 ORDER BY b;
  }
} {0}
integrity_check index-10.9

# Automatically create an index when we specify a primary key.
#
do_test index-11.1 {
  execsql {
    CREATE TABLE t3(
      a text,
      b int,
      c float,
      PRIMARY KEY(b)
    );
  }
  for {set i 1} {$i<=50} {incr i} {
    execsql "INSERT INTO t3 VALUES('x${i}x',$i,0.$i)"
  }
  set sqlite_search_count 0
  concat [execsql {SELECT c FROM t3 WHERE b==10}] $sqlite_search_count
} {0.1 3}
integrity_check index-11.2


# Numeric strings should compare as if they were numbers.  So even if the
# strings are not character-by-character the same, if they represent the
# same number they should compare equal to one another.  Verify that this
# is true in indices.
#
# Updated for sqlite3 v3: SQLite will now store these values as numbers
# (because the affinity of column a is NUMERIC) so the quirky
# representations are not retained. i.e. '+1.0' becomes '1'.
do_test index-12.1 {
  execsql {
    CREATE TABLE t4(a NUM,b);
    INSERT INTO t4 VALUES('0.0',1);
    INSERT INTO t4 VALUES('0.00',2);
    INSERT INTO t4 VALUES('abc',3);
    INSERT INTO t4 VALUES('-1.0',4);
    INSERT INTO t4 VALUES('+1.0',5);
    INSERT INTO t4 VALUES('0',6);
    INSERT INTO t4 VALUES('00000',7);
    SELECT a FROM t4 ORDER BY b;
  }
} {0.0 0.0 abc -1.0 1.0 0 0}
do_test index-12.2 {
  execsql {
    SELECT a FROM t4 WHERE a==0 ORDER BY b
  }
} {0.0 0.0 0 0}
do_test index-12.3 {
  execsql {
    SELECT a FROM t4 WHERE a<0.5 ORDER BY b
  }
} {0.0 0.0 -1.0 0 0}
do_test index-12.4 {
  execsql {
    SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
  }
} {0.0 0.0 abc 1.0 0 0}
do_test index-12.5 {
  execsql {
    CREATE INDEX t4i1 ON t4(a);
    SELECT a FROM t4 WHERE a==0 ORDER BY b
  }
} {0.0 0.0 0 0}
do_test index-12.6 {
  execsql {
    SELECT a FROM t4 WHERE a<0.5 ORDER BY b
  }
} {0.0 0.0 -1.0 0 0}
do_test index-12.7 {
  execsql {
    SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
  }
} {0.0 0.0 abc 1.0 0 0}
integrity_check index-12.8

# Make sure we cannot drop an automatically created index.
#
do_test index-13.1 {
  execsql {
   CREATE TABLE t5(
      a int UNIQUE,
      b float PRIMARY KEY,
      c varchar(10),
      UNIQUE(a,c)
   );
   INSERT INTO t5 VALUES(1,2,3);
   SELECT * FROM t5;
  }
} {1 2 3}
do_test index-13.2 {
  set ::idxlist [execsql {
    SELECT name FROM sqlite_master WHERE type="index" AND tbl_name="t5";
  }]
  llength $::idxlist
} {3}
for {set i 0} {$i<[llength $::idxlist]} {incr i} {
  do_test index-13.3.$i {
    catchsql "
      DROP INDEX '[lindex $::idxlist $i]';
    "
  } {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}}
}
do_test index-13.4 {
  execsql {
    INSERT INTO t5 VALUES('a','b','c');
    SELECT * FROM t5;
  }
} {1 2 3 a b c}
integrity_check index-13.5

# Check the sort order of data in an index.
#
do_test index-14.1 {
  execsql {
    CREATE TABLE t6(a,b,c);
    CREATE INDEX t6i1 ON t6(a,b);
    INSERT INTO t6 VALUES('','',1);
    INSERT INTO t6 VALUES('',NULL,2);
    INSERT INTO t6 VALUES(NULL,'',3);
    INSERT INTO t6 VALUES('abc',123,4);
    INSERT INTO t6 VALUES(123,'abc',5);
    SELECT c FROM t6 ORDER BY a,b;
  }
} {3 5 2 1 4}
do_test index-14.2 {
  execsql {
    SELECT c FROM t6 WHERE a='';
  }
} {2 1}
do_test index-14.3 {
  execsql {
    SELECT c FROM t6 WHERE b='';
  }
} {1 3}
do_test index-14.4 {
  execsql {
    SELECT c FROM t6 WHERE a>'';
  }
} {4}
do_test index-14.5 {
  execsql {
    SELECT c FROM t6 WHERE a>='';
  }
} {2 1 4}
do_test index-14.6 {
  execsql {
    SELECT c FROM t6 WHERE a>123;
  }
} {2 1 4}
do_test index-14.7 {
  execsql {
    SELECT c FROM t6 WHERE a>=123;
  }
} {5 2 1 4}
do_test index-14.8 {
  execsql {
    SELECT c FROM t6 WHERE a<'abc';
  }
} {5 2 1}
do_test index-14.9 {
  execsql {
    SELECT c FROM t6 WHERE a<='abc';
  }
} {5 2 1 4}
do_test index-14.10 {
  execsql {
    SELECT c FROM t6 WHERE a<='';
  }
} {5 2 1}
do_test index-14.11 {
  execsql {
    SELECT c FROM t6 WHERE a<'';
  }
} {5}
integrity_check index-14.12

do_test index-15.1 {
  execsql {
    DELETE FROM t1;
    SELECT * FROM t1;
  }
} {}
do_test index-15.2 {
  execsql {
    INSERT INTO t1 VALUES('1.234e5',1);
    INSERT INTO t1 VALUES('12.33e04',2);
    INSERT INTO t1 VALUES('12.35E4',3);
    INSERT INTO t1 VALUES('12.34e',4);
    INSERT INTO t1 VALUES('12.32e+4',5);
    INSERT INTO t1 VALUES('12.36E+04',6);
    INSERT INTO t1 VALUES('12.36E+',7);
    INSERT INTO t1 VALUES('+123.10000E+0003',8);
    INSERT INTO t1 VALUES('+',9);
    INSERT INTO t1 VALUES('+12347.E+02',10);
    INSERT INTO t1 VALUES('+12347E+02',11);
    SELECT b FROM t1 ORDER BY a;
  }
} {8 5 2 1 3 6 11 9 10 4 7}
integrity_check index-15.1

# The following tests - index-16.* - test that when a table definition
# includes qualifications that specify the same constraint twice only a
# single index is generated to enforce the constraint.
#
# For example: "CREATE TABLE abc( x PRIMARY KEY, UNIQUE(x) );"
#
do_test index-16.1 {
  execsql {
    CREATE TABLE t7(c UNIQUE PRIMARY KEY);
    SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index';
  }
} {1}
do_test index-16.2 {
  execsql {
    DROP TABLE t7;
    CREATE TABLE t7(c UNIQUE PRIMARY KEY);
    SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index';
  }
} {1}
do_test index-16.3 {
  execsql {
    DROP TABLE t7;
    CREATE TABLE t7(c PRIMARY KEY, UNIQUE(c) );
    SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index';
  }
} {1}
do_test index-16.4 {
  execsql {
    DROP TABLE t7;
    CREATE TABLE t7(c, d , UNIQUE(c, d), PRIMARY KEY(c, d) );
    SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index';
  }
} {1}
do_test index-16.5 {
  execsql {
    DROP TABLE t7;
    CREATE TABLE t7(c, d , UNIQUE(c), PRIMARY KEY(c, d) );
    SELECT count(*) FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index';
  }
} {2}

# Test that automatically create indices are named correctly. The current
# convention is: "sqlite_autoindex_<table name>_<integer>"
#
# Then check that it is an error to try to drop any automtically created
# indices.
do_test index-17.1 {
  execsql {
    DROP TABLE t7;
    CREATE TABLE t7(c, d UNIQUE, UNIQUE(c), PRIMARY KEY(c, d) );
    SELECT name FROM sqlite_master WHERE tbl_name = 't7' AND type = 'index';
  }
} {sqlite_autoindex_t7_1 sqlite_autoindex_t7_2 sqlite_autoindex_t7_3}
do_test index-17.2 {
  catchsql {
    DROP INDEX sqlite_autoindex_t7_1;
  }
} {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}}

# The following tests ensure that it is not possible to explicitly name
# a schema object with a name beginning with "sqlite_". Granted that is a
# little outside the focus of this test scripts, but this has got to be
# tested somewhere.
do_test index-18.1 {
  catchsql {
    CREATE TABLE sqlite_t1(a, b, c);
  }
} {1 {object name reserved for internal use: sqlite_t1}}
do_test index-18.2 {
  catchsql {
    CREATE INDEX sqlite_i1 ON t7(c);
  }
} {1 {object name reserved for internal use: sqlite_i1}}
do_test index-18.3 {
  catchsql {
    CREATE VIEW sqlite_v1 AS SELECT * FROM t7;
  }
} {1 {object name reserved for internal use: sqlite_v1}}
do_test index-18.4 {
  catchsql {
    CREATE TRIGGER sqlite_tr1 BEFORE INSERT ON t7 BEGIN SELECT 1; END;
  }
} {1 {object name reserved for internal use: sqlite_tr1}}
do_test index-18.5 {
  execsql {
    DROP TABLE t7;
  }
} {}

# These tests ensure that if multiple table definition constraints are
# implemented by a single indice, the correct ON CONFLICT policy applies.
do_test index-19.1 {
  execsql {
    CREATE TABLE t7(a UNIQUE PRIMARY KEY);
    CREATE TABLE t8(a UNIQUE PRIMARY KEY ON CONFLICT ROLLBACK);
    INSERT INTO t7 VALUES(1);
    INSERT INTO t8 VALUES(1);
  }
} {}
do_test index-19.2 {
  catchsql {
    BEGIN;
    INSERT INTO t7 VALUES(1);
  }
} {1 {column a is not unique}}
do_test index-19.3 {
  catchsql {
    BEGIN;
  }
} {1 {cannot start a transaction within a transaction}}
do_test index-19.4 {
  catchsql {
    INSERT INTO t8 VALUES(1);
  }
} {1 {column a is not unique}}
do_test index-19.5 {
  catchsql {
    BEGIN;
    COMMIT;
  }
} {0 {}}
do_test index-19.6 {
  catchsql {
    DROP TABLE t7;
    DROP TABLE t8;
    CREATE TABLE t7(
       a PRIMARY KEY ON CONFLICT FAIL, 
       UNIQUE(a) ON CONFLICT IGNORE
    );
  }
} {1 {conflicting ON CONFLICT clauses specified}}

# Drop index with a quoted name.  Ticket #695.
#
do_test index-20.1 {
  execsql {
    CREATE INDEX "t6i2" ON t6(c);
    DROP INDEX "t6i2";
  }
} {}
do_test index-20.2 {
  execsql {
    DROP INDEX "t6i1";
  }
} {}
   

finish_test

--- NEW FILE: insert.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the INSERT statement.
#
# $Id: insert.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to insert into a non-existant table.
#
do_test insert-1.1 {
  set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3)}} msg]
  lappend v $msg
} {1 {no such table: test1}}

# Try to insert into sqlite_master
#
do_test insert-1.2 {
  set v [catch {execsql {INSERT INTO sqlite_master VALUES(1,2,3,4)}} msg]
  lappend v $msg
} {1 {table sqlite_master may not be modified}}

# Try to insert the wrong number of entries.
#
do_test insert-1.3 {
  execsql {CREATE TABLE test1(one int, two int, three int)}
  set v [catch {execsql {INSERT INTO test1 VALUES(1,2)}} msg]
  lappend v $msg
} {1 {table test1 has 3 columns but 2 values were supplied}}
do_test insert-1.3b {
  set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3,4)}} msg]
  lappend v $msg
} {1 {table test1 has 3 columns but 4 values were supplied}}
do_test insert-1.3c {
  set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1,2,3,4)}} msg]
  lappend v $msg
} {1 {4 values for 2 columns}}
do_test insert-1.3d {
  set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1)}} msg]
  lappend v $msg
} {1 {1 values for 2 columns}}

# Try to insert into a non-existant column of a table.
#
do_test insert-1.4 {
  set v [catch {execsql {INSERT INTO test1(one,four) VALUES(1,2)}} msg]
  lappend v $msg
} {1 {table test1 has no column named four}}

# Make sure the inserts actually happen
#
do_test insert-1.5 {
  execsql {INSERT INTO test1 VALUES(1,2,3)}
  execsql {SELECT * FROM test1}
} {1 2 3}
do_test insert-1.5b {
  execsql {INSERT INTO test1 VALUES(4,5,6)}
  execsql {SELECT * FROM test1 ORDER BY one}
} {1 2 3 4 5 6}
do_test insert-1.5c {
  execsql {INSERT INTO test1 VALUES(7,8,9)}
  execsql {SELECT * FROM test1 ORDER BY one}
} {1 2 3 4 5 6 7 8 9}

do_test insert-1.6 {
  execsql {DELETE FROM test1}
  execsql {INSERT INTO test1(one,two) VALUES(1,2)}
  execsql {SELECT * FROM test1 ORDER BY one}
} {1 2 {}}
do_test insert-1.6b {
  execsql {INSERT INTO test1(two,three) VALUES(5,6)}
  execsql {SELECT * FROM test1 ORDER BY one}
} {{} 5 6 1 2 {}}
do_test insert-1.6c {
  execsql {INSERT INTO test1(three,one) VALUES(7,8)}
  execsql {SELECT * FROM test1 ORDER BY one}
} {{} 5 6 1 2 {} 8 {} 7}

# A table to use for testing default values
#
do_test insert-2.1 {
  execsql {
    CREATE TABLE test2(
      f1 int default -111, 
      f2 real default +4.32,
      f3 int default +222,
      f4 int default 7.89
    )
  }
  execsql {SELECT * from test2}
} {}
do_test insert-2.2 {
  execsql {INSERT INTO test2(f1,f3) VALUES(+10,-10)}
  execsql {SELECT * FROM test2}
} {10 4.32 -10 7.89}
do_test insert-2.3 {
  execsql {INSERT INTO test2(f2,f4) VALUES(1.23,-3.45)}
  execsql {SELECT * FROM test2 WHERE f1==-111}
} {-111 1.23 222 -3.45}
do_test insert-2.4 {
  execsql {INSERT INTO test2(f1,f2,f4) VALUES(77,+1.23,3.45)}
  execsql {SELECT * FROM test2 WHERE f1==77}
} {77 1.23 222 3.45}
do_test insert-2.10 {
  execsql {
    DROP TABLE test2;
    CREATE TABLE test2(
      f1 int default 111, 
      f2 real default -4.32,
      f3 text default hi,
      f4 text default 'abc-123',
      f5 varchar(10)
    )
  }
  execsql {SELECT * from test2}
} {}
do_test insert-2.11 {
  execsql {INSERT INTO test2(f2,f4) VALUES(-2.22,'hi!')}
  execsql {SELECT * FROM test2}
} {111 -2.22 hi hi! {}}
do_test insert-2.12 {
  execsql {INSERT INTO test2(f1,f5) VALUES(1,'xyzzy')}
  execsql {SELECT * FROM test2 ORDER BY f1}
} {1 -4.32 hi abc-123 xyzzy 111 -2.22 hi hi! {}}

# Do additional inserts with default values, but this time
# on a table that has indices.  In particular we want to verify
# that the correct default values are inserted into the indices.
#
do_test insert-3.1 {
  execsql {
    DELETE FROM test2;
    CREATE INDEX index9 ON test2(f1,f2);
    CREATE INDEX indext ON test2(f4,f5);
    SELECT * from test2;
  }
} {}

# Update for sqlite3 v3:
# Change the 111 to '111' in the following two test cases, because
# the default value is being inserted as a string. TODO: It shouldn't be.
do_test insert-3.2 {
  execsql {INSERT INTO test2(f2,f4) VALUES(-3.33,'hum')}
  execsql {SELECT * FROM test2 WHERE f1='111' AND f2=-3.33}
} {111 -3.33 hi hum {}}
do_test insert-3.3 {
  execsql {INSERT INTO test2(f1,f2,f5) VALUES(22,-4.44,'wham')}
  execsql {SELECT * FROM test2 WHERE f1='111' AND f2=-3.33}
} {111 -3.33 hi hum {}}
do_test insert-3.4 {
  execsql {SELECT * FROM test2 WHERE f1=22 AND f2=-4.44}
} {22 -4.44 hi abc-123 wham}
integrity_check insert-3.5

# Test of expressions in the VALUES clause
#
do_test insert-4.1 {
  execsql {
    CREATE TABLE t3(a,b,c);
    INSERT INTO t3 VALUES(1+2+3,4,5);
    SELECT * FROM t3;
  }
} {6 4 5}
do_test insert-4.2 {
  execsql {
    INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,5,6);
    SELECT * FROM t3 ORDER BY a;
  }
} {6 4 5 7 5 6}
do_test insert-4.3 {
  catchsql {
    INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,t3.a,6);
    SELECT * FROM t3 ORDER BY a;
  }
} {1 {no such column: t3.a}}
do_test insert-4.4 {
  execsql {
    INSERT INTO t3 VALUES((SELECT b FROM t3 WHERE a=0),6,7);
    SELECT * FROM t3 ORDER BY a;
  }
} {{} 6 7 6 4 5 7 5 6}
do_test insert-4.5 {
  execsql {
    SELECT b,c FROM t3 WHERE a IS NULL;
  }
} {6 7}
do_test insert-4.6 {
  catchsql {
    INSERT INTO t3 VALUES(notafunc(2,3),2,3);
  }
} {1 {no such function: notafunc}}
do_test insert-4.7 {
  execsql {
    INSERT INTO t3 VALUES(min(1,2,3),max(1,2,3),99);
    SELECT * FROM t3 WHERE c=99;
  }
} {1 3 99}

# Test the ability to insert from a temporary table into itself.
# Ticket #275.
#
do_test insert-5.1 {
  execsql {
    CREATE TEMP TABLE t4(x);
    INSERT INTO t4 VALUES(1);
    SELECT * FROM t4;
  }
} {1}
do_test insert-5.2 {
  execsql {
    INSERT INTO t4 SELECT x+1 FROM t4;
    SELECT * FROM t4;
  }
} {1 2}
do_test insert-5.3 {
  # verify that a temporary table is used to copy t4 to t4
  set x [execsql {
    EXPLAIN INSERT INTO t4 SELECT x+2 FROM t4;
  }]
  expr {[lsearch $x OpenTemp]>0}
} {1}

do_test insert-5.4 {
  # Verify that table "test1" begins on page 3.  This should be the same
  # page number used by "t4" above.
  #
  # Update for v3 - the first table now begins on page 2 of each file, not 3.
  execsql {
    SELECT rootpage FROM sqlite_master WHERE name='test1';
  }
} {2}
do_test insert-5.5 {
  # Verify that "t4" begins on page 3.
  #
  # Update for v3 - the first table now begins on page 2 of each file, not 3.
  execsql {
    SELECT rootpage FROM sqlite_temp_master WHERE name='t4';
  }
} {2}
do_test insert-5.6 {
  # This should not use an intermediate temporary table.
  execsql {
    INSERT INTO t4 SELECT one FROM test1 WHERE three=7;
    SELECT * FROM t4
  }
} {1 2 8}
do_test insert-5.7 {
  # verify that no temporary table is used to copy test1 to t4
  set x [execsql {
    EXPLAIN INSERT INTO t4 SELECT one FROM test1;
  }]
  expr {[lsearch $x OpenTemp]>0}
} {0}

# Ticket #334:  REPLACE statement corrupting indices.
#
do_test insert-6.1 {
  execsql {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(2,3);
    SELECT b FROM t1 WHERE b=2;
  }
} {2}
do_test insert-6.2 {
  execsql {
    REPLACE INTO t1 VALUES(1,4);
    SELECT b FROM t1 WHERE b=2;
  }
} {}
do_test insert-6.3 {
  execsql {
    UPDATE OR REPLACE t1 SET a=2 WHERE b=4;
    SELECT * FROM t1 WHERE b=4;
  }
} {2 4}
do_test insert-6.4 {
  execsql {
    SELECT * FROM t1 WHERE b=3;
  }
} {}

integrity_check insert-99.0

finish_test

--- NEW FILE: insert2.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the INSERT statement that takes is
# result from a SELECT.
#
# $Id: insert2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create some tables with data that we can select against
#
do_test insert2-1.0 {
  execsql {CREATE TABLE d1(n int, log int);}
  for {set i 1} {$i<=20} {incr i} {
    for {set j 0} {pow(2,$j)<$i} {incr j} {}
    execsql "INSERT INTO d1 VALUES($i,$j)"
  }
  execsql {SELECT * FROM d1 ORDER BY n}
} {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}

# Insert into a new table from the old one.
#
do_test insert2-1.1.1 {
  execsql {
    CREATE TABLE t1(log int, cnt int);
    PRAGMA count_changes=on;
    INSERT INTO t1 SELECT log, count(*) FROM d1 GROUP BY log;
  }
} {6}
do_test insert2-1.1.2 {
  db changes
} {6}
do_test insert2-1.1.3 {
  execsql {SELECT * FROM t1 ORDER BY log}
} {0 1 1 1 2 2 3 4 4 8 5 4}

do_test insert2-1.2.1 {
  catch {execsql {DROP TABLE t1}}
  execsql {
    CREATE TABLE t1(log int, cnt int);
    INSERT INTO t1 
       SELECT log, count(*) FROM d1 GROUP BY log
       EXCEPT SELECT n-1,log FROM d1;
  }
} {4}
do_test insert2-1.2.2 {
  execsql {
    SELECT * FROM t1 ORDER BY log;
  }
} {0 1 3 4 4 8 5 4}
do_test insert2-1.3.1 {
  catch {execsql {DROP TABLE t1}}
  execsql {
    CREATE TABLE t1(log int, cnt int);
    PRAGMA count_changes=off;
    INSERT INTO t1 
       SELECT log, count(*) FROM d1 GROUP BY log
       INTERSECT SELECT n-1,log FROM d1;
  }
} {}
do_test insert2-1.3.2 {
  execsql {
    SELECT * FROM t1 ORDER BY log;
  }
} {1 1 2 2}
do_test insert2-1.4 {
  catch {execsql {DROP TABLE t1}}
  set r [execsql {
    CREATE TABLE t1(log int, cnt int);
    CREATE INDEX i1 ON t1(log);
    CREATE INDEX i2 ON t1(cnt);
    INSERT INTO t1 SELECT log, count() FROM d1 GROUP BY log;
    SELECT * FROM t1 ORDER BY log;
  }]
  lappend r [execsql {SELECT cnt FROM t1 WHERE log=3}]
  lappend r [execsql {SELECT log FROM t1 WHERE cnt=4 ORDER BY log}]
} {0 1 1 1 2 2 3 4 4 8 5 4 4 {3 5}}

do_test insert2-2.0 {
  execsql {
    CREATE TABLE t3(a,b,c);
    CREATE TABLE t4(x,y);
    INSERT INTO t4 VALUES(1,2);
    SELECT * FROM t4;
  }
} {1 2}
do_test insert2-2.1 {
  execsql {
    INSERT INTO t3(a,c) SELECT * FROM t4;
    SELECT * FROM t3;
  }
} {1 {} 2}
do_test insert2-2.2 {
  execsql {
    DELETE FROM t3;
    INSERT INTO t3(c,b) SELECT * FROM t4;
    SELECT * FROM t3;
  }
} {{} 2 1}
do_test insert2-2.3 {
  execsql {
    DELETE FROM t3;
    INSERT INTO t3(c,a,b) SELECT x, 'hi', y FROM t4;
    SELECT * FROM t3;
  }
} {hi 2 1}

integrity_check insert2-3.0

# File table t4 with lots of data
#
do_test insert2-3.1 {
  execsql {
    SELECT * from t4;
  }
} {1 2}
do_test insert2-3.2 {
  set x [db total_changes]
  execsql {
    BEGIN;
    INSERT INTO t4 VALUES(2,4);
    INSERT INTO t4 VALUES(3,6);
    INSERT INTO t4 VALUES(4,8);
    INSERT INTO t4 VALUES(5,10);
    INSERT INTO t4 VALUES(6,12);
    INSERT INTO t4 VALUES(7,14);
    INSERT INTO t4 VALUES(8,16);
    INSERT INTO t4 VALUES(9,18);
    INSERT INTO t4 VALUES(10,20);
    COMMIT;
  }
  expr [db total_changes] - $x
} {9}
do_test insert2-3.2.1 {
  execsql {
    SELECT count(*) FROM t4;
  }
} {10}
do_test insert2-3.3 {
  execsql {
    BEGIN;
    INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
    INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
    INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
    INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
    COMMIT;
    SELECT count(*) FROM t4;
  }
} {160}
do_test insert2-3.4 {
  execsql {
    BEGIN;
    UPDATE t4 SET y='lots of data for the row where x=' || x
                     || ' and y=' || y || ' - even more data to fill space';
    COMMIT;
    SELECT count(*) FROM t4;
  }
} {160}
do_test insert2-3.5 {
  execsql {
    BEGIN;
    INSERT INTO t4 SELECT x+(SELECT max(x)+1 FROM t4),y FROM t4;
    SELECT count(*) from t4;
    ROLLBACK;
  }
} {320}
do_test insert2-3.6 {
  execsql {
    SELECT count(*) FROM t4;
  }
} {160}
do_test insert2-3.7 {
  execsql {
    BEGIN;
    DELETE FROM t4 WHERE x!=123;
    SELECT count(*) FROM t4;
    ROLLBACK;
  }
} {1}
do_test insert2-3.8 {
  db changes
} {159}
integrity_check insert2-3.9

# Ticket #901
#
do_test insert2-4.1 {
  execsql {
    CREATE TABLE Dependencies(depId integer primary key,
      class integer, name str, flag str);
    CREATE TEMPORARY TABLE DepCheck(troveId INT, depNum INT,
      flagCount INT, isProvides BOOL, class INTEGER, name STRING,
      flag STRING);
    INSERT INTO DepCheck 
       VALUES(-1, 0, 1, 0, 2, 'libc.so.6', 'GLIBC_2.0');
    INSERT INTO Dependencies 
       SELECT DISTINCT 
           NULL, 
           DepCheck.class, 
           DepCheck.name, 
           DepCheck.flag 
       FROM DepCheck LEFT OUTER JOIN Dependencies ON 
           DepCheck.class == Dependencies.class AND 
           DepCheck.name == Dependencies.name AND 
           DepCheck.flag == Dependencies.flag 
       WHERE 
           Dependencies.depId is NULL;
  };
} {}

finish_test

--- NEW FILE: interrupt.test ---
# 2004 Feb 8
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is the sqlite_interrupt() API.
#
# $Id: interrupt.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Compute a checksum on the entire database.
#
proc cksum {{db db}} {
  set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n
  foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
    append txt [$db eval "SELECT * FROM $tbl"]\n
  }
  foreach prag {default_synchronous default_cache_size} {
    append txt $prag-[$db eval "PRAGMA $prag"]\n
  }
  set cksum [string length $txt]-[md5 $txt]
  # puts $cksum-[file size test.db]
  return $cksum
}

# This routine attempts to execute the sql in $sql.  It triggers an
# interrupt a progressively later and later points during the processing
# and checks to make sure SQLITE_INTERRUPT is returned.  Eventually,
# the routine completes successfully.
#
proc interrupt_test {testid sql result {initcnt 0}} {
  set orig_sum [cksum]
  set i $initcnt
  while 1 {
    incr i
    set ::sqlite_interrupt_count $i
    do_test $testid.$i.1 [format {
      set ::r [catchsql %s]
      set ::code [db errorcode]
      expr {$::code==0 || $::code==9}
    } [list $sql]] 1
    if {$::code==9} {
      do_test $testid.$i.2 {
        cksum
      } $orig_sum
    } else {
      do_test $testid.$i.99 {
        set ::r
      } [list 0 $result]
      break
    }
  }
  set ::sqlite_interrupt_count 0
}

do_test interrupt-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    SELECT name FROM sqlite_master;
  }
} {t1}
interrupt_test interrupt-1.2 {DROP TABLE t1} {}
do_test interrupt-1.3 {
  execsql {
    SELECT name FROM sqlite_master;
  }
} {}
integrity_check interrupt-1.4

do_test interrrupt-2.1 {
  execsql {
    BEGIN;
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,randstr(300,400));
    INSERT INTO t1 SELECT a+1, randstr(300,400) FROM t1;
    INSERT INTO t1 SELECT a+2, a || '-' || b FROM t1;
    INSERT INTO t1 SELECT a+4, a || '-' || b FROM t1;
    INSERT INTO t1 SELECT a+8, a || '-' || b FROM t1;
    INSERT INTO t1 SELECT a+16, a || '-' || b FROM t1;
    INSERT INTO t1 SELECT a+32, a || '-' || b FROM t1;
    COMMIT;
    UPDATE t1 SET b=substr(b,-5,5);
    SELECT count(*) from t1;
  }
} 64
set origsize [file size test.db]
set cksum [db eval {SELECT md5sum(a || b) FROM t1}]
interrupt_test interrupt-2.2 {VACUUM} {} 100
do_test interrupt-2.3 {
  execsql {
    SELECT md5sum(a || b) FROM t1;
  }
} $cksum
do_test interrupt-2.4 {
  expr {$::origsize>[file size test.db]}
} 1
integrity_check interrupt-2.5

# Ticket #594.  If an interrupt occurs in the middle of a transaction
# and that transaction is later rolled back, the internal schema tables do
# not reset.
#
for {set i 1} {$i<50} {incr i 5} {
  do_test interrupt-3.$i.1 {
    execsql {
      BEGIN;
      CREATE TEMP TABLE t2(x,y);
      SELECT name FROM sqlite_temp_master;
    }
  } {t2}
  do_test interrupt-3.$i.2 {
    set ::sqlite_interrupt_count $::i
    catchsql {
      INSERT INTO t2 SELECT * FROM t1;
    }
  } {1 interrupted}
  do_test interrupt-3.$i.3 {
    execsql {
      SELECT name FROM sqlite_temp_master;
    }
  } {t2}
  do_test interrupt-3.$i.4 {
    catchsql {
      ROLLBACK
    }
  } {0 {}}
  do_test interrupt-3.$i.5 {
    catchsql {SELECT name FROM sqlite_temp_master};
    execsql {
      SELECT name FROM sqlite_temp_master;
    }
  } {}
}

# There are reports of a memory leak if an interrupt occurs during
# the beginning of a complex query - before the first callback.  We
# will try to reproduce it here:
#
execsql {
  CREATE TABLE t2(a,b,c);
  INSERT INTO t2 SELECT round(a/10), randstr(50,80), randstr(50,60) FROM t1;
}
set sql {
  SELECT max(min(b,c)), min(max(b,c)), a FROM t2 GROUP BY a ORDER BY a;
}
set sqlite_interrupt_count 1000000
execsql $sql
set max_count [expr {1000000-$sqlite_interrupt_count}]
for {set i 1} {$i<$max_count-5} {incr i 1} {
  do_test interrupt-4.$i.1 {
    set ::sqlite_interrupt_count $::i
    catchsql $sql
  } {1 interrupted}
}

finish_test

--- NEW FILE: intpkey.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the special processing associated
# with INTEGER PRIMARY KEY columns.
#
# $Id: intpkey.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table with a primary key and a datatype other than
# integer
#
do_test intpkey-1.0 {
  execsql {
    CREATE TABLE t1(a TEXT PRIMARY KEY, b, c);
  }
} {}

# There should be an index associated with the primary key
#
do_test intpkey-1.1 {
  execsql {
    SELECT name FROM sqlite_master
    WHERE type='index' AND tbl_name='t1';
  }
} {sqlite_autoindex_t1_1}

# Now create a table with an integer primary key and verify that
# there is no associated index.
#
do_test intpkey-1.2 {
  execsql {
    DROP TABLE t1;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
    SELECT name FROM sqlite_master
      WHERE type='index' AND tbl_name='t1';
  }
} {}

# Insert some records into the new table.  Specify the primary key
# and verify that the key is used as the record number.
#
do_test intpkey-1.3 {
  execsql {
    INSERT INTO t1 VALUES(5,'hello','world');
  }
  db last_insert_rowid
} {5}
do_test intpkey-1.4 {
  execsql {
    SELECT * FROM t1;
  }
} {5 hello world}
do_test intpkey-1.5 {
  execsql {
    SELECT rowid, * FROM t1;
  }
} {5 5 hello world}

# Attempting to insert a duplicate primary key should give a constraint
# failure.
#
do_test intpkey-1.6 {
  set r [catch {execsql {
     INSERT INTO t1 VALUES(5,'second','entry');
  }} msg]
  lappend r $msg
} {1 {PRIMARY KEY must be unique}}
do_test intpkey-1.7 {
  execsql {
    SELECT rowid, * FROM t1;
  }
} {5 5 hello world}
do_test intpkey-1.8 {
  set r [catch {execsql {
     INSERT INTO t1 VALUES(6,'second','entry');
  }} msg]
  lappend r $msg
} {0 {}}
do_test intpkey-1.8.1 {
  db last_insert_rowid
} {6}
do_test intpkey-1.9 {
  execsql {
    SELECT rowid, * FROM t1;
  }
} {5 5 hello world 6 6 second entry}

# A ROWID is automatically generated for new records that do not specify
# the integer primary key.
#
do_test intpkey-1.10 {
  execsql {
    INSERT INTO t1(b,c) VALUES('one','two');
    SELECT b FROM t1 ORDER BY b;
  }
} {hello one second}

# Try to change the ROWID for the new entry.
#
do_test intpkey-1.11 {
  execsql {
    UPDATE t1 SET a=4 WHERE b='one';
    SELECT * FROM t1;
  }
} {4 one two 5 hello world 6 second entry}

# Make sure SELECT statements are able to use the primary key column
# as an index.
#
do_test intpkey-1.12 {
  execsql {
    SELECT * FROM t1 WHERE a==4;
  }
} {4 one two}

# Try to insert a non-integer value into the primary key field.  This
# should result in a data type mismatch.
#
do_test intpkey-1.13.1 {
  set r [catch {execsql {
    INSERT INTO t1 VALUES('x','y','z');
  }} msg]
  lappend r $msg
} {1 {datatype mismatch}}
do_test intpkey-1.13.2 {
  set r [catch {execsql {
    INSERT INTO t1 VALUES('','y','z');
  }} msg]
  lappend r $msg
} {1 {datatype mismatch}}
do_test intpkey-1.14 {
  set r [catch {execsql {
    INSERT INTO t1 VALUES(3.4,'y','z');
  }} msg]
  lappend r $msg
} {1 {datatype mismatch}}
do_test intpkey-1.15 {
  set r [catch {execsql {
    INSERT INTO t1 VALUES(-3,'y','z');
  }} msg]
  lappend r $msg
} {0 {}}
do_test intpkey-1.16 {
  execsql {SELECT * FROM t1}
} {-3 y z 4 one two 5 hello world 6 second entry}

#### INDICES
# Check to make sure indices work correctly with integer primary keys
#
do_test intpkey-2.1 {
  execsql {
    CREATE INDEX i1 ON t1(b);
    SELECT * FROM t1 WHERE b=='y'
  }
} {-3 y z}
do_test intpkey-2.1.1 {
  execsql {
    SELECT * FROM t1 WHERE b=='y' AND rowid<0
  }
} {-3 y z}
do_test intpkey-2.1.2 {
  execsql {
    SELECT * FROM t1 WHERE b=='y' AND rowid<0 AND rowid>=-20
  }
} {-3 y z}
do_test intpkey-2.1.3 {
  execsql {
    SELECT * FROM t1 WHERE b>='y'
  }
} {-3 y z}
do_test intpkey-2.1.4 {
  execsql {
    SELECT * FROM t1 WHERE b>='y' AND rowid<10
  }
} {-3 y z}

do_test intpkey-2.2 {
  execsql {
    UPDATE t1 SET a=8 WHERE b=='y';
    SELECT * FROM t1 WHERE b=='y';
  }
} {8 y z}
do_test intpkey-2.3 {
  execsql {
    SELECT rowid, * FROM t1;
  }
} {4 4 one two 5 5 hello world 6 6 second entry 8 8 y z}
do_test intpkey-2.4 {
  execsql {
    SELECT rowid, * FROM t1 WHERE b<'second'
  }
} {5 5 hello world 4 4 one two}
do_test intpkey-2.4.1 {
  execsql {
    SELECT rowid, * FROM t1 WHERE 'second'>b
  }
} {5 5 hello world 4 4 one two}
do_test intpkey-2.4.2 {
  execsql {
    SELECT rowid, * FROM t1 WHERE 8>rowid AND 'second'>b
  }
} {4 4 one two 5 5 hello world}
do_test intpkey-2.4.3 {
  execsql {
    SELECT rowid, * FROM t1 WHERE 8>rowid AND 'second'>b AND 0<rowid
  }
} {4 4 one two 5 5 hello world}
do_test intpkey-2.5 {
  execsql {
    SELECT rowid, * FROM t1 WHERE b>'a'
  }
} {5 5 hello world 4 4 one two 6 6 second entry 8 8 y z}
do_test intpkey-2.6 {
  execsql {
    DELETE FROM t1 WHERE rowid=4;
    SELECT * FROM t1 WHERE b>'a';
  }
} {5 hello world 6 second entry 8 y z}
do_test intpkey-2.7 {
  execsql {
    UPDATE t1 SET a=-4 WHERE rowid=8;
    SELECT * FROM t1 WHERE b>'a';
  }
} {5 hello world 6 second entry -4 y z}
do_test intpkey-2.7 {
  execsql {
    SELECT * FROM t1
  }
} {-4 y z 5 hello world 6 second entry}

# Do an SQL statement.  Append the search count to the end of the result.
#
proc count sql {
  set ::sqlite_search_count 0
  return [concat [execsql $sql] $::sqlite_search_count]
}

# Create indices that include the integer primary key as one of their
# columns.
#
do_test intpkey-3.1 {
  execsql {
    CREATE INDEX i2 ON t1(a);
  }
} {}
do_test intpkey-3.2 {
  count {
    SELECT * FROM t1 WHERE a=5;
  }
} {5 hello world 0}
do_test intpkey-3.3 {
  count {
    SELECT * FROM t1 WHERE a>4 AND a<6;
  }
} {5 hello world 2}
do_test intpkey-3.4 {
  count {
    SELECT * FROM t1 WHERE b>='hello' AND b<'hello2';
  }
} {5 hello world 3}
do_test intpkey-3.5 {
  execsql {
    CREATE INDEX i3 ON t1(c,a);
  }
} {}
do_test intpkey-3.6 {
  count {
    SELECT * FROM t1 WHERE c=='world';
  }
} {5 hello world 3}
do_test intpkey-3.7 {
  execsql {INSERT INTO t1 VALUES(11,'hello','world')}
  count {
    SELECT * FROM t1 WHERE c=='world';
  }
} {5 hello world 11 hello world 5}
do_test intpkey-3.8 {
  count {
    SELECT * FROM t1 WHERE c=='world' AND a>7;
  }
} {11 hello world 5}
do_test intpkey-3.9 {
  count {
    SELECT * FROM t1 WHERE 7<a;
  }
} {11 hello world 1}

# Test inequality constraints on integer primary keys and rowids
#
do_test intpkey-4.1 {
  count {
    SELECT * FROM t1 WHERE 11=rowid
  }
} {11 hello world 0}
do_test intpkey-4.2 {
  count {
    SELECT * FROM t1 WHERE 11=rowid AND b=='hello'
  }
} {11 hello world 0}
do_test intpkey-4.3 {
  count {
    SELECT * FROM t1 WHERE 11=rowid AND b=='hello' AND c IS NOT NULL;
  }
} {11 hello world 0}
do_test intpkey-4.4 {
  count {
    SELECT * FROM t1 WHERE rowid==11
  }
} {11 hello world 0}
do_test intpkey-4.5 {
  count {
    SELECT * FROM t1 WHERE oid==11 AND b=='hello'
  }
} {11 hello world 0}
do_test intpkey-4.6 {
  count {
    SELECT * FROM t1 WHERE a==11 AND b=='hello' AND c IS NOT NULL;
  }
} {11 hello world 0}

do_test intpkey-4.7 {
  count {
    SELECT * FROM t1 WHERE 8<rowid;
  }
} {11 hello world 1}
do_test intpkey-4.8 {
  count {
    SELECT * FROM t1 WHERE 8<rowid AND 11>=oid;
  }
} {11 hello world 1}
do_test intpkey-4.9 {
  count {
    SELECT * FROM t1 WHERE 11<=_rowid_ AND 12>=a;
  }
} {11 hello world 1}
do_test intpkey-4.10 {
  count {
    SELECT * FROM t1 WHERE 0>=_rowid_;
  }
} {-4 y z 1}
do_test intpkey-4.11 {
  count {
    SELECT * FROM t1 WHERE a<0;
  }
} {-4 y z 1}
do_test intpkey-4.12 {
  count {
    SELECT * FROM t1 WHERE a<0 AND a>10;
  }
} {1}

# Make sure it is OK to insert a rowid of 0
#
do_test intpkey-5.1 {
  execsql {
    INSERT INTO t1 VALUES(0,'zero','entry');
  }
  count {
    SELECT * FROM t1 WHERE a=0;
  }
} {0 zero entry 0}
do_test intpkey=5.2 {
  execsql {
    SELECT rowid, a FROM t1
  }
} {-4 -4 0 0 5 5 6 6 11 11}

# Test the ability of the COPY command to put data into a
# table that contains an integer primary key.
#
# COPY command has been removed.  But we retain these tests so
# that the tables will contain the right data for tests that follow.
#
do_test intpkey-6.1 {
  execsql {
    BEGIN;
    INSERT INTO t1 VALUES(20,'b-20','c-20');
    INSERT INTO t1 VALUES(21,'b-21','c-21');
    INSERT INTO t1 VALUES(22,'b-22','c-22');
    COMMIT;
    SELECT * FROM t1 WHERE a>=20;
  }
} {20 b-20 c-20 21 b-21 c-21 22 b-22 c-22}
do_test intpkey-6.2 {
  execsql {
    SELECT * FROM t1 WHERE b=='hello'
  }
} {5 hello world 11 hello world}
do_test intpkey-6.3 {
  execsql {
    DELETE FROM t1 WHERE b='b-21';
    SELECT * FROM t1 WHERE b=='b-21';
  }
} {}
do_test intpkey-6.4 {
  execsql {
    SELECT * FROM t1 WHERE a>=20
  }
} {20 b-20 c-20 22 b-22 c-22}

# Do an insert of values with the columns specified out of order.
#
do_test intpkey-7.1 {
  execsql {
    INSERT INTO t1(c,b,a) VALUES('row','new',30);
    SELECT * FROM t1 WHERE rowid>=30;
  }
} {30 new row}
do_test intpkey-7.2 {
  execsql {
    SELECT * FROM t1 WHERE rowid>20;
  }
} {22 b-22 c-22 30 new row}

# Do an insert from a select statement.
#
do_test intpkey-8.1 {
  execsql {
    CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z);
    INSERT INTO t2 SELECT * FROM t1;
    SELECT rowid FROM t2;
  }
} {-4 0 5 6 11 20 22 30}
do_test intpkey-8.2 {
  execsql {
    SELECT x FROM t2;
  }
} {-4 0 5 6 11 20 22 30}

do_test intpkey-9.1 {
  execsql {
    UPDATE t1 SET c='www' WHERE c='world';
    SELECT rowid, a, c FROM t1 WHERE c=='www';
  }
} {5 5 www 11 11 www}


# Check insert of NULL for primary key
#
do_test intpkey-10.1 {
  execsql {
    DROP TABLE t2;
    CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z);
    INSERT INTO t2 VALUES(NULL, 1, 2);
    SELECT * from t2;
  }
} {1 1 2}
do_test intpkey-10.2 {
  execsql {
    INSERT INTO t2 VALUES(NULL, 2, 3);
    SELECT * from t2 WHERE x=2;
  }
} {2 2 3}
do_test intpkey-10.3 {
  execsql {
    INSERT INTO t2 SELECT NULL, z, y FROM t2;
    SELECT * FROM t2;
  }
} {1 1 2 2 2 3 3 2 1 4 3 2}

# This tests checks to see if a floating point number can be used
# to reference an integer primary key.
#
do_test intpkey-11.1 {
  execsql {
    SELECT b FROM t1 WHERE a=2.0+3.0;
  }
} {hello}
do_test intpkey-11.1 {
  execsql {
    SELECT b FROM t1 WHERE a=2.0+3.5;
  }
} {}

integrity_check intpkey-12.1

# Try to use a string that looks like a floating point number as
# an integer primary key.  This should actually work when the floating
# point value can be rounded to an integer without loss of data.
#
do_test intpkey-13.1 {
  execsql {
    SELECT * FROM t1 WHERE a=1;
  }
} {}
do_test intpkey-13.2 {
  execsql {
    INSERT INTO t1 VALUES('1.0',2,3);
    SELECT * FROM t1 WHERE a=1;
  }
} {1 2 3}
do_test intpkey-13.3 {
  catchsql {
    INSERT INTO t1 VALUES('1.5',3,4);
  }
} {1 {datatype mismatch}}
do_test intpkey-13.4 {
  catchsql {
    INSERT INTO t1 VALUES(x'123456',3,4);
  }
} {1 {datatype mismatch}}
do_test intpkey-13.5 {
  catchsql {
    INSERT INTO t1 VALUES('+1234567890',3,4);
  }
} {0 {}}


finish_test

--- NEW FILE: ioerr.test ---
# 2001 October 12
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: ioerr.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set ::go 1
for {set n 1} {$go} {incr n} {
  do_test ioerr-1.$n.1 {
    set ::sqlite_io_error_pending 0
    db close
    catch {file delete -force test.db}
    catch {file delete -force test.db-journal}
    sqlite3 db test.db
    execsql {SELECT * FROM sqlite_master}
  } {}
  do_test ioerr-1.$n.2 [subst {
    set ::sqlite_io_error_pending $n
  }] $n
  do_test ioerr-1.$n.3 {
    set r [catch {db eval {
      CREATE TABLE t1(a,b,c);
      SELECT * FROM sqlite_master;
      BEGIN TRANSACTION;
      INSERT INTO t1 VALUES(1,2,3);
      INSERT INTO t1 VALUES(4,5,6);
      ROLLBACK;
      SELECT * FROM t1;
      BEGIN TRANSACTION;
      INSERT INTO t1 VALUES(1,2,3);
      INSERT INTO t1 VALUES(4,5,6);
      COMMIT;
      SELECT * FROM t1;
      DELETE FROM t1 WHERE a<100;
    }} msg]
    # if {$r} {puts $msg}
    set ::go [expr {$::sqlite_io_error_pending<=0}]
    expr {$::sqlite_io_error_pending>0 || $r!=0}
  } {1}
}
set ::sqlite_io_error_pending 0

proc cksum {{db db}} {
  set txt [$db eval {
      SELECT name, type, sql FROM sqlite_master order by name
  }]\n
  foreach tbl [$db eval {
      SELECT name FROM sqlite_master WHERE type='table' order by name
  }] {
    append txt [$db eval "SELECT * FROM $tbl"]\n
  }
  foreach prag {default_synchronous default_cache_size} {
    append txt $prag-[$db eval "PRAGMA $prag"]\n
  }
  set cksum [string length $txt]-[md5 $txt]
  # puts $cksum-[file size test.db]
  return $cksum
}

set ::go 1
for {set n 1} {$go} {incr n} {
  do_test ioerr-2.$n.1 {
    set ::sqlite_io_error_pending 0
    db close
    catch {file delete -force test.db}
    catch {file delete -force test.db-journal}
    sqlite3 db test.db
    execsql {
      BEGIN;
      CREATE TABLE t1(a, b, c);
      INSERT INTO t1 VALUES(1, randstr(5,50), randstr(5,50));
      INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1;
      INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1;
      INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1;
      INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1;
      INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1;
      INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1;
      INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1;
      CREATE TABLE t2 AS SELECT * FROM t1;
      CREATE TABLE t3 AS SELECT * FROM t1;
      COMMIT;
      DROP TABLE t2;
    }
    set ::cksum [cksum]
    execsql {
      SELECT name FROM sqlite_master WHERE type='table'
    }
  } {t1 t3}
  do_test ioerr-2.$n.2 [subst {
    set ::sqlite_io_error_pending $n
  }] $n
  do_test ioerr-2.$n.3 {
if {$n==41} {
  # set sqlite_os_trace 1
  breakpoint
}
    set r [catch {db eval {
      VACUUM;
    }} msg]
    # puts "error_pending=$::sqlite_io_error_pending"
    # if {$r} {puts $msg}
set sqlite_os_trace 0
    set ::go [expr {$::sqlite_io_error_pending<=0}]
    expr {$::sqlite_io_error_pending>0 || $r!=0}
    set ::sqlite_io_error_pending 0
    db close
    sqlite3 db test.db
    cksum
  } $cksum
}
set ::sqlite_io_error_pending 0

finish_test

--- NEW FILE: join.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for joins, including outer joins.
#
# $Id: join.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test join-1.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 VALUES(2,3,4);
    INSERT INTO t1 VALUES(3,4,5);
    SELECT * FROM t1;
  }  
} {1 2 3 2 3 4 3 4 5}
do_test join-1.2 {
  execsql {
    CREATE TABLE t2(b,c,d);
    INSERT INTO t2 VALUES(1,2,3);
    INSERT INTO t2 VALUES(2,3,4);
    INSERT INTO t2 VALUES(3,4,5);
    SELECT * FROM t2;
  }  
} {1 2 3 2 3 4 3 4 5}

do_test join-1.3 {
  execsql2 {
    SELECT * FROM t1 NATURAL JOIN t2;
  }
} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5}
do_test join-1.3.1 {
  execsql2 {
    SELECT * FROM t2 NATURAL JOIN t1;
  }
} {t2.b 2 t2.c 3 t2.d 4 t1.a 1 t2.b 3 t2.c 4 t2.d 5 t1.a 2}
do_test join-1.4 {
  execsql2 {
    SELECT * FROM t1 INNER JOIN t2 USING(b,c);
  }
} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5}
do_test join-1.5 {
  execsql2 {
    SELECT * FROM t1 INNER JOIN t2 USING(b);
  }
} {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}
do_test join-1.6 {
  execsql2 {
    SELECT * FROM t1 INNER JOIN t2 USING(c);
  }
} {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}
do_test join-1.7 {
  execsql2 {
    SELECT * FROM t1 INNER JOIN t2 USING(c,b);
  }
} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5}

do_test join-1.8 {
  execsql {
    SELECT * FROM t1 NATURAL CROSS JOIN t2;
  }
} {1 2 3 4 2 3 4 5}
do_test join-1.9 {
  execsql {
    SELECT * FROM t1 CROSS JOIN t2 USING(b,c);
  }
} {1 2 3 4 2 3 4 5}
do_test join-1.10 {
  execsql {
    SELECT * FROM t1 NATURAL INNER JOIN t2;
  }
} {1 2 3 4 2 3 4 5}
do_test join-1.11 {
  execsql {
    SELECT * FROM t1 INNER JOIN t2 USING(b,c);
  }
} {1 2 3 4 2 3 4 5}
do_test join-1.12 {
  execsql {
    SELECT * FROM t1 natural inner join t2;
  }
} {1 2 3 4 2 3 4 5}
do_test join-1.13 {
  execsql2 {
    SELECT * FROM t1 NATURAL JOIN 
      (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as t3
  }
} {t1.a 1 t1.b 2 t1.c 3 t3.d 4 t3.e 5}
do_test join-1.14 {
  execsql2 {
    SELECT * FROM (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as 'tx'
        NATURAL JOIN t1
  }
} {tx.c 3 tx.d 4 tx.e 5 t1.a 1 t1.b 2}

do_test join-1.15 {
  execsql {
    CREATE TABLE t3(c,d,e);
    INSERT INTO t3 VALUES(2,3,4);
    INSERT INTO t3 VALUES(3,4,5);
    INSERT INTO t3 VALUES(4,5,6);
    SELECT * FROM t3;
  }  
} {2 3 4 3 4 5 4 5 6}
do_test join-1.16 {
  execsql {
    SELECT * FROM t1 natural join t2 natural join t3;
  }
} {1 2 3 4 5 2 3 4 5 6}
do_test join-1.17 {
  execsql2 {
    SELECT * FROM t1 natural join t2 natural join t3;
  }
} {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}
do_test join-1.18 {
  execsql {
    CREATE TABLE t4(d,e,f);
    INSERT INTO t4 VALUES(2,3,4);
    INSERT INTO t4 VALUES(3,4,5);
    INSERT INTO t4 VALUES(4,5,6);
    SELECT * FROM t4;
  }  
} {2 3 4 3 4 5 4 5 6}
do_test join-1.19 {
  execsql {
    SELECT * FROM t1 natural join t2 natural join t4;
  }
} {1 2 3 4 5 6}
do_test join-1.19 {
  execsql2 {
    SELECT * FROM t1 natural join t2 natural join t4;
  }
} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t4.e 5 t4.f 6}
do_test join-1.20 {
  execsql {
    SELECT * FROM t1 natural join t2 natural join t3 WHERE t1.a=1
  }
} {1 2 3 4 5}

do_test join-2.1 {
  execsql {
    SELECT * FROM t1 NATURAL LEFT JOIN t2;
  }
} {1 2 3 4 2 3 4 5 3 4 5 {}}
do_test join-2.2 {
  execsql {
    SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
  }
} {1 2 3 {} 2 3 4 1 3 4 5 2}
do_test join-2.3 {
  catchsql {
    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
  }
} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
do_test join-2.4 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
  }
} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
do_test join-2.5 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t1.a>1
  }
} {2 3 4 {} {} {} 3 4 5 1 2 3}
do_test join-2.6 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t2.b IS NULL OR t2.b>1
  }
} {1 2 3 {} {} {} 2 3 4 {} {} {}}

do_test join-3.1 {
  catchsql {
    SELECT * FROM t1 NATURAL JOIN t2 ON t1.a=t2.b;
  }
} {1 {a NATURAL join may not have an ON or USING clause}}
do_test join-3.2 {
  catchsql {
    SELECT * FROM t1 NATURAL JOIN t2 USING(b);
  }
} {1 {a NATURAL join may not have an ON or USING clause}}
do_test join-3.3 {
  catchsql {
    SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b);
  }
} {1 {cannot have both ON and USING clauses in the same join}}
do_test join-3.4 {
  catchsql {
    SELECT * FROM t1 JOIN t2 USING(a);
  }
} {1 {cannot join using column a - column not present in both tables}}
do_test join-3.5 {
  catchsql {
    SELECT * FROM t1 USING(a);
  }
} {0 {1 2 3 2 3 4 3 4 5}}
do_test join-3.6 {
  catchsql {
    SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
  }
} {1 {no such column: t3.a}}
do_test join-3.7 {
  catchsql {
    SELECT * FROM t1 INNER OUTER JOIN t2;
  }
} {1 {unknown or unsupported join type: INNER OUTER}}
do_test join-3.7 {
  catchsql {
    SELECT * FROM t1 LEFT BOGUS JOIN t2;
  }
} {1 {unknown or unsupported join type: LEFT BOGUS}}

do_test join-4.1 {
  execsql {
    BEGIN;
    CREATE TABLE t5(a INTEGER PRIMARY KEY);
    CREATE TABLE t6(a INTEGER);
    INSERT INTO t6 VALUES(NULL);
    INSERT INTO t6 VALUES(NULL);
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    COMMIT;
  }
  execsql {
    SELECT * FROM t6 NATURAL JOIN t5;
  }
} {}
do_test join-4.2 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a<t5.a;
  }
} {}
do_test join-4.3 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
  }
} {}
do_test join-4.4 {
  execsql {
    UPDATE t6 SET a='xyz';
    SELECT * FROM t6 NATURAL JOIN t5;
  }
} {}
do_test join-4.6 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a<t5.a;
  }
} {}
do_test join-4.7 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
  }
} {}
do_test join-4.8 {
  execsql {
    UPDATE t6 SET a=1;
    SELECT * FROM t6 NATURAL JOIN t5;
  }
} {}
do_test join-4.9 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a<t5.a;
  }
} {}
do_test join-4.10 {
  execsql {
    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
  }
} {}

do_test join-5.1 {
  execsql {
    BEGIN;
    create table centros (id integer primary key, centro);
    INSERT INTO centros VALUES(1,'xxx');
    create table usuarios (id integer primary key, nombre, apellidos,
    idcentro integer);
    INSERT INTO usuarios VALUES(1,'a','aa',1);
    INSERT INTO usuarios VALUES(2,'b','bb',1);
    INSERT INTO usuarios VALUES(3,'c','cc',NULL);
    create index idcentro on usuarios (idcentro);
    END;
    select usuarios.id, usuarios.nombre, centros.centro from
    usuarios left outer join centros on usuarios.idcentro = centros.id;
  }
} {1 a xxx 2 b xxx 3 c {}}

# A test for ticket #247.
#
do_test join-7.1 {
  execsql {
    CREATE TABLE t7 (x, y);
    INSERT INTO t7 VALUES ("pa1", 1);
    INSERT INTO t7 VALUES ("pa2", NULL);
    INSERT INTO t7 VALUES ("pa3", NULL);
    INSERT INTO t7 VALUES ("pa4", 2);
    INSERT INTO t7 VALUES ("pa30", 131);
    INSERT INTO t7 VALUES ("pa31", 130);
    INSERT INTO t7 VALUES ("pa28", NULL);

    CREATE TABLE t8 (a integer primary key, b);
    INSERT INTO t8 VALUES (1, "pa1");
    INSERT INTO t8 VALUES (2, "pa4");
    INSERT INTO t8 VALUES (3, NULL);
    INSERT INTO t8 VALUES (4, NULL);
    INSERT INTO t8 VALUES (130, "pa31");
    INSERT INTO t8 VALUES (131, "pa30");

    SELECT coalesce(t8.a,999) from t7 LEFT JOIN t8 on y=a;
  }
} {1 999 999 2 131 130 999}

# Make sure a left join where the right table is really a view that
# is itself a join works right.  Ticket #306.
#
do_test join-8.1 {
  execsql {
    BEGIN;
    CREATE TABLE t9(a INTEGER PRIMARY KEY, b);
    INSERT INTO t9 VALUES(1,11);
    INSERT INTO t9 VALUES(2,22);
    CREATE TABLE t10(x INTEGER PRIMARY KEY, y);
    INSERT INTO t10 VALUES(1,2);
    INSERT INTO t10 VALUES(3,3);    
    CREATE TABLE t11(p INTEGER PRIMARY KEY, q);
    INSERT INTO t11 VALUES(2,111);
    INSERT INTO t11 VALUES(3,333);    
    CREATE VIEW v10_11 AS SELECT x, q FROM t10, t11 WHERE t10.y=t11.p;
    COMMIT;
    SELECT * FROM t9 LEFT JOIN v10_11 ON( a=x );
  }
} {1 11 1 111 2 22 {} {}}
do_test join-8.2 {
  execsql {
    SELECT * FROM t9 LEFT JOIN (SELECT x, q FROM t10, t11 WHERE t10.y=t11.p)
         ON( a=x);
  }
} {1 11 1 111 2 22 {} {}}
do_test join-8.3 {
  execsql {
    SELECT * FROM v10_11 LEFT JOIN t9 ON( a=x );
  }
} {1 111 1 11 3 333 {} {}}

# Ticket #350 describes a scenario where LEFT OUTER JOIN does not
# function correctly if the right table in the join is really
# subquery.
#
# To test the problem, we generate the same LEFT OUTER JOIN in two
# separate selects but with on using a subquery and the other calling
# the table directly.  Then connect the two SELECTs using an EXCEPT.
# Both queries should generate the same results so the answer should
# be an empty set.
#
do_test join-9.1 {
  execsql {
    BEGIN;
    CREATE TABLE t12(a,b);
    INSERT INTO t12 VALUES(1,11);
    INSERT INTO t12 VALUES(2,22);
    CREATE TABLE t13(b,c);
    INSERT INTO t13 VALUES(22,222);
    COMMIT;
    SELECT * FROM t12 NATURAL LEFT JOIN t13
      EXCEPT
      SELECT * FROM t12 NATURAL LEFT JOIN (SELECT * FROM t13 WHERE b>0);
  }
} {}
do_test join-9.2 {
  execsql {
    CREATE VIEW v13 AS SELECT * FROM t13 WHERE b>0;
    SELECT * FROM t12 NATURAL LEFT JOIN t13
      EXCEPT
      SELECT * FROM t12 NATURAL LEFT JOIN v13;
  }
} {}

finish_test

--- NEW FILE: join2.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for joins, including outer joins.
#
# $Id: join2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test join2-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,11);
    INSERT INTO t1 VALUES(2,22);
    INSERT INTO t1 VALUES(3,33);
    SELECT * FROM t1;
  }  
} {1 11 2 22 3 33}
do_test join2-1.2 {
  execsql {
    CREATE TABLE t2(b,c);
    INSERT INTO t2 VALUES(11,111);
    INSERT INTO t2 VALUES(33,333);
    INSERT INTO t2 VALUES(44,444);
    SELECT * FROM t2;
  }  
} {11 111 33 333 44 444};
do_test join2-1.3 {
  execsql {
    CREATE TABLE t3(c,d);
    INSERT INTO t3 VALUES(111,1111);
    INSERT INTO t3 VALUES(444,4444);
    INSERT INTO t3 VALUES(555,5555);
    SELECT * FROM t3;
  }  
} {111 1111 444 4444 555 5555}

do_test join2-1.4 {
  execsql {
    SELECT * FROM
      t1 NATURAL JOIN t2 NATURAL JOIN t3
  }
} {1 11 111 1111}
do_test join2-1.5 {
  execsql {
    SELECT * FROM
      t1 NATURAL JOIN t2 NATURAL LEFT OUTER JOIN t3
  }
} {1 11 111 1111 3 33 333 {}}
do_test join2-1.6 {
  execsql {
    SELECT * FROM
      t1 NATURAL LEFT OUTER JOIN t2 NATURAL JOIN t3
  }
} {1 11 111 1111}
do_test join2-1.6 {
  execsql {
    SELECT * FROM
      t1 NATURAL LEFT OUTER JOIN (t2 NATURAL JOIN t3)
  }
} {1 11 111 1111 2 22 {} {} 3 33 {} {}}

finish_test

--- NEW FILE: join3.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for joins, including outer joins, where
# there are a large number of tables involved in the join.
#
# $Id: join3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# An unrestricted join
#
catch {unset ::result}
set result {}
for {set N 1} {$N<=40} {incr N} {
  lappend result $N
  do_test join3-1.$N {
    execsql "CREATE TABLE t${N}(x);"
    execsql "INSERT INTO t$N VALUES($N)"
    set sql "SELECT * FROM t1"
    for {set i 2} {$i<=$N} {incr i} {append sql ", t$i"}
    execsql $sql
  } $result
}

# Joins with a comparison
#
set result {}
for {set N 1} {$N<=40} {incr N} {
  lappend result $N
  do_test join3-2.$N {
    set sql "SELECT * FROM t1"
    for {set i 2} {$i<=$N} {incr i} {append sql ", t$i"}
    set sep WHERE
    for {set i 1} {$i<$N} {incr i} {
      append sql " $sep t[expr {$i+1}].x==t$i.x+1"
      set sep AND
    }
    execsql $sql
  } $result
}

finish_test

--- NEW FILE: join4.test ---
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for left outer joins containing WHERE
# clauses that restrict the scope of the left term of the join.
#
# $Id: join4.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test join4-1.1 {
  execsql {
    create temp table t1(a integer, b varchar(10));
    insert into t1 values(1,'one');
    insert into t1 values(2,'two');
    insert into t1 values(3,'three');
    insert into t1 values(4,'four');

    create temp table t2(x integer, y varchar(10), z varchar(10));
    insert into t2 values(2,'niban','ok');
    insert into t2 values(4,'yonban','err');
  }
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
  }
} {2 two 2 niban ok}
do_test join4-1.2 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
do_test join4-1.3 {
  execsql {
    create index i2 on t2(z);
  }
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
  }
} {2 two 2 niban ok}
do_test join4-1.4 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
do_test join4-1.5 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z>='ok'
  }
} {2 two 2 niban ok}
do_test join4-1.4 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z>='ok'
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
do_test join4-1.6 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z IN ('ok')
  }
} {2 two 2 niban ok}
do_test join4-1.7 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z IN ('ok')
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}


finish_test

--- NEW FILE: lastinsert.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests to make sure that value returned by last_insert_rowid() (LIRID)
# is updated properly, especially inside triggers
#
# Note 1: insert into table is now the only statement which changes LIRID
# Note 2: upon entry into before or instead of triggers,
#           LIRID is unchanged (rather than -1)
# Note 3: LIRID is changed within the context of a trigger,
#           but is restored once the trigger exits
# Note 4: LIRID is not changed by an insert into a view (since everything
#           is done within instead of trigger context)
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# ----------------------------------------------------------------------------
# 1.x - basic tests (no triggers)

# LIRID changed properly after an insert into a table
do_test lastinsert-1.1 {
    catchsql {
        create table t1 (k integer primary key);
        insert into t1 values (1);
        insert into t1 values (NULL);
        insert into t1 values (NULL);
        select last_insert_rowid();
    }
} {0 3}

# LIRID unchanged after an update on a table
do_test lastinsert-1.2 {
    catchsql {
        update t1 set k=4 where k=2;
        select last_insert_rowid();
    }
} {0 3}

# LIRID unchanged after a delete from a table
do_test lastinsert-1.3 {
    catchsql {
        delete from t1 where k=4;
        select last_insert_rowid();
    }
} {0 3}

# LIRID unchanged after create table/view statements
do_test lastinsert-1.4 {
    catchsql {
        create table t2 (k integer primary key, val1, val2, val3);
        create view v as select * from t1;
        select last_insert_rowid();
    }
} {0 3}

# ----------------------------------------------------------------------------
# 2.x - tests with after insert trigger

# LIRID changed properly after an insert into table containing an after trigger
do_test lastinsert-2.1 {
    catchsql {
        delete from t2;
        create trigger r1 after insert on t1 for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        insert into t1 values (13);
        select last_insert_rowid();
    }
} {0 13}

# LIRID equals NEW.k upon entry into after insert trigger
do_test lastinsert-2.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of after insert trigger
do_test lastinsert-2.3 {
    catchsql {
        select val2 from t2;
    }
} {0 126}

# LIRID unchanged by update within context of after insert trigger
do_test lastinsert-2.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1026}

# ----------------------------------------------------------------------------
# 3.x - tests with after update trigger

# LIRID not changed after an update onto a table containing an after trigger
do_test lastinsert-3.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 after update on t1 for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        update t1 set k=14 where k=3;
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into after update trigger
do_test lastinsert-3.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of after update trigger
do_test lastinsert-3.3 {
    catchsql {
        select val2 from t2;
    }
} {0 128}

# LIRID unchanged by update within context of after update trigger
do_test lastinsert-3.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1028}

# ----------------------------------------------------------------------------
# 4.x - tests with instead of insert trigger

# LIRID not changed after an insert into view containing an instead of trigger
do_test lastinsert-4.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 instead of insert on v for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        insert into v values (15);
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into instead of trigger
do_test lastinsert-4.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of instead of trigger
do_test lastinsert-4.3 {
    catchsql {
        select val2 from t2;
    }
} {0 130}

# LIRID unchanged by update within context of instead of trigger
do_test lastinsert-4.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1030}

# ----------------------------------------------------------------------------
# 5.x - tests with before delete trigger

# LIRID not changed after a delete on a table containing a before trigger
do_test lastinsert-5.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 before delete on t1 for each row begin
            insert into t2 values (77, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        delete from t1 where k=1;
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into delete trigger
do_test lastinsert-5.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of delete trigger
do_test lastinsert-5.3 {
    catchsql {
        select val2 from t2;
    }
} {0 177}

# LIRID unchanged by update within context of delete trigger
do_test lastinsert-5.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1077}

# ----------------------------------------------------------------------------
# 6.x - tests with instead of update trigger

# LIRID not changed after an update on a view containing an instead of trigger
do_test lastinsert-6.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 instead of update on v for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        update v set k=16 where k=14;
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into instead of trigger
do_test lastinsert-6.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of instead of trigger
do_test lastinsert-6.3 {
    catchsql {
        select val2 from t2;
    }
} {0 132}

# LIRID unchanged by update within context of instead of trigger
do_test lastinsert-6.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1032}

# ----------------------------------------------------------------------------
# 7.x - complex tests with temporary tables and nested instead of triggers

do_test lastinsert-7.1 {
    catchsql {
        drop table t1; drop table t2; drop trigger r1;
        create temp table t1 (k integer primary key);
        create temp table t2 (k integer primary key);
        create temp view v1 as select * from t1;
        create temp view v2 as select * from t2;
        create temp table rid (k integer primary key, rin, rout);
        insert into rid values (1, NULL, NULL);
        insert into rid values (2, NULL, NULL);
        create temp trigger r1 instead of insert on v1 for each row begin
            update rid set rin=last_insert_rowid() where k=1;
            insert into t1 values (100+NEW.k);
            insert into v2 values (100+last_insert_rowid());
            update rid set rout=last_insert_rowid() where k=1;
        end;
        create temp trigger r2 instead of insert on v2 for each row begin
            update rid set rin=last_insert_rowid() where k=2;
            insert into t2 values (1000+NEW.k);
            update rid set rout=last_insert_rowid() where k=2;
        end;
        insert into t1 values (77);
        select last_insert_rowid();
    }
} {0 77}

do_test lastinsert-7.2 {
    catchsql {
        insert into v1 values (5);
        select last_insert_rowid();
    }
} {0 77}

do_test lastinsert-7.3 {
    catchsql {
        select rin from rid where k=1;
    }
} {0 77}

do_test lastinsert-7.4 {
    catchsql {
        select rout from rid where k=1;
    }
} {0 105}

do_test lastinsert-7.5 {
    catchsql {
        select rin from rid where k=2;
    }
} {0 105}

do_test lastinsert-7.6 {
    catchsql {
        select rout from rid where k=2;
    }
} {0 1205}

finish_test


--- NEW FILE: laststmtchanges.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests to make sure that values returned by changes() and total_changes()
# are updated properly, especially inside triggers
#
# Note 1: changes() remains constant within a statement and only updates
#         once the statement is finished (triggers count as part of
#         statement).
# Note 2: changes() is changed within the context of a trigger much like 
#         last_insert_rowid() (see lastinsert.test), but is restored once
#         the trigger exits.
# Note 3: changes() is not changed by a change to a view (since everything
#         is done within instead of trigger context).
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# ----------------------------------------------------------------------------
# 1.x - basic tests (no triggers)

# changes() set properly after insert
do_test laststmtchanges-1.1 {
    catchsql {
        create table t0 (x);
        insert into t0 values (1);
        insert into t0 values (1);
        insert into t0 values (2);
        insert into t0 values (2);
        insert into t0 values (1);
        insert into t0 values (1);
        insert into t0 values (1);
        insert into t0 values (2);
        select changes(), total_changes();
    }
} {0 {1 8}}

# changes() set properly after update
do_test laststmtchanges-1.2 {
    catchsql {
        update t0 set x=3 where x=1;
        select changes(), total_changes();
    }
} {0 {5 13}}

# changes() unchanged within an update statement
do_test laststmtchanges-1.3 {
    catchsql {
        update t0 set x=x+changes() where x=3;
        select count() from t0 where x=8;
    }
} {0 5}

# changes() set properly after update on table where no rows changed
do_test laststmtchanges-1.4 {
    catchsql {
        update t0 set x=77 where x=88;
        select changes();
    }
} {0 0}

# changes() set properly after delete from table
do_test laststmtchanges-1.5 {
    catchsql {
        delete from t0 where x=2;
        select changes();
    }
} {0 3}

# ----------------------------------------------------------------------------
# 2.x - tests with after insert trigger

# changes() changed properly after insert into table containing after trigger
do_test laststmtchanges-2.1 {
    set ::tc [db total_changes]
    catchsql {
        create table t1 (k integer primary key);
        create table t2 (k integer primary key, v1, v2);
        create trigger r1 after insert on t1 for each row begin
            insert into t2 values (NULL, changes(), NULL);
            update t0 set x=x;
            update t2 set v2=changes();
        end;
        insert into t1 values (77);
        select changes();
    }
} {0 1}

# changes() unchanged upon entry into after insert trigger
do_test laststmtchanges-2.2 {
    catchsql {
        select v1 from t2;
    }
} {0 3}

# changes() changed properly by update within context of after insert trigger
do_test laststmtchanges-2.3 {
    catchsql {
        select v2 from t2;
    }
} {0 5}

# Total changes caused by firing the trigger above:
#
#   1 from "insert into t1 values(77)" + 
#   1 from "insert into t2 values (NULL, changes(), NULL);" +
#   5 from "update t0 set x=x;" +
#   1 from "update t2 set v2=changes();"
#
do_test laststmtchanges-2.4 {
  expr [db total_changes] - $::tc
} {8}

# ----------------------------------------------------------------------------
# 3.x - tests with after update trigger

# changes() changed properly after update into table containing after trigger
do_test laststmtchanges-3.1 {
    catchsql {
        drop trigger r1;
        delete from t2; delete from t2;
        create trigger r1 after update on t1 for each row begin
            insert into t2 values (NULL, changes(), NULL);
            delete from t0 where oid=1 or oid=2;
            update t2 set v2=changes();
        end;
        update t1 set k=k;
        select changes();
    }
} {0 1}

# changes() unchanged upon entry into after update trigger
do_test laststmtchanges-3.2 {
    catchsql {
        select v1 from t2;
    }
} {0 0}

# changes() changed properly by delete within context of after update trigger
do_test laststmtchanges-3.3 {
    catchsql {
        select v2 from t2;
    }
} {0 2}

# ----------------------------------------------------------------------------
# 4.x - tests with before delete trigger

# changes() changed properly on delete from table containing before trigger
do_test laststmtchanges-4.1 {
    catchsql {
        drop trigger r1;
        delete from t2; delete from t2;
        create trigger r1 before delete on t1 for each row begin
            insert into t2 values (NULL, changes(), NULL);
            insert into t0 values (5);
            update t2 set v2=changes();
        end;
        delete from t1;
        select changes();
    }
} {0 1}

# changes() unchanged upon entry into before delete trigger
do_test laststmtchanges-4.2 {
    catchsql {
        select v1 from t2;
    }
} {0 0}

# changes() changed properly by insert within context of before delete trigger
do_test laststmtchanges-4.3 {
    catchsql {
        select v2 from t2;
    }
} {0 1}

# ----------------------------------------------------------------------------
# 5.x - complex tests with temporary tables and nested instead of triggers

do_test laststmtchanges-5.1 {
    catchsql {
        drop table t0; drop table t1; drop table t2;
        create temp table t0(x);
        create temp table t1 (k integer primary key);
        create temp table t2 (k integer primary key);
        create temp view v1 as select * from t1;
        create temp view v2 as select * from t2;
        create temp table n1 (k integer primary key, n);
        create temp table n2 (k integer primary key, n);
        insert into t0 values (1);
        insert into t0 values (2);
        insert into t0 values (1);
        insert into t0 values (1);
        insert into t0 values (1);
        insert into t0 values (2);
        insert into t0 values (2);
        insert into t0 values (1);
        create temp trigger r1 instead of insert on v1 for each row begin
            insert into n1 values (NULL, changes());
            update t0 set x=x*10 where x=1;
            insert into n1 values (NULL, changes());
            insert into t1 values (NEW.k);
            insert into n1 values (NULL, changes());
            update t0 set x=x*10 where x=0;
            insert into v2 values (100+NEW.k);
            insert into n1 values (NULL, changes());
        end;
        create temp trigger r2 instead of insert on v2 for each row begin
            insert into n2 values (NULL, changes());
            insert into t2 values (1000+NEW.k);
            insert into n2 values (NULL, changes());
            update t0 set x=x*100 where x=0;
            insert into n2 values (NULL, changes());
            delete from t0 where x=2;
            insert into n2 values (NULL, changes());
        end;
        insert into t1 values (77);
        select changes();
    }
} {0 1}

do_test laststmtchanges-5.2 {
    catchsql {
        delete from t1 where k=88;
        select changes();
    }
} {0 0}

do_test laststmtchanges-5.3 {
    catchsql {
        insert into v1 values (5);
        select changes();
    }
} {0 0}

do_test laststmtchanges-5.4 {
    catchsql {
        select n from n1;
    }
} {0 {0 5 1 0}}

do_test laststmtchanges-5.5 {
    catchsql {
        select n from n2;
    }
} {0 {0 1 0 3}}

finish_test


--- NEW FILE: limit.test ---
# 2001 November 6
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
execsql {
  CREATE TABLE t1(x int, y int);
  BEGIN;
}
for {set i 1} {$i<=32} {incr i} {
  for {set j 0} {pow(2,$j)<$i} {incr j} {}
  execsql "INSERT INTO t1 VALUES([expr {32-$i}],[expr {10-$j}])"
}
execsql {
  COMMIT;
}

do_test limit-1.0 {
  execsql {SELECT count(*) FROM t1}
} {32}
do_test limit-1.1 {
  execsql {SELECT count(*) FROM t1 LIMIT  5}
} {32}
do_test limit-1.2.1 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5}
} {0 1 2 3 4}
do_test limit-1.2.2 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 2}
} {2 3 4 5 6}
do_test limit-1.2.3 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 2, 5}
} {2 3 4 5 6}
do_test limit-1.3 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 5}
} {5 6 7 8 9}
do_test limit-1.4.1 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 30}
} {30 31}
do_test limit-1.4.2 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 30, 50}
} {30 31}
do_test limit-1.5 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 50}
} {}
do_test limit-1.6 {
  execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5}
} {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5}
do_test limit-1.7 {
  execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5 OFFSET 32}
} {1 5 0 5 1 5 1 5 1 5 2 5 1 5 3 5 1 5 4 5}

do_test limit-2.1 {
  execsql {
    CREATE VIEW v1 AS SELECT * FROM t1 LIMIT 2;
    SELECT count(*) FROM (SELECT * FROM v1);
  }
} 2
do_test limit-2.2 {
  execsql {
    CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 2;
    SELECT count(*) FROM t2;
  }
} 2
do_test limit-2.3 {
  execsql {
    SELECT count(*) FROM t1 WHERE rowid IN (SELECT rowid FROM t1 LIMIT 2);
  }
} 2

do_test limit-3.1 {
  execsql {
    SELECT z FROM (SELECT y*10+x AS z FROM t1 ORDER BY x LIMIT 10)
    ORDER BY z LIMIT 5;
  }
} {50 51 52 53 54}

do_test limit-4.1 {
  execsql {
    BEGIN;
    CREATE TABLE t3(x);
    INSERT INTO t3 SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    END;
    SELECT count(*) FROM t3;
  }
} {10240}
do_test limit-4.2 {
  execsql {
    SELECT x FROM t3 LIMIT 2 OFFSET 10000
  }
} {10001 10002}
do_test limit-4.3 {
  execsql {
    CREATE TABLE t4 AS SELECT x,
       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x AS y
    FROM t3 LIMIT 1000;
    SELECT x FROM t4 ORDER BY y DESC LIMIT 1 OFFSET 999;
  }
} {1000}

do_test limit-5.1 {
  execsql {
    CREATE TABLE t5(x,y);
    INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x BETWEEN 10 AND 15
        ORDER BY x LIMIT 2;
    SELECT * FROM t5 ORDER BY x;
  }
} {5 15 6 16}
do_test limit-5.2 {
  execsql {
    DELETE FROM t5;
    INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x BETWEEN 10 AND 15
        ORDER BY x DESC LIMIT 2;
    SELECT * FROM t5 ORDER BY x;
  }
} {9 19 10 20}
do_test limit-5.3 {
  execsql {
    DELETE FROM t5;
    INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x ORDER BY x DESC LIMIT 31;
    SELECT * FROM t5 ORDER BY x LIMIT 2;
  }
} {-4 6 -3 7}
do_test limit-5.4 {
  execsql {
    SELECT * FROM t5 ORDER BY x DESC, y DESC LIMIT 2;
  }
} {21 41 21 39}
do_test limit-5.5 {
  execsql {
    DELETE FROM t5;
    INSERT INTO t5 SELECT a.x*100+b.x, a.y*100+b.y FROM t1 AS a, t1 AS b
                   ORDER BY 1, 2 LIMIT 1000;
    SELECT count(*), sum(x), sum(y), min(x), max(x), min(y), max(y) FROM t5;
  }
} {1000 1528204.0 593161.0 0 3107 505 1005}

# There is some contraversy about whether LIMIT 0 should be the same as
# no limit at all or if LIMIT 0 should result in zero output rows.
#
do_test limit-6.1 {
  execsql {
    BEGIN;
    CREATE TABLE t6(a);
    INSERT INTO t6 VALUES(1);
    INSERT INTO t6 VALUES(2);
    INSERT INTO t6 SELECT a+2 FROM t6;
    COMMIT;
    SELECT * FROM t6;
  }
} {1 2 3 4}
do_test limit-6.2 {
  execsql {
    SELECT * FROM t6 LIMIT -1 OFFSET -1;
  }
} {1 2 3 4}
do_test limit-6.3 {
  execsql {
    SELECT * FROM t6 LIMIT 2 OFFSET -123;
  }
} {1 2}
do_test limit-6.4 {
  execsql {
    SELECT * FROM t6 LIMIT -432 OFFSET 2;
  }
} {3 4}
do_test limit-6.5 {
  execsql {
    SELECT * FROM t6 LIMIT -1
  }
} {1 2 3 4}
do_test limit-6.6 {
  execsql {
    SELECT * FROM t6 LIMIT -1 OFFSET 1
  }
} {2 3 4}
do_test limit-6.7 {
  execsql {
    SELECT * FROM t6 LIMIT 0
  }
} {}
do_test limit-6.8 {
  execsql {
    SELECT * FROM t6 LIMIT 0 OFFSET 1
  }
} {}

# Make sure LIMIT works well with compound SELECT statements.
# Ticket #393
#
do_test limit-7.1.1 {
  catchsql {
    SELECT x FROM t2 LIMIT 5 UNION ALL SELECT a FROM t6;
  }
} {1 {LIMIT clause should come after UNION ALL not before}}
do_test limit-7.1.2 {
  catchsql {
    SELECT x FROM t2 LIMIT 5 UNION SELECT a FROM t6;
  }
} {1 {LIMIT clause should come after UNION not before}}
do_test limit-7.1.3 {
  catchsql {
    SELECT x FROM t2 LIMIT 5 EXCEPT SELECT a FROM t6 LIMIT 3;
  }
} {1 {LIMIT clause should come after EXCEPT not before}}
do_test limit-7.1.4 {
  catchsql {
    SELECT x FROM t2 LIMIT 0,5 INTERSECT SELECT a FROM t6;
  }
} {1 {LIMIT clause should come after INTERSECT not before}}
do_test limit-7.2 {
  execsql {
    SELECT x FROM t2 UNION ALL SELECT a FROM t6 LIMIT 5;
  }
} {31 30 1 2 3}
do_test limit-7.3 {
  execsql {
    SELECT x FROM t2 UNION ALL SELECT a FROM t6 LIMIT 3 OFFSET 1;
  }
} {30 1 2}
do_test limit-7.4 {
  execsql {
    SELECT x FROM t2 UNION ALL SELECT a FROM t6 ORDER BY 1 LIMIT 3 OFFSET 1;
  }
} {2 3 4}
do_test limit-7.5 {
  execsql {
    SELECT x FROM t2 UNION SELECT x+2 FROM t2 LIMIT 2 OFFSET 1;
  }
} {31 32}
do_test limit-7.6 {
  execsql {
    SELECT x FROM t2 UNION SELECT x+2 FROM t2 ORDER BY 1 DESC LIMIT 2 OFFSET 1;
  }
} {32 31}
do_test limit-7.7 {
  execsql {
    SELECT a+9 FROM t6 EXCEPT SELECT y FROM t2 LIMIT 2;
  }
} {11 12}
do_test limit-7.8 {
  execsql {
    SELECT a+9 FROM t6 EXCEPT SELECT y FROM t2 ORDER BY 1 DESC LIMIT 2;
  }
} {13 12}
do_test limit-7.9 {
  execsql {
    SELECT a+26 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1;
  }
} {30}
do_test limit-7.10 {
  execsql {
    SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1;
  }
} {30}
do_test limit-7.11 {
  execsql {
    SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1 OFFSET 1;
  }
} {31}
do_test limit-7.12 {
  execsql {
    SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 
       ORDER BY 1 DESC LIMIT 1 OFFSET 1;
  }
} {30}

# Tests for limit in conjunction with distinct.  The distinct should
# occur before both the limit and the offset.  Ticket #749.
#
do_test limit-8.1 {
  execsql {
    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5;
  }
} {0 1 2 3 4}
do_test limit-8.2 {
  execsql {
    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 5;
  }
} {5 6 7 8 9}
do_test limit-8.3 {
  execsql {
    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 25;
  }
} {25 26 27 28 29}

finish_test

--- NEW FILE: lock.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is database locks.
#
# $Id: lock.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create an alternative connection to the database
#
do_test lock-1.0 {
  sqlite3 db2 ./test.db
  set dummy {}
} {}
do_test lock-1.1 {
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {}
do_test lock-1.2 {
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} db2
} {}
do_test lock-1.3 {
  execsql {CREATE TABLE t1(a int, b int)}
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {t1}
do_test lock-1.5 {
  catchsql {
     SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
  } db2
} {0 t1}

do_test lock-1.6 {
  execsql {INSERT INTO t1 VALUES(1,2)}
  execsql {SELECT * FROM t1}
} {1 2}
# Update: The schema is now brought up to date by test lock-1.5.
# do_test lock-1.7.1 {
#   catchsql {SELECT * FROM t1} db2
# } {1 {no such table: t1}}
do_test lock-1.7.2 {
  catchsql {SELECT * FROM t1} db2
} {0 {1 2}}
do_test lock-1.8 {
  execsql {UPDATE t1 SET a=b, b=a} db2
  execsql {SELECT * FROM t1} db2
} {2 1}
do_test lock-1.9 {
  execsql {SELECT * FROM t1}
} {2 1}
do_test lock-1.10 {
  execsql {BEGIN TRANSACTION}
  execsql {UPDATE t1 SET a = 0 WHERE 0}
  execsql {SELECT * FROM t1}
} {2 1}
do_test lock-1.11 {
  catchsql {SELECT * FROM t1} db2
} {0 {2 1}}
do_test lock-1.12 {
  execsql {ROLLBACK}
  catchsql {SELECT * FROM t1}
} {0 {2 1}}

do_test lock-1.13 {
  execsql {CREATE TABLE t2(x int, y int)}
  execsql {INSERT INTO t2 VALUES(8,9)}
  execsql {SELECT * FROM t2}
} {8 9}
do_test lock-1.14.1 {
  catchsql {SELECT * FROM t2} db2
} {1 {no such table: t2}}
do_test lock-1.14.2 {
  catchsql {SELECT * FROM t1} db2
} {0 {2 1}}
do_test lock-1.15 {
  catchsql {SELECT * FROM t2} db2
} {0 {8 9}}

do_test lock-1.16 {
  db eval {SELECT * FROM t1} qv {
    set x [db eval {SELECT * FROM t1}]
  }
  set x
} {2 1}
do_test lock-1.17 {
  db eval {SELECT * FROM t1} qv {
    set x [db eval {SELECT * FROM t2}]
  }
  set x
} {8 9}

# You cannot UPDATE a table from within the callback of a SELECT
# on that same table because the SELECT has the table locked.
#
do_test lock-1.18 {
  db eval {SELECT * FROM t1} qv {
    set r [catch {db eval {UPDATE t1 SET a=b, b=a}} msg]
    lappend r $msg
  }
  set r
} {1 {database table is locked}}

# But you can UPDATE a different table from the one that is used in
# the SELECT.
#
do_test lock-1.19 {
  db eval {SELECT * FROM t1} qv {
    set r [catch {db eval {UPDATE t2 SET x=y, y=x}} msg]
    lappend r $msg
  }
  set r
} {0 {}}
do_test lock-1.20 {
  execsql {SELECT * FROM t2}
} {9 8}

# It is possible to do a SELECT of the same table within the
# callback of another SELECT on that same table because two
# or more read-only cursors can be open at once.
#
do_test lock-1.21 {
  db eval {SELECT * FROM t1} qv {
    set r [catch {db eval {SELECT a FROM t1}} msg]
    lappend r $msg
  }
  set r
} {0 2}

# Under UNIX you can do two SELECTs at once with different database
# connections, because UNIX supports reader/writer locks.  Under windows,
# this is not possible.
#
if {$::tcl_platform(platform)=="unix"} {
  do_test lock-1.22 {
    db eval {SELECT * FROM t1} qv {
      set r [catch {db2 eval {SELECT a FROM t1}} msg]
      lappend r $msg
    }
    set r
  } {0 2}
}
integrity_check lock-1.23

# If one thread has a transaction another thread cannot start
# a transaction.  -> Not true in version 3.0.  But if one thread
# as a RESERVED lock another thread cannot acquire one.
#
do_test lock-2.1 {
  execsql {BEGIN TRANSACTION}
  execsql {UPDATE t1 SET a = 0 WHERE 0}
  execsql {BEGIN TRANSACTION} db2
  set r [catch {execsql {UPDATE t1 SET a = 0 WHERE 0} db2} msg]
  execsql {ROLLBACK} db2
  lappend r $msg
} {1 {database is locked}}

# A thread can read when another has a RESERVED lock.
#
do_test lock-2.2 {
  catchsql {SELECT * FROM t2} db2
} {0 {9 8}}

# If the other thread (the one that does not hold the transaction with
# a RESERVED lock) tries to get a RESERVED lock, we do not get a busy callback.
#
do_test lock-2.3 {
  proc callback {count} {
    set ::callback_value $count
    break
  }
  set ::callback_value {}
  db2 busy callback
  set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
  lappend r $msg
  lappend r $::callback_value
} {1 {database is locked} {}}
do_test lock-2.4 {
  proc callback {count} {
    lappend ::callback_value $count
    if {$count>4} break
  }
  set ::callback_value {}
  db2 busy callback
  set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
  lappend r $msg
  lappend r $::callback_value
} {1 {database is locked} {}}
do_test lock-2.5 {
  proc callback {count} {
    lappend ::callback_value $count
    if {$count>4} break
  }
  set ::callback_value {}
  db2 busy callback
  set r [catch {execsql {SELECT * FROM t1} db2} msg]
  lappend r $msg
  lappend r $::callback_value
} {0 {2 1} {}}
execsql {ROLLBACK}

# Test the built-in busy timeout handler
#
do_test lock-2.8 {
  db2 timeout 400
  execsql BEGIN
  execsql {UPDATE t1 SET a = 0 WHERE 0}
  # catchsql BEGIN db2
  catchsql {UPDATE t1 SET a = 0 WHERE 0} db2
} {1 {database is locked}}
do_test lock-2.9 {
  db2 timeout 0
  execsql COMMIT
} {}
integrity_check lock-2.10

# Try to start two transactions in a row
#
do_test lock-3.1 {
  execsql {BEGIN TRANSACTION}
  set r [catch {execsql {BEGIN TRANSACTION}} msg]
  execsql {ROLLBACK}
  lappend r $msg
} {1 {cannot start a transaction within a transaction}}
integrity_check lock-3.2

# Make sure the busy handler and error messages work when
# opening a new pointer to the database while another pointer
# has the database locked.
#
do_test lock-4.1 {
  db2 close
  catch {db eval ROLLBACK}
  db eval BEGIN
  db eval {UPDATE t1 SET a=0 WHERE 0}
  sqlite3 db2 ./test.db
  catchsql {UPDATE t1 SET a=0} db2
} {1 {database is locked}}
do_test lock-4.2 {
  set ::callback_value {}
  set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
  lappend rc $msg $::callback_value
} {1 {database is locked} {}}
do_test lock-4.3 {
  proc callback {count} {
    lappend ::callback_value $count
    if {$count>4} break
  }
  db2 busy callback
  set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
  lappend rc $msg $::callback_value
} {1 {database is locked} {}}
execsql {ROLLBACK}

# When one thread is writing, other threads cannot read.  Except if the
# writing thread is writing to its temporary tables, the other threads
# can still read.  -> Not so in 3.0.  One thread can read while another
# holds a RESERVED lock.
#
proc tx_exec {sql} {
  db2 eval $sql
}
do_test lock-5.1 {
  execsql {
    SELECT * FROM t1
  }
} {2 1}
do_test lock-5.2 {
  db function tx_exec tx_exec
  catchsql {
    INSERT INTO t1(a,b) SELECT 3, tx_exec('SELECT y FROM t2 LIMIT 1');
  }
} {0 {}}
do_test lock-5.3 {
  execsql {
    CREATE TEMP TABLE t3(x);
    SELECT * FROM t3;
  }
} {}
do_test lock-5.4 {
  catchsql {
    INSERT INTO t3 SELECT tx_exec('SELECT y FROM t2 LIMIT 1');
  }
} {0 {}}
do_test lock-5.5 {
  execsql {
    SELECT * FROM t3;
  }
} {8}
do_test lock-5.6 {
  catchsql {
    UPDATE t1 SET a=tx_exec('SELECT x FROM t2');
  }
} {0 {}}
do_test lock-5.7 {
  execsql {
    SELECT * FROM t1;
  }
} {9 1 9 8}
do_test lock-5.8 {
  catchsql {
    UPDATE t3 SET x=tx_exec('SELECT x FROM t2');
  }
} {0 {}}
do_test lock-5.9 {
  execsql {
    SELECT * FROM t3;
  }
} {9}

do_test lock-999.1 {
  rename db2 {}
} {}

finish_test

--- NEW FILE: lock2.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is database locks between competing processes.
#
# $Id: lock2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Launch another testfixture process to be controlled by this one. A
# channel name is returned that may be passed as the first argument to proc
# 'testfixture' to execute a command. The child testfixture process is shut
# down by closing the channel.
proc launch_testfixture {} {
  set chan [open "|[file join . testfixture] tf_main.tcl" r+]
  fconfigure $chan -buffering line
  return $chan
}

# Execute a command in a child testfixture process, connected by two-way
# channel $chan. Return the result of the command, or an error message.
proc testfixture {chan cmd} {
  puts $chan $cmd
  puts $chan OVER
  set r ""
  while { 1 } {
    set line [gets $chan]
    if { $line == "OVER" } { 
      return $r
    }
    append r $line
  }
}

# Write the main loop for the child testfixture processes into file
# tf_main.tcl. The parent (this script) interacts with the child processes
# via a two way pipe. The parent writes a script to the stdin of the child
# process, followed by the word "OVER" on a line of it's own. The child
# process evaluates the script and writes the results to stdout, followed
# by an "OVER" of its own.
set f [open tf_main.tcl w]
puts $f {
  set l [open log w]
  set script ""
  while {![eof stdin]} {
    flush stdout
    set line [gets stdin]
    puts $l "READ $line"
    if { $line == "OVER" } {
      catch {eval $script} result
      puts $result
      puts $l "WRITE $result"
      puts OVER
      puts $l "WRITE OVER"
      flush stdout
      set script ""
    } else {
      append script $line
      append script " ; "
    }
  }
  close $l
}
close $f

# Simple locking test case:
#
# lock2-1.1: Connect a second process to the database.
# lock2-1.2: Establish a RESERVED lock with this process.
# lock2-1.3: Get a SHARED lock with the second process.
# lock2-1.4: Try for a RESERVED lock with process 2. This fails.
# lock2-1.5: Try to upgrade the first process to EXCLUSIVE, this fails so
#            it gets PENDING.
# lock2-1.6: Release the SHARED lock held by the second process. 
# lock2-1.7: Attempt to reaquire a SHARED lock with the second process.
#            this fails due to the PENDING lock.
# lock2-1.8: Ensure the first process can now upgrade to EXCLUSIVE.
#
do_test lock2-1.1 {
  set ::tf1 [launch_testfixture]
  testfixture $::tf1 {
    sqlite3 db test.db -key xyzzy
    db eval {select * from sqlite_master}
  }
} {}
do_test lock2-1.2 {
  execsql {
    BEGIN;
    CREATE TABLE abc(a, b, c);
  }
} {}
do_test lock2-1.3 {
  testfixture $::tf1 {
    db eval {
      BEGIN;
      SELECT * FROM sqlite_master;
    }
  }
} {}
do_test lock2-1.4 {
  testfixture $::tf1 {
    db eval {
      CREATE TABLE def(d, e, f)
    }
  }
} {database is locked}
do_test lock2-1.5 {
  catchsql {
    COMMIT;
  }
} {1 {database is locked}}
do_test lock2-1.6 {
  testfixture $::tf1 {
    db eval {
      SELECT * FROM sqlite_master;
      COMMIT;
    }
  }
} {}
do_test lock2-1.7 {
  testfixture $::tf1 {
    db eval {
      BEGIN;
      SELECT * FROM sqlite_master;
    }
  }
} {database is locked}
do_test lock2-1.8 {
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test lock2-1.9 {
  execsql {
    SELECT * FROM sqlite_master;
  }
} {table abc abc 2 {CREATE TABLE abc(a, b, c)}}
do_test lock2-1.10 {
  testfixture $::tf1 {
    db eval {
      SELECT * FROM sqlite_master;
    }
  }
} {table abc abc 2 {CREATE TABLE abc(a, b, c)}}

catch {testfixture $::tf1 {db close}}
catch {close $::tf1}

finish_test

--- NEW FILE: main.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in main.c.
#
# $Id: main.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests of the sqlite_complete() function.
#
do_test main-1.1 {
  db complete {This is a test}
} {0}
do_test main-1.2 {
  db complete {
  }
} {1}
do_test main-1.3 {
  db complete {
     -- a comment ;
  }
} {1}
do_test main-1.4 {
  db complete {
     -- a comment ;
     ;
  }
} {1}
do_test main-1.5 {
  db complete {DROP TABLE 'xyz;}
} {0}
do_test main-1.6 {
  db complete {DROP TABLE 'xyz';}
} {1}
do_test main-1.7 {
  db complete {DROP TABLE "xyz;}
} {0}
do_test main-1.8 {
  db complete {DROP TABLE "xyz';}
} {0}
do_test main-1.9 {
  db complete {DROP TABLE "xyz";}
} {1}
do_test main-1.10 {
  db complete {DROP TABLE xyz; hi}
} {0}
do_test main-1.11 {
  db complete {DROP TABLE xyz; }
} {1}
do_test main-1.12 {
  db complete {DROP TABLE xyz; -- hi }
} {1}
do_test main-1.13 {
  db complete {DROP TABLE xyz; -- hi
  }
} {1}
do_test main-1.14 {
  db complete {SELECT a-b FROM t1; }
} {1}
do_test main-1.15 {
  db complete {SELECT a-b FROM t1 }
} {0}
do_test main-1.16 {
  db complete {
    CREATE TABLE abc(x,y);
  }
} {1}
do_test main-1.17 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr;
  }
} {0}
do_test main-1.18 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr; END;
  }
} {1}
do_test main-1.19 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE abc BEGIN
       UPDATE pqr;
       unknown command;
  }
} {0}
do_test main-1.20 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr;
  }
} {0}
do_test main-1.21 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE end BEGIN
       SELECT a, b FROM end;
  }
} {0}
do_test main-1.22 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE end BEGIN
       SELECT a, b FROM end;
    END;
  }
} {1}
do_test main-1.23 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE end BEGIN
       SELECT a, b FROM end;
    END;
    SELECT a, b FROM end;
  }
} {1}
do_test main-1.24 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE [;end;] BEGIN
       UPDATE pqr;
  }
} {0}
do_test main-1.25 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=[;end;];;;
  }
} {0}
do_test main-1.26 {
  db complete {
    CREATE -- a comment
    TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {0}
do_test main-1.27.1 {
  db complete {
    CREATE -- a comment
    TRIGGERX xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {1}
do_test main-1.27.2 {
  db complete {
    CREATE/**/TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {0}
do_test main-1.27.3 {
  db complete {
    /* */ EXPLAIN -- A comment
    CREATE/**/TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {0}
do_test main-1.27.4 {
  db complete {
    BOGUS token
    CREATE  TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {1}
do_test main-1.27.5 {
  db complete {
    EXPLAIN 
    CREATE TEMP TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {0}
do_test main-1.28 {
  db complete {
    CREATE TEMP TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
  }
} {0}
do_test main-1.29 {
  db complete {
    CREATE TRIGGER xyz AFTER DELETE backend BEGIN
       UPDATE pqr SET a=5;
       EXPLAIN select * from xyz;
  }
} {0}
do_test main-1.30 {
  db complete {
     CREATE TABLE /* In comment ; */
  }
} {0}
do_test main-1.31 {
  db complete {
     CREATE TABLE /* In comment ; */ hi;
  }
} {1}
do_test main-1.31 {
  db complete {
     CREATE TABLE /* In comment ; */;
  }
} {1}
do_test main-1.32 {
  db complete {
     stuff;
     /*
       CREATE TABLE
       multiple lines
       of text
     */
  }
} {1}
do_test main-1.33 {
  db complete {
     /*
       CREATE TABLE
       multiple lines
       of text;
  }
} {0}
do_test main-1.34 {
  db complete {
     /*
       CREATE TABLE
       multiple lines "*/
       of text;
  }
} {1}
do_test main-1.35 {
  db complete {hi /**/ there;}
} {1}
do_test main-1.36 {
  db complete {hi there/***/;}
} {1}


# Try to open a database with a corrupt database file.
#
do_test main-2.0 {
  catch {db close}
  file delete -force test.db
  set fd [open test.db w]
  puts $fd hi!
  close $fd
  set v [catch {sqlite3 db test.db} msg]
  if {$v} {lappend v $msg} {lappend v {}}
} {0 {}}

# Here are some tests for tokenize.c.  
#
do_test main-3.1 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
  lappend v $msg
} {1 {unrecognized token: "!!"}}
do_test main-3.2 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  set v [catch {execsql {SELECT * from T1 where @x}} msg]
  lappend v $msg
} {1 {unrecognized token: "@"}}

do_test main-3.3 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  execsql {
    create table T1(X REAL);
    insert into T1 values(0.5);
    insert into T1 values(0.5e2);
    insert into T1 values(0.5e-002);
    insert into T1 values(5e-002);
    insert into T1 values(-5.0e-2);
    insert into T1 values(-5.1e-2);
    insert into T1 values(0.5e2);
    insert into T1 values(0.5E+02);
    insert into T1 values(5E+02);
    insert into T1 values(5.0E+03);
    select x*10 from T1 order by x*5;
  }
} {-0.51 -0.5 0.05 0.5 5.0 500.0 500.0 500.0 5000.0 50000.0}
do_test main-3.4 {
  set v [catch {execsql {create bogus}} msg]
  lappend v $msg
} {1 {near "bogus": syntax error}}
do_test main-3.5 {
  set v [catch {execsql {create}} msg]
  lappend v $msg
} {1 {near "create": syntax error}}

finish_test

--- NEW FILE: malloc.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_stat]==""} {
   puts "Skipping malloc tests: not compiled with -DMEMORY_DEBUG..."
   finish_test
   return
}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-1.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
          CREATE TABLE t1(
             a int, b float, c double, d text, e varchar(20),
             primary key(a,b,c)
          );
          CREATE INDEX i1 ON t1(a,b);
          INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
          INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
          SELECT * FROM t1;
          SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
          DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
          SELECT count(*) FROM t1;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-1.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

set fd [open ./data.tmp w]
for {set i 1} {$i<=20} {incr i} {
  puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}]  abcdefghijklmnopqrstuvwxyz"
}
close $fd

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-2.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         CREATE TABLE t1(a int, b int, c int);
         CREATE INDEX i1 ON t1(a,b);
         INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
         SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
         UPDATE t1 SET b=b||b||b||b;
         UPDATE t1 SET b=a WHERE a in (10,12,22);
         INSERT INTO t1(c,b,a) VALUES(20,10,5);
         INSERT INTO t1 SELECT * FROM t1
             WHERE a IN (SELECT a FROM t1 WHERE a<10);
         DELETE FROM t1 WHERE a>=10;
         DROP INDEX i1;
         DELETE FROM t1;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-2.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-3.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a int, b int, c int);
         CREATE INDEX i1 ON t1(a,b);
         INSERT INTO t1 VALUES(1,1,99);
         INSERT INTO t1 VALUES(2,4,98);
         INSERT INTO t1 VALUES(3,9,97);
         INSERT INTO t1 VALUES(4,16,96);
         INSERT INTO t1 VALUES(5,25,95);
         INSERT INTO t1 VALUES(6,36,94);
         INSERT INTO t1(c,b,a) VALUES(20,10,5);
         DELETE FROM t1 WHERE a>=10;
         DROP INDEX i1;
         DELETE FROM t1;
         ROLLBACK;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-3.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-4.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a int, b int, c int);
         CREATE INDEX i1 ON t1(a,b);
         INSERT INTO t1 VALUES(1,1,99);
         INSERT INTO t1 VALUES(2,4,98);
         INSERT INTO t1 VALUES(3,9,97);
         INSERT INTO t1 VALUES(4,16,96);
         INSERT INTO t1 VALUES(5,25,95);
         INSERT INTO t1 VALUES(6,36,94);
         UPDATE t1 SET b=a WHERE a in (10,12,22);
         INSERT INTO t1 SELECT * FROM t1
             WHERE a IN (SELECT a FROM t1 WHERE a<10);
         DROP INDEX i1;
         DELETE FROM t1;
         COMMIT;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-4.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-5.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a,b);
         CREATE TABLE t2(x,y);
         CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
           INSERT INTO t2(x,y) VALUES(new.rowid,1);
         END;
         INSERT INTO t1(a,b) VALUES(2,3);
         COMMIT;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-5.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-6.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite3 db test.db
     execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a);
         INSERT INTO t1 VALUES(1);
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         DELETE FROM t1 where rowid%5 = 0;
         COMMIT;
     }
     sqlite_malloc_fail $i
     set v [catch {execsql {
       VACUUM;
     }} msg]
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-6.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

sqlite_malloc_fail 0
finish_test

--- NEW FILE: memdb.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is in-memory database backend.
#
# $Id: memdb.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# In the following sequence of tests, compute the MD5 sum of the content
# of a table, make lots of modifications to that table, then do a rollback.
# Verify that after the rollback, the MD5 checksum is unchanged.
#
# These tests were browed from trans.tcl.
#
do_test memdb-1.1 {
  db close
  sqlite3 db :memory:
  # sqlite3 db test.db
  execsql {
    BEGIN;
    CREATE TABLE t3(x TEXT);
    INSERT INTO t3 VALUES(randstr(10,400));
    INSERT INTO t3 VALUES(randstr(10,400));
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    COMMIT;
    SELECT count(*) FROM t3;
  }
} {1024}

# The following procedure computes a "signature" for table "t3".  If
# T3 changes in any way, the signature should change.  
#
# This is used to test ROLLBACK.  We gather a signature for t3, then
# make lots of changes to t3, then rollback and take another signature.
# The two signatures should be the same.
#
proc signature {{fn {}}} {
  set rx [db eval {SELECT x FROM t3}]
  # set r1 [md5 $rx\n]
  if {$fn!=""} {
    # set fd [open $fn w]
    # puts $fd $rx
    # close $fd
  }
  # set r [db eval {SELECT count(*), md5sum(x) FROM t3}]
  # puts "SIG($fn)=$r1"
  return [list [string length $rx] $rx]
}

# Do rollbacks.  Make sure the signature does not change.
#
set limit 10
for {set i 2} {$i<=$limit} {incr i} {
  set ::sig [signature one]
  # puts "sig=$sig"
  set cnt [lindex $::sig 0]
  if {$i%2==0} {
    execsql {PRAGMA synchronous=FULL}
  } else {
    execsql {PRAGMA synchronous=NORMAL}
  }
  do_test memdb-1.$i.1-$cnt {
     execsql {
       BEGIN;
       DELETE FROM t3 WHERE random()%10!=0;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       ROLLBACK;
     }
     set sig2 [signature two]
  } $sig
  # puts "sig2=$sig2"
  # if {$sig2!=$sig} exit
  do_test memdb-1.$i.2-$cnt {
     execsql {
       BEGIN;
       DELETE FROM t3 WHERE random()%10!=0;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       DELETE FROM t3 WHERE random()%10!=0;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       ROLLBACK;
     }
     signature
  } $sig
  if {$i<$limit} {
    do_test memdb-1.$i.9-$cnt {
       execsql {
         INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
       }
    } {}
  }
  set ::pager_old_format 0
}

do_test memdb-2.1 {
  execsql {
    PRAGMA integrity_check
  }
} {ok}

do_test memdb-3.1 {
  execsql {
    CREATE TABLE t4(a,b,c,d);
    BEGIN;
    INSERT INTO t4 VALUES(1,2,3,4);
    SELECT * FROM t4;
  }
} {1 2 3 4}
do_test memdb-3.2 {
  execsql {
    SELECT name FROM sqlite_master WHERE type='table';
  }
} {t3 t4}
do_test memdb-3.3 {
  execsql {
    DROP TABLE t4;
    SELECT name FROM sqlite_master WHERE type='table';
  }
} {t3}
do_test memdb-3.4 {
  execsql {
    ROLLBACK;
    SELECT name FROM sqlite_master WHERE type='table';
  }
} {t3 t4}

# Create tables for the first group of tests.
#
do_test memdb-4.0 {
  execsql {
    CREATE TABLE t1(a, b, c, UNIQUE(a,b));
    CREATE TABLE t2(x);
    SELECT c FROM t1 ORDER BY c;
  }
} {}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf   The conflict resolution algorithm on the BEGIN statement
#   cmd    An INSERT or REPLACE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "c" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t2
#
foreach {i conf cmd t0 t1 t2} {
  1 {}       INSERT                  1 {}  1
  2 {}       {INSERT OR IGNORE}      0 3   1
  3 {}       {INSERT OR REPLACE}     0 4   1
  4 {}       REPLACE                 0 4   1
  5 {}       {INSERT OR FAIL}        1 {}  1
  6 {}       {INSERT OR ABORT}       1 {}  1
  7 {}       {INSERT OR ROLLBACK}    1 {}  {}
} {
  do_test memdb-4.$i {
    if {$conf!=""} {set conf "ON CONFLICT $conf"}
    set r0 [catch {execsql [subst {
      DELETE FROM t1;
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);
      BEGIN $conf;
      INSERT INTO t2 VALUES(1); 
      $cmd INTO t1 VALUES(1,2,4);
    }]} r1]
    catch {execsql {COMMIT}}
    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
    set r2 [execsql {SELECT x FROM t2}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

do_test memdb-5.0 {
  execsql {
    DROP TABLE t2;
    DROP TABLE t3;
    CREATE TABLE t2(a,b,c);
    INSERT INTO t2 VALUES(1,2,1);
    INSERT INTO t2 VALUES(2,3,2);
    INSERT INTO t2 VALUES(3,4,1);
    INSERT INTO t2 VALUES(4,5,4);
    SELECT c FROM t2 ORDER BY b;
    CREATE TABLE t3(x);
    INSERT INTO t3 VALUES(1);
  }
} {1 2 1 4}

# Six columns of configuration data as follows:
#
#   i      The reference number of the test
#   conf1  The conflict resolution algorithm on the UNIQUE constraint
#   conf2  The conflict resolution algorithm on the BEGIN statement
#   cmd    An UPDATE command to execute against table t1
#   t0     True if there is an error from $cmd
#   t1     Content of "b" column of t1 assuming no error in $cmd
#   t2     Content of "x" column of t3
#
foreach {i conf1 conf2 cmd t0 t1 t2} {
  1 {}       {}       UPDATE                  1 {6 7 8 9}  1
  2 REPLACE  {}       UPDATE                  0 {7 6 9}    1
  3 IGNORE   {}       UPDATE                  0 {6 7 3 9}  1
  4 FAIL     {}       UPDATE                  1 {6 7 3 4}  1
  5 ABORT    {}       UPDATE                  1 {1 2 3 4}  1
  6 ROLLBACK {}       UPDATE                  1 {1 2 3 4}  0
  7 REPLACE  {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
  8 IGNORE   {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
  9 FAIL     {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
 10 ABORT    {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 11 ROLLBACK {}       {UPDATE OR IGNORE}      0 {6 7 3 9}   1
 12 {}       {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
 13 {}       {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 14 {}       {}       {UPDATE OR FAIL}        1 {6 7 3 4}  1
 15 {}       {}       {UPDATE OR ABORT}       1 {1 2 3 4}  1
 16 {}       {}       {UPDATE OR ROLLBACK}    1 {1 2 3 4}  0
} {
  if {$t0} {set t1 {column a is not unique}}
  do_test memdb-5.$i {
    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
    if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
      CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
      INSERT INTO t1 SELECT * FROM t2;
      UPDATE t3 SET x=0;
      BEGIN $conf2;
      $cmd t3 SET x=1;
      $cmd t1 SET b=b*2;
      $cmd t1 SET a=c+5;
    }]} r1]
    catch {execsql {COMMIT}}
    if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
    set r2 [execsql {SELECT x FROM t3}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}

do_test memdb-6.1 {
  execsql {
    SELECT * FROM t2;
  }
} {1 2 1 2 3 2 3 4 1 4 5 4}
do_test memdb-6.2 {
  execsql {
    BEGIN;
    DROP TABLE t2;
    SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
  }
} {t1 t3 t4}
do_test memdb-6.3 {
  execsql {
    ROLLBACK;
    SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
  }
} {t1 t2 t3 t4}
do_test memdb-6.4 {
  execsql {
    SELECT * FROM t2;
  }
} {1 2 1 2 3 2 3 4 1 4 5 4}
do_test memdb-6.5 {
  execsql {
    SELECT a FROM t2 UNION SELECT b FROM t2 ORDER BY 1;
  }
} {1 2 3 4 5}
do_test memdb-6.6 {
  execsql {
    CREATE INDEX i2 ON t2(c);
    SELECT a FROM t2 ORDER BY c;
  }
} {1 3 2 4}
do_test memdb-6.6 {
  execsql {
    SELECT a FROM t2 ORDER BY c DESC;
  }
} {4 2 3 1}
do_test memdb-6.7 {
  execsql {
    BEGIN;
    CREATE TABLE t5(x,y);
    INSERT INTO t5 VALUES(1,2);
    SELECT * FROM t5;
  }
} {1 2}
do_test memdb-6.8 {
  execsql {
    SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
  }
} {t1 t2 t3 t4 t5}
do_test memdb-6.9 {
  execsql {
    ROLLBACK;
    SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
  }
} {t1 t2 t3 t4}
do_test memdb-6.10 {
  execsql {
    CREATE TABLE t5(x PRIMARY KEY, y UNIQUE);
    SELECT * FROM t5;
  }
} {}
do_test memdb-6.11 {
  execsql {
    SELECT * FROM t5 ORDER BY y DESC;
  }
} {}
do_test memdb-6.12 {
  execsql {
    INSERT INTO t5 VALUES(1,2);
    INSERT INTO t5 VALUES(3,4);
    REPLACE INTO t5 VALUES(1,4);
    SELECT rowid,* FROM t5;
  }
} {3 1 4}
do_test memdb-6.13 {
  execsql {
    DELETE FROM t5 WHERE x>5;
    SELECT * FROM t5;
  }
} {1 4}
do_test memdb-6.14 {
  execsql {
    DELETE FROM t5 WHERE y<3;
    SELECT * FROM t5;
  }
} {1 4}
do_test memdb-6.15 {
  execsql {
    DELETE FROM t5 WHERE x>0;
    SELECT * FROM t5;
  }
} {}

do_test memdb-7.1 {
  execsql {
    CREATE TABLE t6(x);
    INSERT INTO t6 VALUES(1);
    INSERT INTO t6 SELECT x+1 FROM t6;
    INSERT INTO t6 SELECT x+2 FROM t6;
    INSERT INTO t6 SELECT x+4 FROM t6;
    INSERT INTO t6 SELECT x+8 FROM t6;
    INSERT INTO t6 SELECT x+16 FROM t6;
    INSERT INTO t6 SELECT x+32 FROM t6;
    INSERT INTO t6 SELECT x+64 FROM t6;
    INSERT INTO t6 SELECT x+128 FROM t6;
    SELECT count(*) FROM (SELECT DISTINCT x FROM t6);
  }
} {256}
for {set i 1} {$i<=256} {incr i} {
  do_test memdb-7.2.$i {
     execsql "DELETE FROM t6 WHERE x=\
              (SELECT x FROM t6 ORDER BY random() LIMIT 1)"
     execsql {SELECT count(*) FROM t6}
  } [expr {256-$i}]
}

finish_test

--- NEW FILE: memleak.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: memleak.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {
  catch {db close}
  memleak_check
}

if {[file exists ./sqlite_test_count]} {
  set COUNT [exec cat ./sqlite_test_count]
} else {
  set COUNT 3
}

# LeakList will hold a list of the number of unfreed mallocs after
# each round of the test.  This number should be constant.  If it
# grows, it may mean there is a memory leak in the library.
#
set LeakList {}

set EXCLUDE {
  all.test
  quick.test
  malloc.test
  misuse.test
  memleak.test
  btree2.test
  trans.test
  crash.test
  corrupt.test
}
if {[sqlite3 -has-codec]} {
  # lappend EXCLUDE 
}
if {[llength $argv]>0} {
  set FILELIST $argv
  set argv {}
} else {
  set FILELIST [lsort -dictionary [glob $testdir/*.test]]
}

foreach testfile $FILELIST {
  set tail [file tail $testfile]
  if {[lsearch -exact $EXCLUDE $tail]>=0} continue
  set LeakList {}
  for {set COUNTER 0} {$COUNTER<$COUNT} {incr COUNTER} {
    source $testfile
    if {[info exists Leak]} {
      lappend LeakList $Leak
    }
  }
  if {$LeakList!=""} {
    puts -nonewline memory-leak-test-$tail...
    incr ::nTest
    foreach x $LeakList {
      if {$x!=[lindex $LeakList 0]} {
         puts " failed! ($LeakList)"
         incr ::nErr
         lappend ::failList memory-leak-test-$tail
         break
       }
    }
    puts " Ok"
  }
}
really_finish_test

# Run the malloc tests and the misuse test after memory leak detection.
# Both tests leak memory.
#
#catch {source $testdir/misuse.test}
#catch {source $testdir/malloc.test}

really_finish_test

--- NEW FILE: minmax.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing SELECT statements that contain
# aggregate min() and max() functions and which are handled as
# as a special case.
#
# $Id: minmax.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test minmax-1.0 {
  execsql {
    BEGIN;
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1,1);
    INSERT INTO t1 VALUES(2,2);
    INSERT INTO t1 VALUES(3,2);
    INSERT INTO t1 VALUES(4,3);
    INSERT INTO t1 VALUES(5,3);
    INSERT INTO t1 VALUES(6,3);
    INSERT INTO t1 VALUES(7,3);
    INSERT INTO t1 VALUES(8,4);
    INSERT INTO t1 VALUES(9,4);
    INSERT INTO t1 VALUES(10,4);
    INSERT INTO t1 VALUES(11,4);
    INSERT INTO t1 VALUES(12,4);
    INSERT INTO t1 VALUES(13,4);
    INSERT INTO t1 VALUES(14,4);
    INSERT INTO t1 VALUES(15,4);
    INSERT INTO t1 VALUES(16,5);
    INSERT INTO t1 VALUES(17,5);
    INSERT INTO t1 VALUES(18,5);
    INSERT INTO t1 VALUES(19,5);
    INSERT INTO t1 VALUES(20,5);
    COMMIT;
    SELECT DISTINCT y FROM t1 ORDER BY y;
  }
} {1 2 3 4 5}

do_test minmax-1.1 {
  set sqlite_search_count 0
  execsql {SELECT min(x) FROM t1}
} {1}
do_test minmax-1.2 {
  set sqlite_search_count
} {19}
do_test minmax-1.3 {
  set sqlite_search_count 0
  execsql {SELECT max(x) FROM t1}
} {20}
do_test minmax-1.4 {
  set sqlite_search_count
} {19}
do_test minmax-1.5 {
  execsql {CREATE INDEX t1i1 ON t1(x)}
  set sqlite_search_count 0
  execsql {SELECT min(x) FROM t1}
} {1}
do_test minmax-1.6 {
  set sqlite_search_count
} {2}
do_test minmax-1.7 {
  set sqlite_search_count 0
  execsql {SELECT max(x) FROM t1}
} {20}
do_test minmax-1.8 {
  set sqlite_search_count
} {1}
do_test minmax-1.9 {
  set sqlite_search_count 0
  execsql {SELECT max(y) FROM t1}
} {5}
do_test minmax-1.10 {
  set sqlite_search_count
} {19}

do_test minmax-2.0 {
  execsql {
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
    INSERT INTO t2 SELECT * FROM t1;
  }
  set sqlite_search_count 0
  execsql {SELECT min(a) FROM t2}
} {1}
do_test minmax-2.1 {
  set sqlite_search_count
} {0}
do_test minmax-2.2 {
  set sqlite_search_count 0
  execsql {SELECT max(a) FROM t2}
} {20}
do_test minmax-2.3 {
  set sqlite_search_count
} {0}

do_test minmax-3.0 {
  execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)}
  set sqlite_search_count 0
  execsql {SELECT max(a) FROM t2}
} {21}
do_test minmax-3.1 {
  set sqlite_search_count
} {0}
do_test minmax-3.2 {
  execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)}
  set sqlite_search_count 0
  execsql {
    SELECT b FROM t2 WHERE a=(SELECT max(a) FROM t2)
  }
} {999}
do_test minmax-3.3 {
  set sqlite_search_count
} {0}

do_test minmax-4.1 {
  execsql {
    SELECT coalesce(min(x+0),-1), coalesce(max(x+0),-1) FROM
      (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y')
  }
} {1 20}
do_test minmax-4.2 {
  execsql {
    SELECT y, sum(x) FROM
      (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1)
    GROUP BY y ORDER BY y;
  }
} {1 1.0 2 5.0 3 22.0 4 92.0 5 90.0 6 0.0}
do_test minmax-4.3 {
  execsql {
    SELECT y, count(x), count(*) FROM
      (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1)
    GROUP BY y ORDER BY y;
  }
} {1 1 1 2 2 3 3 4 5 4 8 9 5 5 6 6 0 1}

# Make sure the min(x) and max(x) optimizations work on empty tables
# including empty tables with indices. Ticket #296.
#
do_test minmax-5.1 {
  execsql {
    CREATE TABLE t3(x INTEGER UNIQUE NOT NULL);
    SELECT coalesce(min(x),999) FROM t3;
  }
} {999}
do_test minmax-5.2 {
  execsql {
    SELECT coalesce(min(rowid),999) FROM t3;
  }
} {999}
do_test minmax-5.3 {
  execsql {
    SELECT coalesce(max(x),999) FROM t3;
  }
} {999}
do_test minmax-5.4 {
  execsql {
    SELECT coalesce(max(rowid),999) FROM t3;
  }
} {999}
do_test minmax-5.5 {
  execsql {
    SELECT coalesce(max(rowid),999) FROM t3 WHERE rowid<25;
  }
} {999}

# Make sure the min(x) and max(x) optimizations work when there
# is a LIMIT clause.  Ticket #396.
#
do_test minmax-6.1 {
  execsql {
    SELECT min(a) FROM t2 LIMIT 1
  }
} {1}
do_test minmax-6.2 {
  execsql {
    SELECT max(a) FROM t2 LIMIT 3
  }
} {22}
do_test minmax-6.3 {
  execsql {
    SELECT min(a) FROM t2 LIMIT 0,100
  }
} {1}
do_test minmax-6.4 {
  execsql {
    SELECT max(a) FROM t2 LIMIT 1,100
  }
} {}
do_test minmax-6.5 {
  execsql {
    SELECT min(x) FROM t3 LIMIT 1
  }
} {{}}
do_test minmax-6.6 {
  execsql {
    SELECT max(x) FROM t3 LIMIT 0
  }
} {}
do_test minmax-6.7 {
  execsql {
    SELECT max(a) FROM t2 LIMIT 0
  }
} {}

# Make sure the max(x) and min(x) optimizations work for nested
# queries.  Ticket #587.
#
do_test minmax-7.1 {
  execsql {
    SELECT max(x) FROM t1;
  }
} 20
do_test minmax-7.2 {
  execsql {
    SELECT * FROM (SELECT max(x) FROM t1);
  }
} 20
do_test minmax-7.3 {
  execsql {
    SELECT min(x) FROM t1;
  }
} 1
do_test minmax-7.4 {
  execsql {
    SELECT * FROM (SELECT min(x) FROM t1);
  }
} 1

# Make sure min(x) and max(x) work correctly when the datatype is
# TEXT instead of NUMERIC.  Ticket #623.
#
do_test minmax-8.1 {
  execsql {
    CREATE TABLE t4(a TEXT);
    INSERT INTO t4 VALUES('1234');
    INSERT INTO t4 VALUES('234');
    INSERT INTO t4 VALUES('34');
    SELECT min(a), max(a) FROM t4;
  }
} {1234 34}
do_test minmax-8.2 {
  execsql {
    CREATE TABLE t5(a INTEGER);
    INSERT INTO t5 VALUES('1234');
    INSERT INTO t5 VALUES('234');
    INSERT INTO t5 VALUES('34');
    SELECT min(a), max(a) FROM t5;
  }
} {34 1234}

# Ticket #658:  Test the min()/max() optimization when the FROM clause
# is a subquery.
#
do_test minmax-9.1 {
  execsql {
    SELECT max(rowid) FROM (
      SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
    )
  }
} {1}
do_test minmax-9.2 {
  execsql {
    SELECT max(rowid) FROM (
      SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
    )
  }
} {{}}

# If there is a NULL in an aggregate max() or min(), ignore it.  An
# aggregate min() or max() will only return NULL if all values are NULL.
#
do_test minmax-10.1 {
  execsql {
    CREATE TABLE t6(x);
    INSERT INTO t6 VALUES(1);
    INSERT INTO t6 VALUES(2);
    INSERT INTO t6 VALUES(NULL);
    SELECT coalesce(min(x),-1) FROM t6;
  }
} {1}
do_test minmax-10.2 {
  execsql {
    SELECT max(x) FROM t6;
  }
} {2}
do_test minmax-10.3 {
  execsql {
    CREATE INDEX i6 ON t6(x);
    SELECT coalesce(min(x),-1) FROM t6;
  }
} {1}
do_test minmax-10.4 {
  execsql {
    SELECT max(x) FROM t6;
  }
} {2}
do_test minmax-10.5 {
  execsql {
    DELETE FROM t6 WHERE x NOT NULL;
    SELECT count(*) FROM t6;
  }
} 1
do_test minmax-10.6 {
  execsql {
    SELECT count(x) FROM t6;
  }
} 0
do_test minmax-10.7 {
  execsql {
    SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
  }
} {{} {}}
do_test minmax-10.8 {
  execsql {
    SELECT min(x), max(x) FROM t6;
  }
} {{} {}}
do_test minmax-10.9 {
  execsql {
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    SELECT count(*) FROM t6;
  }
} 1024
do_test minmax-10.10 {
  execsql {
    SELECT count(x) FROM t6;
  }
} 0
do_test minmax-10.11 {
  execsql {
    SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
  }
} {{} {}}
do_test minmax-10.12 {
  execsql {
    SELECT min(x), max(x) FROM t6;
  }
} {{} {}}


finish_test

--- NEW FILE: misc1.test ---
# 2001 September 15.
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc1.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Mimic the SQLite 2 collation type NUMERIC.
db collate numeric numeric_collate
proc numeric_collate {lhs rhs} {
  if {$lhs == $rhs} {return 0} 
  return [expr ($lhs>$rhs)?1:-1]
}

# Mimic the SQLite 2 collation type TEXT.
db collate text text_collate
proc numeric_collate {lhs rhs} {
  return [string compare $lhs $rhs]
}

# Test the creation and use of tables that have a large number
# of columns.
#
do_test misc1-1.1 {
  set cmd "CREATE TABLE manycol(x0 text"
  for {set i 1} {$i<=99} {incr i} {
    append cmd ",x$i text"
  }
  append cmd ")";
  execsql $cmd
  set cmd "INSERT INTO manycol VALUES(0"
  for {set i 1} {$i<=99} {incr i} {
    append cmd ",$i"
  }
  append cmd ")";
  execsql $cmd
  execsql "SELECT x99 FROM manycol"
} 99
do_test misc1-1.2 {
  execsql {SELECT x0, x10, x25, x50, x75 FROM manycol}
} {0 10 25 50 75}
do_test misc1-1.3.1 {
  for {set j 100} {$j<=1000} {incr j 100} {
    set cmd "INSERT INTO manycol VALUES($j"
    for {set i 1} {$i<=99} {incr i} {
      append cmd ",[expr {$i+$j}]"
    }
    append cmd ")"
    execsql $cmd
  }
  execsql {SELECT x50 FROM manycol ORDER BY x80+0}
} {50 150 250 350 450 550 650 750 850 950 1050}
do_test misc1-1.3.2 {
  execsql {SELECT x50 FROM manycol ORDER BY x80}
} {1050 150 250 350 450 550 650 750 50 850 950}
do_test misc1-1.4 {
  execsql {SELECT x75 FROM manycol WHERE x50=350}
} 375
do_test misc1-1.5 {
  execsql {SELECT x50 FROM manycol WHERE x99=599}
} 550
do_test misc1-1.6 {
  execsql {CREATE INDEX manycol_idx1 ON manycol(x99)}
  execsql {SELECT x50 FROM manycol WHERE x99=899}
} 850
do_test misc1-1.7 {
  execsql {SELECT count(*) FROM manycol}
} 11
do_test misc1-1.8 {
  execsql {DELETE FROM manycol WHERE x98=1234}
  execsql {SELECT count(*) FROM manycol}
} 11
do_test misc1-1.9 {
  execsql {DELETE FROM manycol WHERE x98=998}
  execsql {SELECT count(*) FROM manycol}
} 10
do_test misc1-1.10 {
  execsql {DELETE FROM manycol WHERE x99=500}
  execsql {SELECT count(*) FROM manycol}
} 10
do_test misc1-1.11 {
  execsql {DELETE FROM manycol WHERE x99=599}
  execsql {SELECT count(*) FROM manycol}
} 9

# Check GROUP BY expressions that name two or more columns.
#
do_test misc1-2.1 {
  execsql {
    BEGIN TRANSACTION;
    CREATE TABLE agger(one text, two text, three text, four text);
    INSERT INTO agger VALUES(1, 'one', 'hello', 'yes');
    INSERT INTO agger VALUES(2, 'two', 'howdy', 'no');
    INSERT INTO agger VALUES(3, 'thr', 'howareya', 'yes');
    INSERT INTO agger VALUES(4, 'two', 'lothere', 'yes');
    INSERT INTO agger VALUES(5, 'one', 'atcha', 'yes');
    INSERT INTO agger VALUES(6, 'two', 'hello', 'no');
    COMMIT
  }
  execsql {SELECT count(*) FROM agger}
} 6
do_test misc1-2.2 {
  execsql {SELECT sum(one), two, four FROM agger
           GROUP BY two, four ORDER BY sum(one) desc}
} {8.0 two no 6.0 one yes 4.0 two yes 3.0 thr yes}
do_test misc1-2.3 {
  execsql {SELECT sum((one)), (two), (four) FROM agger
           GROUP BY (two), (four) ORDER BY sum(one) desc}
} {8.0 two no 6.0 one yes 4.0 two yes 3.0 thr yes}

# Here's a test for a bug found by Joel Lucsy.  The code below
# was causing an assertion failure.
#
do_test misc1-3.1 {
  set r [execsql {
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES('hi');
    PRAGMA full_column_names=on;
    SELECT rowid, * FROM t1;
  }]
  lindex $r 1
} {hi}

# Here's a test for yet another bug found by Joel Lucsy.  The code
# below was causing an assertion failure.
#
do_test misc1-4.1 {
  execsql {
    BEGIN;
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES('This is a long string to use up a lot of disk -');
    UPDATE t2 SET a=a||a||a||a;
    INSERT INTO t2 SELECT '1 - ' || a FROM t2;
    INSERT INTO t2 SELECT '2 - ' || a FROM t2;
    INSERT INTO t2 SELECT '3 - ' || a FROM t2;
    INSERT INTO t2 SELECT '4 - ' || a FROM t2;
    INSERT INTO t2 SELECT '5 - ' || a FROM t2;
    INSERT INTO t2 SELECT '6 - ' || a FROM t2;
    COMMIT;
    SELECT count(*) FROM t2;
  }
} {64}

# Make sure we actually see a semicolon or end-of-file in the SQL input
# before executing a command.  Thus if "WHERE" is misspelled on an UPDATE,
# the user won't accidently update every record.
#
do_test misc1-5.1 {
  catchsql {
    CREATE TABLE t3(a,b);
    INSERT INTO t3 VALUES(1,2);
    INSERT INTO t3 VALUES(3,4);
    UPDATE t3 SET a=0 WHEREwww b=2;
  }
} {1 {near "WHEREwww": syntax error}}
do_test misc1-5.2 {
  execsql {
    SELECT * FROM t3 ORDER BY a;
  }
} {1 2 3 4}

# Certain keywords (especially non-standard keywords like "REPLACE") can
# also be used as identifiers.  The way this works in the parser is that
# the parser first detects a syntax error, the error handling routine
# sees that the special keyword caused the error, then replaces the keyword
# with "ID" and tries again.
#
# Check the operation of this logic.
#
do_test misc1-6.1 {
  catchsql {
    CREATE TABLE t4(
      abort, asc, begin, cluster, conflict, copy, delimiters, desc, end,
      explain, fail, ignore, key, offset, pragma, replace, temp,
      vacuum, view
    );
  }
} {0 {}}
do_test misc1-6.2 {
  catchsql {
    INSERT INTO t4
       VALUES(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
  }
} {0 {}}
do_test misc1-6.3 {
  execsql {
    SELECT * FROM t4
  }
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19}
do_test misc1-6.4 {
  execsql {
    SELECT abort+asc,max(key,pragma,temp) FROM t4
  }
} {3 17}

# Test for multi-column primary keys, and for multiple primary keys.
#
do_test misc1-7.1 {
  catchsql {
    CREATE TABLE error1(
      a TYPE PRIMARY KEY,
      b TYPE PRIMARY KEY
    );
  }
} {1 {table "error1" has more than one primary key}}
do_test misc1-7.2 {
  catchsql {
    CREATE TABLE error1(
      a INTEGER PRIMARY KEY,
      b TYPE PRIMARY KEY
    );
  }
} {1 {table "error1" has more than one primary key}}
do_test misc1-7.3 {
  execsql {
    CREATE TABLE t5(a,b,c,PRIMARY KEY(a,b));
    INSERT INTO t5 VALUES(1,2,3);
    SELECT * FROM t5 ORDER BY a;
  }
} {1 2 3}
do_test misc1-7.4 {
  catchsql {
    INSERT INTO t5 VALUES(1,2,4);
  }
} {1 {columns a, b are not unique}}
do_test misc1-7.5 {
  catchsql {
    INSERT INTO t5 VALUES(0,2,4);
  }
} {0 {}}
do_test misc1-7.6 {
  execsql {
    SELECT * FROM t5 ORDER BY a;
  }
} {0 2 4 1 2 3}

do_test misc1-8.1 {
  catchsql {
    SELECT *;
  }
} {1 {no tables specified}}
do_test misc1-8.2 {
  catchsql {
    SELECT t1.*;
  }
} {1 {no such table: t1}}

execsql {
  DROP TABLE t1;
  DROP TABLE t2;
  DROP TABLE t3;
  DROP TABLE t4;
}

# 64-bit integers are represented exactly.
#
do_test misc1-9.1 {
  catchsql {
    CREATE TABLE t1(a unique not null, b unique not null);
    INSERT INTO t1 VALUES('a',1234567890123456789);
    INSERT INTO t1 VALUES('b',1234567891123456789);
    INSERT INTO t1 VALUES('c',1234567892123456789);
    SELECT * FROM t1;
  }
} {0 {a 1234567890123456789 b 1234567891123456789 c 1234567892123456789}}

# A WHERE clause is not allowed to contain more than 99 terms.  Check to
# make sure this limit is enforced.
#
do_test misc1-10.0 {
  execsql {SELECT count(*) FROM manycol}
} {9}
do_test misc1-10.1 {
  set ::where {WHERE x0>=0}
  for {set i 1} {$i<=99} {incr i} {
    append ::where " AND x$i<>0"
  }
  catchsql "SELECT count(*) FROM manycol $::where"
} {0 9}
do_test misc1-10.2 {
  catchsql "SELECT count(*) FROM manycol $::where AND rowid>0"
} {1 {WHERE clause too complex - no more than 100 terms allowed}}
do_test misc1-10.3 {
  regsub "x0>=0" $::where "x0=0" ::where
  catchsql "DELETE FROM manycol $::where"
} {0 {}}
do_test misc1-10.4 {
  execsql {SELECT count(*) FROM manycol}
} {8}
do_test misc1-10.5 {
  catchsql "DELETE FROM manycol $::where AND rowid>0"
} {1 {WHERE clause too complex - no more than 100 terms allowed}}
do_test misc1-10.6 {
  execsql {SELECT x1 FROM manycol WHERE x0=100}
} {101}
do_test misc1-10.7 {
  regsub "x0=0" $::where "x0=100" ::where
  catchsql "UPDATE manycol SET x1=x1+1 $::where"
} {0 {}}
do_test misc1-10.8 {
  execsql {SELECT x1 FROM manycol WHERE x0=100}
} {102}
do_test misc1-10.9 {
  catchsql "UPDATE manycol SET x1=x1+1 $::where AND rowid>0"
} {1 {WHERE clause too complex - no more than 100 terms allowed}}
do_test misc1-10.10 {
  execsql {SELECT x1 FROM manycol WHERE x0=100}
} {102}

# Make sure the initialization works even if a database is opened while
# another process has the database locked.
#
# Update for v3: The BEGIN doesn't lock the database so the schema is read
# and the SELECT returns successfully.
do_test misc1-11.1 {
  execsql {BEGIN}
  execsql {UPDATE t1 SET a=0 WHERE 0}
  sqlite3 db2 test.db
  set rc [catch {db2 eval {SELECT count(*) FROM t1}} msg]
  lappend rc $msg
# v2 result: {1 {database is locked}}
} {0 3}
do_test misc1-11.2 {
  execsql {COMMIT}
  set rc [catch {db2 eval {SELECT count(*) FROM t1}} msg]
  db2 close
  lappend rc $msg
} {0 3}

# Make sure string comparisons really do compare strings in format4+.
# Similar tests in the format3.test file show that for format3 and earlier
# all comparisions where numeric if either operand looked like a number.
#
do_test misc1-12.1 {
  execsql {SELECT '0'=='0.0'}
} {0}
do_test misc1-12.2 {
  execsql {SELECT '0'==0.0}
} {0}
do_test misc1-12.3 {
  execsql {SELECT '12345678901234567890'=='12345678901234567891'}
} {0}
do_test misc1-12.4 {
  execsql {
    CREATE TABLE t6(a INT UNIQUE, b TEXT UNIQUE);
    INSERT INTO t6 VALUES('0','0.0');
    SELECT * FROM t6;
  }
} {0 0.0}
do_test misc1-12.5 {
  execsql {
    INSERT OR IGNORE INTO t6 VALUES(0.0,'x');
    SELECT * FROM t6;
  }
} {0 0.0}
do_test misc1-12.6 {
  execsql {
    INSERT OR IGNORE INTO t6 VALUES('y',0);
    SELECT * FROM t6;
  }
} {0 0.0 y 0}
do_test misc1-12.7 {
  execsql {
    CREATE TABLE t7(x INTEGER, y TEXT, z);
    INSERT INTO t7 VALUES(0,0,1);
    INSERT INTO t7 VALUES(0.0,0,2);
    INSERT INTO t7 VALUES(0,0.0,3);
    INSERT INTO t7 VALUES(0.0,0.0,4);
    SELECT DISTINCT x, y FROM t7 ORDER BY z;
  }
} {0 0 0 0.0}
do_test misc1-12.8 {
  execsql {
    SELECT min(z), max(z), count(z) FROM t7 GROUP BY x ORDER BY 1;
  }
} {1 4 4}
do_test misc1-12.9 {
  execsql {
    SELECT min(z), max(z), count(z) FROM t7 GROUP BY y ORDER BY 1;
  }
} {1 2 2 3 4 2}

# This used to be an error.  But we changed the code so that arbitrary
# identifiers can be used as a collating sequence.  Collation is by text
# if the identifier contains "text", "blob", or "clob" and is numeric
# otherwise.
#
# Update: In v3, it is an error again.
#
#do_test misc1-12.10 {
#  catchsql {
#    SELECT * FROM t6 ORDER BY a COLLATE unknown;
#  }
#} {0 {0 0.0 y 0}}
do_test misc1-12.11 {
  execsql {
    CREATE TABLE t8(x TEXT COLLATE numeric, y INTEGER COLLATE text, z);
    INSERT INTO t8 VALUES(0,0,1);
    INSERT INTO t8 VALUES(0.0,0,2);
    INSERT INTO t8 VALUES(0,0.0,3);
    INSERT INTO t8 VALUES(0.0,0.0,4);
    SELECT DISTINCT x, y FROM t8 ORDER BY z;
  }
} {0 0 0.0 0}
do_test misc1-12.12 {
  execsql {
    SELECT min(z), max(z), count(z) FROM t8 GROUP BY x ORDER BY 1;
  }
} {1 3 2 2 4 2}
do_test misc1-12.13 {
  execsql {
    SELECT min(z), max(z), count(z) FROM t8 GROUP BY y ORDER BY 1;
  }
} {1 4 4}

# There was a problem with realloc() in the OP_MemStore operation of
# the VDBE.  A buffer was being reallocated but some pointers into 
# the old copy of the buffer were not being moved over to the new copy.
# The following code tests for the problem.
#
do_test misc1-13.1 {
   execsql {
     CREATE TABLE t9(x,y);
     INSERT INTO t9 VALUES('one',1);
     INSERT INTO t9 VALUES('two',2);
     INSERT INTO t9 VALUES('three',3);
     INSERT INTO t9 VALUES('four',4);
     INSERT INTO t9 VALUES('five',5);
     INSERT INTO t9 VALUES('six',6);
     INSERT INTO t9 VALUES('seven',7);
     INSERT INTO t9 VALUES('eight',8);
     INSERT INTO t9 VALUES('nine',9);
     INSERT INTO t9 VALUES('ten',10);
     INSERT INTO t9 VALUES('eleven',11);
     SELECT y FROM t9
     WHERE x=(SELECT x FROM t9 WHERE y=1)
        OR x=(SELECT x FROM t9 WHERE y=2)
        OR x=(SELECT x FROM t9 WHERE y=3)
        OR x=(SELECT x FROM t9 WHERE y=4)
        OR x=(SELECT x FROM t9 WHERE y=5)
        OR x=(SELECT x FROM t9 WHERE y=6)
        OR x=(SELECT x FROM t9 WHERE y=7)
        OR x=(SELECT x FROM t9 WHERE y=8)
        OR x=(SELECT x FROM t9 WHERE y=9)
        OR x=(SELECT x FROM t9 WHERE y=10)
        OR x=(SELECT x FROM t9 WHERE y=11)
        OR x=(SELECT x FROM t9 WHERE y=12)
        OR x=(SELECT x FROM t9 WHERE y=13)
        OR x=(SELECT x FROM t9 WHERE y=14)
     ;
   }
} {1 2 3 4 5 6 7 8 9 10 11}

# Make sure a database connection still works after changing the
# working directory.
#
do_test misc1-14.1 {
  file mkdir tempdir
  cd tempdir
  execsql {BEGIN}
  file exists ./test.db-journal
} {0}
do_test misc1-14.2 {
  execsql {UPDATE t1 SET a=0 WHERE 0}
  file exists ../test.db-journal
} {1}
do_test misc1-14.3 {
  cd ..
  file delete tempdir
  execsql {COMMIT}
  file exists ./test.db-journal
} {0}

# A failed create table should not leave the table in the internal
# data structures.  Ticket #238.
#
do_test misc1-15.1 {
  catchsql {
    CREATE TABLE t10 AS SELECT c1;
  }
} {1 {no such column: c1}}
do_test misc1-15.2 {
  catchsql {
    CREATE TABLE t10 AS SELECT 1;
  }
  # The bug in ticket #238 causes the statement above to fail with
  # the error "table t10 alread exists"
} {0 {}}

# Test for memory leaks when a CREATE TABLE containing a primary key
# fails.  Ticket #249.
#
do_test misc1-16.1 {
  catchsql {SELECT name FROM sqlite_master LIMIT 1}
  catchsql {
    CREATE TABLE test(a integer, primary key(a));
  }
} {0 {}}
do_test misc1-16.2 {
  catchsql {
    CREATE TABLE test(a integer, primary key(a));
  }
} {1 {table test already exists}}
do_test misc1-16.3 {
  catchsql {
    CREATE TABLE test2(a text primary key, b text, primary key(a,b));
  }
} {1 {table "test2" has more than one primary key}}
do_test misc1-16.4 {
  execsql {
    INSERT INTO test VALUES(1);
    SELECT rowid, a FROM test;
  }
} {1 1}
do_test misc1-16.5 {
  execsql {
    INSERT INTO test VALUES(5);
    SELECT rowid, a FROM test;
  }
} {1 1 5 5}
do_test misc1-16.6 {
  execsql {
    INSERT INTO test VALUES(NULL);
    SELECT rowid, a FROM test;
  }
} {1 1 5 5 6 6}

# Ticket #333: Temp triggers that modify persistent tables.
#
do_test misc1-17.1 {
  execsql {
    BEGIN;
    CREATE TABLE RealTable(TestID INTEGER PRIMARY KEY, TestString TEXT);
    CREATE TEMP TABLE TempTable(TestID INTEGER PRIMARY KEY, TestString TEXT);
    CREATE TEMP TRIGGER trigTest_1 AFTER UPDATE ON TempTable BEGIN
      INSERT INTO RealTable(TestString) 
         SELECT new.TestString FROM TempTable LIMIT 1;
    END;
    INSERT INTO TempTable(TestString) VALUES ('1');
    INSERT INTO TempTable(TestString) VALUES ('2');
    UPDATE TempTable SET TestString = TestString + 1 WHERE TestID IN (1, 2);
    COMMIT;
    SELECT TestString FROM RealTable ORDER BY 1;
  }
} {2 3}

finish_test

--- NEW FILE: misc2.test ---
# 2003 June 21
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Test for ticket #360
#
do_test misc2-1.1 {
  catchsql {
    CREATE TABLE FOO(bar integer);
    CREATE TRIGGER foo_insert BEFORE INSERT ON foo BEGIN
      SELECT CASE WHEN (NOT new.bar BETWEEN 0 AND 20)
             THEN raise(rollback, 'aiieee') END;
    END;
    INSERT INTO foo(bar) VALUES (1);
  }
} {0 {}}
do_test misc2-1.2 {
  catchsql {
    INSERT INTO foo(bar) VALUES (111);
  }
} {1 aiieee}

# Make sure ROWID works on a view and a subquery.  Ticket #364
#
do_test misc2-2.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    CREATE TABLE t2(a,b,c);
    INSERT INTO t2 VALUES(7,8,9);
    SELECT rowid, * FROM (SELECT * FROM t1, t2);
  }
} {{} 1 2 3 7 8 9}
do_test misc2-2.2 {
  execsql {
    CREATE VIEW v1 AS SELECT * FROM t1, t2;
    SELECT rowid, * FROM v1;
  }
} {{} 1 2 3 7 8 9}

# Check name binding precedence.  Ticket #387
#
do_test misc2-3.1 {
  catchsql {
    SELECT t1.b+t2.b AS a, t1.a, t2.a FROM t1, t2 WHERE a==10
  }
} {1 {ambiguous column name: a}}

# Make sure 32-bit integer overflow is handled properly in queries.
# ticket #408
#
do_test misc2-4.1 {
  execsql {
    INSERT INTO t1 VALUES(4000000000,'a','b');
    SELECT a FROM t1 WHERE a>1;
  }
} {4000000000}
do_test misc2-4.2 {
  execsql {
    INSERT INTO t1 VALUES(2147483648,'b2','c2');
    INSERT INTO t1 VALUES(2147483647,'b3','c3');
    SELECT a FROM t1 WHERE a>2147483647;
  }
} {4000000000 2147483648}
do_test misc2-4.3 {
  execsql {
    SELECT a FROM t1 WHERE a<2147483648;
  }
} {1 2147483647}
do_test misc2-4.4 {
  execsql {
    SELECT a FROM t1 WHERE a<=2147483648;
  }
} {1 2147483648 2147483647}
do_test misc2-4.5 {
  execsql {
    SELECT a FROM t1 WHERE a<10000000000;
  }
} {1 4000000000 2147483648 2147483647}
do_test misc2-4.6 {
  execsql {
    SELECT a FROM t1 WHERE a<1000000000000 ORDER BY 1;
  }
} {1 2147483647 2147483648 4000000000}

# There were some issues with expanding a SrcList object using a call
# to sqliteSrcListAppend() if the SrcList had previously been duplicated
# using a call to sqliteSrcListDup().  Ticket #416.  The following test
# makes sure the problem has been fixed.
#
do_test misc2-5.1 {
  execsql {
    CREATE TABLE x(a,b);
    CREATE VIEW y AS 
      SELECT x1.b AS p, x2.b AS q FROM x AS x1, x AS x2 WHERE x1.a=x2.a;
    CREATE VIEW z AS
      SELECT y1.p, y2.p FROM y AS y1, y AS y2 WHERE y1.q=y2.q;
    SELECT * from z;
  }
} {}

# Make sure we can open a database with an empty filename.  What this
# does is store the database in a temporary file that is deleted when
# the database is closed.  Ticket #432.
#
do_test misc2-6.1 {
  db close
  sqlite3 db {}
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t1;
  }
} {1 2}

# Make sure we get an error message (not a segfault) on an attempt to
# update a table from within the callback of a select on that same
# table.
#
do_test misc2-7.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
  }
  set rc [catch {
    db eval {SELECT rowid FROM t1} {} {
      db eval "DELETE FROM t1 WHERE rowid=$rowid"
    }
  } msg]
  lappend rc $msg
} {1 {database table is locked}}
do_test misc2-7.2 {
  set rc [catch {
    db eval {SELECT rowid FROM t1} {} {
      db eval "INSERT INTO t1 VALUES(3)"
    }
  } msg]
  lappend rc $msg
} {1 {database table is locked}}
do_test misc2-7.3 {
  db close
  file delete -force test.db
  sqlite3 db :memory:
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
  }
  set rc [catch {
    db eval {SELECT rowid FROM t1} {} {
      db eval "DELETE FROM t1 WHERE rowid=$rowid"
    }
  } msg]
  lappend rc $msg
} {1 {database table is locked}}
do_test misc2-7.4 {
  set rc [catch {
    db eval {SELECT rowid FROM t1} {} {
      db eval "INSERT INTO t1 VALUES(3)"
    }
  } msg]
  lappend rc $msg
} {1 {database table is locked}}

# Ticket #453.  If the SQL ended with "-", the tokenizer was calling that
# an incomplete token, which caused problem.  The solution was to just call
# it a minus sign.
#
do_test misc2-8.1 {
  catchsql {-}
} {1 {near "-": syntax error}}

# Ticket #513.  Make sure the VDBE stack does not grow on a 3-way join.
#
do_test misc2-9.1 {
  execsql {
    BEGIN;
    CREATE TABLE counts(n INTEGER PRIMARY KEY);
    INSERT INTO counts VALUES(0);
    INSERT INTO counts VALUES(1);
    INSERT INTO counts SELECT n+2 FROM counts;
    INSERT INTO counts SELECT n+4 FROM counts;
    INSERT INTO counts SELECT n+8 FROM counts;
    COMMIT;

    CREATE TEMP TABLE x AS
    SELECT dim1.n, dim2.n, dim3.n
    FROM counts AS dim1, counts AS dim2, counts AS dim3
    WHERE dim1.n<10 AND dim2.n<10 AND dim3.n<10;

    SELECT count(*) FROM x;
  }
} {1000}
do_test misc2-9.2 {
  execsql {
    DROP TABLE x;
    CREATE TEMP TABLE x AS
    SELECT dim1.n, dim2.n, dim3.n
    FROM counts AS dim1, counts AS dim2, counts AS dim3
    WHERE dim1.n>=6 AND dim2.n>=6 AND dim3.n>=6;

    SELECT count(*) FROM x;
  }
} {1000}
do_test misc2-9.3 {
  execsql {
    DROP TABLE x;
    CREATE TEMP TABLE x AS
    SELECT dim1.n, dim2.n, dim3.n, dim4.n
    FROM counts AS dim1, counts AS dim2, counts AS dim3, counts AS dim4
    WHERE dim1.n<5 AND dim2.n<5 AND dim3.n<5 AND dim4.n<5;

    SELECT count(*) FROM x;
  }
} [expr 5*5*5*5]

finish_test

--- NEW FILE: misc3.test ---
# 2003 December 17
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Ticket #529.  Make sure an ABORT does not damage the in-memory cache
# that will be used by subsequent statements in the same transaction.
#
do_test misc3-1.1 {
  execsql {
    CREATE TABLE t1(a UNIQUE,b);
    INSERT INTO t1
      VALUES(1,'a23456789_b23456789_c23456789_d23456789_e23456789_');
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    UPDATE t1 SET b=b||b;
    INSERT INTO t1 VALUES(2,'x');
    UPDATE t1 SET b=substr(b,1,500);
    BEGIN;
  }
  catchsql {UPDATE t1 SET a=CASE a WHEN 2 THEN 1 ELSE a END, b='y';}
  execsql {
    CREATE TABLE t2(x,y);
    COMMIT;
    PRAGMA integrity_check;
  }
} ok
do_test misc3-1.2 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    VACUUM;
    CREATE TABLE t1(a UNIQUE,b);
    INSERT INTO t1
       VALUES(1,'a23456789_b23456789_c23456789_d23456789_e23456789_');
    INSERT INTO t1 SELECT a+1, b||b FROM t1;
    INSERT INTO t1 SELECT a+2, b||b FROM t1;
    INSERT INTO t1 SELECT a+4, b FROM t1;
    INSERT INTO t1 SELECT a+8, b FROM t1;
    INSERT INTO t1 SELECT a+16, b FROM t1;
    INSERT INTO t1 SELECT a+32, b FROM t1;
    INSERT INTO t1 SELECT a+64, b FROM t1;

    BEGIN;
  }
  catchsql {UPDATE t1 SET a=CASE a WHEN 128 THEN 127 ELSE a END, b='';}
  execsql {
    INSERT INTO t1 VALUES(200,'hello out there');
    COMMIT;
    PRAGMA integrity_check;
  }
} ok

# Tests of the sqliteAtoF() function in util.c
#
do_test misc3-2.1 {
  execsql {SELECT 2e-25*0.5e25}
} 1.0
do_test misc3-2.2 {
  execsql {SELECT 2.0e-25*000000.500000000000000000000000000000e+00025}
} 1.0
do_test misc3-2.3 {
  execsql {SELECT 000000000002e-0000000025*0.5e25}
} 1.0
do_test misc3-2.4 {
  execsql {SELECT 2e-25*0.5e250}
} 1e+225
do_test misc3-2.5 {
  execsql {SELECT 2.0e-250*0.5e25}
} 1e-225
do_test misc3-2.6 {
  execsql {SELECT '-2.0e-127' * '-0.5e27'}
} 1e-100
do_test misc3-2.7 {
  execsql {SELECT '+2.0e-127' * '-0.5e27'}
} -1e-100
do_test misc3-2.8 {
  execsql {SELECT 2.0e-27 * '+0.5e+127'}
} 1e+100
do_test misc3-2.9 {
  execsql {SELECT 2.0e-27 * '+0.000005e+132'}
} 1e+100

# Ticket #522.  Make sure integer overflow is handled properly in
# indices.
#
do_test misc3-3.1 {
  execsql {PRAGMA integrity_check}
} ok
do_test misc3-3.2 {
  execsql {
    CREATE TABLE t2(a INT UNIQUE);
    PRAGMA integrity_check;
  }
} ok
do_test misc3-3.3 {
  execsql {
    INSERT INTO t2 VALUES(2147483648);
    PRAGMA integrity_check;
  }
} ok
do_test misc3-3.4 {
  execsql {
    INSERT INTO t2 VALUES(-2147483649);
    PRAGMA integrity_check;
  }
} ok
do_test misc3-3.5 {
  execsql {
    INSERT INTO t2 VALUES(+2147483649);
    PRAGMA integrity_check;
  }
} ok
do_test misc3-3.6 {
  execsql {
    INSERT INTO t2 VALUES(+2147483647);
    INSERT INTO t2 VALUES(-2147483648);
    INSERT INTO t2 VALUES(-2147483647);
    INSERT INTO t2 VALUES(2147483646);
    SELECT * FROM t2 ORDER BY a;
  }
} {-2147483649 -2147483648 -2147483647 2147483646 2147483647 2147483648 2147483649}
do_test misc3-3.7 {
  execsql {
    SELECT * FROM t2 WHERE a>=-2147483648 ORDER BY a;
  }
} {-2147483648 -2147483647 2147483646 2147483647 2147483648 2147483649}
do_test misc3-3.8 {
  execsql {
    SELECT * FROM t2 WHERE a>-2147483648 ORDER BY a;
  }
} {-2147483647 2147483646 2147483647 2147483648 2147483649}
do_test misc3-3.9 {
  execsql {
    SELECT * FROM t2 WHERE a>-2147483649 ORDER BY a;
  }
} {-2147483648 -2147483647 2147483646 2147483647 2147483648 2147483649}
do_test misc3-3.10 {
  execsql {
    SELECT * FROM t2 WHERE a>=0 AND a<2147483649 ORDER BY a DESC;
  }
} {2147483648 2147483647 2147483646}
do_test misc3-3.11 {
  execsql {
    SELECT * FROM t2 WHERE a>=0 AND a<=2147483648 ORDER BY a DESC;
  }
} {2147483648 2147483647 2147483646}
do_test misc3-3.12 {
  execsql {
    SELECT * FROM t2 WHERE a>=0 AND a<2147483648 ORDER BY a DESC;
  }
} {2147483647 2147483646}
do_test misc3-3.13 {
  execsql {
    SELECT * FROM t2 WHERE a>=0 AND a<=2147483647 ORDER BY a DESC;
  }
} {2147483647 2147483646}
do_test misc3-3.14 {
  execsql {
    SELECT * FROM t2 WHERE a>=0 AND a<2147483647 ORDER BY a DESC;
  }
} {2147483646}

# Ticket #565.  A stack overflow is occurring when the subquery to the
# right of an IN operator contains many NULLs
#
do_test misc3-4.1 {
  execsql {
    CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
    INSERT INTO t3(b) VALUES('abc');
    INSERT INTO t3(b) VALUES('xyz');
    INSERT INTO t3(b) VALUES(NULL);
    INSERT INTO t3(b) VALUES(NULL);
    INSERT INTO t3(b) SELECT b||'d' FROM t3;
    INSERT INTO t3(b) SELECT b||'e' FROM t3;
    INSERT INTO t3(b) SELECT b||'f' FROM t3;
    INSERT INTO t3(b) SELECT b||'g' FROM t3;
    INSERT INTO t3(b) SELECT b||'h' FROM t3;
    SELECT count(a), count(b) FROM t3;
  }
} {128 64}
do_test misc3-4.2 {
  execsql {
    SELECT count(a) FROM t3 WHERE b IN (SELECT b FROM t3);
  }
} {64}
do_test misc3-4.3 {
  execsql {
    SELECT count(a) FROM t3 WHERE b IN (SELECT b FROM t3 ORDER BY a+1);
  }
} {64}

# Ticket #601:  Putting a left join inside "SELECT * FROM (<join-here>)"
# gives different results that if the outer "SELECT * FROM ..." is omitted.
#
do_test misc3-5.1 {
  execsql {
    CREATE TABLE x1 (b, c);
    INSERT INTO x1 VALUES('dog',3);
    INSERT INTO x1 VALUES('cat',1);
    INSERT INTO x1 VALUES('dog',4);
    CREATE TABLE x2 (c, e);
    INSERT INTO x2 VALUES(1,'one');
    INSERT INTO x2 VALUES(2,'two');
    INSERT INTO x2 VALUES(3,'three');
    INSERT INTO x2 VALUES(4,'four');
    SELECT x2.c AS c, e, b FROM x2 LEFT JOIN
       (SELECT b, max(c)+0 AS c FROM x1 GROUP BY b)
       USING(c);
  }
} {1 one cat 2 two {} 3 three {} 4 four dog}
do_test misc4-5.2 {
  execsql {
    SELECT * FROM (
      SELECT x2.c AS c, e, b FROM x2 LEFT JOIN
         (SELECT b, max(c)+0 AS c FROM x1 GROUP BY b)
         USING(c)
    );
  }
} {1 one cat 2 two {} 3 three {} 4 four dog}

# Ticket #626:  make sure EXPLAIN prevents BEGIN and COMMIT from working.
#
do_test misc3-6.1 {
  execsql {EXPLAIN BEGIN}
  catchsql {BEGIN}
} {0 {}}
do_test misc3-6.2 {
  execsql {EXPLAIN COMMIT}
  catchsql {COMMIT}
} {0 {}}
do_test misc3-6.3 {
  execsql {BEGIN; EXPLAIN ROLLBACK}
  catchsql {ROLLBACK}
} {0 {}}

# Ticket #640:  vdbe stack overflow with a LIMIT clause on a SELECT inside
# of a trigger.
#
do_test misc3-7.1 {
  execsql {
    BEGIN;
    CREATE TABLE y1(a);
    CREATE TABLE y2(b);
    CREATE TABLE y3(c);
    CREATE TRIGGER r1 AFTER DELETE ON y1 FOR EACH ROW BEGIN
      INSERT INTO y3(c) SELECT b FROM y2 ORDER BY b LIMIT 1;
    END;
    INSERT INTO y1 VALUES(1);
    INSERT INTO y1 VALUES(2);
    INSERT INTO y1 SELECT a+2 FROM y1;
    INSERT INTO y1 SELECT a+4 FROM y1;
    INSERT INTO y1 SELECT a+8 FROM y1;
    INSERT INTO y1 SELECT a+16 FROM y1;
    INSERT INTO y2 SELECT a FROM y1;
    COMMIT;
    SELECT count(*) FROM y1;
  }
} 32
do_test misc3-7.2 {
  execsql {
    DELETE FROM y1;
    SELECT count(*) FROM y1;
  }
} 0
do_test misc3-7.3 {
  execsql {
    SELECT count(*) FROM y3;
  }
} 32

# Ticket #668:  VDBE stack overflow occurs when the left-hand side
# of an IN expression is NULL and the result is used as an integer, not
# as a jump.
#
do_test misc-8.1 {
  execsql {
    SELECT count(CASE WHEN b IN ('abc','xyz') THEN 'x' END) FROM t3
  }
} {2}
do_test misc-8.2 {
  execsql {
    SELECT count(*) FROM t3 WHERE 1+(b IN ('abc','xyz'))==2
  }
} {2}

finish_test

--- NEW FILE: misc4.test ---
# 2004 Jun 27
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc4.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Prepare a statement that will create a temporary table.  Then do
# a rollback.  Then try to execute the prepared statement.
#
do_test misc4-1.1 {
  db close
  set DB [sqlite3 db test.db]
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
  }
} {}
do_test misc4-1.2 {
  set sql {CREATE TEMP TABLE t2 AS SELECT * FROM t1}
  set stmt [sqlite3_prepare $DB $sql -1 TAIL]
  execsql {
    BEGIN;
    CREATE TABLE t3(a,b,c);
    INSERT INTO t1 SELECT * FROM t1;
    ROLLBACK;
  }
} {}
do_test misc4-1.3 {
  sqlite3_step $stmt
} SQLITE_DONE
do_test misc4-1.4 {
  execsql {
    SELECT * FROM temp.t2;
  }
} {1}

# Drop the temporary table, then rerun the prepared  statement to
# recreate it again.  This recreates ticket #807.
#
do_test misc4-1.5 {
  execsql {DROP TABLE t2}
  sqlite3_reset $stmt
  sqlite3_step $stmt
} {SQLITE_ERROR}
do_test misc4-1.6 {
  sqlite3_finalize $stmt
} {SQLITE_SCHEMA}

# Prepare but do not execute various CREATE statements.  Then before
# those statements are executed, try to use the tables, indices, views,
# are triggers that were created.
#
do_test misc4-2.1 {
  set stmt [sqlite3_prepare $DB {CREATE TABLE t3(x);} -1 TAIL]
  catchsql {
    INSERT INTO t3 VALUES(1);
  }
} {1 {no such table: t3}}
do_test misc4-2.2 {
  sqlite3_step $stmt
} SQLITE_DONE
do_test misc4-2.3 {
  sqlite3_finalize $stmt
} SQLITE_OK
do_test misc4-2.4 {
  catchsql {
    INSERT INTO t3 VALUES(1);
  }
} {0 {}}


finish_test

--- NEW FILE: misuse.test ---
# 2002 May 10
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the SQLITE_MISUSE detection logic.
# This test file leaks memory and file descriptors.
#
# $Id: misuse.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc catchsql2 {sql} {
  set r [
    catch {
      set res [list]
      db eval $sql data {
        if { $res==[list] } {
          foreach f $data(*) {lappend res $f}
        }
        foreach f $data(*) {lappend res $data($f)}
      }
      set res
    } msg
  ]
  lappend r $msg
}


# Make sure the test logic works
#
do_test misuse-1.1 {
  db close
  catch {file delete -force test2.db}
  set ::DB [sqlite3 db test2.db]
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
  }
  catchsql2 {
    SELECT * FROM t1
  }
} {0 {a b 1 2}}
do_test misuse-1.2 {
  catchsql2 {
    SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1
  }
} {1 {no such function: x_coalesce}}
do_test misuse-1.3 {
  sqlite3_create_function $::DB
  catchsql2 {
    SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1
  }
} {0 {xyz 1}}

# Use the x_sqlite_exec() SQL function to simulate the effect of two
# threads trying to use the same database at the same time.
#
# It used to be prohibited to invoke sqlite_exec() from within a function,
# but that has changed.  The following tests used to cause errors but now
# they do not.
#
do_test misuse-1.4 {
  catchsql2 {
     SELECT x_sqlite_exec('SELECT * FROM t1') AS xyz;
  } 
} {0 {xyz {1 2}}}
do_test misuse-1.5 {
  catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-1.6 {
  catchsql {
    SELECT * FROM t1
  }
} {0 {1 2}}

# Attempt to register a new SQL function while an sqlite_exec() is active.
#
do_test misuse-2.1 {
  db close
  set ::DB [sqlite3 db test2.db]
  execsql {
    SELECT * FROM t1
  }
} {1 2}
do_test misuse-2.2 {
  catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-2.3 {
  set v [catch {
    db eval {SELECT * FROM t1} {} {
      sqlite3_create_function $::DB
    }
  } msg]
  lappend v $msg
} {1 {library routine called out of sequence}}
do_test misuse-2.4 {
  catchsql2 {SELECT * FROM t1}
} {1 {library routine called out of sequence}}
do_test misuse-2.5 {
  catchsql {
    SELECT * FROM t1
  }
} {1 {library routine called out of sequence}}

# Attempt to register a new SQL aggregate while an sqlite_exec() is active.
#
do_test misuse-3.1 {
  db close
  set ::DB [sqlite3 db test2.db]
  execsql {
    SELECT * FROM t1
  }
} {1 2}
do_test misuse-3.2 {
  catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-3.3 {
  set v [catch {
    db eval {SELECT * FROM t1} {} {
      sqlite3_create_aggregate $::DB
    }
  } msg]
  lappend v $msg
} {1 {library routine called out of sequence}}
do_test misuse-3.4 {
  catchsql2 {SELECT * FROM t1}
} {1 {library routine called out of sequence}}
do_test misuse-3.5 {
  catchsql {
    SELECT * FROM t1
  }
} {1 {library routine called out of sequence}}

# Attempt to close the database from an sqlite_exec callback.
#
# Update for v3: The db cannot be closed because there are active
# VMs. The sqlite3_close call would return SQLITE_BUSY.
do_test misuse-4.1 {
  db close
  set ::DB [sqlite3 db test2.db]
  execsql {
    SELECT * FROM t1
  }
} {1 2}
do_test misuse-4.2 {
  catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-4.3 {
  set v [catch {
    db eval {SELECT * FROM t1} {} {
      set r [sqlite3_close $::DB]
    }
  } msg]
  lappend v $msg $r
} {0 {} SQLITE_BUSY}
do_test misuse-4.4 {
  sqlite3_close $::DB
  catchsql2 {SELECT * FROM t1}
} {1 {library routine called out of sequence}}
do_test misuse-4.5 {
  catchsql {
    SELECT * FROM t1
  }
} {1 {library routine called out of sequence}}

# Attempt to use a database after it has been closed.
#
do_test misuse-5.1 {
  db close
  set ::DB [sqlite3 db test2.db]
  execsql {
    SELECT * FROM t1
  }
} {1 2}
do_test misuse-5.2 {
  catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-5.3 {
  db close
  set r [catch {
    sqlite3_prepare $::DB {SELECT * FROM t1} -1 TAIL
  } msg]
  lappend r $msg
} {1 {(21) library routine called out of sequence}}

finish_test

--- NEW FILE: notnull.test ---
# 2002 January 29
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the NOT NULL constraint.
#
# $Id: notnull.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test notnull-1.0 {
  execsql {
    CREATE TABLE t1 (
      a NOT NULL,
      b NOT NULL DEFAULT 5,
      c NOT NULL ON CONFLICT REPLACE DEFAULT 6,
      d NOT NULL ON CONFLICT IGNORE DEFAULT 7,
      e NOT NULL ON CONFLICT ABORT DEFAULT 8
    );
    SELECT * FROM t1;
  }
} {}
do_test notnull-1.1 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-1.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-1.3 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.4 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-1.5 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-1.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.7 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.8 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.9 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.b may not be NULL}}
do_test notnull-1.11 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.12 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-1.13 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-1.14 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-1.15 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-1.16 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.c may not be NULL}}
do_test notnull-1.17 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.d may not be NULL}}
do_test notnull-1.18 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 7 5}}
do_test notnull-1.19 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 4 8}}
do_test notnull-1.20 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.e may not be NULL}}
do_test notnull-1.21 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {0 {5 5 3 2 1}}

do_test notnull-2.1 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-2.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-2.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.4 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR ABORT t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-2.5 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET b=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.b may not be NULL}}
do_test notnull-2.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 5 3 5 4}}
do_test notnull-2.7 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.8 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET c=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 6 5 4}}
do_test notnull-2.9 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET d=null, a=b, b=a;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-2.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET e=null, a=b, b=a;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.e may not be NULL}}

do_test notnull-3.0 {
  execsql {
    CREATE INDEX t1a ON t1(a);
    CREATE INDEX t1b ON t1(b);
    CREATE INDEX t1c ON t1(c);
    CREATE INDEX t1d ON t1(d);
    CREATE INDEX t1e ON t1(e);
    CREATE INDEX t1abc ON t1(a,b,c);
  }
} {}
do_test notnull-3.1 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-3.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-3.3 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.4 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-3.5 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-3.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.7 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.8 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.9 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.b may not be NULL}}
do_test notnull-3.11 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.12 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 5 3 4 5}}
do_test notnull-3.13 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-3.14 {
  catchsql {
    DELETE FROM t1;
    INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {}}
do_test notnull-3.15 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 6 4 5}}
do_test notnull-3.16 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.c may not be NULL}}
do_test notnull-3.17 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.d may not be NULL}}
do_test notnull-3.18 {
  catchsql {
    DELETE FROM t1;
    INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 7 5}}
do_test notnull-3.19 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
    SELECT * FROM t1 order by a;
  }
} {0 {1 2 3 4 8}}
do_test notnull-3.20 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
    SELECT * FROM t1 order by a;
  }
} {1 {t1.e may not be NULL}}
do_test notnull-3.21 {
  catchsql {
    DELETE FROM t1;
    INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
    SELECT * FROM t1 order by a;
  }
} {0 {5 5 3 2 1}}

do_test notnull-4.1 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-4.2 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-4.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.4 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR ABORT t1 SET a=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.a may not be NULL}}
do_test notnull-4.5 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET b=null;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.b may not be NULL}}
do_test notnull-4.6 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 5 3 5 4}}
do_test notnull-4.7 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.8 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET c=null, d=e, e=d;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 6 5 4}}
do_test notnull-4.9 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET d=null, a=b, b=a;
    SELECT * FROM t1 ORDER BY a;
  }
} {0 {1 2 3 4 5}}
do_test notnull-4.10 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2,3,4,5);
    UPDATE t1 SET e=null, a=b, b=a;
    SELECT * FROM t1 ORDER BY a;
  }
} {1 {t1.e may not be NULL}}

finish_test

--- NEW FILE: null.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for proper treatment of the special
# value NULL.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table and some data to work with.
#
do_test null-1.0 {
  execsql {
    begin;
    create table t1(a,b,c);
    insert into t1 values(1,0,0);
    insert into t1 values(2,0,1);
    insert into t1 values(3,1,0);
    insert into t1 values(4,1,1);
    insert into t1 values(5,null,0);
    insert into t1 values(6,null,1);
    insert into t1 values(7,null,null);
    commit;
    select * from t1;
  }
} {1 0 0 2 0 1 3 1 0 4 1 1 5 {} 0 6 {} 1 7 {} {}}

# Check for how arithmetic expressions handle NULL
#
do_test null-1.1 {
  execsql {
    select ifnull(a+b,99) from t1;
  }
} {1 2 4 5 99 99 99}
do_test null-1.2 {
  execsql {
    select ifnull(b*c,99) from t1;
  }
} {0 0 0 1 99 99 99}

# Check to see how the CASE expression handles NULL values.  The
# first WHEN for which the test expression is TRUE is selected.
# FALSE and UNKNOWN test expressions are skipped.
#
do_test null-2.1 {
  execsql {
    select ifnull(case when b<>0 then 1 else 0 end, 99) from t1;
  }
} {0 0 1 1 0 0 0}
do_test null-2.2 {
  execsql {
    select ifnull(case when not b<>0 then 1 else 0 end, 99) from t1;
  }
} {1 1 0 0 0 0 0}
do_test null-2.3 {
  execsql {
    select ifnull(case when b<>0 and c<>0 then 1 else 0 end, 99) from t1;
  }
} {0 0 0 1 0 0 0}
do_test null-2.4 {
  execsql {
    select ifnull(case when not (b<>0 and c<>0) then 1 else 0 end, 99) from t1;
  }
} {1 1 1 0 1 0 0}
do_test null-2.5 {
  execsql {
    select ifnull(case when b<>0 or c<>0 then 1 else 0 end, 99) from t1;
  }
} {0 1 1 1 0 1 0}
do_test null-2.6 {
  execsql {
    select ifnull(case when not (b<>0 or c<>0) then 1 else 0 end, 99) from t1;
  }
} {1 0 0 0 0 0 0}
do_test null-2.7 {
  execsql {
    select ifnull(case b when c then 1 else 0 end, 99) from t1;
  }
} {1 0 0 1 0 0 0}
do_test null-2.8 {
  execsql {
    select ifnull(case c when b then 1 else 0 end, 99) from t1;
  }
} {1 0 0 1 0 0 0}

# Check to see that NULL values are ignored in aggregate functions.
#
do_test null-3.1 {
  execsql {
    select count(*), count(b), count(c), sum(b), sum(c), 
           avg(b), avg(c), min(b), max(b) from t1;
  }
} {7 4 6 2.0 3.0 0.5 0.5 0 1}

# Check to see how WHERE clauses handle NULL values.  A NULL value
# is the same as UNKNOWN.  The WHERE clause should only select those
# rows that are TRUE.  FALSE and UNKNOWN rows are rejected.
#
do_test null-4.1 {
  execsql {
    select a from t1 where b<10
  }
} {1 2 3 4}
do_test null-4.2 {
  execsql {
    select a from t1 where not b>10
  }
} {1 2 3 4}
do_test null-4.3 {
  execsql {
    select a from t1 where b<10 or c=1;
  }
} {1 2 3 4 6}
do_test null-4.4 {
  execsql {
    select a from t1 where b<10 and c=1;
  }
} {2 4}
do_test null-4.5 {
  execsql {
    select a from t1 where not (b<10 and c=1);
  }
} {1 3 5}

# The DISTINCT keyword on a SELECT statement should treat NULL values
# as distinct
#
do_test null-5.1 {
  execsql {
    select distinct b from t1 order by b;
  }
} {{} 0 1}

# A UNION to two queries should treat NULL values
# as distinct
#
do_test null-6.1 {
  execsql {
    select b from t1 union select c from t1 order by c;
  }
} {{} 0 1}

# The UNIQUE constraint only applies to non-null values
#
do_test null-7.1 {
  execsql {
    create table t2(a, b unique on conflict ignore);
    insert into t2 values(1,1);
    insert into t2 values(2,null);
    insert into t2 values(3,null);
    insert into t2 values(4,1);
    select a from t2;
  }
} {1 2 3}
do_test null-7.2 {
  execsql {
    create table t3(a, b, c, unique(b,c) on conflict ignore);
    insert into t3 values(1,1,1);
    insert into t3 values(2,null,1);
    insert into t3 values(3,null,1);
    insert into t3 values(4,1,1);
    select a from t3;
  }
} {1 2 3}

# Ticket #461 - Make sure nulls are handled correctly when doing a
# lookup using an index.
#
do_test null-8.1 {
  execsql {
    CREATE TABLE t4(x,y);
    INSERT INTO t4 VALUES(1,11);
    INSERT INTO t4 VALUES(2,NULL);
    SELECT x FROM t4 WHERE y=NULL;
  }
} {}
do_test null-8.2 {
  execsql {
    SELECT x FROM t4 WHERE y IN (33,NULL);
  }
} {}
do_test null-8.3 {
  execsql {
    SELECT x FROM t4 WHERE y<33 ORDER BY x;
  }
} {1}
do_test null-8.4 {
  execsql {
    SELECT x FROM t4 WHERE y>6 ORDER BY x;
  }
} {1}
do_test null-8.5 {
  execsql {
    SELECT x FROM t4 WHERE y!=33 ORDER BY x;
  }
} {1}
do_test null-8.11 {
  execsql {
    CREATE INDEX t4i1 ON t4(y);
    SELECT x FROM t4 WHERE y=NULL;
  }
} {}
do_test null-8.12 {
  execsql {
    SELECT x FROM t4 WHERE y IN (33,NULL);
  }
} {}
do_test null-8.13 {
  execsql {
    SELECT x FROM t4 WHERE y<33 ORDER BY x;
  }
} {1}
do_test null-8.14 {
  execsql {
    SELECT x FROM t4 WHERE y>6 ORDER BY x;
  }
} {1}
do_test null-8.15 {
  execsql {
    SELECT x FROM t4 WHERE y!=33 ORDER BY x;
  }
} {1}



finish_test

--- NEW FILE: pager.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: pager.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

if {[info commands pager_open]!=""} {
db close

# Basic sanity check.  Open and close a pager.
#
do_test pager-1.0 {
  catch {file delete -force ptf1.db}
  catch {file delete -force ptf1.db-journal}
  set v [catch {
    set ::p1 [pager_open ptf1.db 10]
  } msg]
} {0}
do_test pager-1.1 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager-1.2 {
  pager_pagecount $::p1
} {0}
do_test pager-1.3 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager-1.4 {
  pager_close $::p1
} {}

# Try to write a few pages.
#
do_test pager-2.1 {
  set v [catch {
    set ::p1 [pager_open ptf1.db 10]
  } msg]
} {0}
#do_test pager-2.2 {
#  set v [catch {
#    set ::g1 [page_get $::p1 0]
#  } msg]
#  lappend v $msg
#} {1 SQLITE_ERROR}
do_test pager-2.3.1 {
  set ::gx [page_lookup $::p1 1]
} {}
do_test pager-2.3.2 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager-2.3.3 {
  set v [catch {
    set ::g1 [page_get $::p1 1]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager-2.3.3 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.3.4 {
  set ::gx [page_lookup $::p1 1]
  expr {$::gx!=""}
} {1}
do_test pager-2.3.5 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.3.6 {
  expr {$::g1==$::gx}
} {1}
do_test pager-2.3.7 {
  page_unref $::gx
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.4 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.5 {
  pager_pagecount $::p1
} {0}
do_test pager-2.6 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.7 {
  page_number $::g1
} {1}
do_test pager-2.8 {
  page_read $::g1
} {}
do_test pager-2.9 {
  page_unref $::g1
} {}
do_test pager-2.10 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 1 ovfl 0}
do_test pager-2.11 {
  set ::g1 [page_get $::p1 1]
  expr {$::g1!=0}
} {1}
do_test pager-2.12 {
  page_number $::g1
} {1}
do_test pager-2.13 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.14 {
  set v [catch {
    page_write $::g1 "Page-One"
  } msg]
  lappend v $msg
} {0 {}}
do_test pager-2.15 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 0 miss 2 ovfl 0}
do_test pager-2.16 {
  page_read $::g1
} {Page-One}
do_test pager-2.17 {
  set v [catch {
    pager_commit $::p1
  } msg]
  lappend v $msg
} {0 {}}
do_test pager-2.20 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size -1 state 1 err 0 hit 1 miss 2 ovfl 0}
do_test pager-2.19 {
  pager_pagecount $::p1
} {1}
do_test pager-2.21 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 2 ovfl 0}
do_test pager-2.22 {
  page_unref $::g1
} {}
do_test pager-2.23 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 1 miss 2 ovfl 0}
do_test pager-2.24 {
  set v [catch {
    page_get $::p1 1
  } ::g1]
  if {$v} {lappend v $::g1}
  set v
} {0}
do_test pager-2.25 {
  page_read $::g1
} {Page-One}
do_test pager-2.26 {
  set v [catch {
    page_write $::g1 {page-one}
  } msg]
  lappend v $msg
} {0 {}}
do_test pager-2.27 {
  page_read $::g1
} {page-one}
do_test pager-2.28 {
  set v [catch {
    pager_rollback $::p1
  } msg]
  lappend v $msg
} {0 {}}
do_test pager-2.29 {
  page_unref $::g1
  set ::g1 [page_get $::p1 1]
  page_read $::g1
} {Page-One}
do_test pager-2.99 {
  pager_close $::p1
} {}

do_test pager-3.1 {
  set v [catch {
    set ::p1 [pager_open ptf1.db 15]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager-3.2 {
  pager_pagecount $::p1
} {1}
do_test pager-3.3 {
  set v [catch {
    set ::g(1) [page_get $::p1 1]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager-3.4 {
  page_read $::g(1)
} {Page-One}
do_test pager-3.5 {
  for {set i 2} {$i<=20} {incr i} {
    set gx [page_get $::p1 $i]
    page_write $gx "Page-$i"
    page_unref $gx
  }
  pager_commit $::p1
} {}
for {set i 2} {$i<=20} {incr i} {
  do_test pager-3.6.[expr {$i-1}] [subst {
    set gx \[page_get $::p1 $i\]
    set v \[page_read \$gx\]
    page_unref \$gx
    set v
  }] "Page-$i"
}
for {set i 1} {$i<=20} {incr i} {
  regsub -all CNT {
    set ::g1 [page_get $::p1 CNT]
    set ::g2 [page_get $::p1 CNT]
    set ::vx [page_read $::g2]
    expr {$::g1==$::g2}
  } $i body;
  do_test pager-3.7.$i.1 $body {1}
  regsub -all CNT {
    page_unref $::g2
    set vy [page_read $::g1]
    expr {$vy==$::vx}
  } $i body;
  do_test pager-3.7.$i.2 $body {1}
  regsub -all CNT {
    page_unref $::g1
    set gx [page_get $::p1 CNT]
    set vy [page_read $gx]
    page_unref $gx
    expr {$vy==$::vx}
  } $i body;
  do_test pager-3.7.$i.3 $body {1}
}
do_test pager-3.99 {
  pager_close $::p1
} {}

# tests of the checkpoint mechanism and api
#
do_test pager-4.0 {
  set v [catch {
    file delete -force ptf1.db
    set ::p1 [pager_open ptf1.db 15]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager-4.1 {
  set g1 [page_get $::p1 1]
  page_write $g1 "Page-1 v0"
  for {set i 2} {$i<=20} {incr i} {
    set gx [page_get $::p1 $i]
    page_write $gx "Page-$i v0"
    page_unref $gx
  }
  pager_commit $::p1
} {}
for {set i 1} {$i<=20} {incr i} {
  do_test pager-4.2.$i {
    set gx [page_get $p1 $i]
    set v [page_read $gx]
    page_unref $gx
    set v
  } "Page-$i v0"
}
do_test pager-4.3 {
  lrange [pager_stats $::p1] 0 1
} {ref 1}
do_test pager-4.4 {
  lrange [pager_stats $::p1] 8 9
} {state 1}

for {set i 1} {$i<20} {incr i} {
  do_test pager-4.5.$i.0 {
    set res {}
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v[expr {$i-1}]"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager-4.5.$i.1 {
    page_write $g1 "Page-1 v$i"
    lrange [pager_stats $p1] 8 9
  } {state 2}
  do_test pager-4.5.$i.2 {
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      page_write $gx "Page-$j v$i"
      page_unref $gx
      if {$j==$i} {
        pager_stmt_begin $p1
      }
    }
  } {}
  do_test pager-4.5.$i.3 {
    set res {}
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v$i"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager-4.5.$i.4 {
    pager_rollback $p1
    set res {}
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v[expr {$i-1}]"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager-4.5.$i.5 {
    page_write $g1 "Page-1 v$i"
    lrange [pager_stats $p1] 8 9
  } {state 2}
  do_test pager-4.5.$i.6 {
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      page_write $gx "Page-$j v$i"
      page_unref $gx
      if {$j==$i} {
        pager_stmt_begin $p1
      }
    }
  } {}
  do_test pager-4.5.$i.7 {
    pager_stmt_rollback $p1
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      if {$j<=$i || $i==1} {
        set shouldbe "Page-$j v$i"
      } else {
        set shouldbe "Page-$j v[expr {$i-1}]"
      }
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager-4.5.$i.8 {
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      page_write $gx "Page-$j v$i"
      page_unref $gx
      if {$j==$i} {
        pager_stmt_begin $p1
      }
    }
  } {}
  do_test pager-4.5.$i.9 {
    pager_stmt_commit $p1
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v$i"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager-4.5.$i.10 {
    pager_commit $p1
    lrange [pager_stats $p1] 8 9
  } {state 1}
}

do_test pager-4.99 {
  pager_close $::p1
} {}



  file delete -force ptf1.db

} ;# end if( not mem: and has pager_open command );

if 0 {
# Ticket #615: an assertion fault inside the pager.  It is a benign
# fault, but we might as well test for it.
#
do_test pager-5.1 {
  sqlite3 db test.db
  execsql {
    BEGIN;
    CREATE TABLE t1(x);
    PRAGMA synchronous=off;
    COMMIT;
  }
} {}
}

finish_test

--- NEW FILE: pager2.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: pager2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

if {[info commands pager_open]!=""} {
db close

# Basic sanity check.  Open and close a pager.
#
do_test pager2-1.0 {
  set v [catch {
    set ::p1 [pager_open :memory: 10]
  } msg]
} {0}
do_test pager2-1.1 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager2-1.2 {
  pager_pagecount $::p1
} {0}
do_test pager2-1.3 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager2-1.4 {
  pager_close $::p1
} {}

# Try to write a few pages.
#
do_test pager2-2.1 {
  set v [catch {
    set ::p1 [pager_open :memory: 10]
  } msg]
} {0}
#do_test pager2-2.2 {
#  set v [catch {
#    set ::g1 [page_get $::p1 0]
#  } msg]
#  lappend v $msg
#} {1 SQLITE_ERROR}
do_test pager2-2.3.1 {
  set ::gx [page_lookup $::p1 1]
} {}
do_test pager2-2.3.2 {
  pager_stats $::p1
} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
do_test pager2-2.3.3 {
  set v [catch {
    set ::g1 [page_get $::p1 1]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager2-2.3.3 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.3.4 {
  set ::gx [page_lookup $::p1 1]
  expr {$::gx!=""}
} {1}
do_test pager2-2.3.5 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.3.6 {
  expr {$::g1==$::gx}
} {1}
do_test pager2-2.3.7 {
  page_unref $::gx
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.4 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.5 {
  pager_pagecount $::p1
} {0}
do_test pager2-2.6 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.7 {
  page_number $::g1
} {1}
do_test pager2-2.8 {
  page_read $::g1
} {}
do_test pager2-2.9 {
  page_unref $::g1
} {}
do_test pager2-2.10 {
  pager_stats $::p1
} {ref 0 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
do_test pager2-2.11 {
  set ::g1 [page_get $::p1 1]
  expr {$::g1!=0}
} {1}
do_test pager2-2.12 {
  page_number $::g1
} {1}
do_test pager2-2.13 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 1 miss 1 ovfl 0}
do_test pager2-2.14 {
  set v [catch {
    page_write $::g1 "Page-One"
  } msg]
  lappend v $msg
} {0 {}}
do_test pager2-2.15 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 3 err 0 hit 1 miss 1 ovfl 0}
do_test pager2-2.16 {
  page_read $::g1
} {Page-One}
do_test pager2-2.17 {
  set v [catch {
    pager_commit $::p1
  } msg]
  lappend v $msg
} {0 {}}
do_test pager2-2.20 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
do_test pager2-2.19 {
  pager_pagecount $::p1
} {1}
do_test pager2-2.21 {
  pager_stats $::p1
} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
do_test pager2-2.22 {
  page_unref $::g1
} {}
do_test pager2-2.23 {
  pager_stats $::p1
} {ref 0 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
do_test pager2-2.24 {
  set v [catch {
    page_get $::p1 1
  } ::g1]
  if {$v} {lappend v $::g1}
  set v
} {0}
do_test pager2-2.25 {
  page_read $::g1
} {Page-One}
do_test pager2-2.26 {
  set v [catch {
    page_write $::g1 {page-one}
  } msg]
  lappend v $msg
} {0 {}}
do_test pager2-2.27 {
  page_read $::g1
} {page-one}
do_test pager2-2.28 {
  set v [catch {
    pager_rollback $::p1
  } msg]
  lappend v $msg
} {0 {}}
do_test pager2-2.29 {
  page_unref $::g1
  set ::g1 [page_get $::p1 1]
  page_read $::g1
} {Page-One}
#do_test pager2-2.99 {
#  pager_close $::p1
#} {}

#do_test pager2-3.1 {
#  set v [catch {
#    set ::p1 [pager_open :memory: 15]
#  } msg]
#  if {$v} {lappend v $msg}
#  set v
#} {0}
do_test pager2-3.2 {
  pager_pagecount $::p1
} {1}
do_test pager2-3.3 {
  set v [catch {
    set ::g(1) [page_get $::p1 1]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager2-3.4 {
  page_read $::g(1)
} {Page-One}
do_test pager2-3.5 {
  for {set i 2} {$i<=20} {incr i} {
    set gx [page_get $::p1 $i]
    page_write $gx "Page-$i"
    page_unref $gx
  }
  pager_commit $::p1
} {}
for {set i 2} {$i<=20} {incr i} {
  do_test pager2-3.6.[expr {$i-1}] [subst {
    set gx \[page_get $::p1 $i\]
    set v \[page_read \$gx\]
    page_unref \$gx
    set v
  }] "Page-$i"
}
for {set i 1} {$i<=20} {incr i} {
  regsub -all CNT {
    set ::g1 [page_get $::p1 CNT]
    set ::g2 [page_get $::p1 CNT]
    set ::vx [page_read $::g2]
    expr {$::g1==$::g2}
  } $i body;
  do_test pager2-3.7.$i.1 $body {1}
  regsub -all CNT {
    page_unref $::g2
    set vy [page_read $::g1]
    expr {$vy==$::vx}
  } $i body;
  do_test pager2-3.7.$i.2 $body {1}
  regsub -all CNT {
    page_unref $::g1
    set gx [page_get $::p1 CNT]
    set vy [page_read $gx]
    page_unref $gx
    expr {$vy==$::vx}
  } $i body;
  do_test pager2-3.7.$i.3 $body {1}
}
do_test pager2-3.99 {
  pager_close $::p1
} {}

# tests of the checkpoint mechanism and api
#
do_test pager2-4.0 {
  set v [catch {
    set ::p1 [pager_open :memory: 15]
  } msg]
  if {$v} {lappend v $msg}
  set v
} {0}
do_test pager2-4.1 {
  set g1 [page_get $::p1 1]
  page_write $g1 "Page-1 v0"
  for {set i 2} {$i<=20} {incr i} {
    set gx [page_get $::p1 $i]
    page_write $gx "Page-$i v0"
    page_unref $gx
  }
  pager_commit $::p1
} {}
for {set i 1} {$i<=20} {incr i} {
  do_test pager2-4.2.$i {
    set gx [page_get $p1 $i]
    set v [page_read $gx]
    page_unref $gx
    set v
  } "Page-$i v0"
}
do_test pager2-4.3 {
  lrange [pager_stats $::p1] 0 1
} {ref 1}
do_test pager2-4.4 {
  lrange [pager_stats $::p1] 8 9
} {state 1}

for {set i 1} {$i<20} {incr i} {
  do_test pager2-4.5.$i.0 {
    set res {}
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v[expr {$i-1}]"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager2-4.5.$i.1 {
    page_write $g1 "Page-1 v$i"
    lrange [pager_stats $p1] 8 9
  } {state 3}
  do_test pager2-4.5.$i.2 {
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      page_write $gx "Page-$j v$i"
      page_unref $gx
      if {$j==$i} {
        pager_stmt_begin $p1
      }
    }
  } {}
  do_test pager2-4.5.$i.3 {
    set res {}
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v$i"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager2-4.5.$i.4 {
    pager_rollback $p1
    set res {}
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v[expr {$i-1}]"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager2-4.5.$i.5 {
    page_write $g1 "Page-1 v$i"
    lrange [pager_stats $p1] 8 9
  } {state 3}
  do_test pager2-4.5.$i.6 {
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      page_write $gx "Page-$j v$i"
      page_unref $gx
      if {$j==$i} {
        pager_stmt_begin $p1
      }
    }
  } {}
  do_test pager2-4.5.$i.7 {
    pager_stmt_rollback $p1
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      if {$j<=$i || $i==1} {
        set shouldbe "Page-$j v$i"
      } else {
        set shouldbe "Page-$j v[expr {$i-1}]"
      }
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager2-4.5.$i.8 {
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      page_write $gx "Page-$j v$i"
      page_unref $gx
      if {$j==$i} {
        pager_stmt_begin $p1
      }
    }
  } {}
  do_test pager2-4.5.$i.9 {
    pager_stmt_commit $p1
    for {set j 2} {$j<=20} {incr j} {
      set gx [page_get $p1 $j]
      set value [page_read $gx]
      page_unref $gx
      set shouldbe "Page-$j v$i"
      if {$value!=$shouldbe} {
        lappend res $value $shouldbe
      }
    }
    set res
  } {}
  do_test pager2-4.5.$i.10 {
    pager_commit $p1
    lrange [pager_stats $p1] 8 9
  } {state 1}
}

do_test pager2-4.99 {
  pager_close $::p1
} {}

} ;# end if( not mem: and has pager_open command );


finish_test

--- NEW FILE: pager3.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: pager3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This test makes sure the database file is truncated back to the correct
# length on a rollback.
#
# After some preliminary setup, a transaction is start at NOTE (1).
# The create table on the following line allocates an additional page
# at the end of the database file.  But that page is not written because
# the database still has a RESERVED lock, not an EXCLUSIVE lock.  The
# new page is held in memory and the size of the file is unchanged.
# The insert at NOTE (2) begins adding additional pages.  Then it hits
# a constraint error and aborts.  The abort causes sqlite3OsTruncate()
# to be called to restore the file to the same length as it was after
# the create table.  But the create table results had not yet been
# written so the file is actually lengthened by this truncate.  Finally,
# the rollback at NOTE (3) is called to undo all the changes since the
# begin.  This rollback should truncate the database again.
# 
# This test was added because the second truncate at NOTE (3) was not
# occurring on early versions of SQLite 3.0.
#
do_test pager3-1.1 {
  execsql {
    create table t1(a unique, b);
    insert into t1 values(1, 'abcdefghijklmnopqrstuvwxyz');
    insert into t1 values(2, 'abcdefghijklmnopqrstuvwxyz');
    update t1 set b=b||a||b;
    update t1 set b=b||a||b;
    update t1 set b=b||a||b;
    update t1 set b=b||a||b;
    update t1 set b=b||a||b;
    update t1 set b=b||a||b;
    create temp table t2 as select * from t1;
    begin;                  ------- NOTE (1)
    create table t3(x);
  }
  catchsql {
    insert into t1 select 4-a, b from t2;  ----- NOTE (2)
  }
  execsql {
    rollback;  ------- NOTE (3)
  }
  db close
  sqlite3 db test.db
  execsql {
    pragma integrity_check;
  }
} ok


finish_test

--- NEW FILE: pagesize.test ---
# 2004 September 2
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
# This file implements tests for the page_size PRAGMA.
#
# $Id: pagesize.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test pagesize-1.1 {
  execsql {PRAGMA page_size}
} 1024
do_test pagesize-1.2 {
  catch {execsql {EXPLAIN PRAGMA page_size}}
} 0
do_test pagesize-1.3 {
  execsql {
    CREATE TABLE t1(a);
    PRAGMA page_size=2048;
    PRAGMA page_size;
  }
} 1024

do_test pagesize-1.4 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=511;
    PRAGMA page_size;
  }
} 1024
do_test pagesize-1.5 {
  execsql {
    PRAGMA page_size=512;
    PRAGMA page_size;
  }
} 512
do_test pagesize-1.6 {
  execsql {
    PRAGMA page_size=8192;
    PRAGMA page_size;
  }
} 8192
do_test pagesize-1.7 {
  execsql {
    PRAGMA page_size=65537;
    PRAGMA page_size;
  }
} 8192
  


foreach PGSZ {512 2000 2048 3000 4096} {
  do_test pagesize-2.$PGSZ.1 {
    db close
    file delete -force test.db
    sqlite3 db test.db
    execsql "PRAGMA page_size=$PGSZ"
    execsql {
      CREATE TABLE t1(x);
      PRAGMA page_size;
    }
  } $PGSZ
  do_test pagesize-2.$PGSZ.2 {
    db close
    sqlite3 db test.db
    execsql {
      PRAGMA page_size
    }
  } $PGSZ
  do_test pagesize-2.$PGSZ.3 {
    file size test.db
  } [expr {$PGSZ*2}]
  do_test pagesize-2.$PGSZ.4 {
    execsql {VACUUM}
  } {}
  integrity_check pagesize-2.$PGSZ.5
  do_test pagesize-2.$PGSZ.6 {
    db close
    sqlite3 db test.db
    execsql {PRAGMA page_size}
  } $PGSZ
  do_test pagesize-2.$PGSZ.7 {
    execsql {
      INSERT INTO t1 VALUES(randstr(10,9000));
      INSERT INTO t1 VALUES(randstr(10,9000));
      INSERT INTO t1 VALUES(randstr(10,9000));
      BEGIN;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      SELECT count(*) FROM t1;
    }
  } 48
  do_test pagesize-2.$PGSZ.8 {
    execsql {
      ROLLBACK;
      SELECT count(*) FROM t1;
    }
  } 3
  integrity_check pagesize-2.$PGSZ.9
  do_test pagesize-2.$PGSZ.10 {
    db close
    sqlite3 db test.db
    execsql {PRAGMA page_size}
  } $PGSZ
  do_test pagesize-2.$PGSZ.11 {
    execsql {
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      INSERT INTO t1 SELECT x||x FROM t1;
      SELECT count(*) FROM t1;
    }
  } 192
  do_test pagesize-2.$PGSZ.12 {
    execsql {
      BEGIN;
      DELETE FROM t1 WHERE rowid%5!=0;
      SELECT count(*) FROM t1;
    }
  } 38
  do_test pagesize-2.$PGSZ.13 {
    execsql {
      ROLLBACK;
      SELECT count(*) FROM t1;
    }
  } 192
  integrity_check pagesize-2.$PGSZ.14
  do_test pagesize-2.$PGSZ.15 {
    execsql {
      DELETE FROM t1 WHERE rowid%5!=0;
      VACUUM;
      SELECT count(*) FROM t1;
    }
  } 38
  do_test pagesize-2.$PGSZ.16 {
    execsql {
      DROP TABLE t1;
      VACUUM;
    }
  } {}
  integrity_check pagesize-2.$PGSZ.17
}

finish_test

--- NEW FILE: pragma.test ---
# 2002 March 6
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Test organization:
#
# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db.
# pragma-2.*: Test synchronous on attached db.
# pragma-3.*: Test detection of table/index inconsistency by integrity_check.
# pragma-4.*: Test cache_size and default_cache_size on attached db.
# pragma-5.*: Test that pragma synchronous may not be used inside of a
#             transaction.
#

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
file delete test.db
set DB [sqlite3 db test.db]

do_test pragma-1.1 {
  execsql {
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {2000 2000 2}
do_test pragma-1.2 {
  execsql {
    PRAGMA cache_size=1234;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {1234 2000 2}
do_test pragma-1.3 {
  db close
  sqlite3 db test.db
  execsql {
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {2000 2000 2}
do_test pragma-1.4 {
  execsql {
    PRAGMA synchronous=OFF;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {2000 2000 0}
do_test pragma-1.5 {
  execsql {
    PRAGMA cache_size=4321;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {4321 2000 0}
do_test pragma-1.6 {
  execsql {
    PRAGMA synchronous=ON;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {4321 2000 1}
do_test pragma-1.7 {
  db close
  sqlite3 db test.db
  execsql {
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {2000 2000 2}
do_test pragma-1.8 {
  execsql {
    PRAGMA default_cache_size=123;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {123 123 2}
do_test pragma-1.9 {
  db close
  set ::DB [sqlite3 db test.db]
  execsql {
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {123 123 2}
do_test pragma-1.10 {
  execsql {
    PRAGMA synchronous=NORMAL;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {123 123 1}
do_test pragma-1.11 {
  execsql {
    PRAGMA synchronous=FULL;
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {123 123 2}
do_test pragma-1.12 {
  db close
  set ::DB [sqlite3 db test.db]
  execsql {
    PRAGMA cache_size;
    PRAGMA default_cache_size;
    PRAGMA synchronous;
  }
} {123 123 2}

# Make sure the pragma handler understands numeric values in addition
# to keywords like "off" and "full".
#
do_test pragma-1.13 {
  execsql {
    PRAGMA synchronous=0;
    PRAGMA synchronous;
  }
} {0}
do_test pragma-1.14 {
  execsql {
    PRAGMA synchronous=2;
    PRAGMA synchronous;
  }
} {2}

# Test turning "flag" pragmas on and off.
#
do_test pragma-1.15 {
  execsql {
    PRAGMA vdbe_listing=YES;
    PRAGMA vdbe_listing;
  }
} {1}
do_test pragma-1.16 {
  execsql {
    PRAGMA vdbe_listing=NO;
    PRAGMA vdbe_listing;
  }
} {0}
do_test pragma-1.17 {
  execsql {
    PRAGMA parser_trace=ON;
    PRAGMA parser_trace=OFF;
  }
} {}
do_test pragma-1.18 {
  execsql {
    PRAGMA bogus = -1234;  -- Parsing of negative values
  }
} {}

# Test modifying the safety_level of an attached database.
do_test pragma-2.1 {
  file delete -force test2.db
  file delete -force test2.db-journal
  execsql {
    ATTACH 'test2.db' AS aux;
  } 
} {}
do_test pragma-2.2 {
  execsql {
    pragma aux.synchronous;
  } 
} {2}
do_test pragma-2.3 {
  execsql {
    pragma aux.synchronous = OFF;
    pragma aux.synchronous;
    pragma synchronous;
  } 
} {0 2}
do_test pragma-2.4 {
  execsql {
    pragma aux.synchronous = ON;
    pragma synchronous;
    pragma aux.synchronous;
  } 
} {2 1}

# Construct a corrupted index and make sure the integrity_check
# pragma finds it.
#
# These tests won't work if the database is encrypted
#
do_test pragma-3.1 {
  execsql {
    BEGIN;
    CREATE TABLE t2(a,b,c);
    CREATE INDEX i2 ON t2(a);
    INSERT INTO t2 VALUES(11,2,3);
    INSERT INTO t2 VALUES(22,3,4);
    COMMIT;
    SELECT rowid, * from t2;
  }
} {1 11 2 3 2 22 3 4}
if {![sqlite3 -has-codec]} {
  do_test pragma-3.2 {
    set rootpage [execsql {SELECT rootpage FROM sqlite_master WHERE name='i2'}]
    set db [btree_open test.db 100 0]
    btree_begin_transaction $db
    set c [btree_cursor $db $rootpage 1]
    btree_first $c
    btree_delete $c
    btree_commit $db
    btree_close $db
    execsql {PRAGMA integrity_check}
  } {{rowid 1 missing from index i2} {wrong # of entries in index i2}}
}
do_test pragma-3.3 {
  execsql {
    DROP INDEX i2;
  } 
} {}

# Test modifying the cache_size of an attached database.
do_test pragma-4.1 {
  execsql {
    pragma aux.cache_size;
    pragma aux.default_cache_size;
  } 
} {2000 2000}
do_test pragma-4.2 {
  execsql {
    pragma aux.cache_size = 50;
    pragma aux.cache_size;
    pragma aux.default_cache_size;
  } 
} {50 2000}
do_test pragma-4.3 {
  execsql {
    pragma aux.default_cache_size = 456;
    pragma aux.cache_size;
    pragma aux.default_cache_size;
  } 
} {456 456}
do_test pragma-4.4 {
  execsql {
    pragma cache_size;
    pragma default_cache_size;
  } 
} {123 123}
do_test pragma-4.5 {
  execsql {
    DETACH aux;
    ATTACH 'test3.db' AS aux;
    pragma aux.cache_size;
    pragma aux.default_cache_size;
  } 
} {2000 2000}
do_test pragma-4.6 {
  execsql {
    DETACH aux;
    ATTACH 'test2.db' AS aux;
    pragma aux.cache_size;
    pragma aux.default_cache_size;
  } 
} {456 456}

# Test that modifying the sync-level in the middle of a transaction is
# disallowed.
do_test pragma-5.0 {
  execsql {
    pragma synchronous;
  } 
} {2}
do_test pragma-5.1 {
  catchsql {
    BEGIN;
    pragma synchronous = OFF;
  } 
} {1 {Safety level may not be changed inside a transaction}}
do_test pragma-5.2 {
  execsql {
    pragma synchronous;
  } 
} {2}
catchsql {COMMIT;}

# Test schema-query pragmas
#
do_test pragma-6.1 {
  set res {}
  foreach {idx name file} [execsql {pragma database_list}] {
    lappend res $idx $name
  }
  set res
} {0 main 1 temp 2 aux}
do_test pragma-6.2 {
  execsql {
    pragma table_info(t2)
  }
} {0 a numeric 0 {} 0 1 b numeric 0 {} 0 2 c numeric 0 {} 0}
do_test pragma-6.3 {
  execsql {
    CREATE TABLE t3(a int references t2(b), b UNIQUE);
    pragma foreign_key_list(t3);
  }
} {0 0 t2 a b}
do_test pragma-6.4 {
  execsql {
    pragma index_list(t3);
  }
} {0 sqlite_autoindex_t3_1 1}
do_test pragma-6.5 {
  execsql {
    CREATE INDEX t3i1 ON t3(a,b);
    pragma index_info(t3i1);
  }
} {0 0 a 1 1 b}

# Miscellaneous tests
#
do_test pragma-7.1 {
  # Make sure a pragma knows to read the schema if it needs to
  db close
  sqlite3 db test.db
  execsql {
    pragma index_list(t3);
  }
} {0 t3i1 0 1 sqlite_autoindex_t3_1 1}
do_test pragma-7.2 {
  db close
  sqlite3 db test.db
  catchsql {
    pragma encoding=bogus;
  }
} {1 {unsupported encoding: bogus}}
do_test pragma-7.3 {
  db close
  sqlite3 db test.db
  execsql {
    pragma lock_status;
  }
} {main unlocked temp closed}



finish_test

--- NEW FILE: printf.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  set v32 [expr {$v&0xffffffff}]
  do_test printf-1.$n.1 [subst {
    sqlite3_mprintf_int {Three integers: %d %x %o} $v $v $v
  }] [format {Three integers: %d %x %o} $v $v32 $v32]
  do_test printf-1.$n.2 [subst {
    sqlite3_mprintf_int {Three integers: (%6d) (%6x) (%6o)} $v $v $v
  }] [format {Three integers: (%6d) (%6x) (%6o)} $v $v32 $v32]
  do_test printf-1.$n.3 [subst {
    sqlite3_mprintf_int {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v
  }] [format {Three integers: (%-6d) (%-6x) (%-6o)} $v $v32 $v32]
  do_test printf-1.$n.4 [subst {
    sqlite3_mprintf_int {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v
  }] [format {Three integers: (%+6d) (%+6x) (%+6o)} $v $v32 $v32]
  do_test printf-1.$n.5 [subst {
    sqlite3_mprintf_int {Three integers: (%06d) (%06x) (%06o)} $v $v $v
  }] [format {Three integers: (%06d) (%06x) (%06o)} $v $v32 $v32]
  do_test printf-1.$n.6 [subst {
    sqlite3_mprintf_int {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v
  }] [format {Three integers: (% 6d) (% 6x) (% 6o)} $v $v32 $v32]
  do_test printf-1.$n.7 [subst {
    sqlite3_mprintf_int {Three integers: (%#6d) (%#6x) (%#6o)} $v $v $v
  }] [format {Three integers: (%#6d) (%#6x) (%#6o)} $v $v32 $v32]
  incr n
}


if {$::tcl_platform(platform)!="windows"} {

set m 1
foreach {a b} {1 1 5 5 10 10 10 5} {
  set n 1
  foreach x {0.001 1.0e-20 1.0 0.0 100.0 9.99999 -0.00543 -1.0 -99.99999} {
    do_test printf-2.$m.$n.1 [subst {
      sqlite3_mprintf_double {A double: %*.*f} $a $b $x
    }] [format {A double: %*.*f} $a $b $x]
    do_test printf-2.$m.$n.2 [subst {
      sqlite3_mprintf_double {A double: %*.*e} $a $b $x
    }] [format {A double: %*.*e} $a $b $x]
    do_test printf-2.$m.$n.3 [subst {
      sqlite3_mprintf_double {A double: %*.*g} $a $b $x
    }] [format {A double: %*.*g} $a $b $x]
    do_test printf-2.$m.$n.4 [subst {
      sqlite3_mprintf_double {A double: %d %d %g} $a $b $x
    }] [format {A double: %d %d %g} $a $b $x]
    do_test printf-2.$m.$n.5 [subst {
      sqlite3_mprintf_double {A double: %d %d %#g} $a $b $x
    }] [format {A double: %d %d %#g} $a $b $x]
    do_test printf-2.$m.$n.6 [subst {
      sqlite3_mprintf_double {A double: %d %d %010g} $a $b $x
    }] [format {A double: %d %d %010g} $a $b $x]
    incr n
  }
  incr m
}

}

do_test printf-3.1 {
  sqlite3_mprintf_str {A String: (%*.*s)} 10 10 {This is the string}
} [format {A String: (%*.*s)} 10 10 {This is the string}]
do_test printf-3.2 {
  sqlite3_mprintf_str {A String: (%*.*s)} 10 5 {This is the string}
} [format {A String: (%*.*s)} 10 5 {This is the string}]
do_test printf-3.3 {
  sqlite3_mprintf_str {A String: (%*.*s)} -10 5 {This is the string}
} [format {A String: (%*.*s)} -10 5 {This is the string}]
do_test printf-3.4 {
  sqlite3_mprintf_str {%d %d A String: (%s)} 1 2 {This is the string}
} [format {%d %d A String: (%s)} 1 2 {This is the string}]
do_test printf-3.5 {
  sqlite3_mprintf_str {%d %d A String: (%30s)} 1 2 {This is the string}
} [format {%d %d A String: (%30s)} 1 2 {This is the string}]
do_test printf-3.6 {
  sqlite3_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string}
} [format {%d %d A String: (%-30s)} 1 2 {This is the string}]

do_test printf-4.1 {
  sqlite3_mprintf_str {%d %d A quoted string: '%q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.2 {
  sqlite3_mprintf_str {%d %d A NULL pointer in %%q: '%q'} 1 2
} {1 2 A NULL pointer in %q: '(NULL)'}
do_test printf-4.3 {
  sqlite3_mprintf_str {%d %d A quoted string: %Q} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.4 {
  sqlite3_mprintf_str {%d %d A NULL pointer in %%Q: %Q} 1 2
} {1 2 A NULL pointer in %Q: NULL}

do_test printf-5.1 {
  set x [sqlite3_mprintf_str {%d %d %100000s} 0 0 {Hello}]
  string length $x
} {994}
do_test printf-5.2 {
  sqlite3_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
} {-9 -10 (HelloHello) %}

do_test printf-6.1 {
  sqlite3_mprintf_z_test , one two three four five six
} {,one,two,three,four,five,six}


do_test printf-7.1 {
  sqlite3_mprintf_scaled {A double: %g} 1.0e307 1.0
} {A double: 1e+307}
do_test printf-7.2 {
  sqlite3_mprintf_scaled {A double: %g} 1.0e307 10.0
} {A double: 1e+308}
do_test printf-7.3 {
  sqlite3_mprintf_scaled {A double: %g} 1.0e307 100.0
} {A double: NaN}

do_test printf-8.1 {
  sqlite3_mprintf_int {%u %u %u} 0x7fffffff 0x80000000 0xffffffff
} {2147483647 2147483648 4294967295}
do_test printf-8.2 {
  sqlite3_mprintf_int {%lu %lu %lu} 0x7fffffff 0x80000000 0xffffffff
} {2147483647 2147483648 4294967295}
do_test printf-8.3 {
  sqlite3_mprintf_int64 {%llu %llu %llu} 2147483647 2147483648 4294967296
} {2147483647 2147483648 4294967296}
do_test printf-8.4 {
  sqlite3_mprintf_int64 {%lld %lld %lld} 2147483647 2147483648 4294967296
} {2147483647 2147483648 4294967296}
do_test printf-8.5 {
  sqlite3_mprintf_int64 {%llx %llx %llx} 2147483647 2147483648 4294967296
} {7fffffff 80000000 100000000}
do_test printf-8.6 {
  sqlite3_mprintf_int64 {%llx %llo %lld} -1 -1 -1
} {ffffffffffffffff 1777777777777777777777 -1}

do_test printf-9.1 {
  sqlite3_mprintf_int {%*.*c} 4 4 65
} {AAAA}
do_test printf-9.2 {
  sqlite3_mprintf_int {%*.*c} -4 1 66
} {B   }
do_test printf-9.3 {
  sqlite3_mprintf_int {%*.*c} 4 1 67
} {   C}
do_test printf-9.4 {
  sqlite3_mprintf_int {%yhello} 0 0 0
} {%}

# Ticket #812
#
do_test printf-10.1 {
  sqlite3_mprintf_stronly %s {}
} {}

# Ticket #831
#
do_test printf-10.2 {
  sqlite3_mprintf_stronly %q {}
} {}


finish_test

--- NEW FILE: progress.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the 'progress callback'.
#
# $Id: progress.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
execsql {
  BEGIN;
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1);
  INSERT INTO t1 VALUES(2);
  INSERT INTO t1 VALUES(3);
  INSERT INTO t1 VALUES(4);
  INSERT INTO t1 VALUES(5);
  INSERT INTO t1 VALUES(6);
  INSERT INTO t1 VALUES(7);
  INSERT INTO t1 VALUES(8);
  INSERT INTO t1 VALUES(9);
  INSERT INTO t1 VALUES(10);
  COMMIT;
}


# Test that the progress callback is invoked.
do_test progress-1.0 {
  set counter 0
  db progress 1 "[namespace code {incr counter}] ; expr 0"
  execsql {
    SELECT * FROM t1
  }
  expr $counter > 1
} 1
do_test progress-1.0.1 {
  db progress
} {::namespace inscope :: {incr counter} ; expr 0}
do_test progress-1.0.2 {
  set v [catch {db progress xyz bogus} msg]
  lappend v $msg
} {1 {expected integer but got "xyz"}}

# Test that the query is abandoned when the progress callback returns non-zero
do_test progress1.1 {
  set counter 0
  db progress 1 "[namespace code {incr counter}] ; expr 1"
  set rc [catch {execsql {
    SELECT * FROM t1
  }}]
  list $counter $rc
} {1 1}

# Test that the query is rolled back when the progress callback returns
# non-zero.
do_test progress1.2 {

  # This figures out how many opcodes it takes to copy 5 extra rows into t1.
  db progress 1 "[namespace code {incr five_rows}] ; expr 0"
  set five_rows 0
  execsql {
    INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 6
  }
  db progress 0 ""
  execsql {
    DELETE FROM t1 WHERE a > 10
  }

  # Now set up the progress callback to abandon the query after the number of
  # opcodes to copy 5 rows. That way, when we try to copy 6 rows, we know
  # some data will have been inserted into the table by the time the progress
  # callback abandons the query.
  db progress $five_rows "expr 1"
  catchsql {
    INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 9
  }
  execsql {
    SELECT count(*) FROM t1
  }
} 10

# Test that an active transaction remains active and not rolled back after the
# progress query abandons a query. 
do_test progress1.3 {

  db progress 0 ""
  execsql BEGIN
  execsql {
    INSERT INTO t1 VALUES(11)
  }
  db progress 1 "expr 1"
  catchsql {
    INSERT INTO t1 VALUES(12)
  }
  db progress 0 ""
  execsql COMMIT
  execsql {
    SELECT count(*) FROM t1
  }
} 11

# Check that a value of 0 for N means no progress callback
do_test progress1.4 {
  set counter 0
  db progress 0 "[namespace code {incr counter}] ; expr 0"
  execsql {
    SELECT * FROM t1;
  }
  set counter
} 0

db progress 0 ""

finish_test

--- NEW FILE: quick.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {}
set ISQUICK 1

set EXCLUDE {
  all.test
  btree2.test
  btree3.test
  btree4.test
  btree5.test
  btree6.test
  corrupt.test
  crash.test
  malloc.test
  memleak.test
  misuse.test
  quick.test
  utf16.test
}

if {[sqlite3 -has-codec]} {
  # lappend EXCLUDE \
  #  conflict.test
}

foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
  set tail [file tail $testfile]
  if {[lsearch -exact $EXCLUDE $tail]>=0} continue
  source $testfile
  catch {db close}
  if {$sqlite_open_file_count>0} {
    puts "$tail did not close all files: $sqlite_open_file_count"
    incr nErr
    lappend ::failList $tail
  }
}
source $testdir/misuse.test

set sqlite_open_file_count 0
really_finish_test

--- NEW FILE: quote.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is the ability to specify table and column names
# as quoted strings.
#
# $Id: quote.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table with a strange name and with strange column names.
#
do_test quote-1.0 {
  set r [catch {
    execsql {CREATE TABLE '@abc' ( '#xyz' int, '!pqr' text );}
  } msg]
  lappend r $msg
} {0 {}}

# Insert, update and query the table.
#
do_test quote-1.1 {
  set r [catch {
    execsql {INSERT INTO '@abc' VALUES(5,'hello')}
  } msg]
  lappend r $msg
} {0 {}}
do_test quote-1.2 {
  set r [catch {
    execsql {SELECT * FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {5 hello}}
do_test quote-1.3 {
  set r [catch {
    execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {hello 10}}
do_test quote-1.3.1 {
  catchsql {
    SELECT '!pqr', '#xyz'+5 FROM '@abc'
  }
} {0 {!pqr 5.0}}
do_test quote-1.3.2 {
  catchsql {
    SELECT "!pqr", "#xyz"+5 FROM '@abc'
  }
} {0 {hello 10}}
do_test quote-1.3 {
  set r [catch {
    execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {hello 10}}
do_test quote-1.4 {
  set r [catch {
    execsql {UPDATE '@abc' SET '#xyz'=11}
  } msg ]
  lappend r $msg
} {0 {}}
do_test quote-1.5 {
  set r [catch {
    execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
  } msg ]
  lappend r $msg
} {0 {hello 16}}

# Drop the table with the strange name.
#
do_test quote-1.6 {
  set r [catch {
    execsql {DROP TABLE '@abc'}
  } msg ]
  lappend r $msg
} {0 {}}
 

finish_test

--- NEW FILE: rollback.test ---
# 2004 June 30
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is verifying that a rollback in one statement
# caused by an ON CONFLICT ROLLBACK clause aborts any other pending
# statements.
#
# $Id: rollback.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

db close
set DB [sqlite3 db test.db]

do_test rollback-1.1 {
  execsql {
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    INSERT INTO t1 VALUES(4);
    SELECT * FROM t1;
  }
} {1 2 3 4}

do_test rollback-1.2 {
  execsql {
    CREATE TABLE t3(a unique on conflict rollback);
    INSERT INTO t3 SELECT a FROM t1;
    BEGIN;
    INSERT INTO t1 SELECT * FROM t1;
  }
} {}
do_test rollback-1.3 {
  set STMT [sqlite3_prepare $DB "SELECT a FROM t1" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}

# This causes a ROLLBACK, which deletes the table out from underneath the
# SELECT statement.
#
do_test rollback-1.4 {
  catchsql {
    INSERT INTO t3 SELECT a FROM t1;
  }
} {1 {column a is not unique}}

# Try to continue with the SELECT statement
#
do_test rollback-1.5 {
  sqlite3_step $STMT
} {SQLITE_ABORT}

# Restart the SELECT statement
#
do_test rollback-1.6 {
  sqlite3_reset $STMT
} {}
do_test rollback-1.7 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test rollback-1.8 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test rollback-1.9 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

finish_test

--- NEW FILE: rowid.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the magic ROWID column that is
# found on all tables.
#
# $Id: rowid.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Basic ROWID functionality tests.
#
do_test rowid-1.1 {
  execsql {
    CREATE TABLE t1(x int, y int);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(3,4);
    SELECT x FROM t1 ORDER BY y;
  }
} {1 3}
do_test rowid-1.2 {
  set r [execsql {SELECT rowid FROM t1 ORDER BY x}]
  global x2rowid rowid2x
  set x2rowid(1) [lindex $r 0]
  set x2rowid(3) [lindex $r 1]
  set rowid2x($x2rowid(1)) 1
  set rowid2x($x2rowid(3)) 3
  llength $r
} {2}
do_test rowid-1.3 {
  global x2rowid
  set sql "SELECT x FROM t1 WHERE rowid==$x2rowid(1)"
  execsql $sql
} {1}
do_test rowid-1.4 {
  global x2rowid
  set sql "SELECT x FROM t1 WHERE rowid==$x2rowid(3)"
  execsql $sql
} {3}
do_test rowid-1.5 {
  global x2rowid
  set sql "SELECT x FROM t1 WHERE oid==$x2rowid(1)"
  execsql $sql
} {1}
do_test rowid-1.6 {
  global x2rowid
  set sql "SELECT x FROM t1 WHERE OID==$x2rowid(3)"
  execsql $sql
} {3}
do_test rowid-1.7 {
  global x2rowid
  set sql "SELECT x FROM t1 WHERE _rowid_==$x2rowid(1)"
  execsql $sql
} {1}
do_test rowid-1.7.1 {
  while 1 {
    set norow [expr {int(rand()*1000000)}]
    if {$norow!=$x2rowid(1) && $norow!=$x2rowid(3)} break
  }
  execsql "SELECT x FROM t1 WHERE rowid=$norow"
} {}
do_test rowid-1.8 {
  global x2rowid
  set v [execsql {SELECT x, oid FROM t1 order by x}]
  set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
  expr {$v==$v2}
} {1}
do_test rowid-1.9 {
  global x2rowid
  set v [execsql {SELECT x, RowID FROM t1 order by x}]
  set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
  expr {$v==$v2}
} {1}
do_test rowid-1.9 {
  global x2rowid
  set v [execsql {SELECT x, _rowid_ FROM t1 order by x}]
  set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
  expr {$v==$v2}
} {1}

# We can insert or update the ROWID column.
#
do_test rowid-2.1 {
  catchsql {
    INSERT INTO t1(rowid,x,y) VALUES(1234,5,6);
    SELECT rowid, * FROM t1;
  }
} {0 {1 1 2 2 3 4 1234 5 6}}
do_test rowid-2.2 {
  catchsql {
    UPDATE t1 SET rowid=12345 WHERE x==1;
    SELECT rowid, * FROM t1
  }
} {0 {2 3 4 1234 5 6 12345 1 2}}
do_test rowid-2.3 {
  catchsql {
    INSERT INTO t1(y,x,oid) VALUES(8,7,1235);
    SELECT rowid, * FROM t1 WHERE rowid>1000;
  }
} {0 {1234 5 6 1235 7 8 12345 1 2}}
do_test rowid-2.4 {
  catchsql {
    UPDATE t1 SET oid=12346 WHERE x==1;
    SELECT rowid, * FROM t1;
  }
} {0 {2 3 4 1234 5 6 1235 7 8 12346 1 2}}
do_test rowid-2.5 {
  catchsql {
    INSERT INTO t1(x,_rowid_,y) VALUES(9,1236,10);
    SELECT rowid, * FROM t1 WHERE rowid>1000;
  }
} {0 {1234 5 6 1235 7 8 1236 9 10 12346 1 2}}
do_test rowid-2.6 {
  catchsql {
    UPDATE t1 SET _rowid_=12347 WHERE x==1;
    SELECT rowid, * FROM t1 WHERE rowid>1000;
  }
} {0 {1234 5 6 1235 7 8 1236 9 10 12347 1 2}}

# But we can use ROWID in the WHERE clause of an UPDATE that does not
# change the ROWID.
#
do_test rowid-2.7 {
  global x2rowid
  set sql "UPDATE t1 SET x=2 WHERE OID==$x2rowid(3)"
  execsql $sql
  execsql {SELECT x FROM t1 ORDER BY x}
} {1 2 5 7 9}
do_test rowid-2.8 {
  global x2rowid
  set sql "UPDATE t1 SET x=3 WHERE _rowid_==$x2rowid(3)"
  execsql $sql
  execsql {SELECT x FROM t1 ORDER BY x}
} {1 3 5 7 9}

# We cannot index by ROWID
#
do_test rowid-2.9 {
  set v [catch {execsql {CREATE INDEX idxt1 ON t1(rowid)}} msg]
  lappend v $msg
} {1 {table t1 has no column named rowid}}
do_test rowid-2.10 {
  set v [catch {execsql {CREATE INDEX idxt1 ON t1(_rowid_)}} msg]
  lappend v $msg
} {1 {table t1 has no column named _rowid_}}
do_test rowid-2.11 {
  set v [catch {execsql {CREATE INDEX idxt1 ON t1(oid)}} msg]
  lappend v $msg
} {1 {table t1 has no column named oid}}
do_test rowid-2.12 {
  set v [catch {execsql {CREATE INDEX idxt1 ON t1(x, rowid)}} msg]
  lappend v $msg
} {1 {table t1 has no column named rowid}}

# Columns defined in the CREATE statement override the buildin ROWID
# column names.
#
do_test rowid-3.1 {
  execsql {
    CREATE TABLE t2(rowid int, x int, y int);
    INSERT INTO t2 VALUES(0,2,3);
    INSERT INTO t2 VALUES(4,5,6);
    INSERT INTO t2 VALUES(7,8,9);
    SELECT * FROM t2 ORDER BY x;
  }
} {0 2 3 4 5 6 7 8 9}
do_test rowid-3.2 {
  execsql {SELECT * FROM t2 ORDER BY rowid}
} {0 2 3 4 5 6 7 8 9}
do_test rowid-3.3 {
  execsql {SELECT rowid, x, y FROM t2 ORDER BY rowid}
} {0 2 3 4 5 6 7 8 9}
do_test rowid-3.4 {
  set r1 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY rowid}]
  foreach {a b c d e f} $r1 {}
  set r2 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY x DESC}]
  foreach {u v w x y z} $r2 {}
  expr {$u==$e && $w==$c && $y==$a}
} {1}
# sqlite3 v3 - do_probtest doesn't exist anymore?
if 0 {
do_probtest rowid-3.5 {
  set r1 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY rowid}]
  foreach {a b c d e f} $r1 {}
  expr {$a!=$b && $c!=$d && $e!=$f}
} {1}
}

# Let's try some more complex examples, including some joins.
#
do_test rowid-4.1 {
  execsql {
    DELETE FROM t1;
    DELETE FROM t2;
  }
  for {set i 1} {$i<=50} {incr i} {
    execsql "INSERT INTO t1(x,y) VALUES($i,[expr {$i*$i}])"
  }
  execsql {INSERT INTO t2 SELECT _rowid_, x*y, y*y FROM t1}
  execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1.rowid==t2.rowid}
} {256}
do_test rowid-4.2 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.rowid==t2.rowid}
} {256}
do_test rowid-4.2.1 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.oid==t2.rowid}
} {256}
do_test rowid-4.2.2 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
} {256}
do_test rowid-4.2.3 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t2.rowid==t1.rowid}
} {256}
do_test rowid-4.2.4 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t2.rowid==t1.oid AND t1.x==4}
} {256}
do_test rowid-4.2.5 {
  execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
} {256}
do_test rowid-4.2.6 {
  execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t2.rowid==t1.rowid}
} {256}
do_test rowid-4.2.7 {
  execsql {SELECT t2.y FROM t1, t2 WHERE t2.rowid==t1.oid AND t1.x==4}
} {256}
do_test rowid-4.3 {
  execsql {CREATE INDEX idxt1 ON t1(x)}
  execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1.rowid==t2.rowid}
} {256}
do_test rowid-4.3.1 {
  execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
} {256}
do_test rowid-4.3.2 {
  execsql {SELECT t2.y FROM t1, t2 WHERE t2.rowid==t1.oid AND 4==t1.x}
} {256}
do_test rowid-4.4 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.rowid==t2.rowid}
} {256}
do_test rowid-4.4.1 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
} {256}
do_test rowid-4.4.2 {
  execsql {SELECT t2.y FROM t2, t1 WHERE t2.rowid==t1.oid AND 4==t1.x}
} {256}
do_test rowid-4.5 {
  execsql {CREATE INDEX idxt2 ON t2(y)}
  set sqlite_search_count 0
  concat [execsql {
    SELECT t1.x FROM t2, t1 
    WHERE t2.y==256 AND t1.rowid==t2.rowid
  }] $sqlite_search_count
} {4 3}
do_test rowid-4.5.1 {
  set sqlite_search_count 0
  concat [execsql {
    SELECT t1.x FROM t2, t1 
    WHERE t1.OID==t2.rowid AND t2.y==81
  }] $sqlite_search_count
} {3 3}
do_test rowid-4.6 {
  execsql {
    SELECT t1.x FROM t1, t2
    WHERE t2.y==256 AND t1.rowid==t2.rowid
  }
} {4}

do_test rowid-5.1 {
  execsql {DELETE FROM t1 WHERE _rowid_ IN (SELECT oid FROM t1 WHERE x>8)}
  execsql {SELECT max(x) FROM t1}
} {8}

# Make sure a "WHERE rowid=X" clause works when there is no ROWID of X.
#
do_test rowid-6.1 {
  execsql {
    SELECT x FROM t1
  }
} {1 2 3 4 5 6 7 8}
do_test rowid-6.2 {
  for {set ::norow 1} {1} {incr ::norow} {
    if {[execsql "SELECT x FROM t1 WHERE rowid=$::norow"]==""}  break
  }
  execsql [subst {
    DELETE FROM t1 WHERE rowid=$::norow
  }]
} {}
do_test rowid-6.3 {
  execsql {
    SELECT x FROM t1
  }
} {1 2 3 4 5 6 7 8}

# Beginning with version 2.3.4, SQLite computes rowids of new rows by
# finding the maximum current rowid and adding one.  It falls back to
# the old random algorithm if the maximum rowid is the largest integer.
# The following tests are for this new behavior.
#
do_test rowid-7.0 {
  execsql {
    DELETE FROM t1;
    DROP TABLE t2;
    DROP INDEX idxt1;
    INSERT INTO t1 VALUES(1,2);
    SELECT rowid, * FROM t1;
  }
} {1 1 2}
do_test rowid-7.1 {
  execsql {
    INSERT INTO t1 VALUES(99,100);
    SELECT rowid,* FROM t1
  }
} {1 1 2 2 99 100}
do_test rowid-7.2 {
  execsql {
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
    INSERT INTO t2(b) VALUES(55);
    SELECT * FROM t2;
  }
} {1 55}
do_test rowid-7.3 {
  execsql {
    INSERT INTO t2(b) VALUES(66);
    SELECT * FROM t2;
  }
} {1 55 2 66}
do_test rowid-7.4 {
  execsql {
    INSERT INTO t2(a,b) VALUES(1000000,77);
    INSERT INTO t2(b) VALUES(88);
    SELECT * FROM t2;
  }
} {1 55 2 66 1000000 77 1000001 88}
do_test rowid-7.5 {
  execsql {
    INSERT INTO t2(a,b) VALUES(2147483647,99);
    INSERT INTO t2(b) VALUES(11);
    SELECT b FROM t2 ORDER BY b;
  }
} {11 55 66 77 88 99}
do_test rowid-7.6 {
  execsql {
    SELECT b FROM t2 WHERE a NOT IN(1,2,1000000,1000001,2147483647);
  }
} {11}
do_test rowid-7.7 {
  execsql {
    INSERT INTO t2(b) VALUES(22);
    INSERT INTO t2(b) VALUES(33);
    INSERT INTO t2(b) VALUES(44);
    INSERT INTO t2(b) VALUES(55);
    SELECT b FROM t2 WHERE a NOT IN(1,2,1000000,1000001,2147483647) ORDER BY b;
  }
} {11 22 33 44 55}
do_test rowid-7.8 {
  execsql {
    DELETE FROM t2 WHERE a!=2;
    INSERT INTO t2(b) VALUES(111);
    SELECT * FROM t2;
  }
} {2 66 3 111}

# Make sure AFTER triggers that do INSERTs do not change the last_insert_rowid.
# Ticket #290
#
do_test rowid-8.1 {
  execsql {
    CREATE TABLE t3(a integer primary key);
    CREATE TABLE t4(x);
    INSERT INTO t4 VALUES(1);
    CREATE TRIGGER r3 AFTER INSERT on t3 FOR EACH ROW BEGIN
      INSERT INTO t4 VALUES(NEW.a+10);
    END;
    SELECT * FROM t3;
  }
} {}
do_test rowid-8.2 {
  execsql {
    SELECT rowid, * FROM t4;
  }
} {1 1}
do_test rowid-8.3 {
  execsql {
    INSERT INTO t3 VALUES(123);
    SELECT last_insert_rowid();
  }
} {123}
do_test rowid-8.4 {
  execsql {
    SELECT * FROM t3;
  }
} {123}
do_test rowid-8.5 {
  execsql {
    SELECT rowid, * FROM t4;
  }
} {1 1 2 133}
do_test rowid-8.6 {
  execsql {
    INSERT INTO t3 VALUES(NULL);
    SELECT last_insert_rowid();
  }
} {124}
do_test rowid-8.7 {
  execsql {
    SELECT * FROM t3;
  }
} {123 124}
do_test rowid-8.8 {
  execsql {
    SELECT rowid, * FROM t4;
  }
} {1 1 2 133 3 134}

# ticket #377: Comparison between integer primiary key and floating point
# values.
#
do_test rowid-9.1 {
  execsql {
    SELECT * FROM t3 WHERE a<123.5
  }
} {123}
do_test rowid-9.2 {
  execsql {
    SELECT * FROM t3 WHERE a<124.5
  }
} {123 124}
do_test rowid-9.3 {
  execsql {
    SELECT * FROM t3 WHERE a>123.5
  }
} {124}
do_test rowid-9.4 {
  execsql {
    SELECT * FROM t3 WHERE a>122.5
  }
} {123 124}
do_test rowid-9.5 {
  execsql {
    SELECT * FROM t3 WHERE a==123.5
  }
} {}
do_test rowid-9.6 {
  execsql {
    SELECT * FROM t3 WHERE a==123.000
  }
} {123}
do_test rowid-9.7 {
  execsql {
    SELECT * FROM t3 WHERE a>100.5 AND a<200.5
  }
} {123 124}
do_test rowid-9.8 {
  execsql {
    SELECT * FROM t3 WHERE a>'xyz';
  }
} {}
do_test rowid-9.9 {
  execsql {
    SELECT * FROM t3 WHERE a<'xyz';
  }
} {123 124}
do_test rowid-9.10 {
  execsql {
    SELECT * FROM t3 WHERE a>=122.9 AND a<=123.1
  }
} {123}

# Ticket #567.  Comparisons of ROWID or integery primary key against
# floating point numbers still do not always work.
#
do_test rowid-10.1 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES(1);
    INSERT INTO t5 VALUES(2);
    INSERT INTO t5 SELECT a+2 FROM t5;
    INSERT INTO t5 SELECT a+4 FROM t5;
    SELECT rowid, * FROM t5;
  }
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
do_test rowid-10.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.5}
} {6 6 7 7 8 8}
do_test rowid-10.3 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.0}
} {5 5 6 6 7 7 8 8}
do_test rowid-10.4 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>5.5}
} {6 6 7 7 8 8}
do_test rowid-10.3.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>5.0}
} {6 6 7 7 8 8}
do_test rowid-10.5 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5<=rowid}
} {6 6 7 7 8 8}
do_test rowid-10.6 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5<rowid}
} {6 6 7 7 8 8}
do_test rowid-10.7 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<=5.5}
} {1 1 2 2 3 3 4 4 5 5}
do_test rowid-10.8 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<5.5}
} {1 1 2 2 3 3 4 4 5 5}
do_test rowid-10.9 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5>=rowid}
} {1 1 2 2 3 3 4 4 5 5}
do_test rowid-10.10 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5>rowid}
} {1 1 2 2 3 3 4 4 5 5}
do_test rowid-10.11 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.5 ORDER BY rowid DESC}
} {8 8 7 7 6 6}
do_test rowid-10.11.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.0 ORDER BY rowid DESC}
} {8 8 7 7 6 6 5 5}
do_test rowid-10.12 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>5.5 ORDER BY rowid DESC}
} {8 8 7 7 6 6}
do_test rowid-10.12.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>5.0 ORDER BY rowid DESC}
} {8 8 7 7 6 6}
do_test rowid-10.13 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5<=rowid ORDER BY rowid DESC}
} {8 8 7 7 6 6}
do_test rowid-10.14 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5<rowid ORDER BY rowid DESC}
} {8 8 7 7 6 6}
do_test rowid-10.15 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<=5.5 ORDER BY rowid DESC}
} {5 5 4 4 3 3 2 2 1 1}
do_test rowid-10.16 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<5.5 ORDER BY rowid DESC}
} {5 5 4 4 3 3 2 2 1 1}
do_test rowid-10.17 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5>=rowid ORDER BY rowid DESC}
} {5 5 4 4 3 3 2 2 1 1}
do_test rowid-10.18 {
  execsql {SELECT rowid, a FROM t5 WHERE 5.5>rowid ORDER BY rowid DESC}
} {5 5 4 4 3 3 2 2 1 1}

do_test rowid-10.30 {
  execsql {
    CREATE TABLE t6(a);
    INSERT INTO t6(rowid,a) SELECT -a,a FROM t5;
    SELECT rowid, * FROM t6;
  }
} {-8 8 -7 7 -6 6 -5 5 -4 4 -3 3 -2 2 -1 1}
do_test rowid-10.31.1 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.5}
} {-5 5 -4 4 -3 3 -2 2 -1 1}
do_test rowid-10.31.2 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.0}
} {-5 5 -4 4 -3 3 -2 2 -1 1}
do_test rowid-10.32.1 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.5 ORDER BY rowid DESC}
} {-1 1 -2 2 -3 3 -4 4 -5 5}
do_test rowid-10.32.1 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.0 ORDER BY rowid DESC}
} {-1 1 -2 2 -3 3 -4 4 -5 5}
do_test rowid-10.33 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5<=rowid}
} {-5 5 -4 4 -3 3 -2 2 -1 1}
do_test rowid-10.34 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5<=rowid ORDER BY rowid DESC}
} {-1 1 -2 2 -3 3 -4 4 -5 5}
do_test rowid-10.35.1 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.5}
} {-5 5 -4 4 -3 3 -2 2 -1 1}
do_test rowid-10.35.2 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.0}
} {-4 4 -3 3 -2 2 -1 1}
do_test rowid-10.36.1 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.5 ORDER BY rowid DESC}
} {-1 1 -2 2 -3 3 -4 4 -5 5}
do_test rowid-10.36.2 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.0 ORDER BY rowid DESC}
} {-1 1 -2 2 -3 3 -4 4}
do_test rowid-10.37 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5<rowid}
} {-5 5 -4 4 -3 3 -2 2 -1 1}
do_test rowid-10.38 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5<rowid ORDER BY rowid DESC}
} {-1 1 -2 2 -3 3 -4 4 -5 5}
do_test rowid-10.39 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid<=-5.5}
} {-8 8 -7 7 -6 6}
do_test rowid-10.40 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid<=-5.5 ORDER BY rowid DESC}
} {-6 6 -7 7 -8 8}
do_test rowid-10.41 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5>=rowid}
} {-8 8 -7 7 -6 6}
do_test rowid-10.42 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5>=rowid ORDER BY rowid DESC}
} {-6 6 -7 7 -8 8}
do_test rowid-10.43 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid<-5.5}
} {-8 8 -7 7 -6 6}
do_test rowid-10.44 {
  execsql {SELECT rowid, a FROM t6 WHERE rowid<-5.5 ORDER BY rowid DESC}
} {-6 6 -7 7 -8 8}
do_test rowid-10.44 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5>rowid}
} {-8 8 -7 7 -6 6}
do_test rowid-10.46 {
  execsql {SELECT rowid, a FROM t6 WHERE -5.5>rowid ORDER BY rowid DESC}
} {-6 6 -7 7 -8 8}

# Comparison of rowid against string values.
#
do_test rowid-11.1 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>'abc'}
} {}
do_test rowid-11.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>='abc'}
} {}
do_test rowid-11.3 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc'}
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
do_test rowid-11.4 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc'}
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}

# Test the automatic generation of rowids when the table already contains
# a rowid with the maximum value.
#
do_test rowid-12.1 {
  execsql {
    CREATE TABLE t7(x INTEGER PRIMARY KEY, y);
    INSERT INTO t7 VALUES(9223372036854775807,'a');
    SELECT y FROM t7;
  }
} {a}
do_test rowid-12.2 {
  execsql {
    INSERT INTO t7 VALUES(NULL,'b');
    SELECT y FROM t7;
  }
} {b a}

finish_test

--- NEW FILE: select1.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
  set v [catch {execsql {SELECT * FROM test1}} msg]
  lappend v $msg
} {1 {no such table: test1}}

execsql {CREATE TABLE test1(f1 int, f2 int)}

do_test select1-1.2 {
  set v [catch {execsql {SELECT * FROM test1, test2}} msg]
  lappend v $msg
} {1 {no such table: test2}}
do_test select1-1.3 {
  set v [catch {execsql {SELECT * FROM test2, test1}} msg]
  lappend v $msg
} {1 {no such table: test2}}

execsql {INSERT INTO test1(f1,f2) VALUES(11,22)}


# Make sure the columns are extracted correctly.
#
do_test select1-1.4 {
  execsql {SELECT f1 FROM test1}
} {11}
do_test select1-1.5 {
  execsql {SELECT f2 FROM test1}
} {22}
do_test select1-1.6 {
  execsql {SELECT f2, f1 FROM test1}
} {22 11}
do_test select1-1.7 {
  execsql {SELECT f1, f2 FROM test1}
} {11 22}
do_test select1-1.8 {
  execsql {SELECT * FROM test1}
} {11 22}
do_test select1-1.8.1 {
  execsql {SELECT *, * FROM test1}
} {11 22 11 22}
do_test select1-1.8.2 {
  execsql {SELECT *, min(f1,f2), max(f1,f2) FROM test1}
} {11 22 11 22}
do_test select1-1.8.3 {
  execsql {SELECT 'one', *, 'two', * FROM test1}
} {one 11 22 two 11 22}

execsql {CREATE TABLE test2(r1 real, r2 real)}
execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)}

do_test select1-1.9 {
  execsql {SELECT * FROM test1, test2}
} {11 22 1.1 2.2}
do_test select1-1.9.1 {
  execsql {SELECT *, 'hi' FROM test1, test2}
} {11 22 1.1 2.2 hi}
do_test select1-1.9.2 {
  execsql {SELECT 'one', *, 'two', * FROM test1, test2}
} {one 11 22 1.1 2.2 two 11 22 1.1 2.2}
do_test select1-1.10 {
  execsql {SELECT test1.f1, test2.r1 FROM test1, test2}
} {11 1.1}
do_test select1-1.11 {
  execsql {SELECT test1.f1, test2.r1 FROM test2, test1}
} {11 1.1}
do_test select1-1.11.1 {
  execsql {SELECT * FROM test2, test1}
} {1.1 2.2 11 22}
do_test select1-1.11.2 {
  execsql {SELECT * FROM test1 AS a, test1 AS b}
} {11 22 11 22}
do_test select1-1.12 {
  execsql {SELECT max(test1.f1,test2.r1), min(test1.f2,test2.r2)
           FROM test2, test1}
} {11 2.2}
do_test select1-1.13 {
  execsql {SELECT min(test1.f1,test2.r1), max(test1.f2,test2.r2)
           FROM test1, test2}
} {1.1 22}

set long {This is a string that is too big to fit inside a NBFS buffer}
do_test select1-2.0 {
  execsql "
    DROP TABLE test2;
    DELETE FROM test1;
    INSERT INTO test1 VALUES(11,22);
    INSERT INTO test1 VALUES(33,44);
    CREATE TABLE t3(a,b);
    INSERT INTO t3 VALUES('abc',NULL);
    INSERT INTO t3 VALUES(NULL,'xyz');
    INSERT INTO t3 SELECT * FROM test1;
    CREATE TABLE t4(a,b);
    INSERT INTO t4 VALUES(NULL,'$long');
    SELECT * FROM t3;
  "
} {abc {} {} xyz 11 22 33 44}

# Error messges from sqliteExprCheck
#
do_test select1-2.1 {
  set v [catch {execsql {SELECT count(f1,f2) FROM test1}} msg]
  lappend v $msg
} {1 {wrong number of arguments to function count()}}
do_test select1-2.2 {
  set v [catch {execsql {SELECT count(f1) FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select1-2.3 {
  set v [catch {execsql {SELECT Count() FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select1-2.4 {
  set v [catch {execsql {SELECT COUNT(*) FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select1-2.5 {
  set v [catch {execsql {SELECT COUNT(*)+1 FROM test1}} msg]
  lappend v $msg
} {0 3}
do_test select1-2.5.1 {
  execsql {SELECT count(*),count(a),count(b) FROM t3}
} {4 3 3}
do_test select1-2.5.2 {
  execsql {SELECT count(*),count(a),count(b) FROM t4}
} {1 0 1}
do_test select1-2.5.3 {
  execsql {SELECT count(*),count(a),count(b) FROM t4 WHERE b=5}
} {0 0 0}
do_test select1-2.6 {
  set v [catch {execsql {SELECT min(*) FROM test1}} msg]
  lappend v $msg
} {1 {wrong number of arguments to function min()}}
do_test select1-2.7 {
  set v [catch {execsql {SELECT Min(f1) FROM test1}} msg]
  lappend v $msg
} {0 11}
do_test select1-2.8 {
  set v [catch {execsql {SELECT MIN(f1,f2) FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select1-2.8.1 {
  execsql {SELECT coalesce(min(a),'xyzzy') FROM t3}
} {11}
do_test select1-2.8.2 {
  execsql {SELECT min(coalesce(a,'xyzzy')) FROM t3}
} {11}
do_test select1-2.8.3 {
  execsql {SELECT min(b), min(b) FROM t4}
} [list $long $long]
do_test select1-2.9 {
  set v [catch {execsql {SELECT MAX(*) FROM test1}} msg]
  lappend v $msg
} {1 {wrong number of arguments to function MAX()}}
do_test select1-2.10 {
  set v [catch {execsql {SELECT Max(f1) FROM test1}} msg]
  lappend v $msg
} {0 33}
do_test select1-2.11 {
  set v [catch {execsql {SELECT max(f1,f2) FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {22 44}}
do_test select1-2.12 {
  set v [catch {execsql {SELECT MAX(f1,f2)+1 FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {23 45}}
do_test select1-2.13 {
  set v [catch {execsql {SELECT MAX(f1)+1 FROM test1}} msg]
  lappend v $msg
} {0 34}
do_test select1-2.13.1 {
  execsql {SELECT coalesce(max(a),'xyzzy') FROM t3}
} {abc}
do_test select1-2.13.2 {
  execsql {SELECT max(coalesce(a,'xyzzy')) FROM t3}
} {xyzzy}
do_test select1-2.14 {
  set v [catch {execsql {SELECT SUM(*) FROM test1}} msg]
  lappend v $msg
} {1 {wrong number of arguments to function SUM()}}
do_test select1-2.15 {
  set v [catch {execsql {SELECT Sum(f1) FROM test1}} msg]
  lappend v $msg
} {0 44.0}
do_test select1-2.16 {
  set v [catch {execsql {SELECT sum(f1,f2) FROM test1}} msg]
  lappend v $msg
} {1 {wrong number of arguments to function sum()}}
do_test select1-2.17 {
  set v [catch {execsql {SELECT SUM(f1)+1 FROM test1}} msg]
  lappend v $msg
} {0 45.0}
do_test select1-2.17.1 {
  execsql {SELECT sum(a) FROM t3}
} {44.0}
do_test select1-2.18 {
  set v [catch {execsql {SELECT XYZZY(f1) FROM test1}} msg]
  lappend v $msg
} {1 {no such function: XYZZY}}
do_test select1-2.19 {
  set v [catch {execsql {SELECT SUM(min(f1,f2)) FROM test1}} msg]
  lappend v $msg
} {0 44.0}
do_test select1-2.20 {
  set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg]
  lappend v $msg
} {1 {misuse of aggregate function min()}}

# WHERE clause expressions
#
do_test select1-3.1 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<11}} msg]
  lappend v $msg
} {0 {}}
do_test select1-3.2 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<=11}} msg]
  lappend v $msg
} {0 11}
do_test select1-3.3 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1=11}} msg]
  lappend v $msg
} {0 11}
do_test select1-3.4 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>=11}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select1-3.5 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select1-3.6 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1!=11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select1-3.7 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE min(f1,f2)!=11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select1-3.8 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE max(f1,f2)!=11}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select1-3.9 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE count(f1,f2)!=11}} msg]
  lappend v $msg
} {1 {wrong number of arguments to function count()}}

# ORDER BY expressions
#
do_test select1-4.1 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg]
  lappend v $msg
} {0 {11 33}}
do_test select1-4.2 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg]
  lappend v $msg
} {0 {33 11}}
do_test select1-4.3 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1,f2)}} msg]
  lappend v $msg
} {0 {11 33}}
do_test select1-4.4 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
  lappend v $msg
} {1 {misuse of aggregate function min()}}
do_test select1-4.5 {
  catchsql {
    SELECT f1 FROM test1 ORDER BY 8.4;
  }
} {1 {ORDER BY terms must not be non-integer constants}}
do_test select1-4.6 {
  catchsql {
    SELECT f1 FROM test1 ORDER BY '8.4';
  }
} {1 {ORDER BY terms must not be non-integer constants}}
do_test select1-4.7 {
  catchsql {
    SELECT f1 FROM test1 ORDER BY 'xyz';
  }
} {1 {ORDER BY terms must not be non-integer constants}}
do_test select1-4.8 {
  execsql {
    CREATE TABLE t5(a,b);
    INSERT INTO t5 VALUES(1,10);
    INSERT INTO t5 VALUES(2,9);
    SELECT * FROM t5 ORDER BY 1;
  }
} {1 10 2 9}
do_test select1-4.9 {
  execsql {
    SELECT * FROM t5 ORDER BY 2;
  }
} {2 9 1 10}
do_test select1-4.10 {
  catchsql {
    SELECT * FROM t5 ORDER BY 3;
  }
} {1 {ORDER BY column number 3 out of range - should be between 1 and 2}}
do_test select1-4.11 {
  execsql {
    INSERT INTO t5 VALUES(3,10);
    SELECT * FROM t5 ORDER BY 2, 1 DESC;
  }
} {2 9 3 10 1 10}
do_test select1-4.12 {
  execsql {
    SELECT * FROM t5 ORDER BY 1 DESC, b;
  }
} {3 10 2 9 1 10}
do_test select1-4.13 {
  execsql {
    SELECT * FROM t5 ORDER BY b DESC, 1;
  }
} {1 10 3 10 2 9}


# ORDER BY ignored on an aggregate query
#
do_test select1-5.1 {
  set v [catch {execsql {SELECT max(f1) FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 33}

execsql {CREATE TABLE test2(t1 test, t2 text)}
execsql {INSERT INTO test2 VALUES('abc','xyz')}

# Check for column naming
#
do_test select1-6.1 {
  set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {f1 11 f1 33}}
do_test select1-6.1.1 {
  execsql {PRAGMA full_column_names=on}
  set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {test1.f1 11 test1.f1 33}}
do_test select1-6.1.2 {
  set v [catch {execsql2 {SELECT f1 as 'f1' FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {f1 11 f1 33}}
do_test select1-6.1.3 {
  set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg]
  lappend v $msg
} {0 {test1.f1 11 test1.f2 22}}
do_test select1-6.1.4 {
  set v [catch {execsql2 {SELECT DISTINCT * FROM test1 WHERE f1==11}} msg]
  execsql {PRAGMA full_column_names=off}
  lappend v $msg
} {0 {test1.f1 11 test1.f2 22}}
do_test select1-6.1.5 {
  set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg]
  lappend v $msg
} {0 {f1 11 f2 22}}
do_test select1-6.1.6 {
  set v [catch {execsql2 {SELECT DISTINCT * FROM test1 WHERE f1==11}} msg]
  lappend v $msg
} {0 {f1 11 f2 22}}
do_test select1-6.2 {
  set v [catch {execsql2 {SELECT f1 as xyzzy FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 11 xyzzy 33}}
do_test select1-6.3 {
  set v [catch {execsql2 {SELECT f1 as "xyzzy" FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 11 xyzzy 33}}
do_test select1-6.3.1 {
  set v [catch {execsql2 {SELECT f1 as 'xyzzy ' FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {{xyzzy } 11 {xyzzy } 33}}
do_test select1-6.4 {
  set v [catch {execsql2 {SELECT f1+F2 as xyzzy FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 33 xyzzy 77}}
do_test select1-6.4a {
  set v [catch {execsql2 {SELECT f1+F2 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {f1+F2 33 f1+F2 77}}
do_test select1-6.5 {
  set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {test1.f1+F2 33 test1.f1+F2 77}}
do_test select1-6.5.1 {
  execsql2 {PRAGMA full_column_names=on}
  set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg]
  execsql2 {PRAGMA full_column_names=off}
  lappend v $msg
} {0 {test1.f1+F2 33 test1.f1+F2 77}}
do_test select1-6.6 {
  set v [catch {execsql2 {SELECT test1.f1+F2, t1 FROM test1, test2 
         ORDER BY f2}} msg]
  lappend v $msg
} {0 {test1.f1+F2 33 t1 abc test1.f1+F2 77 t1 abc}}
do_test select1-6.7 {
  set v [catch {execsql2 {SELECT A.f1, t1 FROM test1 as A, test2 
         ORDER BY f2}} msg]
  lappend v $msg
} {0 {A.f1 11 t1 abc A.f1 33 t1 abc}}
do_test select1-6.8 {
  set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as B 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous column name: f1}}
do_test select1-6.8b {
  set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous column name: f2}}
do_test select1-6.8c {
  set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as A 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous column name: A.f1}}
do_test select1-6.9 {
  set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B 
         ORDER BY A.f1, B.f1}} msg]
  lappend v $msg
} {0 {A.f1 11 B.f1 11 A.f1 11 B.f1 33 A.f1 33 B.f1 11 A.f1 33 B.f1 33}}
do_test select1-6.10 {
  set v [catch {execsql2 {
    SELECT f1 FROM test1 UNION SELECT f2 FROM test1
    ORDER BY f2;
  }} msg]
  lappend v $msg
} {0 {f2 11 f2 22 f2 33 f2 44}}
do_test select1-6.11 {
  set v [catch {execsql2 {
    SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1
    ORDER BY f2+100;
  }} msg]
  lappend v $msg
} {0 {f2+100 11 f2+100 33 f2+100 122 f2+100 144}}

do_test select1-7.1 {
  set v [catch {execsql {
     SELECT f1 FROM test1 WHERE f2=;
  }} msg]
  lappend v $msg
} {1 {near ";": syntax error}}
do_test select1-7.2 {
  set v [catch {execsql {
     SELECT f1 FROM test1 UNION SELECT WHERE;
  }} msg]
  lappend v $msg
} {1 {near "WHERE": syntax error}}
do_test select1-7.3 {
  set v [catch {execsql {SELECT f1 FROM test1 as 'hi', test2 as}} msg]
  lappend v $msg
} {1 {near "as": syntax error}}
do_test select1-7.4 {
  set v [catch {execsql {
     SELECT f1 FROM test1 ORDER BY;
  }} msg]
  lappend v $msg
} {1 {near ";": syntax error}}
do_test select1-7.5 {
  set v [catch {execsql {
     SELECT f1 FROM test1 ORDER BY f1 desc, f2 where;
  }} msg]
  lappend v $msg
} {1 {near "where": syntax error}}
do_test select1-7.6 {
  set v [catch {execsql {
     SELECT count(f1,f2 FROM test1;
  }} msg]
  lappend v $msg
} {1 {near "FROM": syntax error}}
do_test select1-7.7 {
  set v [catch {execsql {
     SELECT count(f1,f2+) FROM test1;
  }} msg]
  lappend v $msg
} {1 {near ")": syntax error}}
do_test select1-7.8 {
  set v [catch {execsql {
     SELECT f1 FROM test1 ORDER BY f2, f1+;
  }} msg]
  lappend v $msg
} {1 {near ";": syntax error}}

do_test select1-8.1 {
  execsql {SELECT f1 FROM test1 WHERE 4.3+2.4 OR 1 ORDER BY f1}
} {11 33}
do_test select1-8.2 {
  execsql {
    SELECT f1 FROM test1 WHERE ('x' || f1) BETWEEN 'x10' AND 'x20'
    ORDER BY f1
  }
} {11}
do_test select1-8.3 {
  execsql {
    SELECT f1 FROM test1 WHERE 5-3==2
    ORDER BY f1
  }
} {11 33}

# TODO: This test is failing because f1 is now being loaded off the
# disk as a vdbe integer, not a string. Hence the value of f1/(f1-11)
# changes because of rounding. Disable the test for now.
if 0 {
do_test select1-8.4 {
  execsql {
    SELECT coalesce(f1/(f1-11),'x'),
           coalesce(min(f1/(f1-11),5),'y'),
           coalesce(max(f1/(f1-33),6),'z')
    FROM test1 ORDER BY f1
  }
} {x y 6 1.5 1.5 z}
}
do_test select1-8.5 {
  execsql {
    SELECT min(1,2,3), -max(1,2,3)
    FROM test1 ORDER BY f1
  }
} {1 -3 1 -3}


# Check the behavior when the result set is empty
#
# SQLite v3 always sets r(*).
#
# do_test select1-9.1 {
#   catch {unset r}
#   set r(*) {}
#   db eval {SELECT * FROM test1 WHERE f1<0} r {}
#   set r(*)
# } {}
do_test select1-9.2 {
  execsql {PRAGMA empty_result_callbacks=on}
  catch {unset r}
  set r(*) {}
  db eval {SELECT * FROM test1 WHERE f1<0} r {}
  set r(*)
} {f1 f2}
do_test select1-9.3 {
  set r(*) {}
  db eval {SELECT * FROM test1 WHERE f1<(select count(*) from test2)} r {}
  set r(*)
} {f1 f2}
do_test select1-9.4 {
  set r(*) {}
  db eval {SELECT * FROM test1 ORDER BY f1} r {}
  set r(*)
} {f1 f2}
do_test select1-9.5 {
  set r(*) {}
  db eval {SELECT * FROM test1 WHERE f1<0 ORDER BY f1} r {}
  set r(*)
} {f1 f2}
unset r

# Check for ORDER BY clauses that refer to an AS name in the column list
#
do_test select1-10.1 {
  execsql {
    SELECT f1 AS x FROM test1 ORDER BY x
  }
} {11 33}
do_test select1-10.2 {
  execsql {
    SELECT f1 AS x FROM test1 ORDER BY -x
  }
} {33 11}
do_test select1-10.3 {
  execsql {
    SELECT f1-23 AS x FROM test1 ORDER BY abs(x)
  }
} {10 -12}
do_test select1-10.4 {
  execsql {
    SELECT f1-23 AS x FROM test1 ORDER BY -abs(x)
  }
} {-12 10}
do_test select1-10.5 {
  execsql {
    SELECT f1-22 AS x, f2-22 as y FROM test1
  }
} {-11 0 11 22}
do_test select1-10.6 {
  execsql {
    SELECT f1-22 AS x, f2-22 as y FROM test1 WHERE x>0 AND y<50
  }
} {11 22}

# Check the ability to specify "TABLE.*" in the result set of a SELECT
#
do_test select1-11.1 {
  execsql {
    DELETE FROM t3;
    DELETE FROM t4;
    INSERT INTO t3 VALUES(1,2);
    INSERT INTO t4 VALUES(3,4);
    SELECT * FROM t3, t4;
  }
} {1 2 3 4}
do_test select1-11.2 {
  execsql2 {
    SELECT * FROM t3, t4;
  }
} {t3.a 1 t3.b 2 t4.a 3 t4.b 4}
do_test select1-11.3 {
  execsql2 {
    SELECT * FROM t3 AS x, t4 AS y;
  }
} {x.a 1 x.b 2 y.a 3 y.b 4}
do_test select1-11.4.1 {
  execsql {
    SELECT t3.*, t4.b FROM t3, t4;
  }
} {1 2 4}
do_test select1-11.4.2 {
  execsql {
    SELECT "t3".*, t4.b FROM t3, t4;
  }
} {1 2 4}
do_test select1-11.5 {
  execsql2 {
    SELECT t3.*, t4.b FROM t3, t4;
  }
} {t3.a 1 t3.b 2 t4.b 4}
do_test select1-11.6 {
  execsql2 {
    SELECT x.*, y.b FROM t3 AS x, t4 AS y;
  }
} {x.a 1 x.b 2 y.b 4}
do_test select1-11.7 {
  execsql {
    SELECT t3.b, t4.* FROM t3, t4;
  }
} {2 3 4}
do_test select1-11.8 {
  execsql2 {
    SELECT t3.b, t4.* FROM t3, t4;
  }
} {t3.b 2 t4.a 3 t4.b 4}
do_test select1-11.9 {
  execsql2 {
    SELECT x.b, y.* FROM t3 AS x, t4 AS y;
  }
} {x.b 2 y.a 3 y.b 4}
do_test select1-11.10 {
  catchsql {
    SELECT t5.* FROM t3, t4;
  }
} {1 {no such table: t5}}
do_test select1-11.11 {
  catchsql {
    SELECT t3.* FROM t3 AS x, t4;
  }
} {1 {no such table: t3}}
do_test select1-11.12 {
  execsql2 {
    SELECT t3.* FROM t3, (SELECT max(a), max(b) FROM t4)
  }
} {t3.a 1 t3.b 2}
do_test select1-11.13 {
  execsql2 {
    SELECT t3.* FROM (SELECT max(a), max(b) FROM t4), t3
  }
} {t3.a 1 t3.b 2}
do_test select1-11.14 {
  execsql2 {
    SELECT * FROM t3, (SELECT max(a), max(b) FROM t4) AS 'tx'
  }
} {t3.a 1 t3.b 2 tx.max(a) 3 tx.max(b) 4}
do_test select1-11.15 {
  execsql2 {
    SELECT y.*, t3.* FROM t3, (SELECT max(a), max(b) FROM t4) AS y
  }
} {y.max(a) 3 y.max(b) 4 t3.a 1 t3.b 2}
do_test select1-11.16 {
  execsql2 {
    SELECT y.* FROM t3 as y, t4 as z
  }
} {y.a 1 y.b 2}

# Tests of SELECT statements without a FROM clause.
#
do_test select1-12.1 {
  execsql2 {
    SELECT 1+2+3
  }
} {1+2+3 6}
do_test select1-12.2 {
  execsql2 {
    SELECT 1,'hello',2
  }
} {1 1 'hello' hello 2 2}
do_test select1-12.3 {
  execsql2 {
    SELECT 1 AS 'a','hello' AS 'b',2 AS 'c'
  }
} {a 1 b hello c 2}
do_test select1-12.4 {
  execsql {
    DELETE FROM t3;
    INSERT INTO t3 VALUES(1,2);
    SELECT * FROM t3 UNION SELECT 3 AS 'a', 4 ORDER BY a;
  }
} {1 2 3 4}
do_test select1-12.5 {
  execsql {
    SELECT 3, 4 UNION SELECT * FROM t3;
  }
} {1 2 3 4}
do_test select1-12.6 {
  execsql {
    SELECT * FROM t3 WHERE a=(SELECT 1);
  }
} {1 2}
do_test select1-12.7 {
  execsql {
    SELECT * FROM t3 WHERE a=(SELECT 2);
  }
} {}
do_test select1-12.8 {
  execsql2 {
    SELECT x FROM (
      SELECT a,b FROM t3 UNION SELECT a AS 'x', b AS 'y' FROM t4 ORDER BY a,b
    ) ORDER BY x;
  }
} {x 1 x 3}
do_test select1-12.9 {
  execsql2 {
    SELECT z.x FROM (
      SELECT a,b FROM t3 UNION SELECT a AS 'x', b AS 'y' FROM t4 ORDER BY a,b
    ) AS 'z' ORDER BY x;
  }
} {z.x 1 z.x 3}


finish_test

--- NEW FILE: select2.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table with some data
#
execsql {CREATE TABLE tbl1(f1 int, f2 int)}
execsql {BEGIN}
for {set i 0} {$i<=30} {incr i} {
  execsql "INSERT INTO tbl1 VALUES([expr {$i%9}],[expr {$i%10}])"
}
execsql {COMMIT}

# Do a second query inside a first.
#
do_test select2-1.1 {
  set sql {SELECT DISTINCT f1 FROM tbl1 ORDER BY f1}
  set r {}
  catch {unset data}
  db eval $sql data {
    set f1 $data(f1)
    lappend r $f1:
    set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2"
    db eval $sql2 d2 {
      lappend r $d2(f2)
    }
  }
  set r
} {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}

do_test select2-1.2 {
  set sql {SELECT DISTINCT f1 FROM tbl1 WHERE f1>3 AND f1<5}
  set r {}
  db eval $sql data {
    set f1 $data(f1)
    lappend r $f1:
    set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2"
    db eval $sql2 d2 {
      lappend r $d2(f2)
    }
  }
  set r
} {4: 2 3 4}

# Create a largish table
#
do_test select2-2.0 {
  execsql {CREATE TABLE tbl2(f1 int, f2 int, f3 int); BEGIN;}
  for {set i 1} {$i<=30000} {incr i} {
    execsql "INSERT INTO tbl2 VALUES($i,[expr {$i*2}],[expr {$i*3}])"
  }
  execsql {COMMIT}
} {}

do_test select2-2.1 {
  execsql {SELECT count(*) FROM tbl2}
} {30000}
do_test select2-2.2 {
  execsql {SELECT count(*) FROM tbl2 WHERE f2>1000}
} {29500}

do_test select2-3.1 {
  execsql {SELECT f1 FROM tbl2 WHERE 1000=f2}
} {500}

do_test select2-3.2a {
  execsql {CREATE INDEX idx1 ON tbl2(f2)}
} {}
do_test select2-3.2b {
  execsql {SELECT f1 FROM tbl2 WHERE 1000=f2}
} {500}
do_test select2-3.2c {
  execsql {SELECT f1 FROM tbl2 WHERE f2=1000}
} {500}
do_test select2-3.2d {
  set sqlite_search_count 0
  execsql {SELECT * FROM tbl2 WHERE 1000=f2}
  set sqlite_search_count
} {3}
do_test select2-3.2e {
  set sqlite_search_count 0
  execsql {SELECT * FROM tbl2 WHERE f2=1000}
  set sqlite_search_count
} {3}

# Make sure queries run faster with an index than without
#
do_test select2-3.3 {
  execsql {DROP INDEX idx1}
  set sqlite_search_count 0
  execsql {SELECT f1 FROM tbl2 WHERE f2==2000}
  set sqlite_search_count
} {29999}

# Make sure we can optimize functions in the WHERE clause that
# use fields from two or more different table.  (Bug #6)
#
do_test select2-4.1 {
  execsql {
    CREATE TABLE aa(a);
    CREATE TABLE bb(b);
    INSERT INTO aa VALUES(1);
    INSERT INTO aa VALUES(3);
    INSERT INTO bb VALUES(2);
    INSERT INTO bb VALUES(4);
    SELECT * FROM aa, bb WHERE max(a,b)>2;
  }
} {1 4 3 2 3 4}
do_test select2-4.2 {
  execsql {
    INSERT INTO bb VALUES(0);
    SELECT * FROM aa, bb WHERE b;
  }
} {1 2 1 4 3 2 3 4}
do_test select2-4.3 {
  execsql {
    SELECT * FROM aa, bb WHERE NOT b;
  }
} {1 0 3 0}
do_test select2-4.4 {
  execsql {
    SELECT * FROM aa, bb WHERE min(a,b);
  }
} {1 2 1 4 3 2 3 4}
do_test select2-4.5 {
  execsql {
    SELECT * FROM aa, bb WHERE NOT min(a,b);
  }
} {1 0 3 0}
do_test select2-4.6 {
  execsql {
    SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 1 END;
  }
} {1 2 3 4}
do_test select2-4.7 {
  execsql {
    SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 0 ELSE 1 END;
  }
} {1 4 1 0 3 2 3 0}

finish_test

--- NEW FILE: select3.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing aggregate functions and the
# GROUP BY and HAVING clauses of SELECT statements.
#
# $Id: select3.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test select3-1.0 {
  execsql {
    CREATE TABLE t1(n int, log int);
    BEGIN;
  }
  for {set i 1} {$i<32} {incr i} {
    for {set j 0} {pow(2,$j)<$i} {incr j} {}
    execsql "INSERT INTO t1 VALUES($i,$j)"
  }
  execsql {
    COMMIT
  }
  execsql {SELECT DISTINCT log FROM t1 ORDER BY log}
} {0 1 2 3 4 5}

# Basic aggregate functions.
#
do_test select3-1.1 {
  execsql {SELECT count(*) FROM t1}
} {31}
do_test select3-1.2 {
  execsql {
    SELECT min(n),min(log),max(n),max(log),sum(n),sum(log),avg(n),avg(log)
    FROM t1
  }
} {1 0 31 5 496.0 124.0 16.0 4.0}
do_test select3-1.3 {
  execsql {SELECT max(n)/avg(n), max(log)/avg(log) FROM t1}
} {1.9375 1.25}

# Try some basic GROUP BY clauses
#
do_test select3-2.1 {
  execsql {SELECT log, count(*) FROM t1 GROUP BY log ORDER BY log}
} {0 1 1 1 2 2 3 4 4 8 5 15}
do_test select3-2.2 {
  execsql {SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log}
} {0 1 1 2 2 3 3 5 4 9 5 17}
do_test select3-2.3 {
  execsql {SELECT log, avg(n) FROM t1 GROUP BY log ORDER BY log}
} {0 1.0 1 2.0 2 3.5 3 6.5 4 12.5 5 24.0}
do_test select3-2.3 {
  execsql {SELECT log, avg(n)+1 FROM t1 GROUP BY log ORDER BY log}
} {0 2.0 1 3.0 2 4.5 3 7.5 4 13.5 5 25.0}
do_test select3-2.4 {
  execsql {SELECT log, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log}
} {0 0.0 1 0.0 2 0.5 3 1.5 4 3.5 5 7.0}
do_test select3-2.5 {
  execsql {SELECT log*2+1, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log}
} {1 0.0 3 0.0 5 0.5 7 1.5 9 3.5 11 7.0}
do_test select3-2.6 {
  execsql {
    SELECT log*2+1 as x, count(*) FROM t1 GROUP BY x ORDER BY x
  }
} {1 1 3 1 5 2 7 4 9 8 11 15}
do_test select3-2.7 {
  execsql {
    SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY y
  }
} {3 1 1 1 5 2 7 4 9 8 11 15}
do_test select3-2.8 {
  execsql {
    SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY 10-(x+y)
  }
} {11 15 9 8 7 4 5 2 3 1 1 1}
do_test select3-2.9 {
  catchsql {
    SELECT log, count(*) FROM t1 GROUP BY 'x' ORDER BY log;
  }
} {1 {GROUP BY terms must not be non-integer constants}}
do_test select3-2.10 {
  catchsql {
    SELECT log, count(*) FROM t1 GROUP BY 0 ORDER BY log;
  }
} {1 {GROUP BY column number 0 out of range - should be between 1 and 2}}
do_test select3-2.11 {
  catchsql {
    SELECT log, count(*) FROM t1 GROUP BY 3 ORDER BY log;
  }
} {1 {GROUP BY column number 3 out of range - should be between 1 and 2}}
do_test select3-2.12 {
  catchsql {
    SELECT log, count(*) FROM t1 GROUP BY 1 ORDER BY log;
  }
} {0 {0 1 1 1 2 2 3 4 4 8 5 15}}
#do_test select3-2.13 {
#  catchsql {
#    SELECT log, count(*) FROM t1 GROUP BY 2 ORDER BY log;
#  }
#} {0 {0 1 1 1 2 2 3 4 4 8 5 15}}
#do_test select3-2.14 {
#  catchsql {
#    SELECT log, count(*) FROM t1 GROUP BY count(*) ORDER BY log;
#  }
#} {0 {0 1 1 1 2 2 3 4 4 8 5 15}}

# Cannot have a HAVING without a GROUP BY
#
do_test select3-3.1 {
  set v [catch {execsql {SELECT log, count(*) FROM t1 HAVING log>=4}} msg]
  lappend v $msg
} {1 {a GROUP BY clause is required before HAVING}}

# Toss in some HAVING clauses
#
do_test select3-4.1 {
  execsql {SELECT log, count(*) FROM t1 GROUP BY log HAVING log>=4 ORDER BY log}
} {4 8 5 15}
do_test select3-4.2 {
  execsql {
    SELECT log, count(*) FROM t1 
    GROUP BY log 
    HAVING count(*)>=4 
    ORDER BY log
  }
} {3 4 4 8 5 15}
do_test select3-4.3 {
  execsql {
    SELECT log, count(*) FROM t1 
    GROUP BY log 
    HAVING count(*)>=4 
    ORDER BY max(n)+0
  }
} {3 4 4 8 5 15}
do_test select3-4.4 {
  execsql {
    SELECT log AS x, count(*) AS y FROM t1 
    GROUP BY x
    HAVING y>=4 
    ORDER BY max(n)+0
  }
} {3 4 4 8 5 15}
do_test select3-4.5 {
  execsql {
    SELECT log AS x FROM t1 
    GROUP BY x
    HAVING count(*)>=4 
    ORDER BY max(n)+0
  }
} {3 4 5}

do_test select3-5.1 {
  execsql {
    SELECT log, count(*), avg(n), max(n+log*2) FROM t1 
    GROUP BY log 
    ORDER BY max(n+log*2)+0, avg(n)+0
  }
} {0 1 1.0 1 1 1 2.0 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24.0 41}
do_test select3-5.2 {
  execsql {
    SELECT log, count(*), avg(n), max(n+log*2) FROM t1 
    GROUP BY log 
    ORDER BY max(n+log*2)+0, min(log,avg(n))+0
  }
} {0 1 1.0 1 1 1 2.0 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24.0 41}

# Test sorting of GROUP BY results in the presence of an index
# on the GROUP BY column.
#
do_test select3-6.1 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log;
  }
} {0 1 1 2 2 3 3 5 4 9 5 17}
do_test select3-6.2 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log DESC;
  }
} {5 17 4 9 3 5 2 3 1 2 0 1}
do_test select3-6.3 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1;
  }
} {0 1 1 2 2 3 3 5 4 9 5 17}
do_test select3-6.4 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1 DESC;
  }
} {5 17 4 9 3 5 2 3 1 2 0 1}
do_test select3-6.5 {
  execsql {
    CREATE INDEX i1 ON t1(log);
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log;
  }
} {0 1 1 2 2 3 3 5 4 9 5 17}
do_test select3-6.6 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log DESC;
  }
} {5 17 4 9 3 5 2 3 1 2 0 1}
do_test select3-6.7 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1;
  }
} {0 1 1 2 2 3 3 5 4 9 5 17}
do_test select3-6.8 {
  execsql {
    SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1 DESC;
  }
} {5 17 4 9 3 5 2 3 1 2 0 1}



finish_test

--- NEW FILE: select4.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements.
#
# $Id: select4.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
execsql {
  CREATE TABLE t1(n int, log int);
  BEGIN;
}
for {set i 1} {$i<32} {incr i} {
  for {set j 0} {pow(2,$j)<$i} {incr j} {}
  execsql "INSERT INTO t1 VALUES($i,$j)"
}
execsql {
  COMMIT;
}

do_test select4-1.0 {
  execsql {SELECT DISTINCT log FROM t1 ORDER BY log}
} {0 1 2 3 4 5}

# Union All operator
#
do_test select4-1.1a {
  lsort [execsql {SELECT DISTINCT log FROM t1}]
} {0 1 2 3 4 5}
do_test select4-1.1b {
  lsort [execsql {SELECT n FROM t1 WHERE log=3}]
} {5 6 7 8}
do_test select4-1.1c {
  execsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }
} {0 1 2 3 4 5 5 6 7 8}
do_test select4-1.1d {
  execsql {
    CREATE TABLE t2 AS
      SELECT DISTINCT log FROM t1
      UNION ALL
      SELECT n FROM t1 WHERE log=3
      ORDER BY log;
    SELECT * FROM t2;
  }
} {0 1 2 3 4 5 5 6 7 8}
execsql {DROP TABLE t2}
do_test select4-1.1e {
  execsql {
    CREATE TABLE t2 AS
      SELECT DISTINCT log FROM t1
      UNION ALL
      SELECT n FROM t1 WHERE log=3
      ORDER BY log DESC;
    SELECT * FROM t2;
  }
} {8 7 6 5 5 4 3 2 1 0}
execsql {DROP TABLE t2}
do_test select4-1.1f {
  execsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=2
  }
} {0 1 2 3 4 5 3 4}
do_test select4-1.1g {
  execsql {
    CREATE TABLE t2 AS 
      SELECT DISTINCT log FROM t1
      UNION ALL
      SELECT n FROM t1 WHERE log=2;
    SELECT * FROM t2;
  }
} {0 1 2 3 4 5 3 4}
execsql {DROP TABLE t2}
do_test select4-1.2 {
  execsql {
    SELECT log FROM t1 WHERE n IN 
      (SELECT DISTINCT log FROM t1 UNION ALL
       SELECT n FROM t1 WHERE log=3)
    ORDER BY log;
  }
} {0 1 2 2 3 3 3 3}
do_test select4-1.3 {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1 ORDER BY log
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }} msg]
  lappend v $msg
} {1 {ORDER BY clause should come after UNION ALL not before}}

# Union operator
#
do_test select4-2.1 {
  execsql {
    SELECT DISTINCT log FROM t1
    UNION
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }
} {0 1 2 3 4 5 6 7 8}
do_test select4-2.2 {
  execsql {
    SELECT log FROM t1 WHERE n IN 
      (SELECT DISTINCT log FROM t1 UNION
       SELECT n FROM t1 WHERE log=3)
    ORDER BY log;
  }
} {0 1 2 2 3 3 3 3}
do_test select4-2.3 {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1 ORDER BY log
    UNION
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }} msg]
  lappend v $msg
} {1 {ORDER BY clause should come after UNION not before}}

# Except operator
#
do_test select4-3.1.1 {
  execsql {
    SELECT DISTINCT log FROM t1
    EXCEPT
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }
} {0 1 2 3 4}
do_test select4-3.1.2 {
  execsql {
    CREATE TABLE t2 AS 
      SELECT DISTINCT log FROM t1
      EXCEPT
      SELECT n FROM t1 WHERE log=3
      ORDER BY log;
    SELECT * FROM t2;
  }
} {0 1 2 3 4}
execsql {DROP TABLE t2}
do_test select4-3.1.3 {
  execsql {
    CREATE TABLE t2 AS 
      SELECT DISTINCT log FROM t1
      EXCEPT
      SELECT n FROM t1 WHERE log=3
      ORDER BY log DESC;
    SELECT * FROM t2;
  }
} {4 3 2 1 0}
execsql {DROP TABLE t2}
do_test select4-3.2 {
  execsql {
    SELECT log FROM t1 WHERE n IN 
      (SELECT DISTINCT log FROM t1 EXCEPT
       SELECT n FROM t1 WHERE log=3)
    ORDER BY log;
  }
} {0 1 2 2}
do_test select4-3.3 {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1 ORDER BY log
    EXCEPT
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }} msg]
  lappend v $msg
} {1 {ORDER BY clause should come after EXCEPT not before}}

# Intersect operator
#
do_test select4-4.1.1 {
  execsql {
    SELECT DISTINCT log FROM t1
    INTERSECT
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }
} {5}

do_test select4-4.1.2 {
  execsql {
    SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
    INTERSECT
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }
} {5 6}
do_test select4-4.1.3 {
  execsql {
    CREATE TABLE t2 AS
      SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
      INTERSECT
      SELECT n FROM t1 WHERE log=3
      ORDER BY log;
    SELECT * FROM t2;
  }
} {5 6}
execsql {DROP TABLE t2}
do_test select4-4.1.4 {
  execsql {
    CREATE TABLE t2 AS
      SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
      INTERSECT
      SELECT n FROM t1 WHERE log=3
      ORDER BY log DESC;
    SELECT * FROM t2;
  }
} {6 5}
execsql {DROP TABLE t2}
do_test select4-4.2 {
  execsql {
    SELECT log FROM t1 WHERE n IN 
      (SELECT DISTINCT log FROM t1 INTERSECT
       SELECT n FROM t1 WHERE log=3)
    ORDER BY log;
  }
} {3}
do_test select4-4.3 {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1 ORDER BY log
    INTERSECT
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }} msg]
  lappend v $msg
} {1 {ORDER BY clause should come after INTERSECT not before}}

# Various error messages while processing UNION or INTERSECT
#
do_test select4-5.1 {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t2
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }} msg]
  lappend v $msg
} {1 {no such table: t2}}
do_test select4-5.2 {
  set v [catch {execsql {
    SELECT DISTINCT log AS "xyzzy" FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY xyzzy;
  }} msg]
  lappend v $msg
} {0 {0 1 2 3 4 5 5 6 7 8}}
do_test select4-5.2b {
  set v [catch {execsql {
    SELECT DISTINCT log AS xyzzy FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY 'xyzzy';
  }} msg]
  lappend v $msg
} {0 {0 1 2 3 4 5 5 6 7 8}}
do_test select4-5.2c {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY 'xyzzy';
  }} msg]
  lappend v $msg
} {1 {ORDER BY term number 1 does not match any result column}}
do_test select4-5.2d {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1
    INTERSECT
    SELECT n FROM t1 WHERE log=3
    ORDER BY 'xyzzy';
  }} msg]
  lappend v $msg
} {1 {ORDER BY term number 1 does not match any result column}}
do_test select4-5.2e {
  set v [catch {execsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY n;
  }} msg]
  lappend v $msg
} {0 {0 1 2 3 4 5 5 6 7 8}}
do_test select4-5.2f {
  catchsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }
} {0 {0 1 2 3 4 5 5 6 7 8}}
do_test select4-5.2g {
  catchsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY 1;
  }
} {0 {0 1 2 3 4 5 5 6 7 8}}
do_test select4-5.2h {
  catchsql {
    SELECT DISTINCT log FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY 2;
  }
} {1 {ORDER BY position 2 should be between 1 and 1}}
do_test select4-5.2i {
  catchsql {
    SELECT DISTINCT 1, log FROM t1
    UNION ALL
    SELECT 2, n FROM t1 WHERE log=3
    ORDER BY 2, 1;
  }
} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}}
do_test select4-5.2j {
  catchsql {
    SELECT DISTINCT 1, log FROM t1
    UNION ALL
    SELECT 2, n FROM t1 WHERE log=3
    ORDER BY 1, 2 DESC;
  }
} {0 {1 5 1 4 1 3 1 2 1 1 1 0 2 8 2 7 2 6 2 5}}
do_test select4-5.2k {
  catchsql {
    SELECT DISTINCT 1, log FROM t1
    UNION ALL
    SELECT 2, n FROM t1 WHERE log=3
    ORDER BY n, 1;
  }
} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}}
do_test select4-5.3 {
  set v [catch {execsql {
    SELECT DISTINCT log, n FROM t1
    UNION ALL
    SELECT n FROM t1 WHERE log=3
    ORDER BY log;
  }} msg]
  lappend v $msg
} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}}
do_test select4-5.4 {
  set v [catch {execsql {
    SELECT log FROM t1 WHERE n=2
    UNION ALL
    SELECT log FROM t1 WHERE n=3
    UNION ALL
    SELECT log FROM t1 WHERE n=4
    UNION ALL
    SELECT log FROM t1 WHERE n=5
    ORDER BY log;
  }} msg]
  lappend v $msg
} {0 {1 2 2 3}}

do_test select4-6.1 {
  execsql {
    SELECT log, count(*) as cnt FROM t1 GROUP BY log
    UNION
    SELECT log, n FROM t1 WHERE n=7
    ORDER BY cnt, log;
  }
} {0 1 1 1 2 2 3 4 3 7 4 8 5 15}
do_test select4-6.2 {
  execsql {
    SELECT log, count(*) FROM t1 GROUP BY log
    UNION
    SELECT log, n FROM t1 WHERE n=7
    ORDER BY count(*), log;
  }
} {0 1 1 1 2 2 3 4 3 7 4 8 5 15}

# NULLs are indistinct for the UNION operator.
# Make sure the UNION operator recognizes this
#
do_test select4-6.3 {
  execsql {
    SELECT NULL UNION SELECT NULL UNION
    SELECT 1 UNION SELECT 2 AS 'x'
    ORDER BY x;
  }
} {{} 1 2}
do_test select4-6.3.1 {
  execsql {
    SELECT NULL UNION ALL SELECT NULL UNION ALL
    SELECT 1 UNION ALL SELECT 2 AS 'x'
    ORDER BY x;
  }
} {{} {} 1 2}

# Make sure the DISTINCT keyword treats NULLs as indistinct.
#
do_test select4-6.4 {
  execsql {
    SELECT * FROM (
       SELECT NULL, 1 UNION ALL SELECT NULL, 1
    );
  }
} {{} 1 {} 1}
do_test select4-6.5 {
  execsql {
    SELECT DISTINCT * FROM (
       SELECT NULL, 1 UNION ALL SELECT NULL, 1
    );
  }
} {{} 1}
do_test select4-6.6 {
  execsql {
    SELECT DISTINCT * FROM (
       SELECT 1,2  UNION ALL SELECT 1,2
    );
  }
} {1 2}

# Test distinctness of NULL in other ways.
#
do_test select4-6.7 {
  execsql {
    SELECT NULL EXCEPT SELECT NULL
  }
} {}


# Make sure column names are correct when a compound select appears as
# an expression in the WHERE clause.
#
do_test select4-7.1 {
  execsql {
    CREATE TABLE t2 AS SELECT log AS 'x', count(*) AS 'y' FROM t1 GROUP BY log;
    SELECT * FROM t2 ORDER BY x;
  }
} {0 1 1 1 2 2 3 4 4 8 5 15}  
do_test select4-7.2 {
  execsql2 {
    SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 INTERSECT SELECT x FROM t2)
    ORDER BY n
  }
} {n 1 log 0 n 2 log 1 n 3 log 2 n 4 log 2 n 5 log 3}
do_test select4-7.3 {
  execsql2 {
    SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 EXCEPT SELECT x FROM t2)
    ORDER BY n LIMIT 2
  }
} {n 6 log 3 n 7 log 3}
do_test select4-7.4 {
  execsql2 {
    SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 UNION SELECT x FROM t2)
    ORDER BY n LIMIT 2
  }
} {n 1 log 0 n 2 log 1}

# Make sure DISTINCT works appropriately on TEXT and NUMERIC columns.
do_test select4-8.1 {
  execsql {
    BEGIN;
    CREATE TABLE t3(a text, b float, c text);
    INSERT INTO t3 VALUES(1, 1.1, '1.1');
    INSERT INTO t3 VALUES(2, 1.10, '1.10');
    INSERT INTO t3 VALUES(3, 1.10, '1.1');
    INSERT INTO t3 VALUES(4, 1.1, '1.10');
    INSERT INTO t3 VALUES(5, 1.2, '1.2');
    INSERT INTO t3 VALUES(6, 1.3, '1.3');
    COMMIT;
  }
  execsql {
    SELECT DISTINCT b FROM t3 ORDER BY c;
  }
} {1.1 1.2 1.3}
do_test select4-8.2 {
  execsql {
    SELECT DISTINCT c FROM t3 ORDER BY c;
  }
} {1.1 1.10 1.2 1.3}


finish_test

--- NEW FILE: select5.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing aggregate functions and the
# GROUP BY and HAVING clauses of SELECT statements.
#
# $Id: select5.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
execsql {
  CREATE TABLE t1(x int, y int);
  BEGIN;
}
for {set i 1} {$i<32} {incr i} {
  for {set j 0} {pow(2,$j)<$i} {incr j} {}
  execsql "INSERT INTO t1 VALUES([expr {32-$i}],[expr {10-$j}])"
}
execsql {
  COMMIT
}

do_test select5-1.0 {
  execsql {SELECT DISTINCT y FROM t1 ORDER BY y}
} {5 6 7 8 9 10}

# Sort by an aggregate function.
#
do_test select5-1.1 {
  execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY y}
} {5 15 6 8 7 4 8 2 9 1 10 1}
do_test select5-1.2 {
  execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY count(*), y}
} {9 1 10 1 8 2 7 4 6 8 5 15}
do_test select5-1.3 {
  execsql {SELECT count(*), y FROM t1 GROUP BY y ORDER BY count(*), y}
} {1 9 1 10 2 8 4 7 8 6 15 5}

# Some error messages associated with aggregates and GROUP BY
#
do_test select5-2.1 {
  set v [catch {execsql {
    SELECT y, count(*) FROM t1 GROUP BY z ORDER BY y
  }} msg]
  lappend v $msg
} {1 {no such column: z}}
do_test select5-2.2 {
  set v [catch {execsql {
    SELECT y, count(*) FROM t1 GROUP BY z(y) ORDER BY y
  }} msg]
  lappend v $msg
} {1 {no such function: z}}
do_test select5-2.3 {
  set v [catch {execsql {
    SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<3 ORDER BY y
  }} msg]
  lappend v $msg
} {0 {8 2 9 1 10 1}}
do_test select5-2.4 {
  set v [catch {execsql {
    SELECT y, count(*) FROM t1 GROUP BY y HAVING z(y)<3 ORDER BY y
  }} msg]
  lappend v $msg
} {1 {no such function: z}}
do_test select5-2.5 {
  set v [catch {execsql {
    SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<z ORDER BY y
  }} msg]
  lappend v $msg
} {1 {no such column: z}}

# Get the Agg function to rehash in vdbe.c
#
do_test select5-3.1 {
  execsql {
    SELECT x, count(*), avg(y) FROM t1 GROUP BY x HAVING x<4 ORDER BY x
  }
} {1 1 5.0 2 1 5.0 3 1 5.0}

# Run various aggregate functions when the count is zero.
#
do_test select5-4.1 {
  execsql {
    SELECT avg(x) FROM t1 WHERE x>100
  }
} {{}}
do_test select5-4.2 {
  execsql {
    SELECT count(x) FROM t1 WHERE x>100
  }
} {0}
do_test select5-4.3 {
  execsql {
    SELECT min(x) FROM t1 WHERE x>100
  }
} {{}}
do_test select5-4.4 {
  execsql {
    SELECT max(x) FROM t1 WHERE x>100
  }
} {{}}
do_test select5-4.5 {
  execsql {
    SELECT sum(x) FROM t1 WHERE x>100
  }
} {0.0}

finish_test

--- NEW FILE: select6.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing SELECT statements that contain
# subqueries in their FROM clause.
#
# $Id: select6.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test select6-1.0 {
  execsql {
    BEGIN;
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1,1);
    INSERT INTO t1 VALUES(2,2);
    INSERT INTO t1 VALUES(3,2);
    INSERT INTO t1 VALUES(4,3);
    INSERT INTO t1 VALUES(5,3);
    INSERT INTO t1 VALUES(6,3);
    INSERT INTO t1 VALUES(7,3);
    INSERT INTO t1 VALUES(8,4);
    INSERT INTO t1 VALUES(9,4);
    INSERT INTO t1 VALUES(10,4);
    INSERT INTO t1 VALUES(11,4);
    INSERT INTO t1 VALUES(12,4);
    INSERT INTO t1 VALUES(13,4);
    INSERT INTO t1 VALUES(14,4);
    INSERT INTO t1 VALUES(15,4);
    INSERT INTO t1 VALUES(16,5);
    INSERT INTO t1 VALUES(17,5);
    INSERT INTO t1 VALUES(18,5);
    INSERT INTO t1 VALUES(19,5);
    INSERT INTO t1 VALUES(20,5);
    COMMIT;
    SELECT DISTINCT y FROM t1 ORDER BY y;
  }
} {1 2 3 4 5}

do_test select6-1.1 {
  execsql2 {SELECT * FROM (SELECT x, y FROM t1 WHERE x<2)}
} {x 1 y 1}
do_test select6-1.2 {
  execsql {SELECT count(*) FROM (SELECT y FROM t1)}
} {20}
do_test select6-1.3 {
  execsql {SELECT count(*) FROM (SELECT DISTINCT y FROM t1)}
} {5}
do_test select6-1.4 {
  execsql {SELECT count(*) FROM (SELECT DISTINCT * FROM (SELECT y FROM t1))}
} {5}
do_test select6-1.5 {
  execsql {SELECT count(*) FROM (SELECT * FROM (SELECT DISTINCT y FROM t1))}
} {5}

do_test select6-1.6 {
  execsql {
    SELECT * 
    FROM (SELECT count(*),y FROM t1 GROUP BY y) AS a,
         (SELECT max(x),y FROM t1 GROUP BY y) as b
    WHERE a.y=b.y ORDER BY a.y
  }
} {1 1 1 1 2 2 3 2 4 3 7 3 8 4 15 4 5 5 20 5}
do_test select6-1.7 {
  execsql {
    SELECT a.y, a.[count(*)], [max(x)], [count(*)]
    FROM (SELECT count(*),y FROM t1 GROUP BY y) AS a,
         (SELECT max(x),y FROM t1 GROUP BY y) as b
    WHERE a.y=b.y ORDER BY a.y
  }
} {1 1 1 1 2 2 3 2 3 4 7 4 4 8 15 8 5 5 20 5}
do_test select6-1.8 {
  execsql {
    SELECT q, p, r
    FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
         (SELECT max(x) as r, y as s FROM t1 GROUP BY y) as b
    WHERE q=s ORDER BY s
  }
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-1.9 {
  execsql {
    SELECT q, p, r, b.[min(x)+y]
    FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
         (SELECT max(x) as r, y as s, min(x)+y FROM t1 GROUP BY y) as b
    WHERE q=s ORDER BY s
  }
} {1 1 1 2 2 2 3 4 3 4 7 7 4 8 15 12 5 5 20 21}

do_test select6-2.0 {
  execsql {
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
    INSERT INTO t2 SELECT * FROM t1;
    SELECT DISTINCT b FROM t2 ORDER BY b;
  }
} {1 2 3 4 5}
do_test select6-2.1 {
  execsql2 {SELECT * FROM (SELECT a, b FROM t2 WHERE a<2)}
} {a 1 b 1}
do_test select6-2.2 {
  execsql {SELECT count(*) FROM (SELECT b FROM t2)}
} {20}
do_test select6-2.3 {
  execsql {SELECT count(*) FROM (SELECT DISTINCT b FROM t2)}
} {5}
do_test select6-2.4 {
  execsql {SELECT count(*) FROM (SELECT DISTINCT * FROM (SELECT b FROM t2))}
} {5}
do_test select6-2.5 {
  execsql {SELECT count(*) FROM (SELECT * FROM (SELECT DISTINCT b FROM t2))}
} {5}

do_test select6-2.6 {
  execsql {
    SELECT * 
    FROM (SELECT count(*),b FROM t2 GROUP BY b) AS a,
         (SELECT max(a),b FROM t2 GROUP BY b) as b
    WHERE a.b=b.b ORDER BY a.b
  }
} {1 1 1 1 2 2 3 2 4 3 7 3 8 4 15 4 5 5 20 5}
do_test select6-2.7 {
  execsql {
    SELECT a.b, a.[count(*)], [max(a)], [count(*)]
    FROM (SELECT count(*),b FROM t2 GROUP BY b) AS a,
         (SELECT max(a),b FROM t2 GROUP BY b) as b
    WHERE a.b=b.b ORDER BY a.b
  }
} {1 1 1 1 2 2 3 2 3 4 7 4 4 8 15 8 5 5 20 5}
do_test select6-2.8 {
  execsql {
    SELECT q, p, r
    FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY b) AS a,
         (SELECT max(a) as r, b as s FROM t2 GROUP BY b) as b
    WHERE q=s ORDER BY s
  }
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-2.9 {
  execsql {
    SELECT a.q, a.p, b.r
    FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
         (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
    WHERE a.q=b.s ORDER BY a.q
  }
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}

do_test sqlite6-3.1 {
  execsql2 {
    SELECT * FROM (SELECT * FROM (SELECT * FROM t1 WHERE x=3));
  }
} {x 3 y 2}
do_test sqlite6-3.2 {
  execsql {
    SELECT * FROM
      (SELECT a.q, a.p, b.r
       FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
            (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
       WHERE a.q=b.s ORDER BY a.q)
    ORDER BY q
  }
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-3.3 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
  }
} {10.5 3.7 14.2}
do_test select6-3.4 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
  }
} {11.5 4.0 15.5}
do_test select6-3.5 {
  execsql {
    SELECT x,y,x+y FROM (SELECT avg(a) as 'x', avg(b) as 'y' FROM t2 WHERE a=4)
  }
} {4.0 3.0 7.0}
do_test select6-3.6 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
    WHERE a>10
  }
} {10.5 3.7 14.2}
do_test select6-3.7 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
    WHERE a<10
  }
} {}
do_test select6-3.8 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
    WHERE a>10
  }
} {11.5 4.0 15.5}
do_test select6-3.9 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
    WHERE a<10
  }
} {}
do_test select6-3.10 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b)
    ORDER BY a
  }
} {1.0 1 2.0 2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18.0 5 23.0}
do_test select6-3.11 {
  execsql {
    SELECT a,b,a+b FROM 
       (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b)
    WHERE b<4 ORDER BY a
  }
} {1.0 1 2.0 2.5 2 4.5 5.5 3 8.5}
do_test select6-3.12 {
  execsql {
    SELECT a,b,a+b FROM 
       (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1)
    WHERE b<4 ORDER BY a
  }
} {2.5 2 4.5 5.5 3 8.5}
do_test select6-3.13 {
  execsql {
    SELECT a,b,a+b FROM 
       (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1)
    ORDER BY a
  }
} {2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18.0 5 23.0}
do_test select6-3.14 {
  execsql {
    SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y)
    ORDER BY [count(*)]
  }
} {1 1 2 2 4 3 5 5 8 4}
do_test select6-3.15 {
  execsql {
    SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y)
    ORDER BY y
  }
} {1 1 2 2 4 3 8 4 5 5}

do_test select6-4.1 {
  execsql {
    SELECT a,b,c FROM 
      (SELECT x AS 'a', y AS 'b', x+y AS 'c' FROM t1 WHERE y=4)
    WHERE a<10 ORDER BY a;
  }
} {8 4 12 9 4 13}
do_test select6-4.2 {
  execsql {
    SELECT y FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y
  }
} {1 2 3 4}
do_test select6-4.3 {
  execsql {
    SELECT DISTINCT y FROM (SELECT y FROM t1) WHERE y<5 ORDER BY y
  }
} {1 2 3 4}
do_test select6-4.4 {
  execsql {
    SELECT avg(y) FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y
  }
} {2.5}
do_test select6-4.5 {
  execsql {
    SELECT avg(y) FROM (SELECT DISTINCT y FROM t1 WHERE y<5) ORDER BY y
  }
} {2.5}

do_test select6-5.1 {
  execsql {
    SELECT a,x,b FROM
      (SELECT x+3 AS 'a', x FROM t1 WHERE y=3) AS 'p',
      (SELECT x AS 'b' FROM t1 WHERE y=4) AS 'q'
    WHERE a=b
    ORDER BY a
  }
} {8 5 8 9 6 9 10 7 10}
do_test select6-5.2 {
  execsql {
    SELECT a,x,b FROM
      (SELECT x+3 AS 'a', x FROM t1 WHERE y=3),
      (SELECT x AS 'b' FROM t1 WHERE y=4)
    WHERE a=b
    ORDER BY a
  }
} {8 5 8 9 6 9 10 7 10}

# Tests of compound sub-selects
#
do_test select5-6.1 {
  execsql {
    DELETE FROM t1 WHERE x>4;
    SELECT * FROM t1
  }
} {1 1 2 2 3 2 4 3}
do_test select6-6.2 {
  execsql {
    SELECT * FROM (
      SELECT x AS 'a' FROM t1 UNION ALL SELECT x+10 AS 'a' FROM t1
    ) ORDER BY a;
  }
} {1 2 3 4 11 12 13 14}
do_test select6-6.3 {
  execsql {
    SELECT * FROM (
      SELECT x AS 'a' FROM t1 UNION ALL SELECT x+1 AS 'a' FROM t1
    ) ORDER BY a;
  }
} {1 2 2 3 3 4 4 5}
do_test select6-6.4 {
  execsql {
    SELECT * FROM (
      SELECT x AS 'a' FROM t1 UNION SELECT x+1 AS 'a' FROM t1
    ) ORDER BY a;
  }
} {1 2 3 4 5}
do_test select6-6.5 {
  execsql {
    SELECT * FROM (
      SELECT x AS 'a' FROM t1 INTERSECT SELECT x+1 AS 'a' FROM t1
    ) ORDER BY a;
  }
} {2 3 4}
do_test select6-6.6 {
  execsql {
    SELECT * FROM (
      SELECT x AS 'a' FROM t1 EXCEPT SELECT x*2 AS 'a' FROM t1
    ) ORDER BY a;
  }
} {1 3}

# Subselects with no FROM clause
#
do_test select6-7.1 {
  execsql {
    SELECT * FROM (SELECT 1)
  }
} {1}
do_test select6-7.2 {
  execsql {
    SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c')
  }
} {abc 2 1 1 2 abc}
do_test select6-7.3 {
  execsql {
    SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c' WHERE 0)
  }
} {}
do_test select6-7.4 {
  execsql2 {
    SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c' WHERE 1)
  }
} {c abc b 2 a 1 a 1 b 2 c abc}

# The following procedure compiles the SQL given as an argument and returns
# TRUE if that SQL uses any transient tables and returns FALSE if no
# transient tables are used.  This is used to make sure that the
# sqliteFlattenSubquery() routine in select.c is doing its job.
#
proc is_flat {sql} {
  return [expr 0>[lsearch [execsql "EXPLAIN $sql"] OpenTemp]]
}

# Check that the flattener works correctly for deeply nested subqueries
# involving joins.
#
do_test select6-8.1 {
  execsql {
    BEGIN;
    CREATE TABLE t3(p,q);
    INSERT INTO t3 VALUES(1,11);
    INSERT INTO t3 VALUES(2,22);
    CREATE TABLE t4(q,r);
    INSERT INTO t4 VALUES(11,111);
    INSERT INTO t4 VALUES(22,222);
    COMMIT;
    SELECT * FROM t3 NATURAL JOIN t4;
  }
} {1 11 111 2 22 222}
do_test select6-8.2 {
  execsql {
    SELECT y, p, q, r FROM
       (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
       (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
    WHERE  y=p
  }
} {1 1 11 111 2 2 22 222 2 2 22 222}
do_test select6-8.3 {
  is_flat {
    SELECT y, p, q, r FROM
       (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
       (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
    WHERE  y=p
  }
} {1}
do_test select6-8.4 {
  execsql {
    SELECT DISTINCT y, p, q, r FROM
       (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
       (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
    WHERE  y=p
  }
} {1 1 11 111 2 2 22 222}
do_test select6-8.5 {
  execsql {
    SELECT * FROM 
      (SELECT y, p, q, r FROM
         (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
         (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
      WHERE  y=p) AS e,
      (SELECT r AS z FROM t4 WHERE q=11) AS f
    WHERE e.r=f.z
  }
} {1 1 11 111 111}
do_test select6-8.6 {
  is_flat {
    SELECT * FROM 
      (SELECT y, p, q, r FROM
         (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
         (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
      WHERE  y=p) AS e,
      (SELECT r AS z FROM t4 WHERE q=11) AS f
    WHERE e.r=f.z
  }
} {1}


finish_test

--- NEW FILE: select7.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing compute SELECT statements and nested
# views.
#
# $Id: select7.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# A 3-way INTERSECT.  Ticket #875
do_test select7-1.1 {
  execsql {
    create temp table t1(x);
    insert into t1 values('amx');
    insert into t1 values('anx');
    insert into t1 values('amy');
    insert into t1 values('bmy');
    select * from t1 where x like 'a__'
      intersect select * from t1 where x like '_m_'
      intersect select * from t1 where x like '__x';
  }
} {amx}


# Nested views do not handle * properly.  Ticket #826.
#
do_test select7-2.1 {
  execsql {
    CREATE TABLE x(id integer primary key, a TEXT NULL);
    INSERT INTO x (a) VALUES ('first');
    CREATE TABLE tempx(id integer primary key, a TEXT NULL);
    INSERT INTO tempx (a) VALUES ('t-first');
    CREATE VIEW tv1 AS SELECT x.id, tx.id FROM x JOIN tempx tx ON tx.id=x.id;
    CREATE VIEW tv1b AS SELECT x.id, tx.id FROM x JOIN tempx tx on tx.id=x.id;
    CREATE VIEW tv2 AS SELECT * FROM tv1 UNION SELECT * FROM tv1b;
    SELECT * FROM tv2;
  }
} {1 1}


finish_test

--- NEW FILE: sort.test ---
# 2001 September 15.
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE TABLE statement.
#
# $Id: sort.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a bunch of data to sort against
#
do_test sort-1.0 {
  execsql {
    CREATE TABLE t1(
       n int,
       v varchar(10),
       log int,
       roman varchar(10),
       flt real
    );
    INSERT INTO t1 VALUES(1,'one',0,'I',3.141592653);
    INSERT INTO t1 VALUES(2,'two',1,'II',2.15);
    INSERT INTO t1 VALUES(3,'three',1,'III',4221.0);
    INSERT INTO t1 VALUES(4,'four',2,'IV',-0.0013442);
    INSERT INTO t1 VALUES(5,'five',2,'V',-11);
    INSERT INTO t1 VALUES(6,'six',2,'VI',0.123);
    INSERT INTO t1 VALUES(7,'seven',2,'VII',123.0);
    INSERT INTO t1 VALUES(8,'eight',3,'VIII',-1.6);
  }
  execsql {SELECT count(*) FROM t1}
} {8}

do_test sort-1.1 {
  execsql {SELECT n FROM t1 ORDER BY n}
} {1 2 3 4 5 6 7 8}
do_test sort-1.1.1 {
  execsql {SELECT n FROM t1 ORDER BY n ASC}
} {1 2 3 4 5 6 7 8}
do_test sort-1.1.1 {
  execsql {SELECT ALL n FROM t1 ORDER BY n ASC}
} {1 2 3 4 5 6 7 8}
do_test sort-1.2 {
  execsql {SELECT n FROM t1 ORDER BY n DESC}
} {8 7 6 5 4 3 2 1}
do_test sort-1.3a {
  execsql {SELECT v FROM t1 ORDER BY v}
} {eight five four one seven six three two}
do_test sort-1.3b {
  execsql {SELECT n FROM t1 ORDER BY v}
} {8 5 4 1 7 6 3 2}
do_test sort-1.4 {
  execsql {SELECT n FROM t1 ORDER BY v DESC}
} {2 3 6 7 1 4 5 8}
do_test sort-1.5 {
  execsql {SELECT flt FROM t1 ORDER BY flt}
} {-11 -1.6 -0.0013442 0.123 2.15 3.141592653 123.0 4221.0}
do_test sort-1.6 {
  execsql {SELECT flt FROM t1 ORDER BY flt DESC}
} {4221.0 123.0 3.141592653 2.15 0.123 -0.0013442 -1.6 -11}
do_test sort-1.7 {
  execsql {SELECT roman FROM t1 ORDER BY roman}
} {I II III IV V VI VII VIII}
do_test sort-1.8 {
  execsql {SELECT n FROM t1 ORDER BY log, flt}
} {1 2 3 5 4 6 7 8}
do_test sort-1.8.1 {
  execsql {SELECT n FROM t1 ORDER BY log asc, flt}
} {1 2 3 5 4 6 7 8}
do_test sort-1.8.2 {
  execsql {SELECT n FROM t1 ORDER BY log, flt ASC}
} {1 2 3 5 4 6 7 8}
do_test sort-1.8.3 {
  execsql {SELECT n FROM t1 ORDER BY log ASC, flt asc}
} {1 2 3 5 4 6 7 8}
do_test sort-1.9 {
  execsql {SELECT n FROM t1 ORDER BY log, flt DESC}
} {1 3 2 7 6 4 5 8}
do_test sort-1.9.1 {
  execsql {SELECT n FROM t1 ORDER BY log ASC, flt DESC}
} {1 3 2 7 6 4 5 8}
do_test sort-1.10 {
  execsql {SELECT n FROM t1 ORDER BY log DESC, flt}
} {8 5 4 6 7 2 3 1}
do_test sort-1.11 {
  execsql {SELECT n FROM t1 ORDER BY log DESC, flt DESC}
} {8 7 6 4 5 3 2 1}

# These tests are designed to reach some hard-to-reach places
# inside the string comparison routines.
#
# (Later) The sorting behavior changed in 2.7.0.  But we will
# keep these tests.  You can never have too many test cases!
#
do_test sort-2.1.1 {
  execsql {
    UPDATE t1 SET v='x' || -flt;
    UPDATE t1 SET v='x-2b' where v=='x-0.123';
    SELECT v FROM t1 ORDER BY v;
  }
} {x-123 x-2.15 x-2b x-3.141592653 x-4221 x0.0013442 x1.6 x11}
do_test sort-2.1.2 {
  execsql {
    SELECT v FROM t1 ORDER BY substr(v,2,999);
  }
} {x-123 x-2.15 x-2b x-3.141592653 x-4221 x0.0013442 x1.6 x11}
do_test sort-2.1.3 {
  execsql {
    SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0;
  }
} {x-4221 x-123 x-3.141592653 x-2.15 x-2b x0.0013442 x1.6 x11}
do_test sort-2.1.4 {
  execsql {
    SELECT v FROM t1 ORDER BY substr(v,2,999) DESC;
  }
} {x11 x1.6 x0.0013442 x-4221 x-3.141592653 x-2b x-2.15 x-123}
do_test sort-2.1.5 {
  execsql {
    SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0 DESC;
  }
} {x11 x1.6 x0.0013442 x-2b x-2.15 x-3.141592653 x-123 x-4221}

# This is a bug fix for 2.2.4.
# Strings are normally mapped to upper-case for a caseless comparison.
# But this can cause problems for characters in between 'Z' and 'a'.
#
do_test sort-3.1 {
  execsql {
    CREATE TABLE t2(a,b);
    INSERT INTO t2 VALUES('AGLIENTU',1);
    INSERT INTO t2 VALUES('AGLIE`',2);
    INSERT INTO t2 VALUES('AGNA',3);
    SELECT a, b FROM t2 ORDER BY a;
  }
} {AGLIENTU 1 AGLIE` 2 AGNA 3}
do_test sort-3.2 {
  execsql {
    SELECT a, b FROM t2 ORDER BY a DESC;
  }
} {AGNA 3 AGLIE` 2 AGLIENTU 1}
do_test sort-3.3 {
  execsql {
    DELETE FROM t2;
    INSERT INTO t2 VALUES('aglientu',1);
    INSERT INTO t2 VALUES('aglie`',2);
    INSERT INTO t2 VALUES('agna',3);
    SELECT a, b FROM t2 ORDER BY a;
  }
} {aglie` 2 aglientu 1 agna 3}
do_test sort-3.4 {
  execsql {
    SELECT a, b FROM t2 ORDER BY a DESC;
  }
} {agna 3 aglientu 1 aglie` 2}

# Version 2.7.0 testing.
#
do_test sort-4.1 {
  execsql {
    INSERT INTO t1 VALUES(9,'x2.7',3,'IX',4.0e5);
    INSERT INTO t1 VALUES(10,'x5.0e10',3,'X',-4.0e5);
    INSERT INTO t1 VALUES(11,'x-4.0e9',3,'XI',4.1e4);
    INSERT INTO t1 VALUES(12,'x01234567890123456789',3,'XII',-4.2e3);
    SELECT n FROM t1 ORDER BY n;
  }
} {1 2 3 4 5 6 7 8 9 10 11 12}
do_test sort-4.2 {
  execsql {
    SELECT n||'' FROM t1 ORDER BY 1;
  }
} {1 10 11 12 2 3 4 5 6 7 8 9}
do_test sort-4.3 {
  execsql {
    SELECT n+0 FROM t1 ORDER BY 1;
  }
} {1 2 3 4 5 6 7 8 9 10 11 12}
do_test sort-4.4 {
  execsql {
    SELECT n||'' FROM t1 ORDER BY 1 DESC;
  }
} {9 8 7 6 5 4 3 2 12 11 10 1}
do_test sort-4.5 {
  execsql {
    SELECT n+0 FROM t1 ORDER BY 1 DESC;
  }
} {12 11 10 9 8 7 6 5 4 3 2 1}
do_test sort-4.6 {
  execsql {
    SELECT v FROM t1 ORDER BY 1;
  }
} {x-123 x-2.15 x-2b x-3.141592653 x-4.0e9 x-4221 x0.0013442 x01234567890123456789 x1.6 x11 x2.7 x5.0e10}
do_test sort-4.7 {
  execsql {
    SELECT v FROM t1 ORDER BY 1 DESC;
  }
} {x5.0e10 x2.7 x11 x1.6 x01234567890123456789 x0.0013442 x-4221 x-4.0e9 x-3.141592653 x-2b x-2.15 x-123}
do_test sort-4.8 {
  execsql {
    SELECT substr(v,2,99) FROM t1 ORDER BY 1;
  }
} {-123 -2.15 -2b -3.141592653 -4.0e9 -4221 0.0013442 01234567890123456789 1.6 11 2.7 5.0e10}
#do_test sort-4.9 {
#  execsql {
#    SELECT substr(v,2,99)+0.0 FROM t1 ORDER BY 1;
#  }
#} {-4000000000 -4221 -123 -3.141592653 -2.15 -2 0.0013442 1.6 2.7 11 50000000000 1.23456789012346e+18}

do_test sort-5.1 {
  execsql {
    create table t3(a,b);
    insert into t3 values(5,NULL);
    insert into t3 values(6,NULL);
    insert into t3 values(3,NULL);
    insert into t3 values(4,'cd');
    insert into t3 values(1,'ab');
    insert into t3 values(2,NULL);
    select a from t3 order by b, a;
  }
} {2 3 5 6 1 4}
do_test sort-5.2 {
  execsql {
    select a from t3 order by b, a desc;
  }
} {6 5 3 2 1 4}
do_test sort-5.3 {
  execsql {
    select a from t3 order by b desc, a;
  }
} {4 1 2 3 5 6}
do_test sort-5.4 {
  execsql {
    select a from t3 order by b desc, a desc;
  }
} {4 1 6 5 3 2}

do_test sort-6.1 {
  execsql {
    create index i3 on t3(b,a);
    select a from t3 order by b, a;
  }
} {2 3 5 6 1 4}
do_test sort-6.2 {
  execsql {
    select a from t3 order by b, a desc;
  }
} {6 5 3 2 1 4}
do_test sort-6.3 {
  execsql {
    select a from t3 order by b desc, a;
  }
} {4 1 2 3 5 6}
do_test sort-6.4 {
  execsql {
    select a from t3 order by b desc, a desc;
  }
} {4 1 6 5 3 2}

do_test sort-7.1 {
  execsql {
    CREATE TABLE t4(
      a INTEGER,
      b VARCHAR(30)
    );
    INSERT INTO t4 VALUES(1,1);
    INSERT INTO t4 VALUES(2,2);
    INSERT INTO t4 VALUES(11,11);
    INSERT INTO t4 VALUES(12,12);
    SELECT a FROM t4 ORDER BY 1;
  }
} {1 2 11 12}
do_test sort-7.2 {
  execsql {
    SELECT b FROM t4 ORDER BY 1
  }
} {1 11 12 2}
do_test sort-7.3 {
  execsql {
    CREATE VIEW v4 AS SELECT * FROM t4;
    SELECT a FROM v4 ORDER BY 1;
  }
} {1 2 11 12}
do_test sort-7.4 {
  execsql {
    SELECT b FROM v4 ORDER BY 1;
  }
} {1 11 12 2}
do_test sort-7.5 {
  execsql {
    SELECT a FROM t4 UNION SELECT a FROM v4 ORDER BY 1;
  }
} {1 2 11 12}
do_test sort-7.6 {
  execsql {
    SELECT b FROM t4 UNION SELECT a FROM v4 ORDER BY 1;
  }
} {1 2 11 12 1 11 12 2}  ;# text from t4.b and numeric from v4.a
do_test sort-7.7 {
  execsql {
    SELECT a FROM t4 UNION SELECT b FROM v4 ORDER BY 1;
  }
} {1 2 11 12 1 11 12 2} ;# numeric from t4.a and text from v4.b
do_test sort-7.8 {
  execsql {
    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1;
  }
} {1 11 12 2}
#### Version 3 works differently here:
#do_test sort-7.9 {
#  execsql {
#    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE numeric;
#  }
#} {1 2 11 12}
#do_test sort-7.10 {
#  execsql {
#    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE integer;
#  }
#} {1 2 11 12}
#do_test sort-7.11 {
#  execsql {
#    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE text;
#  }
#} {1 11 12 2}
#do_test sort-7.12 {
#  execsql {
#    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE blob;
#  }
#} {1 11 12 2}
#do_test sort-7.13 {
#  execsql {
#    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE clob;
#  }
#} {1 11 12 2}
#do_test sort-7.14 {
#  execsql {
#    SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE varchar;
#  }
#} {1 11 12 2}

# Ticket #297
#
do_test sort-8.1 {
  execsql {
    CREATE TABLE t5(a real, b text);
    INSERT INTO t5 VALUES(100,'A1');
    INSERT INTO t5 VALUES(100.0,'A2');
    SELECT * FROM t5 ORDER BY a, b;
  }
} {100 A1 100.0 A2}

# BLOBs should sort after TEXT
#
do_test sort-9.1 {
  execsql {
    CREATE TABLE t6(x, y);
    INSERT INTO t6 VALUES(1,1);
    INSERT INTO t6 VALUES(2,'1');
    INSERT INTO t6 VALUES(3,x'31');
    INSERT INTO t6 VALUES(4,NULL);
    SELECT x FROM t6 ORDER BY y;
  }
} {4 1 2 3}
do_test sort-9.2 {
  execsql {
    SELECT x FROM t6 ORDER BY y DESC;
  }
} {3 2 1 4}
do_test sort-9.3 {
  execsql {
    SELECT x FROM t6 WHERE y<1
  }
} {}
do_test sort-9.4 {
  execsql {
    SELECT x FROM t6 WHERE y<'1'
  }
} {1}
do_test sort-9.5 {
  execsql {
    SELECT x FROM t6 WHERE y<x'31'
  }
} {1 2}
do_test sort-9.6 {
  execsql {
    SELECT x FROM t6 WHERE y>1
  }
} {2 3}
do_test sort-9.7 {
  execsql {
    SELECT x FROM t6 WHERE y>'1'
  }
} {3}


finish_test

--- NEW FILE: subselect.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing SELECT statements that are part of
# expressions.
#
# $Id: subselect.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Basic sanity checking.  Try a simple subselect.
#
do_test subselect-1.1 {
  execsql {
    CREATE TABLE t1(a int, b int);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(3,4);
    INSERT INTO t1 VALUES(5,6);
  }
  execsql {SELECT * FROM t1 WHERE a = (SELECT count(*) FROM t1)}
} {3 4}

# Try a select with more than one result column.
#
do_test subselect-1.2 {
  set v [catch {execsql {SELECT * FROM t1 WHERE a = (SELECT * FROM t1)}} msg]
  lappend v $msg
} {1 {only a single result allowed for a SELECT that is part of an expression}}

# A subselect without an aggregate.
#
do_test subselect-1.3a {
  execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=2)}
} {2}
do_test subselect-1.3b {
  execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=4)}
} {4}
do_test subselect-1.3c {
  execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=6)}
} {6}
do_test subselect-1.3c {
  execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=8)}
} {}

# What if the subselect doesn't return any value.  We should get
# NULL as the result.  Check it out.
#
do_test subselect-1.4 {
  execsql {SELECT b from t1 where a = coalesce((SELECT a FROM t1 WHERE b=5),1)}
} {2}

# Try multiple subselects within a single expression.
#
do_test subselect-1.5 {
  execsql {
    CREATE TABLE t2(x int, y int);
    INSERT INTO t2 VALUES(1,2);
    INSERT INTO t2 VALUES(2,4);
    INSERT INTO t2 VALUES(3,8);
    INSERT INTO t2 VALUES(4,16);
  }
  execsql {
    SELECT y from t2 
    WHERE x = (SELECT sum(b) FROM t1 where a notnull) - (SELECT sum(a) FROM t1)
  }
} {8}

# Try something useful.  Delete every entry from t2 where the
# x value is less than half of the maximum.
#
do_test subselect-1.6 {
  execsql {DELETE FROM t2 WHERE x < 0.5*(SELECT max(x) FROM t2)}
  execsql {SELECT x FROM t2 ORDER BY x}
} {2 3 4}

# Make sure sorting works for SELECTs there used as a scalar expression.
#
do_test subselect-2.1 {
  execsql {
    SELECT (SELECT a FROM t1 ORDER BY a), (SELECT a FROM t1 ORDER BY a DESC)
  }
} {1 5}
do_test subselect-2.2 {
  execsql {
    SELECT 1 IN (SELECT a FROM t1 ORDER BY a);
  }
} {1}
do_test subselect-2.3 {
  execsql {
    SELECT 2 IN (SELECT a FROM t1 ORDER BY a DESC);
  }
} {0}

# Verify that the ORDER BY clause is honored in a subquery.
#
do_test subselect-3.1 {
  execsql {
    CREATE TABLE t3(x int);
    INSERT INTO t3 SELECT a FROM t1 UNION ALL SELECT b FROM t1;
    SELECT * FROM t3 ORDER BY x;
  }
} {1 2 3 4 5 6}
do_test subselect-3.2 {
  execsql {
    SELECT sum(x) FROM (SELECT x FROM t3 ORDER BY x LIMIT 2);
  }
} {3.0}
do_test subselect-3.3 {
  execsql {
    SELECT sum(x) FROM (SELECT x FROM t3 ORDER BY x DESC LIMIT 2);
  }
} {11.0}
do_test subselect-3.4 {
  execsql {
    SELECT (SELECT x FROM t3 ORDER BY x);
  }
} {1}
do_test subselect-3.5 {
  execsql {
    SELECT (SELECT x FROM t3 ORDER BY x DESC);
  }
} {6}
do_test subselect-3.6 {
  execsql {
    SELECT (SELECT x FROM t3 ORDER BY x LIMIT 1);
  }
} {1}
do_test subselect-3.7 {
  execsql {
    SELECT (SELECT x FROM t3 ORDER BY x DESC LIMIT 1);
  }
} {6}
do_test subselect-3.8 {
  execsql {
    SELECT (SELECT x FROM t3 ORDER BY x LIMIT 1 OFFSET 2);
  }
} {3}
do_test subselect-3.9 {
  execsql {
    SELECT (SELECT x FROM t3 ORDER BY x DESC LIMIT 1 OFFSET 2);
  }
} {4}
do_test subselect-3.10 {
  execsql {
    SELECT x FROM t3 WHERE x IN
       (SELECT x FROM t3 ORDER BY x DESC LIMIT 1 OFFSET 2);
  }
} {4}

finish_test

--- NEW FILE: table.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE TABLE statement.
#
# $Id: table.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a basic table and verify it is added to sqlite_master
#
do_test table-1.1 {
  execsql {
    CREATE TABLE test1 (
      one varchar(10),
      two text
    )
  }
  execsql {
    SELECT sql FROM sqlite_master WHERE type!='meta'
  }
} {{CREATE TABLE test1 (
      one varchar(10),
      two text
    )}}


# Verify the other fields of the sqlite_master file.
#
do_test table-1.3 {
  execsql {SELECT name, tbl_name, type FROM sqlite_master WHERE type!='meta'}
} {test1 test1 table}

# Close and reopen the database.  Verify that everything is
# still the same.
#
do_test table-1.4 {
  db close
  sqlite3 db test.db
  execsql {SELECT name, tbl_name, type from sqlite_master WHERE type!='meta'}
} {test1 test1 table}

# Drop the database and make sure it disappears.
#
do_test table-1.5 {
  execsql {DROP TABLE test1}
  execsql {SELECT * FROM sqlite_master WHERE type!='meta'}
} {}

# Close and reopen the database.  Verify that the table is
# still gone.
#
do_test table-1.6 {
  db close
  sqlite3 db test.db
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Repeat the above steps, but this time quote the table name.
#
do_test table-1.10 {
  execsql {CREATE TABLE "create" (f1 int)}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {create}
do_test table-1.11 {
  execsql {DROP TABLE "create"}
  execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'}
} {}
do_test table-1.12 {
  execsql {CREATE TABLE test1("f1 ho" int)}
  execsql {SELECT name as "X" FROM sqlite_master WHERE type!='meta'}
} {test1}
do_test table-1.13 {
  execsql {DROP TABLE "TEST1"}
  execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'}
} {}



# Verify that we cannot make two tables with the same name
#
do_test table-2.1 {
  execsql {CREATE TABLE TEST2(one text)}
  set v [catch {execsql {CREATE TABLE test2(two text)}} msg]
  lappend v $msg
} {1 {table test2 already exists}}
do_test table-2.1b {
  set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg]
  lappend v $msg
} {1 {object name reserved for internal use: sqlite_master}}
do_test table-2.1c {
  db close
  sqlite3 db test.db
  set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg]
  lappend v $msg
} {1 {object name reserved for internal use: sqlite_master}}
do_test table-2.1d {
  execsql {DROP TABLE test2; SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Verify that we cannot make a table with the same name as an index
#
do_test table-2.2a {
  execsql {CREATE TABLE test2(one text); CREATE INDEX test3 ON test2(one)}
  set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
  lappend v $msg
} {1 {there is already an index named test3}}
do_test table-2.2b {
  db close
  sqlite3 db test.db
  set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
  lappend v $msg
} {1 {there is already an index named test3}}
do_test table-2.2c {
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {test2 test3}
do_test table-2.2d {
  execsql {DROP INDEX test3}
  set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
  lappend v $msg
} {0 {}}
do_test table-2.2e {
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {test2 test3}
do_test table-2.2f {
  execsql {DROP TABLE test2; DROP TABLE test3}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {}

# Create a table with many field names
#
set big_table \
{CREATE TABLE big(
  f1 varchar(20),
  f2 char(10),
  f3 varchar(30) primary key,
  f4 text,
  f5 text,
  f6 text,
  f7 text,
  f8 text,
  f9 text,
  f10 text,
  f11 text,
  f12 text,
  f13 text,
  f14 text,
  f15 text,
  f16 text,
  f17 text,
  f18 text,
  f19 text,
  f20 text
)}
do_test table-3.1 {
  execsql $big_table
  execsql {SELECT sql FROM sqlite_master WHERE type=='table'}
} \{$big_table\}
do_test table-3.2 {
  set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg]
  lappend v $msg
} {1 {table BIG already exists}}
do_test table-3.3 {
  set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg]
  lappend v $msg
} {1 {table biG already exists}}
do_test table-3.4 {
  set v [catch {execsql {CREATE TABLE bIg(xyz foo)}} msg]
  lappend v $msg
} {1 {table bIg already exists}}
do_test table-3.5 {
  db close
  sqlite3 db test.db
  set v [catch {execsql {CREATE TABLE Big(xyz foo)}} msg]
  lappend v $msg
} {1 {table Big already exists}}
do_test table-3.6 {
  execsql {DROP TABLE big}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Try creating large numbers of tables
#
set r {}
for {set i 1} {$i<=100} {incr i} {
  lappend r [format test%03d $i]
}
do_test table-4.1 {
  for {set i 1} {$i<=100} {incr i} {
    set sql "CREATE TABLE [format test%03d $i] ("
    for {set k 1} {$k<$i} {incr k} {
      append sql "field$k text,"
    }
    append sql "last_field text)"
    execsql $sql
  }
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} $r
do_test table-4.1b {
  db close
  sqlite3 db test.db
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} $r

# Drop the even numbered tables
#
set r {}
for {set i 1} {$i<=100} {incr i 2} {
  lappend r [format test%03d $i]
}
do_test table-4.2 {
  for {set i 2} {$i<=100} {incr i 2} {
    # if {$i==38} {execsql {pragma vdbe_trace=on}}
    set sql "DROP TABLE [format TEST%03d $i]"
    execsql $sql
  }
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} $r
#exit

# Drop the odd number tables
#
do_test table-4.3 {
  for {set i 1} {$i<=100} {incr i 2} {
    set sql "DROP TABLE [format test%03d $i]"
    execsql $sql
  }
  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {}

# Try to drop a table that does not exist
#
do_test table-5.1 {
  set v [catch {execsql {DROP TABLE test009}} msg]
  lappend v $msg
} {1 {no such table: test009}}

# Try to drop sqlite_master
#
do_test table-5.2 {
  set v [catch {execsql {DROP TABLE sqlite_master}} msg]
  lappend v $msg
} {1 {table sqlite_master may not be dropped}}

# Make sure an EXPLAIN does not really create a new table
#
do_test table-5.3 {
  execsql {EXPLAIN CREATE TABLE test1(f1 int)}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Make sure an EXPLAIN does not really drop an existing table
#
do_test table-5.4 {
  execsql {CREATE TABLE test1(f1 int)}
  execsql {EXPLAIN DROP TABLE test1}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {test1}

# Create a table with a goofy name
#
#do_test table-6.1 {
#  execsql {CREATE TABLE 'Spaces In This Name!'(x int)}
#  execsql {INSERT INTO 'spaces in this name!' VALUES(1)}
#  set list [glob -nocomplain testdb/spaces*.tbl]
#} {testdb/spaces+in+this+name+.tbl}

# Try using keywords as table names or column names.
# 
do_test table-7.1 {
  set v [catch {execsql {
    CREATE TABLE weird(
      desc text,
      asc text,
      explain int,
      [14_vac] boolean,
      fuzzy_dog_12 varchar(10),
      begin blob,
      end clob
    )
  }} msg]
  lappend v $msg
} {0 {}}
do_test table-7.2 {
  execsql {
    INSERT INTO weird VALUES('a','b',9,0,'xyz','hi','y''all');
    SELECT * FROM weird;
  }
} {a b 9 0 xyz hi y'all}
do_test table-7.3 {
  execsql2 {
    SELECT * FROM weird;
  }
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}

# Try out the CREATE TABLE AS syntax
#
do_test table-8.1 {
breakpoint
  execsql2 {
    CREATE TABLE t2 AS SELECT * FROM weird;
    SELECT * FROM t2;
  }
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
do_test table-8.1.1 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name='t2';
  }
} {{CREATE TABLE t2(
  "desc" text,
  "asc" text,
  "explain" int,
  "14_vac" boolean,
  fuzzy_dog_12 varchar(10),
  "begin" blob,
  "end" clob
)}}
do_test table-8.2 {
  execsql {
    CREATE TABLE "t3""xyz"(a,b,c);
    INSERT INTO [t3"xyz] VALUES(1,2,3);
    SELECT * FROM [t3"xyz];
  }
} {1 2 3}
do_test table-8.3 {
  execsql2 {
    CREATE TABLE [t4"abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3"xyz];
    SELECT * FROM [t4"abc];
  }
} {cnt 1 max(b+c) 5}

# Update for v3: The declaration type of anything except a column is now a
# NULL pointer, so the created table has no column types. (Changed result
# from {{CREATE TABLE 't4"abc'(cnt NUMERIC,"max(b+c)" NUMERIC)}}).
do_test table-8.3.1 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name='t4"abc'
  }
} {{CREATE TABLE "t4""abc"(cnt,"max(b+c)")}}
do_test table-8.4 {
  execsql2 {
    CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3"xyz];
    SELECT * FROM t5;
  }
} {y'all 1}
do_test table-8.5 {
  db close
  sqlite3 db test.db
  execsql2 {
    SELECT * FROM [t4"abc];
  }
} {cnt 1 max(b+c) 5}
do_test table-8.6 {
  execsql2 {
    SELECT * FROM t2;
  }
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
do_test table-8.7 {
  catchsql {
    SELECT * FROM t5;
  }
} {1 {no such table: t5}}
do_test table-8.8 {
  catchsql {
    CREATE TABLE t5 AS SELECT * FROM no_such_table;
  }
} {1 {no such table: no_such_table}}

# Make sure we cannot have duplicate column names within a table.
#
do_test table-9.1 {
  catchsql {
    CREATE TABLE t6(a,b,a);
  }
} {1 {duplicate column name: a}}

# Check the foreign key syntax.
#
do_test table-10.1 {
  catchsql {
    CREATE TABLE t6(a REFERENCES t4(a) NOT NULL);
    INSERT INTO t6 VALUES(NULL);
  }
} {1 {t6.a may not be NULL}}
do_test table-10.2 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a REFERENCES t4(a) MATCH PARTIAL);
  }
} {0 {}}
do_test table-10.3 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON DELETE SET NULL NOT NULL);
  }
} {0 {}}
do_test table-10.4 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON UPDATE SET DEFAULT DEFAULT 1);
  }
} {0 {}}
do_test table-10.5 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a NOT NULL NOT DEFERRABLE INITIALLY IMMEDIATE);
  }
} {0 {}}
do_test table-10.6 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a NOT NULL DEFERRABLE INITIALLY DEFERRED);
  }
} {0 {}}
do_test table-10.7 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a,
      FOREIGN KEY (a) REFERENCES t4(b) DEFERRABLE INITIALLY DEFERRED
    );
  }
} {0 {}}
do_test table-10.8 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a,b,c,
      FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL
        ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
    );
  }
} {0 {}}
do_test table-10.9 {
  catchsql {
    DROP TABLE t6;
    CREATE TABLE t6(a,b,c,
      FOREIGN KEY (b,c) REFERENCES t4(x)
    );
  }
} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
do_test table-10.10 {
  catchsql {DROP TABLE t6}
  catchsql {
    CREATE TABLE t6(a,b,c,
      FOREIGN KEY (b,c) REFERENCES t4(x,y,z)
    );
  }
} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
do_test table-10.11 {
  catchsql {DROP TABLE t6}
  catchsql {
    CREATE TABLE t6(a,b, c REFERENCES t4(x,y));
  }
} {1 {foreign key on c should reference only one column of table t4}}
do_test table-10.12 {
  catchsql {DROP TABLE t6}
  catchsql {
    CREATE TABLE t6(a,b,c,
      FOREIGN KEY (b,x) REFERENCES t4(x,y)
    );
  }
} {1 {unknown column "x" in foreign key definition}}
do_test table-10.13 {
  catchsql {DROP TABLE t6}
  catchsql {
    CREATE TABLE t6(a,b,c,
      FOREIGN KEY (x,b) REFERENCES t4(x,y)
    );
  }
} {1 {unknown column "x" in foreign key definition}}


# Test for the "typeof" function. More tests for the
# typeof() function are found in bind.test and types.test.
#
do_test table-11.1 {
  execsql {
    CREATE TABLE t7(
       a integer primary key,
       b number(5,10),
       c character varying (8),
       d VARCHAR(9),
       e clob,
       f BLOB,
       g Text,
       h
    );
    INSERT INTO t7(a) VALUES(1);
    SELECT typeof(a), typeof(b), typeof(c), typeof(d),
           typeof(e), typeof(f), typeof(g), typeof(h)
    FROM t7 LIMIT 1;
  }
} {integer null null null null null null null} 
do_test table-11.2 {
  execsql {
    SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d)
    FROM t7 LIMIT 1;
  }
} {null null null null}

# Test that when creating a table using CREATE TABLE AS, column types are
# assigned correctly for (SELECT ...) and 'x AS y' expressions.
do_test table-12.1 {
  execsql {
    CREATE TABLE t8 AS SELECT b, h, a as i, (SELECT f FROM t7) as j FROM t7;
  }
} {}
do_test table-12.2 {
  execsql {
    SELECT sql FROM sqlite_master WHERE tbl_name = 't8'
  }
} {{CREATE TABLE t8(b number(5,10),h,i integer,j BLOB)}}

finish_test

--- NEW FILE: tableapi.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_exec_printf() and
# sqlite_get_table_printf() APIs.
#
# $Id: tableapi.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test tableapi-1.0 {
  set ::dbx [sqlite3_open test.db]
  catch {sqlite_exec_printf $::dbx {DROP TABLE xyz} {}}
  sqlite3_exec_printf $::dbx {CREATE TABLE %s(a int, b text)} xyz
} {0 {}}
do_test tableapi-1.1 {
  sqlite3_exec_printf $::dbx {
    INSERT INTO xyz VALUES(1,'%q')
  } {Hi Y'all}
} {0 {}}
do_test tableapi-1.2 {
  sqlite3_exec_printf $::dbx {SELECT * FROM xyz} {}
} {0 {a b 1 {Hi Y'all}}}

do_test tableapi-2.1 {
  sqlite3_get_table_printf $::dbx {
    BEGIN TRANSACTION;
    SELECT * FROM xyz WHERE b='%q'
  } {Hi Y'all}
} {0 1 2 a b 1 {Hi Y'all}}
do_test tableapi-2.2 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz
  } {}
} {0 1 2 a b 1 {Hi Y'all}}
do_test tableapi-2.3 {
  for {set i 2} {$i<=50} {incr i} {
    sqlite3_get_table_printf $::dbx \
       "INSERT INTO xyz VALUES($i,'(%s)')" $i
  }
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz ORDER BY a
  } {}
} {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)}
do_test tableapi-2.3.1 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz  WHERE a>49 ORDER BY a
  } {}
} {0 1 2 a b 50 (50)}
do_test tableapi-2.3.2 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>47 ORDER BY a
  } {}
} {0 3 2 a b 48 (48) 49 (49) 50 (50)}
do_test tableapi-2.4 {
  set manyquote ''''''''
  append manyquote $manyquote
  append manyquote $manyquote
  append manyquote $manyquote
  append manyquote $manyquote
  append manyquote $manyquote
  append manyquote $manyquote
  set ::big_str "$manyquote Hello $manyquote"
  sqlite3_get_table_printf $::dbx {
    INSERT INTO xyz VALUES(51,'%q')
  } $::big_str
} {0 0 0}
do_test tableapi-2.5 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>49 ORDER BY a;
  } {}
} "0 2 2 a b 50 (50) 51 \173$::big_str\175"
do_test tableapi-2.6 {
  sqlite3_get_table_printf $::dbx {
    INSERT INTO xyz VALUES(52,NULL)
  } {}
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC
  } {}
} {0 3 2 a b 52 NULL 50 (50) 42 (42)}
do_test tableapi-2.7 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>1000
  } {}
} {0 0 0}

# Repeat all tests with the empty_result_callbacks pragma turned on
#
do_test tableapi-3.1 {
  sqlite3_get_table_printf $::dbx {
    ROLLBACK;
    PRAGMA empty_result_callbacks = ON;
    SELECT * FROM xyz WHERE b='%q'
  } {Hi Y'all}
} {0 1 2 a b 1 {Hi Y'all}}
do_test tableapi-3.2 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz
  } {}
} {0 1 2 a b 1 {Hi Y'all}}
do_test tableapi-3.3 {
  for {set i 2} {$i<=50} {incr i} {
    sqlite3_get_table_printf $::dbx \
       "INSERT INTO xyz VALUES($i,'(%s)')" $i
  }
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz ORDER BY a
  } {}
} {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)}
do_test tableapi-3.3.1 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz  WHERE a>49 ORDER BY a
  } {}
} {0 1 2 a b 50 (50)}
do_test tableapi-3.3.2 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>47 ORDER BY a
  } {}
} {0 3 2 a b 48 (48) 49 (49) 50 (50)}
do_test tableapi-3.4 {
  sqlite3_get_table_printf $::dbx {
    INSERT INTO xyz VALUES(51,'%q')
  } $::big_str
} {0 0 0}
do_test tableapi-3.5 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>49 ORDER BY a;
  } {}
} "0 2 2 a b 50 (50) 51 \173$::big_str\175"
do_test tableapi-3.6 {
  sqlite3_get_table_printf $::dbx {
    INSERT INTO xyz VALUES(52,NULL)
  } {}
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC
  } {}
} {0 3 2 a b 52 NULL 50 (50) 42 (42)}
do_test tableapi-3.7 {
  sqlite3_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>1000
  } {}
} {0 0 2 a b}

do_test tableapi-4.1 {
  set rc [catch {
    sqlite3_get_table_printf $::dbx {
      SELECT * FROM xyz;  SELECT * FROM sqlite_master
    } {}
  } msg]
  concat $rc $msg
} {0 1 {sqlite3_get_table() called with two or more incompatible queries}}

# A report on the mailing list says that the sqlite_get_table() api fails
# on queries involving more than 40 columns.  The following code attempts
# to test that complaint
#
do_test tableapi-5.1 {
  set sql "CREATE TABLE t2("
  set sep ""
  for {set i 1} {$i<=100} {incr i} {
    append sql ${sep}x$i
    set sep ,
  }
  append sql )
  sqlite3_get_table_printf $::dbx $sql {}
  set sql "INSERT INTO t2 VALUES("
  set sep ""
  for {set i 1} {$i<=100} {incr i} {
    append sql ${sep}$i
    set sep ,
  }
  append sql )
  sqlite3_get_table_printf $::dbx $sql {}
  sqlite3_get_table_printf $::dbx {SELECT * FROM t2} {}
} {0 1 100 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 x73 x74 x75 x76 x77 x78 x79 x80 x81 x82 x83 x84 x85 x86 x87 x88 x89 x90 x91 x92 x93 x94 x95 x96 x97 x98 x99 x100 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100}
do_test tableapi-5.2 {
  set sql "INSERT INTO t2 VALUES("
  set sep ""
  for {set i 1} {$i<=100} {incr i} {
    append sql ${sep}[expr {$i+1000}]
    set sep ,
  }
  append sql )
  sqlite3_get_table_printf $::dbx $sql {}
  sqlite3_get_table_printf $::dbx {SELECT * FROM t2} {}
} {0 2 100 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 x73 x74 x75 x76 x77 x78 x79 x80 x81 x82 x83 x84 x85 x86 x87 x88 x89 x90 x91 x92 x93 x94 x95 x96 x97 x98 x99 x100 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100}

do_test tableapi-99.0 {
  sqlite3_close $::dbx
} {SQLITE_OK}

finish_test

--- NEW FILE: tclsqlite.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested.  This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Check the error messages generated by tclsqlite
#
if {[sqlite3 -has-codec]} {
  set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
} else {
  set r "sqlite3 HANDLE FILENAME ?MODE?"
}
do_test tcl-1.1 {
  set v [catch {sqlite3 bogus} msg]
  lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.2 {
  set v [catch {db bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be authorizer, busy, changes, close, collate, collation_needed, commit_hook, complete, errorcode, eval, function, last_insert_rowid, onecolumn, progress, rekey, timeout, total_changes, or trace}}
do_test tcl-1.3 {
  execsql {CREATE TABLE t1(a int, b int)}
  execsql {INSERT INTO t1 VALUES(10,20)}
  set v [catch {
    db eval {SELECT * FROM t1} data {
      error "The error message"
    }
  } msg]
  lappend v $msg
} {1 {The error message}}
do_test tcl-1.4 {
  set v [catch {
    db eval {SELECT * FROM t2} data {
      error "The error message"
    }
  } msg]
  lappend v $msg
} {1 {no such table: t2}}
do_test tcl-1.5 {
  set v [catch {
    db eval {SELECT * FROM t1} data {
      break
    }
  } msg]
  lappend v $msg
} {0 {}}
do_test tcl-1.6 {
  set v [catch {
    db eval {SELECT * FROM t1} data {
      expr x*
    }
  } msg]
  regsub {:.*$} $msg {} msg
  lappend v $msg
} {1 {syntax error in expression "x*"}}
do_test tcl-1.7 {
  set v [catch {db} msg]
  lappend v $msg
} {1 {wrong # args: should be "db SUBCOMMAND ..."}}
if {[catch {db auth {}}]==0} {
  do_test tcl-1.8 {
    set v [catch {db authorizer 1 2 3} msg]
    lappend v $msg
  } {1 {wrong # args: should be "db authorizer ?CALLBACK?"}}
}
do_test tcl-1.9 {
  set v [catch {db busy 1 2 3} msg]
  lappend v $msg
} {1 {wrong # args: should be "db busy CALLBACK"}}
do_test tcl-1.10 {
  set v [catch {db progress 1} msg]
  lappend v $msg
} {1 {wrong # args: should be "db progress N CALLBACK"}}
do_test tcl-1.11 {
  set v [catch {db changes xyz} msg]
  lappend v $msg
} {1 {wrong # args: should be "db changes "}}
do_test tcl-1.12 {
  set v [catch {db commit_hook a b c} msg]
  lappend v $msg
} {1 {wrong # args: should be "db commit_hook ?CALLBACK?"}}
do_test tcl-1.13 {
  set v [catch {db complete} msg]
  lappend v $msg
} {1 {wrong # args: should be "db complete SQL"}}
do_test tcl-1.14 {
  set v [catch {db eval} msg]
  lappend v $msg
} {1 {wrong # args: should be "db eval SQL ?ARRAY-NAME? ?SCRIPT?"}}
do_test tcl-1.15 {
  set v [catch {db function} msg]
  lappend v $msg
} {1 {wrong # args: should be "db function NAME SCRIPT"}}
do_test tcl-1.14 {
  set v [catch {db last_insert_rowid xyz} msg]
  lappend v $msg
} {1 {wrong # args: should be "db last_insert_rowid "}}
do_test tcl-1.15 {
  set v [catch {db rekey} msg]
  lappend v $msg
} {1 {wrong # args: should be "db rekey KEY"}}
do_test tcl-1.16 {
  set v [catch {db timeout} msg]
  lappend v $msg
} {1 {wrong # args: should be "db timeout MILLISECONDS"}}
do_test tcl-1.17 {
  set v [catch {db collate} msg]
  lappend v $msg
} {1 {wrong # args: should be "db collate NAME SCRIPT"}}
do_test tcl-1.18 {
  set v [catch {db collation_needed} msg]
  lappend v $msg
} {1 {wrong # args: should be "db collation_needed SCRIPT"}}
do_test tcl-1.19 {
  set v [catch {db total_changes xyz} msg]
  lappend v $msg
} {1 {wrong # args: should be "db total_changes "}}


if {[sqlite3 -tcl-uses-utf]} {
  catch {unset ::result}
  do_test tcl-2.1 {
    execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
    execsql "PRAGMA table_info(t\u0123x)"
  } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
  do_test tcl-2.2 {
    execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
    db eval "SELECT * FROM t\u0123x" result break
    set result(*)
  } "a b\u1235"
}


# Test the onecolumn method
#
do_test tcl-3.1 {
  execsql {
    INSERT INTO t1 SELECT a*2, b*2 FROM t1;
    INSERT INTO t1 SELECT a*2+1, b*2+1 FROM t1;
    INSERT INTO t1 SELECT a*2+3, b*2+3 FROM t1;
  }
  set rc [catch {db onecolumn {SELECT * FROM t1 ORDER BY a}} msg]
  lappend rc $msg
} {0 10}
do_test tcl-3.2 {
  db onecolumn {SELECT * FROM t1 WHERE a<0}
} {}
do_test tcl-3.3 {
  set rc [catch {db onecolumn} errmsg]
  lappend rc $errmsg
} {1 {wrong # args: should be "db onecolumn SQL"}}
do_test tcl-3.4 {
  set rc [catch {db onecolumn {SELECT bogus}} errmsg]
  lappend rc $errmsg
} {1 {no such column: bogus}}
do_test tcl-3.5 {
  set b 50
  set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
  lappend rc $msg
} {0 41}
do_test tcl-3.6 {
  set b 500
  set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
  lappend rc $msg
} {0 {}}
do_test tcl-3.7 {
  set b 500
  set rc [catch {db one {
    INSERT INTO t1 VALUES(99,510);
    SELECT * FROM t1 WHERE b>$b
  }} msg]
  lappend rc $msg
} {0 99}

# Turn the busy handler on and off
#
do_test tcl-4.1 {
  proc busy_callback {cnt} {
    break
  }
  db busy busy_callback
  db busy
} {busy_callback}
do_test tcl-4.2 {
  db busy {}
  db busy
} {}

# Parsing of TCL variable names within SQL into bound parameters.
#
do_test tcl-5.1 {
  execsql {CREATE TABLE t3(a,b,c)}
  catch {unset x}
  set x(1) 5
  set x(2) 7
  execsql {
    INSERT INTO t3 VALUES($::x(1),$::x(2),$::x(3));
    SELECT * FROM t3
  }
} {5 7 {}}
do_test tcl-5.2 {
  execsql {
    SELECT typeof(a), typeof(b), typeof(c) FROM t3
  }
} {text text null}
do_test tcl-5.3 {
  catch {unset x}
  set x [binary format h12 686900686f00]
  execsql {
    UPDATE t3 SET a=$::x;
  }
  db eval {
    SELECT a FROM t3
  } break
  binary scan $a h12 adata
  set adata
} {686900686f00}
do_test tcl-5.4 {
  execsql {
    SELECT typeof(a), typeof(b), typeof(c) FROM t3
  }
} {blob text null}

# Operation of "break" and "continue" within row scripts
#
do_test tcl-6.1 {
  db eval {SELECT * FROM t1} {
    break
  }
  lappend a $b
} {10 20}
do_test tcl-6.2 {
  set cnt 0
  db eval {SELECT * FROM t1} {
    if {$a>40} continue
    incr cnt
  }
  set cnt
} {4}
do_test tcl-6.3 {
  set cnt 0
  db eval {SELECT * FROM t1} {
    if {$a<40} continue
    incr cnt
  }
  set cnt
} {5}
do_test tcl-6.4 {
  proc return_test {x} {
    db eval {SELECT * FROM t1} {
      if {$a==$x} {return $b}
    }
  }
  return_test 10
} 20
do_test tcl-6.5 {
  return_test 20
} 40
do_test tcl-6.6 {
  return_test 99
} 510
do_test tcl-6.7 {
  return_test 0
} {}

finish_test

--- NEW FILE: temptable.test ---
# 2001 October 7
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for temporary tables and indices.
#
# $Id: temptable.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create an alternative connection to the database
#
do_test temptable-1.0 {
  sqlite3 db2 ./test.db
  set dummy {}
} {}

# Create a permanent table.
#
do_test temptable-1.1 {
  execsql {CREATE TABLE t1(a,b,c);}
  execsql {INSERT INTO t1 VALUES(1,2,3);}
  execsql {SELECT * FROM t1}
} {1 2 3}
do_test temptable-1.2 {
  catch {db2 eval {SELECT * FROM sqlite_master}}
  db2 eval {SELECT * FROM t1}
} {1 2 3}
do_test temptable-1.3 {
  execsql {SELECT name FROM sqlite_master}
} {t1}
do_test temptable-1.4 {
  db2 eval {SELECT name FROM sqlite_master}
} {t1}

# Create a temporary table.  Verify that only one of the two
# processes can see it.
#
do_test temptable-1.5 {
  db2 eval {
    CREATE TEMP TABLE t2(x,y,z);
    INSERT INTO t2 VALUES(4,5,6);
  }
  db2 eval {SELECT * FROM t2}
} {4 5 6}
do_test temptable-1.6 {
  catch {execsql {SELECT * FROM sqlite_master}}
  catchsql {SELECT * FROM t2}
} {1 {no such table: t2}}
do_test temptable-1.7 {
  catchsql {INSERT INTO t2 VALUES(8,9,0);}
} {1 {no such table: t2}}
do_test temptable-1.8 {
  db2 eval {INSERT INTO t2 VALUES(8,9,0);}
  db2 eval {SELECT * FROM t2 ORDER BY x}
} {4 5 6 8 9 0}
do_test temptable-1.9 {
  db2 eval {DELETE FROM t2 WHERE x==8}
  db2 eval {SELECT * FROM t2 ORDER BY x}
} {4 5 6}
do_test temptable-1.10 {
  db2 eval {DELETE FROM t2}
  db2 eval {SELECT * FROM t2}
} {}
do_test temptable-1.11 {
  db2 eval {
     INSERT INTO t2 VALUES(7,6,5);
     INSERT INTO t2 VALUES(4,3,2);
     SELECT * FROM t2 ORDER BY x;
  }
} {4 3 2 7 6 5}
do_test temptable-1.12 {
  db2 eval {DROP TABLE t2;}
  set r [catch {db2 eval {SELECT * FROM t2}} msg]
  lappend r $msg
} {1 {no such table: t2}}

# Make sure temporary tables work with transactions
#
do_test temptable-2.1 {
  execsql {
    BEGIN TRANSACTION;
    CREATE TEMPORARY TABLE t2(x,y);
    INSERT INTO t2 VALUES(1,2);
    SELECT * FROM t2;
  }
} {1 2}
do_test temptable-2.2 {
  execsql {ROLLBACK}
  catchsql {SELECT * FROM t2}
} {1 {no such table: t2}}
do_test temptable-2.3 {
  execsql {
    BEGIN TRANSACTION;
    CREATE TEMPORARY TABLE t2(x,y);
    INSERT INTO t2 VALUES(1,2);
    SELECT * FROM t2;
  }
} {1 2}
do_test temptable-2.4 {
  execsql {COMMIT}
  catchsql {SELECT * FROM t2}
} {0 {1 2}}
do_test temptable-2.5 {
  set r [catch {db2 eval {SELECT * FROM t2}} msg]
  lappend r $msg
} {1 {no such table: t2}}

# Make sure indices on temporary tables are also temporary.
#
do_test temptable-3.1 {
  execsql {
    CREATE INDEX i2 ON t2(x);
    SELECT name FROM sqlite_master WHERE type='index';
  }
} {}
do_test temptable-3.2 {
  execsql {
    SELECT y FROM t2 WHERE x=1;
  }
} {2}
do_test temptable-3.3 {
  execsql {
    DROP INDEX i2;
    SELECT y FROM t2 WHERE x=1;
  }
} {2}
do_test temptable-3.4 {
  execsql {
    CREATE INDEX i2 ON t2(x);
    DROP TABLE t2;
  }
  catchsql {DROP INDEX i2}
} {1 {no such index: i2}}

# Check for correct name collision processing. A name collision can
# occur when process A creates a temporary table T then process B
# creates a permanent table also named T.  The temp table in process A
# hides the existance of the permanent table.
#
do_test temptable-4.1 {
  execsql {
    CREATE TEMP TABLE t2(x,y);
    INSERT INTO t2 VALUES(10,20);
    SELECT * FROM t2;
  } db2
} {10 20}
do_test temptable-4.2 {
  execsql {
    CREATE TABLE t2(x,y,z);
    INSERT INTO t2 VALUES(9,8,7);
    SELECT * FROM t2;
  }
} {9 8 7}
do_test temptable-4.3 {
  catchsql {
    SELECT * FROM t2;
  } db2
} {0 {10 20}}
do_test temptable-4.4.1 {
  catchsql {
    SELECT * FROM temp.t2;
  } db2
} {0 {10 20}}
do_test temptable-4.4.2 {
  catchsql {
    SELECT * FROM main.t2;
  } db2
} {1 {no such table: main.t2}}
#do_test temptable-4.4.3 {
#  catchsql {
#    SELECT name FROM main.sqlite_master WHERE type='table';
#  } db2
#} {1 {database schema has changed}}
do_test temptable-4.4.4 {
  catchsql {
    SELECT name FROM main.sqlite_master WHERE type='table';
  } db2
} {0 {t1 t2}}
do_test temptable-4.4.5 {
  catchsql {
    SELECT * FROM main.t2;
  } db2
} {0 {9 8 7}}
do_test temptable-4.4.6 {
  # TEMP takes precedence over MAIN
  catchsql {
    SELECT * FROM t2;
  } db2
} {0 {10 20}}
do_test temptable-4.5 {
  catchsql {
    DROP TABLE t2;     -- should drop TEMP
    SELECT * FROM t2;  -- data should be from MAIN
  } db2
} {0 {9 8 7}}
do_test temptable-4.6 {
  db2 close
  sqlite3 db2 ./test.db
  catchsql {
    SELECT * FROM t2;
  } db2
} {0 {9 8 7}}
do_test temptable-4.7 {
  catchsql {
    DROP TABLE t2;
    SELECT * FROM t2;
  }
} {1 {no such table: t2}}
do_test temptable-4.8 {
  db2 close
  sqlite3 db2 ./test.db
  execsql {
    CREATE TEMP TABLE t2(x unique,y);
    INSERT INTO t2 VALUES(1,2);
    SELECT * FROM t2;
  } db2
} {1 2}
do_test temptable-4.9 {
  execsql {
    CREATE TABLE t2(x unique, y);
    INSERT INTO t2 VALUES(3,4);
    SELECT * FROM t2;
  }
} {3 4}
do_test temptable-4.10.1 {
  catchsql {
    SELECT * FROM t2;
  } db2
} {0 {1 2}}
# Update: The schema is reloaded in test temptable-4.10.1. And tclsqlite.c
#         handles it and retries the query anyway.
# do_test temptable-4.10.2 {
#   catchsql {
#     SELECT name FROM sqlite_master WHERE type='table'
#   } db2
# } {1 {database schema has changed}}
do_test temptable-4.10.3 {
  catchsql {
    SELECT name FROM sqlite_master WHERE type='table'
  } db2
} {0 {t1 t2}}
do_test temptable-4.11 {
  execsql {
    SELECT * FROM t2;
  } db2
} {1 2}
do_test temptable-4.12 {
  execsql {
    SELECT * FROM t2;
  }
} {3 4}
do_test temptable-4.13 {
  catchsql {
    DROP TABLE t2;     -- drops TEMP.T2
    SELECT * FROM t2;  -- uses MAIN.T2
  } db2
} {0 {3 4}}
do_test temptable-4.14 {
  execsql {
    SELECT * FROM t2;
  }
} {3 4}
do_test temptable-4.15 {
  db2 close
  sqlite3 db2 ./test.db
  execsql {
    SELECT * FROM t2;
  } db2
} {3 4}

# Now create a temporary table in db2 and a permanent index in db.  The
# temporary table in db2 should mask the name of the permanent index,
# but the permanent index should still be accessible and should still
# be updated when its corresponding table changes.
#
do_test temptable-5.1 {
  execsql {
    CREATE TEMP TABLE mask(a,b,c)
  } db2
  execsql {
    CREATE INDEX mask ON t2(x);
    SELECT * FROM t2;
  }
} {3 4}
#do_test temptable-5.2 {
#  catchsql {
#    SELECT * FROM t2;
#  } db2
#} {1 {database schema has changed}}
do_test temptable-5.3 {
  catchsql {
    SELECT * FROM t2;
  } db2
} {0 {3 4}}
do_test temptable-5.4 {
  execsql {
    SELECT y FROM t2 WHERE x=3
  }
} {4}
do_test temptable-5.5 {
  execsql {
    SELECT y FROM t2 WHERE x=3
  } db2
} {4}
do_test temptable-5.6 {
  execsql {
    INSERT INTO t2 VALUES(1,2);
    SELECT y FROM t2 WHERE x=1;
  } db2
} {2}
do_test temptable-5.7 {
  execsql {
    SELECT y FROM t2 WHERE x=3
  } db2
} {4}
do_test temptable-5.8 {
  execsql {
    SELECT y FROM t2 WHERE x=1;
  }
} {2}
do_test temptable-5.9 {
  execsql {
    SELECT y FROM t2 WHERE x=3
  }
} {4}

db2 close

# Test for correct operation of read-only databases
#
do_test temptable-6.1 {
  execsql {
    CREATE TABLE t8(x);
    INSERT INTO t8 VALUES('xyzzy');
    SELECT * FROM t8;
  }
} {xyzzy}
do_test temptable-6.2 {
  db close
  catch {file attributes test.db -permissions 0444}
  catch {file attributes test.db -readonly 1}
  sqlite3 db test.db
  if {[file writable test.db]} {
    error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
  }
  execsql {
    SELECT * FROM t8;
  }
} {xyzzy}
do_test temptable-6.3 {
  if {[file writable test.db]} {
    error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
  }
  catchsql {
    CREATE TABLE t9(x,y);
  }
} {1 {attempt to write a readonly database}}
do_test temptable-6.4 {
  catchsql {
    CREATE TEMP TABLE t9(x,y);
  }
} {0 {}}
do_test temptable-6.5 {
  catchsql {
    INSERT INTO t9 VALUES(1,2);
    SELECT * FROM t9;
  }
} {0 {1 2}}
do_test temptable-6.6 {
  if {[file writable test.db]} {
    error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
  }
  catchsql {
    INSERT INTO t8 VALUES('hello');
    SELECT * FROM t8;
  }
} {1 {attempt to write a readonly database}}
do_test temptable-6.7 {
  catchsql {
    SELECT * FROM t8,t9;
  }
} {0 {xyzzy 1 2}}
do_test temptable-6.8 {
  db close
  sqlite3 db test.db
  catchsql {
    SELECT * FROM t8,t9;
  }
} {1 {no such table: t9}}

finish_test

--- NEW FILE: tester.tcl ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.1 2004/11/15 14:42:04 anthm Exp $

# Make sure tclsqlite3 was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite3 -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
    puts stderr "$argv0 was linked against an older version"
    puts stderr "of TCL that does not support Unicode, but uses a header"
    puts stderr "file (\"tcl.h\") from a new TCL version that does support"
    puts stderr "Unicode.  This combination causes internal errors."
    puts stderr "Recompile using a TCL library and header file that match"
    puts stderr "and try again.\n**************************"
    exit 1
  }
} else {
  if {"\u1234"!="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
    puts stderr "$argv0 was linked against an newer version"
    puts stderr "of TCL that supports Unicode, but uses a header file"
    puts stderr "(\"tcl.h\") from a old TCL version that does not support"
    puts stderr "Unicode.  This combination causes internal errors."
    puts stderr "Recompile using a TCL library and header file that match"
    puts stderr "and try again.\n**************************"
    exit 1
  }
}

set tcl_precision 15

# Use the pager codec if it is available
#
if {[sqlite3 -has-codec] && [info command sqlite_orig]==""} {
  rename sqlite3 sqlite_orig
  proc sqlite3 {args} {
    if {[llength $args]==2 && [string index [lindex $args 0] 0]!="-"} {
      lappend args -key {xyzzy}
    }
    uplevel 1 sqlite_orig $args
  }
}


# Create a test database
#
catch {db close}
file delete -force test.db
file delete -force test.db-journal
sqlite3 db ./test.db
if {[info exists ::SETUP_SQL]} {
  db eval $::SETUP_SQL
}

# Abort early if this script has been run before.
#
if {[info exists nTest]} return

# Set the test counters to zero
#
set nErr 0
set nTest 0
set nProb 0
set skip_test 0
set failList {}
set maxErr 1000

# Invoke the do_test procedure to run a single test 
#
proc do_test {name cmd expected} {
  global argv nErr nTest skip_test maxErr
  if {$skip_test} {
    set skip_test 0
    return
  }
  if {[llength $argv]==0} { 
    set go 1
  } else {
    set go 0
    foreach pattern $argv {
      if {[string match $pattern $name]} {
        set go 1
        break
      }
    }
  }
  if {!$go} return
  incr nTest
  puts -nonewline $name...
  flush stdout
  if {[catch {uplevel #0 "$cmd;\n"} result]} {
    puts "\nError: $result"
    incr nErr
    lappend ::failList $name
    if {$nErr>$maxErr} {puts "*** Giving up..."; finalize_testing}
  } elseif {[string compare $result $expected]} {
    puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
    incr nErr
    lappend ::failList $name
    if {$nErr>=$maxErr} {puts "*** Giving up..."; finalize_testing}
  } else {
    puts " Ok"
  }
}

# The procedure uses the special "sqlite_malloc_stat" command
# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
# to see how many malloc()s have not been free()ed.  The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
  if {[info command sqlite_malloc_stat]!=""} {
    set r [sqlite_malloc_stat]
    set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
  }
}

# Run this routine last
#
proc finish_test {} {
  finalize_testing
}
proc finalize_testing {} {
  global nTest nErr nProb sqlite_open_file_count
  if {$nErr==0} memleak_check
  catch {db close}
  puts "$nErr errors out of $nTest tests"
  puts "Failures on these tests: $::failList"
  if {$nProb>0} {
    puts "$nProb probabilistic tests also failed, but this does"
    puts "not necessarily indicate a malfunction."
  }
  if 0 {
  if {$sqlite_open_file_count} {
    puts "$sqlite_open_file_count files were left open"
    incr nErr
  }
  }
  exit [expr {$nErr>0}]
}

# A procedure to execute SQL
#
proc execsql {sql {db db}} {
  # puts "SQL = $sql"
  return [$db eval $sql]
}

# Execute SQL and catch exceptions.
#
proc catchsql {sql {db db}} {
  # puts "SQL = $sql"
  set r [catch {$db eval $sql} msg]
  lappend r $msg
  return $r
}

# Do an VDBE code dump on the SQL given
#
proc explain {sql {db db}} {
  puts ""
  puts "addr  opcode        p1       p2     p3             "
  puts "----  ------------  ------  ------  ---------------"
  $db eval "explain $sql" {} {
    puts [format {%-4d  %-12.12s  %-6d  %-6d  %s} $addr $opcode $p1 $p2 $p3]
  }
}

# Another procedure to execute SQL.  This one includes the field
# names in the returned list.
#
proc execsql2 {sql} {
  set result {}
  db eval $sql data {
    foreach f $data(*) {
      lappend result $f $data($f)
    }
  }
  return $result
}

# Use the non-callback API to execute multiple SQL statements
#
proc stepsql {dbptr sql} {
  set sql [string trim $sql]
  set r 0
  while {[string length $sql]>0} {
    if {[catch {sqlite3_prepare $dbptr $sql -1 sqltail} vm]} {
      return [list 1 $vm]
    }
    set sql [string trim $sqltail]
#    while {[sqlite_step $vm N VAL COL]=="SQLITE_ROW"} {
#      foreach v $VAL {lappend r $v}
#    }
    while {[sqlite3_step $vm]=="SQLITE_ROW"} {
      for {set i 0} {$i<[sqlite3_data_count $vm]} {incr i} {
        lappend r [sqlite3_column_text $vm $i]
      }
    }
    if {[catch {sqlite3_finalize $vm} errmsg]} {
      return [list 1 $errmsg]
    }
  }
  return $r
}

# Delete a file or directory
#
proc forcedelete {filename} {
  if {[catch {file delete -force $filename}]} {
    exec rm -rf $filename
  }
}

# Do an integrity check of the entire database
#
proc integrity_check {name} {
  do_test $name {
    execsql {PRAGMA integrity_check}
  } {ok}
}

--- NEW FILE: thread1.test ---
# 2003 December 18
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is multithreading behavior
#
# $Id: thread1.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Skip this whole file if the thread testing code is not enabled
#
if {[llength [info command thread_step]]==0 || [sqlite3 -has-codec]} {
  finish_test
  return
}

# Create some data to work with
#
do_test thread1-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,'abcdefgh');
    INSERT INTO t1 SELECT a+1, b||b FROM t1;
    INSERT INTO t1 SELECT a+2, b||b FROM t1;
    INSERT INTO t1 SELECT a+4, b||b FROM t1;
    SELECT count(*), max(length(b)) FROM t1;
  }
} {8 64}

# Interleave two threads on read access.  Then make sure a third
# thread can write the database.  In other words:
#
#    read-lock A
#    read-lock B
#    unlock A
#    unlock B
#    write-lock C
#
# At one point, the write-lock of C would fail on Linux. 
#
do_test thread1-1.2 {
  thread_create A test.db
  thread_create B test.db
  thread_create C test.db
  thread_compile A {SELECT a FROM t1}
  thread_step A
  thread_result A
} SQLITE_ROW
do_test thread1-1.3 {
  thread_argc A
} 1
do_test thread1-1.4 {
  thread_argv A 0
} 1
do_test thread1-1.5 {
  thread_compile B {SELECT b FROM t1}
  thread_step B
  thread_result B
} SQLITE_ROW
do_test thread1-1.6 {
  thread_argc B
} 1
do_test thread1-1.7 {
  thread_argv B 0
} abcdefgh
do_test thread1-1.8 {
  thread_finalize A
  thread_result A
} SQLITE_OK
do_test thread1-1.9 {
  thread_finalize B
  thread_result B
} SQLITE_OK
do_test thread1-1.10 {
  thread_compile C {CREATE TABLE t2(x,y)}
  thread_step C
  thread_result C
} SQLITE_DONE
do_test thread1-1.11 {
  thread_finalize C
  thread_result C
} SQLITE_OK
do_test thread1-1.12 {
  catchsql {SELECT name FROM sqlite_master}
  execsql {SELECT name FROM sqlite_master}
} {t1 t2}


#
# The following tests - thread1-2.* - test the following scenario:
#
# 1:  Read-lock thread A
# 2:  Read-lock thread B
# 3:  Attempt to write in thread C -> SQLITE_BUSY
# 4:  Check db write failed from main thread.
# 5:  Unlock from thread A.
# 6:  Attempt to write in thread C -> SQLITE_BUSY
# 7:  Check db write failed from main thread.
# 8:  Unlock from thread B.
# 9:  Attempt to write in thread C -> SQLITE_DONE
# 10: Finalize the write from thread C
# 11: Check db write succeeded from main thread.
#
do_test thread1-2.1 {
  thread_halt *
  thread_create A test.db
  thread_compile A {SELECT a FROM t1}
  thread_step A
  thread_result A
} SQLITE_ROW
do_test thread1-2.2 {
  thread_create B test.db
  thread_compile B {SELECT b FROM t1}
  thread_step B
  thread_result B
} SQLITE_ROW
do_test thread1-2.3 {
  thread_create C test.db
  thread_compile C {INSERT INTO t2 VALUES(98,99)}
  thread_step C
  thread_result C
  thread_finalize C
  thread_result C
} SQLITE_BUSY

do_test thread1-2.4 {
  execsql {SELECT * FROM t2}
} {}

do_test thread1-2.5 {
  thread_finalize A
  thread_result A
} SQLITE_OK
do_test thread1-2.6 {
  thread_compile C {INSERT INTO t2 VALUES(98,99)}
  thread_step C
  thread_result C
  thread_finalize C
  thread_result C
} SQLITE_BUSY
do_test thread1-2.7 {
  execsql {SELECT * FROM t2}
} {}
do_test thread1-2.8 {
  thread_finalize B
  thread_result B
} SQLITE_OK
do_test thread1-2.9 {
  thread_compile C {INSERT INTO t2 VALUES(98,99)}
  thread_step C
  thread_result C
} SQLITE_DONE
do_test thread1-2.10 {
  thread_finalize C
  thread_result C
} SQLITE_OK
do_test thread1-2.11 {
  execsql {SELECT * FROM t2}
} {98 99}

thread_halt *   
finish_test

--- NEW FILE: threadtest1.c ---
/*
** 2002 January 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a simple standalone program used to test whether
** or not the SQLite library is threadsafe.
**
** Testing the thread safety of SQLite is difficult because there are very
** few places in the code that are even potentially unsafe, and those
** places execute for very short periods of time.  So even if the library
** is compiled with its mutexes disabled, it is likely to work correctly
** in a multi-threaded program most of the time.  
**
** This file is NOT part of the standard SQLite library.  It is used for
** testing only.
*/
#include "sqlite.h"
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/*
** Enable for tracing
*/
static int verbose = 0;

/*
** Come here to die.
*/
static void Exit(int rc){
  exit(rc);
}

extern char *sqlite3_mprintf(const char *zFormat, ...);
extern char *sqlite3_vmprintf(const char *zFormat, va_list);

/*
** When a lock occurs, yield.
*/
static int db_is_locked(void *NotUsed, int iCount){
  /* sched_yield(); */
  if( verbose ) printf("BUSY %s #%d\n", (char*)NotUsed, iCount);
  usleep(100);
  return iCount<25;
}

/*
** Used to accumulate query results by db_query()
*/
struct QueryResult {
  const char *zFile;  /* Filename - used for error reporting */
  int nElem;          /* Number of used entries in azElem[] */
  int nAlloc;         /* Number of slots allocated for azElem[] */
  char **azElem;      /* The result of the query */
};

/*
** The callback function for db_query
*/
static int db_query_callback(
  void *pUser,     /* Pointer to the QueryResult structure */
  int nArg,        /* Number of columns in this result row */
  char **azArg,    /* Text of data in all columns */
  char **NotUsed   /* Names of the columns */
){
  struct QueryResult *pResult = (struct QueryResult*)pUser;
  int i;
  if( pResult->nElem + nArg >= pResult->nAlloc ){
    if( pResult->nAlloc==0 ){
      pResult->nAlloc = nArg+1;
    }else{
      pResult->nAlloc = pResult->nAlloc*2 + nArg + 1;
    }
    pResult->azElem = realloc( pResult->azElem, pResult->nAlloc*sizeof(char*));
    if( pResult->azElem==0 ){
      fprintf(stdout,"%s: malloc failed\n", pResult->zFile);
      return 1;
    }
  }
  if( azArg==0 ) return 0;
  for(i=0; i<nArg; i++){
    pResult->azElem[pResult->nElem++] =
        sqlite3_mprintf("%s",azArg[i] ? azArg[i] : ""); 
  }
  return 0;
}

/*
** Execute a query against the database.  NULL values are returned
** as an empty string.  The list is terminated by a single NULL pointer.
*/
char **db_query(sqlite *db, const char *zFile, const char *zFormat, ...){
  char *zSql;
  int rc;
  char *zErrMsg = 0;
  va_list ap;
  struct QueryResult sResult;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  memset(&sResult, 0, sizeof(sResult));
  sResult.zFile = zFile;
  if( verbose ) printf("QUERY %s: %s\n", zFile, zSql);
  rc = sqlite3_exec(db, zSql, db_query_callback, &sResult, &zErrMsg);
  if( rc==SQLITE_SCHEMA ){
    if( zErrMsg ) free(zErrMsg);
    rc = sqlite3_exec(db, zSql, db_query_callback, &sResult, &zErrMsg);
  }
  if( verbose ) printf("DONE %s %s\n", zFile, zSql);
  if( zErrMsg ){
    fprintf(stdout,"%s: query failed: %s - %s\n", zFile, zSql, zErrMsg);
    free(zErrMsg);
    free(zSql);
    Exit(1);
  }
  sqlite3_free(zSql);
  if( sResult.azElem==0 ){
    db_query_callback(&sResult, 0, 0, 0);
  }
  sResult.azElem[sResult.nElem] = 0;
  return sResult.azElem;
}

/*
** Execute an SQL statement.
*/
void db_execute(sqlite *db, const char *zFile, const char *zFormat, ...){
  char *zSql;
  int rc;
  char *zErrMsg = 0;
  va_list ap;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( verbose ) printf("EXEC %s: %s\n", zFile, zSql);
  do{
    rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
  }while( rc==SQLITE_BUSY );
  if( verbose ) printf("DONE %s: %s\n", zFile, zSql);
  if( zErrMsg ){
    fprintf(stdout,"%s: command failed: %s - %s\n", zFile, zSql, zErrMsg);
    free(zErrMsg);
    sqlite3_free(zSql);
    Exit(1);
  }
  sqlite3_free(zSql);
}

/*
** Free the results of a db_query() call.
*/
void db_query_free(char **az){
  int i;
  for(i=0; az[i]; i++){
    sqlite3_free(az[i]);
  }
  free(az);
}

/*
** Check results
*/
void db_check(const char *zFile, const char *zMsg, char **az, ...){
  va_list ap;
  int i;
  char *z;
  va_start(ap, az);
  for(i=0; (z = va_arg(ap, char*))!=0; i++){
    if( az[i]==0 || strcmp(az[i],z)!=0 ){
      fprintf(stdout,"%s: %s: bad result in column %d: %s\n",
        zFile, zMsg, i+1, az[i]);
      db_query_free(az);
      Exit(1);
    }
  }
  va_end(ap);
  db_query_free(az);
}

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t sig = PTHREAD_COND_INITIALIZER;
int thread_cnt = 0;

static void *worker_bee(void *pArg){
  const char *zFilename = (char*)pArg;
  char *azErr;
  int i, cnt;
  int t = atoi(zFilename);
  char **az;
  sqlite *db;

  pthread_mutex_lock(&lock);
  thread_cnt++;
  pthread_mutex_unlock(&lock);
  printf("%s: START\n", zFilename);
  fflush(stdout);
  for(cnt=0; cnt<10; cnt++){
    sqlite3_open(&zFilename[2], &db);
    if( db==0 ){
      fprintf(stdout,"%s: can't open\n", zFilename);
      Exit(1);
    }
    sqlite3_busy_handler(db, db_is_locked, zFilename);
    db_execute(db, zFilename, "CREATE TABLE t%d(a,b,c);", t);
    for(i=1; i<=100; i++){
      db_execute(db, zFilename, "INSERT INTO t%d VALUES(%d,%d,%d);",
         t, i, i*2, i*i);
    }
    az = db_query(db, zFilename, "SELECT count(*) FROM t%d", t);
    db_check(zFilename, "tX size", az, "100", 0);  
    az = db_query(db, zFilename, "SELECT avg(b) FROM t%d", t);
    db_check(zFilename, "tX avg", az, "101", 0);  
    db_execute(db, zFilename, "DELETE FROM t%d WHERE a>50", t);
    az = db_query(db, zFilename, "SELECT avg(b) FROM t%d", t);
    db_check(zFilename, "tX avg2", az, "51", 0);
    for(i=1; i<=50; i++){
      char z1[30], z2[30];
      az = db_query(db, zFilename, "SELECT b, c FROM t%d WHERE a=%d", t, i);
      sprintf(z1, "%d", i*2);
      sprintf(z2, "%d", i*i);
      db_check(zFilename, "readback", az, z1, z2, 0);
    }
    db_execute(db, zFilename, "DROP TABLE t%d;", t);
    sqlite3_close(db);
  }
  printf("%s: END\n", zFilename);
  /* unlink(zFilename); */
  fflush(stdout);
  pthread_mutex_lock(&lock);
  thread_cnt--;
  if( thread_cnt<=0 ){
    pthread_cond_signal(&sig);
  }
  pthread_mutex_unlock(&lock);
  return 0;
}

int main(int argc, char **argv){
  char *zFile;
  int i, n;
  pthread_t id;
  if( argc>2 && strcmp(argv[1], "-v")==0 ){
    verbose = 1;
    argc--;
    argv++;
  }
  if( argc<2 || (n=atoi(argv[1]))<1 ) n = 10;
  for(i=0; i<n; i++){
    char zBuf[200];
    sprintf(zBuf, "testdb-%d", (i+1)/2);
    unlink(zBuf);
  }
  for(i=0; i<n; i++){
    zFile = sqlite3_mprintf("%d.testdb-%d", i%2+1, (i+2)/2);
    if( (i%2)==0 ){
      /* Remove both the database file and any old journal for the file
      ** being used by this thread and the next one. */
      char *zDb = &zFile[2];
      char *zJournal = sqlite3_mprintf("%s-journal", zDb);
      unlink(zDb);
      unlink(zJournal);
      free(zJournal);
    }
      
    pthread_create(&id, 0, worker_bee, (void*)zFile);
    pthread_detach(id);
  }
  pthread_mutex_lock(&lock);
  while( thread_cnt>0 ){
    pthread_cond_wait(&sig, &lock);
  }
  pthread_mutex_unlock(&lock);
  for(i=0; i<n; i++){
    char zBuf[200];
    sprintf(zBuf, "testdb-%d", (i+1)/2);
    unlink(zBuf);
  }
  return 0;
}

--- NEW FILE: threadtest2.c ---
/*
** 2004 January 13
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a simple standalone program used to test whether
** or not the SQLite library is threadsafe.
**
** This file is NOT part of the standard SQLite library.  It is used for
** testing only.
*/
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite.h"

/*
** Name of the database
*/
#define DB_FILE "test.db"

/* 
** When this variable becomes non-zero, all threads stop
** what they are doing.
*/
volatile int all_stop = 0;

/* 
** Callback from the integrity check.  If the result is anything other
** than "ok" it means the integrity check has failed.  Set the "all_stop"
** global variable to stop all other activity.  Print the error message
** or print OK if the string "ok" is seen.
*/
int check_callback(void *notUsed, int argc, char **argv, char **notUsed2){
  if( strcmp(argv[0],"ok") ){
    all_stop = 1;
    fprintf(stderr,"pid=%d. %s\n", getpid(), argv[0]);
  }else{
    /* fprintf(stderr,"pid=%d. OK\n", getpid()); */
  }
  return 0;
}

/*
** Do an integrity check on the database.  If the first integrity check
** fails, try it a second time.
*/
int integrity_check(sqlite *db){
  int rc;
  if( all_stop ) return 0;
  /* fprintf(stderr,"pid=%d: CHECK\n", getpid()); */
  rc = sqlite3_exec(db, "pragma integrity_check", check_callback, 0, 0);
  if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
    fprintf(stderr,"pid=%d, Integrity check returns %d\n", getpid(), rc);
  }
  if( all_stop ){
    sqlite3_exec(db, "pragma integrity_check", check_callback, 0, 0);
  }
  return 0;
}

/*
** This is the worker thread
*/
void *worker(void *notUsed){
  sqlite *db;
  int rc;
  int cnt = 0;
  while( !all_stop && cnt++<10000 ){
    if( cnt%1000==0 ) printf("pid=%d: %d\n", getpid(), cnt);
    while( (sqlite3_open(DB_FILE, &db))!=SQLITE_OK ) sched_yield();
    sqlite3_exec(db, "PRAGMA synchronous=OFF", 0, 0, 0);
    integrity_check(db);
    if( all_stop ){ sqlite3_close(db); break; }
    /* fprintf(stderr, "pid=%d: BEGIN\n", getpid()); */
    rc = sqlite3_exec(db, "INSERT INTO t1 VALUES('bogus data')", 0, 0, 0);
    /* fprintf(stderr, "pid=%d: END rc=%d\n", getpid(), rc); */
    sqlite3_close(db);
  }
  return 0;
}

/*
** Initialize the database and start the threads
*/
int main(int argc, char **argv){
  sqlite *db;
  int i, rc;
  pthread_t aThread[5];

  if( strcmp(DB_FILE,":memory:") ){
    char *zJournal = sqlite3_mprintf("%s-journal", DB_FILE);
    unlink(DB_FILE);
    unlink(zJournal);
    free(zJournal);
  }  
  sqlite3_open(DB_FILE, &db);
  if( db==0 ){
    fprintf(stderr,"unable to initialize database\n");
    exit(1);
  }
  rc = sqlite3_exec(db, "CREATE TABLE t1(x);", 0,0,0);
  if( rc ){
    fprintf(stderr,"cannot create table t1: %d\n", rc);
    exit(1);
  }
  sqlite3_close(db);
  for(i=0; i<sizeof(aThread)/sizeof(aThread[0]); i++){
    pthread_create(&aThread[i], 0, worker, 0);
  }
  for(i=0; i<sizeof(aThread)/sizeof(aThread[i]); i++){
    pthread_join(aThread[i], 0);
  }
  if( !all_stop ){
    printf("Everything seems ok.\n");
    return 0;
  }else{
    printf("We hit an error.\n");
    return 1;
  }
}

--- NEW FILE: trace.test ---
# 2004 Jun 29
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the "sqlite3_trace()" API.
#
# $Id: trace.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set ::stmtlist {}
do_test trace-1.1 {
  set rc [catch {db trace 1 2 3} msg]
  lappend rc $msg
} {1 {wrong # args: should be "db trace ?CALLBACK?"}}
proc trace_proc cmd {
  lappend ::stmtlist [string trim $cmd]
}
do_test trace-1.2 {
  db trace trace_proc
  db trace
} {trace_proc}
do_test trace-1.3 {
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t1;
  }
} {1 2}
do_test trace-1.4 {
  set ::stmtlist
} {{CREATE TABLE t1(a,b);} {INSERT INTO t1 VALUES(1,2);} {SELECT * FROM t1;}}
do_test trace-1.5 {
  db trace {}
  db trace
} {}

# If we prepare a statement and execute it multiple times, the trace
# happens on each execution.
#
db close
set DB [sqlite3 db test.db]
do_test trace-2.1 {
  set STMT [sqlite3_prepare $DB {INSERT INTO t1 VALUES(2,3)} -1 TAIL]
  db trace trace_proc
  proc trace_proc sql {
    global TRACE_OUT
    set TRACE_OUT $sql
  }
  set TRACE_OUT {}
  sqlite3_step $STMT
  set TRACE_OUT
} {INSERT INTO t1 VALUES(2,3)}
do_test trace-2.2 {
  set TRACE_OUT {}
  sqlite3_reset $STMT
  set TRACE_OUT 
} {}
do_test trace-2.3 {
  sqlite3_step $STMT
  set TRACE_OUT
} {INSERT INTO t1 VALUES(2,3)}
do_test trace-2.4 {
  execsql {SELECT * FROM t1}
} {1 2 2 3 2 3}
do_test trace-2.5 {
  set TRACE_OUT
} {SELECT * FROM t1}
catch {sqlite3_finalize $STMT}


finish_test

--- NEW FILE: trans.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is database locks.
#
# $Id: trans.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl


# Create several tables to work with.
#
do_test trans-1.0 {
  execsql {
    CREATE TABLE one(a int PRIMARY KEY, b text);
    INSERT INTO one VALUES(1,'one');
    INSERT INTO one VALUES(2,'two');
    INSERT INTO one VALUES(3,'three');
    SELECT b FROM one ORDER BY a;
  }
} {one two three}
do_test trans-1.1 {
  execsql {
    CREATE TABLE two(a int PRIMARY KEY, b text);
    INSERT INTO two VALUES(1,'I');
    INSERT INTO two VALUES(5,'V');
    INSERT INTO two VALUES(10,'X');
    SELECT b FROM two ORDER BY a;
  }
} {I V X}
do_test trans-1.9 {
  sqlite3 altdb test.db
  execsql {SELECT b FROM one ORDER BY a} altdb
} {one two three}
do_test trans-1.10 {
  execsql {SELECT b FROM two ORDER BY a} altdb
} {I V X}
integrity_check trans-1.11

# Basic transactions
#
do_test trans-2.1 {
  set v [catch {execsql {BEGIN}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.2 {
  set v [catch {execsql {END}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.3 {
  set v [catch {execsql {BEGIN TRANSACTION}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.4 {
  set v [catch {execsql {COMMIT TRANSACTION}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.5 {
  set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.6 {
  set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.10 {
  execsql {
    BEGIN;
    SELECT a FROM one ORDER BY a;
    SELECT a FROM two ORDER BY a;
    END;
  }
} {1 2 3 1 5 10}
integrity_check trans-2.11

# Check the locking behavior
#
do_test trans-3.1 {
  execsql {
    BEGIN;
    UPDATE one SET a = 0 WHERE 0;
    SELECT a FROM one ORDER BY a;
  }
} {1 2 3}
do_test trans-3.2 {
  catchsql {
    SELECT a FROM two ORDER BY a;
  } altdb
} {0 {1 5 10}}
do_test trans-3.3 {
  catchsql {
    SELECT a FROM one ORDER BY a;
  } altdb
} {0 {1 2 3}}
do_test trans-3.4 {
  catchsql {
    INSERT INTO one VALUES(4,'four');
  }
} {0 {}}
do_test trans-3.5 {
  catchsql {
    SELECT a FROM two ORDER BY a;
  } altdb
} {0 {1 5 10}}
do_test trans-3.6 {
  catchsql {
    SELECT a FROM one ORDER BY a;
  } altdb
} {0 {1 2 3}}
do_test trans-3.7 {
  catchsql {
    INSERT INTO two VALUES(4,'IV');
  }
} {0 {}}
do_test trans-3.8 {
  catchsql {
    SELECT a FROM two ORDER BY a;
  } altdb
} {0 {1 5 10}}
do_test trans-3.9 {
  catchsql {
    SELECT a FROM one ORDER BY a;
  } altdb
} {0 {1 2 3}}
do_test trans-3.10 {
  execsql {END TRANSACTION}
} {}
do_test trans-3.11 {
  set v [catch {execsql {
    SELECT a FROM two ORDER BY a;
  } altdb} msg]
  lappend v $msg
} {0 {1 4 5 10}}
do_test trans-3.12 {
  set v [catch {execsql {
    SELECT a FROM one ORDER BY a;
  } altdb} msg]
  lappend v $msg
} {0 {1 2 3 4}}
do_test trans-3.13 {
  set v [catch {execsql {
    SELECT a FROM two ORDER BY a;
  } db} msg]
  lappend v $msg
} {0 {1 4 5 10}}
do_test trans-3.14 {
  set v [catch {execsql {
    SELECT a FROM one ORDER BY a;
  } db} msg]
  lappend v $msg
} {0 {1 2 3 4}}
integrity_check trans-3.15

do_test trans-4.1 {
  set v [catch {execsql {
    COMMIT;
  } db} msg]
  lappend v $msg
} {1 {cannot commit - no transaction is active}}
do_test trans-4.2 {
  set v [catch {execsql {
    ROLLBACK;
  } db} msg]
  lappend v $msg
} {1 {cannot rollback - no transaction is active}}
do_test trans-4.3 {
  catchsql {
    BEGIN TRANSACTION;
    UPDATE two SET a = 0 WHERE 0;
    SELECT a FROM two ORDER BY a;
  } db
} {0 {1 4 5 10}}
do_test trans-4.4 {
  catchsql {
    SELECT a FROM two ORDER BY a;
  } altdb
} {0 {1 4 5 10}}
do_test trans-4.5 {
  catchsql {
    SELECT a FROM one ORDER BY a;
  } altdb
} {0 {1 2 3 4}}
do_test trans-4.6 {
  catchsql {
    BEGIN TRANSACTION;
    SELECT a FROM one ORDER BY a;
  } db
} {1 {cannot start a transaction within a transaction}}
do_test trans-4.7 {
  catchsql {
    SELECT a FROM two ORDER BY a;
  } altdb
} {0 {1 4 5 10}}
do_test trans-4.8 {
  catchsql {
    SELECT a FROM one ORDER BY a;
  } altdb
} {0 {1 2 3 4}}
do_test trans-4.9 {
  set v [catch {execsql {
    END TRANSACTION;
    SELECT a FROM two ORDER BY a;
  } db} msg]
  lappend v $msg
} {0 {1 4 5 10}}
do_test trans-4.10 {
  set v [catch {execsql {
    SELECT a FROM two ORDER BY a;
  } altdb} msg]
  lappend v $msg
} {0 {1 4 5 10}}
do_test trans-4.11 {
  set v [catch {execsql {
    SELECT a FROM one ORDER BY a;
  } altdb} msg]
  lappend v $msg
} {0 {1 2 3 4}}
integrity_check trans-4.12
do_test trans-4.98 {
  altdb close
  execsql {
    DROP TABLE one;
    DROP TABLE two;
  }
} {}
integrity_check trans-4.99

# Check out the commit/rollback behavior of the database
#
do_test trans-5.1 {
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {}
do_test trans-5.2 {
  execsql {BEGIN TRANSACTION}
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {}
do_test trans-5.3 {
  execsql {CREATE TABLE one(a text, b int)}
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {one}
do_test trans-5.4 {
  execsql {SELECT a,b FROM one ORDER BY b}
} {}
do_test trans-5.5 {
  execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
  execsql {SELECT a,b FROM one ORDER BY b}
} {hello 1}
do_test trans-5.6 {
  execsql {ROLLBACK}
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {}
do_test trans-5.7 {
  set v [catch {
    execsql {SELECT a,b FROM one ORDER BY b}
  } msg]
  lappend v $msg
} {1 {no such table: one}}

# Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
# DROP TABLEs and DROP INDEXs
#
do_test trans-5.8 {
  execsql {
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name
  }
} {}
do_test trans-5.9 {
  execsql {
    BEGIN TRANSACTION;
    CREATE TABLE t1(a int, b int, c int);
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {t1}
do_test trans-5.10 {
  execsql {
    CREATE INDEX i1 ON t1(a);
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i1 t1}
do_test trans-5.11 {
  execsql {
    COMMIT;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i1 t1}
do_test trans-5.12 {
  execsql {
    BEGIN TRANSACTION;
    CREATE TABLE t2(a int, b int, c int);
    CREATE INDEX i2a ON t2(a);
    CREATE INDEX i2b ON t2(b);
    DROP TABLE t1;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i2a i2b t2}
do_test trans-5.13 {
  execsql {
    ROLLBACK;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i1 t1}
do_test trans-5.14 {
  execsql {
    BEGIN TRANSACTION;
    DROP INDEX i1;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {t1}
do_test trans-5.15 {
  execsql {
    ROLLBACK;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i1 t1}
do_test trans-5.16 {
  execsql {
    BEGIN TRANSACTION;
    DROP INDEX i1;
    CREATE TABLE t2(x int, y int, z int);
    CREATE INDEX i2x ON t2(x);
    CREATE INDEX i2y ON t2(y);
    INSERT INTO t2 VALUES(1,2,3);
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i2x i2y t1 t2}
do_test trans-5.17 {
  execsql {
    COMMIT;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i2x i2y t1 t2}
do_test trans-5.18 {
  execsql {
    SELECT * FROM t2;
  }
} {1 2 3}
do_test trans-5.19 {
  execsql {
    SELECT x FROM t2 WHERE y=2;
  }
} {1}
do_test trans-5.20 {
  execsql {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    DROP TABLE t2;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {}
do_test trans-5.21 {
  set r [catch {execsql {
    SELECT * FROM t2
  }} msg]
  lappend r $msg
} {1 {no such table: t2}}
do_test trans-5.22 {
  execsql {
    ROLLBACK;
    SELECT name fROM sqlite_master 
    WHERE type='table' OR type='index'
    ORDER BY name;
  }
} {i2x i2y t1 t2}
do_test trans-5.23 {
  execsql {
    SELECT * FROM t2;
  }
} {1 2 3}
integrity_check trans-5.23


# Try to DROP and CREATE tables and indices with the same name
# within a transaction.  Make sure ROLLBACK works.
#
do_test trans-6.1 {
  execsql2 {
    INSERT INTO t1 VALUES(1,2,3);
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(p,q,r);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {a 1 b 2 c 3}
do_test trans-6.2 {
  execsql2 {
    INSERT INTO t1 VALUES(1,2,3);
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(p,q,r);
    COMMIT;
    SELECT * FROM t1;
  }
} {}
do_test trans-6.3 {
  execsql2 {
    INSERT INTO t1 VALUES(1,2,3);
    SELECT * FROM t1;
  }
} {p 1 q 2 r 3}
do_test trans-6.4 {
  execsql2 {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(4,5,6);
    SELECT * FROM t1;
    DROP TABLE t1;
  }
} {a 4 b 5 c 6}
do_test trans-6.5 {
  execsql2 {
    ROLLBACK;
    SELECT * FROM t1;
  }
} {p 1 q 2 r 3}
do_test trans-6.6 {
  execsql2 {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(4,5,6);
    SELECT * FROM t1;
    DROP TABLE t1;
  }
} {a 4 b 5 c 6}
do_test trans-6.7 {
  catchsql {
    COMMIT;
    SELECT * FROM t1;
  }
} {1 {no such table: t1}}

# Repeat on a table with an automatically generated index.
#
do_test trans-6.10 {
  execsql2 {
    CREATE TABLE t1(a unique,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(p unique,q,r);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {a 1 b 2 c 3}
do_test trans-6.11 {
  execsql2 {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(p unique,q,r);
    COMMIT;
    SELECT * FROM t1;
  }
} {}
do_test trans-6.12 {
  execsql2 {
    INSERT INTO t1 VALUES(1,2,3);
    SELECT * FROM t1;
  }
} {p 1 q 2 r 3}
do_test trans-6.13 {
  execsql2 {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(a unique,b,c);
    INSERT INTO t1 VALUES(4,5,6);
    SELECT * FROM t1;
    DROP TABLE t1;
  }
} {a 4 b 5 c 6}
do_test trans-6.14 {
  execsql2 {
    ROLLBACK;
    SELECT * FROM t1;
  }
} {p 1 q 2 r 3}
do_test trans-6.15 {
  execsql2 {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(a unique,b,c);
    INSERT INTO t1 VALUES(4,5,6);
    SELECT * FROM t1;
    DROP TABLE t1;
  }
} {a 4 b 5 c 6}
do_test trans-6.16 {
  catchsql {
    COMMIT;
    SELECT * FROM t1;
  }
} {1 {no such table: t1}}

do_test trans-6.20 {
  execsql {
    CREATE TABLE t1(a integer primary key,b,c);
    INSERT INTO t1 VALUES(1,-2,-3);
    INSERT INTO t1 VALUES(4,-5,-6);
    SELECT * FROM t1;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.21 {
  execsql {
    CREATE INDEX i1 ON t1(b);
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.22 {
  execsql {
    BEGIN TRANSACTION;
    DROP INDEX i1;
    SELECT * FROM t1 WHERE b<1;
    ROLLBACK;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.23 {
  execsql {
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.24 {
  execsql {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    ROLLBACK;
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}

do_test trans-6.25 {
  execsql {
    BEGIN TRANSACTION;
    DROP INDEX i1;
    CREATE INDEX i1 ON t1(c);
    SELECT * FROM t1 WHERE b<1;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.26 {
  execsql {
    SELECT * FROM t1 WHERE c<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.27 {
  execsql {
    ROLLBACK;
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.28 {
  execsql {
    SELECT * FROM t1 WHERE c<1;
  }
} {1 -2 -3 4 -5 -6}

# The following repeats steps 6.20 through 6.28, but puts a "unique"
# constraint the first field of the table in order to generate an
# automatic index.
#
do_test trans-6.30 {
  execsql {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    CREATE TABLE t1(a int unique,b,c);
    COMMIT;
    INSERT INTO t1 VALUES(1,-2,-3);
    INSERT INTO t1 VALUES(4,-5,-6);
    SELECT * FROM t1 ORDER BY a;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.31 {
  execsql {
    CREATE INDEX i1 ON t1(b);
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.32 {
  execsql {
    BEGIN TRANSACTION;
    DROP INDEX i1;
    SELECT * FROM t1 WHERE b<1;
    ROLLBACK;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.33 {
  execsql {
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.34 {
  execsql {
    BEGIN TRANSACTION;
    DROP TABLE t1;
    ROLLBACK;
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}

do_test trans-6.35 {
  execsql {
    BEGIN TRANSACTION;
    DROP INDEX i1;
    CREATE INDEX i1 ON t1(c);
    SELECT * FROM t1 WHERE b<1;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.36 {
  execsql {
    SELECT * FROM t1 WHERE c<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.37 {
  execsql {
    DROP INDEX i1;
    SELECT * FROM t1 WHERE c<1;
  }
} {1 -2 -3 4 -5 -6}
do_test trans-6.38 {
  execsql {
    ROLLBACK;
    SELECT * FROM t1 WHERE b<1;
  }
} {4 -5 -6 1 -2 -3}
do_test trans-6.39 {
  execsql {
    SELECT * FROM t1 WHERE c<1;
  }
} {1 -2 -3 4 -5 -6}
integrity_check trans-6.40

# Test to make sure rollback restores the database back to its original
# state.
#
do_test trans-7.1 {
  execsql {BEGIN}
  for {set i 0} {$i<1000} {incr i} {
    set r1 [expr {rand()}]
    set r2 [expr {rand()}]
    set r3 [expr {rand()}]
    execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)"
  }
  execsql {COMMIT}
  set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
  set ::checksum2 [
    execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
  ]
  execsql {SELECT count(*) FROM t2}
} {1001}
do_test trans-7.2 {
  execsql {SELECT md5sum(x,y,z) FROM t2}
} $checksum
do_test trans-7.2.1 {
  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
} $checksum2
do_test trans-7.3 {
  execsql {
    BEGIN;
    DELETE FROM t2;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.4 {
  execsql {
    BEGIN;
    INSERT INTO t2 SELECT * FROM t2;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.5 {
  execsql {
    BEGIN;
    DELETE FROM t2;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.6 {
  execsql {
    BEGIN;
    INSERT INTO t2 SELECT * FROM t2;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.7 {
  execsql {
    BEGIN;
    CREATE TABLE t3 AS SELECT * FROM t2;
    INSERT INTO t2 SELECT * FROM t3;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.8 {
  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
} $checksum2
do_test trans-7.9 {
  execsql {
    BEGIN;
    CREATE TEMP TABLE t3 AS SELECT * FROM t2;
    INSERT INTO t2 SELECT * FROM t3;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.10 {
  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
} $checksum2
do_test trans-7.11 {
  execsql {
    BEGIN;
    CREATE TEMP TABLE t3 AS SELECT * FROM t2;
    INSERT INTO t2 SELECT * FROM t3;
    DROP INDEX i2x;
    DROP INDEX i2y;
    CREATE INDEX i3a ON t3(x);
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.12 {
  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
} $checksum2
do_test trans-7.13 {
  execsql {
    BEGIN;
    DROP TABLE t2;
    ROLLBACK;
    SELECT md5sum(x,y,z) FROM t2;
  }
} $checksum
do_test trans-7.14 {
  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
} $checksum2
integrity_check trans-7.15

# Arrange for another process to begin modifying the database but abort
# and die in the middle of the modification.  Then have this process read
# the database.  This process should detect the journal file and roll it
# back.  Verify that this happens correctly.
#
set fd [open test.tcl w]
puts $fd {
  sqlite3 db test.db
  db eval {
    PRAGMA default_cache_size=20;
    BEGIN;
    CREATE TABLE t3 AS SELECT * FROM t2;
    DELETE FROM t2;
  }
  sqlite_abort
}
close $fd
do_test trans-8.1 {
  catch {exec [info nameofexec] test.tcl}
  execsql {SELECT md5sum(x,y,z) FROM t2}
} $checksum
do_test trans-8.2 {
  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
} $checksum2
integrity_check trans-8.3

# In the following sequence of tests, compute the MD5 sum of the content
# of a table, make lots of modifications to that table, then do a rollback.
# Verify that after the rollback, the MD5 checksum is unchanged.
#
do_test trans-9.1 {
  execsql {
    PRAGMA default_cache_size=10;
  }
  db close
  sqlite3 db test.db
  execsql {
    BEGIN;
    CREATE TABLE t3(x TEXT);
    INSERT INTO t3 VALUES(randstr(10,400));
    INSERT INTO t3 VALUES(randstr(10,400));
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
    COMMIT;
    SELECT count(*) FROM t3;
  }
} {1024}

# The following procedure computes a "signature" for table "t3".  If
# T3 changes in any way, the signature should change.  
#
# This is used to test ROLLBACK.  We gather a signature for t3, then
# make lots of changes to t3, then rollback and take another signature.
# The two signatures should be the same.
#
proc signature {} {
  return [db eval {SELECT count(*), md5sum(x) FROM t3}]
}

# Repeat the following group of tests 20 times for quick testing and
# 40 times for full testing.  Each iteration of the test makes table
# t3 a little larger, and thus takes a little longer, so doing 40 tests
# is more than 2.0 times slower than doing 20 tests.  Considerably more.
#
if {[info exists ISQUICK]} {
  set limit 20
} else {
  set limit 40
}

# Do rollbacks.  Make sure the signature does not change.
#
for {set i 2} {$i<=$limit} {incr i} {
  set ::sig [signature]
  set cnt [lindex $::sig 0]
  if {$i%2==0} {
    execsql {PRAGMA synchronous=FULL}
  } else {
    execsql {PRAGMA synchronous=NORMAL}
  }
  do_test trans-9.$i.1-$cnt {
     execsql {
       BEGIN;
       DELETE FROM t3 WHERE random()%10!=0;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       ROLLBACK;
     }
     signature
  } $sig
  do_test trans-9.$i.2-$cnt {
     execsql {
       BEGIN;
       DELETE FROM t3 WHERE random()%10!=0;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       DELETE FROM t3 WHERE random()%10!=0;
       INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
       ROLLBACK;
     }
     signature
  } $sig
  if {$i<$limit} {
    do_test trans-9.$i.9-$cnt {
       execsql {
         INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
       }
    } {}
  }
  set ::pager_old_format 0
}
   
finish_test

--- NEW FILE: trigger1.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests creating and dropping triggers, and interaction thereof
# with the database COMMIT/ROLLBACK logic.
#
# 1. CREATE and DROP TRIGGER tests
# trig-1.1: Error if table does not exist
# trig-1.2: Error if trigger already exists
# trig-1.3: Created triggers are deleted if the transaction is rolled back
# trig-1.4: DROP TRIGGER removes trigger
# trig-1.5: Dropped triggers are restored if the transaction is rolled back
# trig-1.6: Error if dropped trigger doesn't exist
# trig-1.7: Dropping the table automatically drops all triggers
# trig-1.8: A trigger created on a TEMP table is not inserted into sqlite_master
# trig-1.9: Ensure that we cannot create a trigger on sqlite_master
# trig-1.10:
# trig-1.11:
# trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables
# trig-1.13: Ensure that AFTER triggers cannot be created on views
# trig-1.14: Ensure that BEFORE triggers cannot be created on views
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test trigger1-1.1.2 {
   catchsql {
     CREATE TRIGGER trig UPDATE ON no_such_table BEGIN
       SELECT * from sqlite_master;
     END;
   } 
} {1 {no such table: main.no_such_table}}
do_test trigger1-1.1.2 {
   catchsql {
     CREATE TEMP TRIGGER trig UPDATE ON no_such_table BEGIN
       SELECT * from sqlite_master;
     END;
   } 
} {1 {no such table: no_such_table}}

execsql {
    CREATE TABLE t1(a);
}
execsql {
	CREATE TRIGGER tr1 INSERT ON t1 BEGIN
	  INSERT INTO t1 values(1);
 	END;
}
do_test trigger1-1.2 {
    catchsql {
	CREATE TRIGGER tr1 DELETE ON t1 BEGIN
	    SELECT * FROM sqlite_master;
 	END
     }
} {1 {trigger tr1 already exists}}

do_test trigger1-1.3 {
    catchsql {
	BEGIN;
	CREATE TRIGGER tr2 INSERT ON t1 BEGIN
	    SELECT * from sqlite_master; END;
        ROLLBACK;
	CREATE TRIGGER tr2 INSERT ON t1 BEGIN
	    SELECT * from sqlite_master; END;
    }
} {0 {}}

do_test trigger1-1.4 {
    catchsql {
	DROP TRIGGER tr1;
	CREATE TRIGGER tr1 DELETE ON t1 BEGIN
	    SELECT * FROM sqlite_master;
	END
    }
} {0 {}}

do_test trigger1-1.5 {
    execsql {
	BEGIN;
	DROP TRIGGER tr2;
	ROLLBACK;
	DROP TRIGGER tr2;
    }
} {}

do_test trigger1-1.6 {
    catchsql {
	DROP TRIGGER biggles;
    }
} {1 {no such trigger: biggles}}

do_test trigger1-1.7 {
    catchsql {
	DROP TABLE t1;
	DROP TRIGGER tr1;
    }
} {1 {no such trigger: tr1}}

execsql {
  CREATE TEMP TABLE temp_table(a);
}
do_test trigger1-1.8 {
  execsql {
	CREATE TRIGGER temp_trig UPDATE ON temp_table BEGIN
	    SELECT * from sqlite_master;
	END;
	SELECT count(*) FROM sqlite_master WHERE name = 'temp_trig';
  } 
} {0}

do_test trigger1-1.9 {
  catchsql {
    CREATE TRIGGER tr1 AFTER UPDATE ON sqlite_master BEGIN
       SELECT * FROM sqlite_master;
    END;
  }
} {1 {cannot create trigger on system table}}

# Check to make sure that a DELETE statement within the body of
# a trigger does not mess up the DELETE that caused the trigger to
# run in the first place.
#
do_test trigger1-1.10 {
  execsql {
    create table t1(a,b);
    insert into t1 values(1,'a');
    insert into t1 values(2,'b');
    insert into t1 values(3,'c');
    insert into t1 values(4,'d');
    create trigger r1 after delete on t1 for each row begin
      delete from t1 WHERE a=old.a+2;
    end;
    delete from t1 where a in (1,3);
    select * from t1;
    drop table t1;
  }
} {2 b 4 d}
do_test trigger1-1.11 {
  execsql {
    create table t1(a,b);
    insert into t1 values(1,'a');
    insert into t1 values(2,'b');
    insert into t1 values(3,'c');
    insert into t1 values(4,'d');
    create trigger r1 after update on t1 for each row begin
      delete from t1 WHERE a=old.a+2;
    end;
    update t1 set b='x-' || b where a in (1,3);
    select * from t1;
    drop table t1;
  }
} {1 x-a 2 b 4 d}

# Ensure that we cannot create INSTEAD OF triggers on tables
do_test trigger1-1.12 {
  catchsql {
    create table t1(a,b);
    create trigger t1t instead of update on t1 for each row begin
      delete from t1 WHERE a=old.a+2;
    end;
  }
} {1 {cannot create INSTEAD OF trigger on table: main.t1}}
# Ensure that we cannot create BEFORE triggers on views
do_test trigger1-1.13 {
  catchsql {
    create view v1 as select * from t1;
    create trigger v1t before update on v1 for each row begin
      delete from t1 WHERE a=old.a+2;
    end;
  }
} {1 {cannot create BEFORE trigger on view: main.v1}}
# Ensure that we cannot create AFTER triggers on views
do_test trigger1-1.14 {
  catchsql {
    drop view v1;
    create view v1 as select * from t1;
    create trigger v1t AFTER update on v1 for each row begin
      delete from t1 WHERE a=old.a+2;
    end;
  }
} {1 {cannot create AFTER trigger on view: main.v1}}

# Check for memory leaks in the trigger parser
#
do_test trigger1-2.1 {
  catchsql {
    CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
      SELECT * FROM;  -- Syntax error
    END;
  }
} {1 {near ";": syntax error}}
do_test trigger1-2.2 {
  catchsql {
    CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
      SELECT * FROM t1;
      SELECT * FROM;  -- Syntax error
    END;
  }
} {1 {near ";": syntax error}}

# Create a trigger that refers to a table that might not exist.
#
do_test trigger1-3.1 {
  execsql {
    CREATE TEMP TABLE t2(x,y);
  }
  catchsql {
    CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
      INSERT INTO t2 VALUES(NEW.a,NEW.b);
    END;
  }
} {0 {}}
do_test trigger-3.2 {
  catchsql {
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t2;
  }
} {1 {no such table: main.t2}}
do_test trigger-3.3 {
  db close
  set rc [catch {sqlite3 db test.db} err]
  if {$rc} {lappend rc $err}
  set rc
} {0}
do_test trigger-3.4 {
  catchsql {
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t2;
  }
} {1 {no such table: main.t2}}
do_test trigger-3.5 {
  catchsql {
    CREATE TEMP TABLE t2(x,y);
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t2;
  }
} {1 {no such table: main.t2}}
do_test trigger-3.6 {
  catchsql {
    DROP TRIGGER r1;
    CREATE TEMP TRIGGER r1 AFTER INSERT ON t1 BEGIN
      INSERT INTO t2 VALUES(NEW.a,NEW.b);
    END;
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t2;
  }
} {0 {1 2}}
do_test trigger-3.7 {
  execsql {
    DROP TABLE t2;
    CREATE TABLE t2(x,y);
    SELECT * FROM t2;
  }
} {}
do_test trigger-3.8 {
  execsql {
    INSERT INTO t1 VALUES(3,4);
    SELECT * FROM t1 UNION ALL SELECT * FROM t2;
  }
} {1 2 3 4 3 4}
do_test trigger-3.9 {
  db close
  sqlite3 db test.db
  execsql {
    INSERT INTO t1 VALUES(5,6);
    SELECT * FROM t1 UNION ALL SELECT * FROM t2;
  }
} {1 2 3 4 5 6 3 4}

do_test trigger-4.1 {
  execsql {
    CREATE TEMP TRIGGER r1 BEFORE INSERT ON t1 BEGIN
      INSERT INTO t2 VALUES(NEW.a,NEW.b);
    END;
    INSERT INTO t1 VALUES(7,8);
    SELECT * FROM t2;
  }
} {3 4 7 8}
do_test trigger-4.2 {
  sqlite3 db2 test.db
  execsql {
    INSERT INTO t1 VALUES(9,10);
  } db2;
  db2 close
  execsql {
    SELECT * FROM t2;
  }
} {3 4 7 8}
do_test trigger-4.3 {
  execsql {
    DROP TABLE t1;
    SELECT * FROM t2;
  };
} {3 4 7 8}
do_test trigger-4.4 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM t2;
  };
} {3 4 7 8}

integrity_check trigger-5.1

# Create a trigger with the same name as a table.  Make sure the
# trigger works.  Then drop the trigger.  Make sure the table is
# still there.
#
do_test trigger-6.1 {
  execsql {SELECT type, name FROM sqlite_master}
} {view v1 table t2}
do_test trigger-6.2 {
  execsql {
    CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN
      SELECT RAISE(ABORT,'deletes are not allows');
    END;
    SELECT type, name FROM sqlite_master;
  }
} {view v1 table t2 trigger t2}
do_test trigger-6.3 {
  catchsql {DELETE FROM t2}
} {1 {deletes are not allows}}
do_test trigger-6.4 {
  execsql {SELECT * FROM t2}
} {3 4 7 8}
do_test trigger-6.5 {
  db close
  sqlite3 db test.db
  execsql {SELECT type, name FROM sqlite_master}
} {view v1 table t2 trigger t2}
do_test trigger-6.6 {
  execsql {
    DROP TRIGGER t2;
    SELECT type, name FROM sqlite_master;
  }
} {view v1 table t2}
do_test trigger-6.7 {
  execsql {SELECT * FROM t2}
} {3 4 7 8}
do_test trigger-6.8 {
  db close
  sqlite3 db test.db
  execsql {SELECT * FROM t2}
} {3 4 7 8}

integrity_check trigger-7.1

# Check to make sure the name of a trigger can be quoted so that keywords
# can be used as trigger names.  Ticket #468
#
do_test trigger-8.1 {
  execsql {
    CREATE TRIGGER 'trigger' AFTER INSERT ON t2 BEGIN SELECT 1; END;
    SELECT name FROM sqlite_master WHERE type='trigger';
  }
} {trigger}
do_test trigger-8.2 {
  execsql {
    DROP TRIGGER 'trigger';
    SELECT name FROM sqlite_master WHERE type='trigger';
  }
} {}
do_test trigger-8.3 {
  execsql {
    CREATE TRIGGER "trigger" AFTER INSERT ON t2 BEGIN SELECT 1; END;
    SELECT name FROM sqlite_master WHERE type='trigger';
  }
} {trigger}
do_test trigger-8.4 {
  execsql {
    DROP TRIGGER "trigger";
    SELECT name FROM sqlite_master WHERE type='trigger';
  }
} {}
do_test trigger-8.5 {
  execsql {
    CREATE TRIGGER [trigger] AFTER INSERT ON t2 BEGIN SELECT 1; END;
    SELECT name FROM sqlite_master WHERE type='trigger';
  }
} {trigger}
do_test trigger-8.6 {
  execsql {
    DROP TRIGGER [trigger];
    SELECT name FROM sqlite_master WHERE type='trigger';
  }
} {}

# Make sure REPLACE works inside of triggers.
#
do_test trigger-9.1 {
  execsql {
    CREATE TABLE t3(a,b);
    CREATE TABLE t4(x UNIQUE, b);
    CREATE TRIGGER r34 AFTER INSERT ON t3 BEGIN
      REPLACE INTO t4 VALUES(new.a,new.b);
    END;
    INSERT INTO t3 VALUES(1,2);
    SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
  }
} {1 2 99 99 1 2}
do_test trigger-9.2 {
  execsql {
    INSERT INTO t3 VALUES(1,3);
    SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
  }
} {1 2 1 3 99 99 1 3}

execsql {
  DROP TABLE t2;
  DROP TABLE t3;
  DROP TABLE t4;
}

# Ticket #764. At one stage TEMP triggers would fail to re-install when the
# schema was reloaded. The following tests ensure that TEMP triggers are
# correctly re-installed.
#
# Also verify that references within trigger programs are resolved at
# statement compile time, not trigger installation time. This means, for
# example, that you can drop and re-create tables referenced by triggers. 
do_test trigger-10.0 {
  file delete -force test2.db
  file delete -force test2.db-journal
  execsql {
    ATTACH 'test2.db' AS aux;
  }
} {}
do_test trigger-10.1 {
  execsql {
    CREATE TABLE main.t4(a, b, c);
    CREATE TABLE temp.t4(a, b, c);
    CREATE TABLE aux.t4(a, b, c);
    CREATE TABLE insert_log(db, a, b, c);
  }
} {}
do_test trigger-10.2 {
  execsql {
    CREATE TEMP TRIGGER trig1 AFTER INSERT ON main.t4 BEGIN 
      INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
    END;
    CREATE TEMP TRIGGER trig2 AFTER INSERT ON temp.t4 BEGIN 
      INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
    END;
    CREATE TEMP TRIGGER trig3 AFTER INSERT ON aux.t4 BEGIN 
      INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
    END;
  }
} {}
do_test trigger-10.3 {
  execsql {
    INSERT INTO main.t4 VALUES(1, 2, 3);
    INSERT INTO temp.t4 VALUES(4, 5, 6);
    INSERT INTO aux.t4  VALUES(7, 8, 9);
  }
} {}
do_test trigger-10.4 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 1 2 3 temp 4 5 6 aux 7 8 9}
do_test trigger-10.5 {
  execsql {
    BEGIN;
    INSERT INTO main.t4 VALUES(1, 2, 3);
    INSERT INTO temp.t4 VALUES(4, 5, 6);
    INSERT INTO aux.t4  VALUES(7, 8, 9);
    ROLLBACK;
  }
} {}
do_test trigger-10.6 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 1 2 3 temp 4 5 6 aux 7 8 9}
do_test trigger-10.7 {
  execsql {
    DELETE FROM insert_log;
    INSERT INTO main.t4 VALUES(11, 12, 13);
    INSERT INTO temp.t4 VALUES(14, 15, 16);
    INSERT INTO aux.t4  VALUES(17, 18, 19);
  }
} {}
do_test trigger-10.8 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 11 12 13 temp 14 15 16 aux 17 18 19}
do_test trigger-10.8 {
# Drop and re-create the insert_log table in a different database. Note
# that we can change the column names because the trigger programs don't
# use them explicitly.
  execsql {
    DROP TABLE insert_log;
    CREATE TABLE aux.insert_log(db, d, e, f);
  }
} {}
do_test trigger-10.10 {
  execsql {
    INSERT INTO main.t4 VALUES(21, 22, 23);
    INSERT INTO temp.t4 VALUES(24, 25, 26);
    INSERT INTO aux.t4  VALUES(27, 28, 29);
  }
} {}
do_test trigger-10.11 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 21 22 23 temp 24 25 26 aux 27 28 29}

finish_test

--- NEW FILE: trigger2.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Regression testing of FOR EACH ROW table triggers
#
# 1. Trigger execution order tests. 
# These tests ensure that BEFORE and AFTER triggers are fired at the correct
# times relative to each other and the triggering statement. 
#
# trigger2-1.1.*: ON UPDATE trigger execution model.
# trigger2-1.2.*: DELETE trigger execution model.
# trigger2-1.3.*: INSERT trigger execution model.
#
# 2. Trigger program execution tests.
# These tests ensure that trigger programs execute correctly (ie. that a
# trigger program can correctly execute INSERT, UPDATE, DELETE * SELECT
# statements, and combinations thereof).
#
# 3. Selective trigger execution 
# This tests that conditional triggers (ie. UPDATE OF triggers and triggers
# with WHEN clauses) are fired only fired when they are supposed to be.
#
# trigger2-3.1: UPDATE OF triggers
# trigger2-3.2: WHEN clause
#
# 4. Cascaded trigger execution 
# Tests that trigger-programs may cause other triggers to fire. Also that a 
# trigger-program is never executed recursively.
# 
# trigger2-4.1: Trivial cascading trigger
# trigger2-4.2: Trivial recursive trigger handling 
#
# 5. Count changes behaviour.
# Verify that rows altered by triggers are not included in the return value
# of the "count changes" interface.
#
# 6. ON CONFLICT clause handling
# trigger2-6.1[a-f]: INSERT statements
# trigger2-6.2[a-f]: UPDATE statements
#
# 7. Triggers on views fire correctly.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# 1.
set ii 0
foreach tbl_defn {
	{CREATE TEMP TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);} 
	{CREATE TEMPORARY TABLE tbl (a INTEGER PRIMARY KEY, b);} 
        {CREATE TABLE tbl (a, b PRIMARY KEY);} 
	{CREATE TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} 
	{CREATE TEMP TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} 
} {
  incr ii
  catchsql { DROP INDEX tbl_idx; }
  catchsql {
    DROP TABLE rlog;
    DROP TABLE clog;
    DROP TABLE tbl;
    DROP TABLE other_tbl;
  }

  execsql $tbl_defn

  execsql {
    INSERT INTO tbl VALUES(1, 2);
    INSERT INTO tbl VALUES(3, 4);

    CREATE TABLE rlog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b);
    CREATE TABLE clog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b);

    CREATE TRIGGER before_update_row BEFORE UPDATE ON tbl FOR EACH ROW 
      BEGIN
      INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
	  old.a, old.b, 
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  new.a, new.b);
    END;

    CREATE TRIGGER after_update_row AFTER UPDATE ON tbl FOR EACH ROW 
      BEGIN
      INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
	  old.a, old.b, 
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  new.a, new.b);
    END;

    CREATE TRIGGER conditional_update_row AFTER UPDATE ON tbl FOR EACH ROW
      WHEN old.a = 1
      BEGIN
      INSERT INTO clog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM clog), 
	  old.a, old.b, 
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  new.a, new.b);
    END;
  }

  do_test trigger2-1.$ii.1 {
    set r {}
    foreach v [execsql { 
      UPDATE tbl SET a = a * 10, b = b * 10;
      SELECT * FROM rlog ORDER BY idx;
      SELECT * FROM clog ORDER BY idx;
    }] {
      lappend r [expr {int($v)}]
    }
    set r
  } [list 1 1 2  4  6 10 20 \
          2 1 2 13 24 10 20 \
	  3 3 4 13 24 30 40 \
	  4 3 4 40 60 30 40 \
          1 1 2 13 24 10 20 ]

  execsql {
    DELETE FROM rlog;
    DELETE FROM tbl;
    INSERT INTO tbl VALUES (100, 100);
    INSERT INTO tbl VALUES (300, 200);
    CREATE TRIGGER delete_before_row BEFORE DELETE ON tbl FOR EACH ROW
      BEGIN
      INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
	  old.a, old.b, 
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  0, 0);
    END;

    CREATE TRIGGER delete_after_row AFTER DELETE ON tbl FOR EACH ROW
      BEGIN
      INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
	  old.a, old.b, 
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  0, 0);
    END;
  }
  do_test trigger2-1.$ii.2 {
    set r {}
    foreach v [execsql {
      DELETE FROM tbl;
      SELECT * FROM rlog;
    }] {
      lappend r [expr {int($v)}]
    }
    set r
  } [list 1 100 100 400 300 0 0 \
          2 100 100 300 200 0 0 \
          3 300 200 300 200 0 0 \
          4 300 200 0 0 0 0 ]

  execsql {
    DELETE FROM rlog;
    CREATE TRIGGER insert_before_row BEFORE INSERT ON tbl FOR EACH ROW
      BEGIN
      INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
	  0, 0,
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  new.a, new.b);
    END;

    CREATE TRIGGER insert_after_row AFTER INSERT ON tbl FOR EACH ROW
      BEGIN
      INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
	  0, 0,
	  (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl), 
	  new.a, new.b);
    END;
  }
  do_test trigger2-1.$ii.3 {
    execsql {

      CREATE TABLE other_tbl(a, b);
      INSERT INTO other_tbl VALUES(1, 2);
      INSERT INTO other_tbl VALUES(3, 4);
      -- INSERT INTO tbl SELECT * FROM other_tbl;
      INSERT INTO tbl VALUES(5, 6);
      DROP TABLE other_tbl;

      SELECT * FROM rlog;
    }
  } [list 1 0 0 0.0 0.0 5 6 \
          2 0 0 5.0 6.0 5 6 ]

  do_test trigger2-1.$ii.4 {
    execsql {
      PRAGMA integrity_check;
    }
  } {ok}
}
catchsql {
  DROP TABLE rlog;
  DROP TABLE clog;
  DROP TABLE tbl;
  DROP TABLE other_tbl;
}

# 2.
set ii 0
foreach tr_program {
  {UPDATE tbl SET b = old.b;}
  {INSERT INTO log VALUES(new.c, 2, 3);}
  {DELETE FROM log WHERE a = 1;}
  {INSERT INTO tbl VALUES(500, new.b * 10, 700); 
    UPDATE tbl SET c = old.c; 
    DELETE FROM log;}
  {INSERT INTO log select * from tbl;} 
} {
  foreach test_varset [ list \
    {
      set statement {UPDATE tbl SET c = 10 WHERE a = 1;} 
      set prep      {INSERT INTO tbl VALUES(1, 2, 3);}
      set newC 10
      set newB 2
      set newA 1
      set oldA 1
      set oldB 2
      set oldC 3
    } \
    {
      set statement {DELETE FROM tbl WHERE a = 1;}
      set prep      {INSERT INTO tbl VALUES(1, 2, 3);}
      set oldA 1
      set oldB 2
      set oldC 3
    } \
    {
      set statement {INSERT INTO tbl VALUES(1, 2, 3);}
      set newA 1
      set newB 2
      set newC 3
    }
  ] \
  {
    set statement {}
    set prep {}
    set newA {''}
    set newB {''}
    set newC {''}
    set oldA {''}
    set oldB {''}
    set oldC {''}

    incr ii

    eval $test_varset

    set statement_type [string range $statement 0 5]
    set tr_program_fixed $tr_program
    if {$statement_type == "DELETE"} {
      regsub -all new\.a $tr_program_fixed {''} tr_program_fixed 
      regsub -all new\.b $tr_program_fixed {''} tr_program_fixed 
      regsub -all new\.c $tr_program_fixed {''} tr_program_fixed 
    }
    if {$statement_type == "INSERT"} {
      regsub -all old\.a $tr_program_fixed {''} tr_program_fixed 
      regsub -all old\.b $tr_program_fixed {''} tr_program_fixed 
      regsub -all old\.c $tr_program_fixed {''} tr_program_fixed 
    }


    set tr_program_cooked $tr_program
    regsub -all new\.a $tr_program_cooked $newA tr_program_cooked 
    regsub -all new\.b $tr_program_cooked $newB tr_program_cooked 
    regsub -all new\.c $tr_program_cooked $newC tr_program_cooked 
    regsub -all old\.a $tr_program_cooked $oldA tr_program_cooked 
    regsub -all old\.b $tr_program_cooked $oldB tr_program_cooked 
    regsub -all old\.c $tr_program_cooked $oldC tr_program_cooked 

    catchsql {
      DROP TABLE tbl;
      DROP TABLE log;
    }

    execsql {
      CREATE TABLE tbl(a PRIMARY KEY, b, c);
      CREATE TABLE log(a, b, c);
    }

    set query {SELECT * FROM tbl; SELECT * FROM log;}
    set prep "$prep; INSERT INTO log VALUES(1, 2, 3);\
             INSERT INTO log VALUES(10, 20, 30);"

# Check execution of BEFORE programs:

    set before_data [ execsql "$prep $tr_program_cooked $statement $query" ]

    execsql "DELETE FROM tbl; DELETE FROM log; $prep";
    execsql "CREATE TRIGGER the_trigger BEFORE [string range $statement 0 6]\
             ON tbl BEGIN $tr_program_fixed END;"

    do_test trigger2-2.$ii-before "execsql {$statement $query}" $before_data

    execsql "DROP TRIGGER the_trigger;"
    execsql "DELETE FROM tbl; DELETE FROM log;"

# Check execution of AFTER programs
    set after_data [ execsql "$prep $statement $tr_program_cooked $query" ]

    execsql "DELETE FROM tbl; DELETE FROM log; $prep";
    execsql "CREATE TRIGGER the_trigger AFTER [string range $statement 0 6]\
             ON tbl BEGIN $tr_program_fixed END;"

    do_test trigger2-2.$ii-after "execsql {$statement $query}" $after_data
    execsql "DROP TRIGGER the_trigger;"

    do_test trigger2-2.$ii-integrity {
      execsql {
        PRAGMA integrity_check;
      }
    } {ok}

  }
}
catchsql {
  DROP TABLE tbl;
  DROP TABLE log;
}

# 3.

# trigger2-3.1: UPDATE OF triggers
execsql {
  CREATE TABLE tbl (a, b, c, d);
  CREATE TABLE log (a);
  INSERT INTO log VALUES (0);
  INSERT INTO tbl VALUES (0, 0, 0, 0);
  INSERT INTO tbl VALUES (1, 0, 0, 0);
  CREATE TRIGGER tbl_after_update_cd BEFORE UPDATE OF c, d ON tbl
    BEGIN
      UPDATE log SET a = a + 1;
    END;
}
do_test trigger2-3.1 {
  execsql {
    UPDATE tbl SET b = 1, c = 10; -- 2
    UPDATE tbl SET b = 10; -- 0
    UPDATE tbl SET d = 4 WHERE a = 0; --1
    UPDATE tbl SET a = 4, b = 10; --0
    SELECT * FROM log;
  }
} {3}
execsql {
  DROP TABLE tbl;
  DROP TABLE log;
}

# trigger2-3.2: WHEN clause
set when_triggers [ list \
             {t1 BEFORE INSERT ON tbl WHEN new.a > 20} \
             {t2 BEFORE INSERT ON tbl WHEN (SELECT count(*) FROM tbl) = 0} ]

execsql {
  CREATE TABLE tbl (a, b, c, d);
  CREATE TABLE log (a);
  INSERT INTO log VALUES (0);
}

foreach trig $when_triggers {
  execsql "CREATE TRIGGER $trig BEGIN UPDATE log set a = a + 1; END;"
}

do_test trigger2-3.2 {
  execsql { 

    INSERT INTO tbl VALUES(0, 0, 0, 0);     -- 1
    SELECT * FROM log;
    UPDATE log SET a = 0;

    INSERT INTO tbl VALUES(0, 0, 0, 0);     -- 0
    SELECT * FROM log;
    UPDATE log SET a = 0;

    INSERT INTO tbl VALUES(200, 0, 0, 0);     -- 1
    SELECT * FROM log;
    UPDATE log SET a = 0;
  }
} {1 0 1}
execsql {
  DROP TABLE tbl;
  DROP TABLE log;
}
do_test trigger2-3.3 {
  execsql {
    PRAGMA integrity_check;
  }
} {ok}

# Simple cascaded trigger
execsql {
  CREATE TABLE tblA(a, b);
  CREATE TABLE tblB(a, b);
  CREATE TABLE tblC(a, b);

  CREATE TRIGGER tr1 BEFORE INSERT ON tblA BEGIN
    INSERT INTO tblB values(new.a, new.b);
  END;

  CREATE TRIGGER tr2 BEFORE INSERT ON tblB BEGIN
    INSERT INTO tblC values(new.a, new.b);
  END;
}
do_test trigger2-4.1 {
  execsql {
    INSERT INTO tblA values(1, 2);
    SELECT * FROM tblA;
    SELECT * FROM tblB;
    SELECT * FROM tblC;
  }
} {1 2 1 2 1 2}
execsql {
  DROP TABLE tblA;
  DROP TABLE tblB;
  DROP TABLE tblC;
}

# Simple recursive trigger
execsql {
  CREATE TABLE tbl(a, b, c);
  CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl 
    BEGIN
      INSERT INTO tbl VALUES (new.a, new.b, new.c);
    END;
}
do_test trigger2-4.2 {
  execsql {
    INSERT INTO tbl VALUES (1, 2, 3);
    select * from tbl;
  }
} {1 2 3 1 2 3}
execsql {
  DROP TABLE tbl;
}

# 5.
execsql {
  CREATE TABLE tbl(a, b, c);
  CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl 
    BEGIN
      INSERT INTO tbl VALUES (1, 2, 3);
      INSERT INTO tbl VALUES (2, 2, 3);
      UPDATE tbl set b = 10 WHERE a = 1;
      DELETE FROM tbl WHERE a = 1;
      DELETE FROM tbl;
    END;
}
do_test trigger2-5 {
  execsql {
    INSERT INTO tbl VALUES(100, 200, 300);
  }
  db changes
} {1}
execsql {
  DROP TABLE tbl;
}

# Handling of ON CONFLICT by INSERT statements inside triggers
execsql {
  CREATE TABLE tbl (a primary key, b, c);
  CREATE TRIGGER ai_tbl AFTER INSERT ON tbl BEGIN
    INSERT OR IGNORE INTO tbl values (new.a, 0, 0);
  END;
}
do_test trigger2-6.1a {
  execsql {
    BEGIN;
    INSERT INTO tbl values (1, 2, 3);
    SELECT * from tbl;
  }
} {1 2 3}
do_test trigger2-6.1b {
  catchsql {
    INSERT OR ABORT INTO tbl values (2, 2, 3);
  }
} {1 {column a is not unique}}
do_test trigger2-6.1c {
  execsql {
    SELECT * from tbl;
  }
} {1 2 3}
do_test trigger2-6.1d {
  catchsql {
    INSERT OR FAIL INTO tbl values (2, 2, 3);
  }
} {1 {column a is not unique}}
do_test trigger2-6.1e {
  execsql {
    SELECT * from tbl;
  }
} {1 2 3 2 2 3}
do_test trigger2-6.1f {
  execsql {
    INSERT OR REPLACE INTO tbl values (2, 2, 3);
    SELECT * from tbl;
  }
} {1 2 3 2 0 0}
do_test trigger2-6.1g {
  catchsql {
    INSERT OR ROLLBACK INTO tbl values (3, 2, 3);
  }
} {1 {column a is not unique}}
do_test trigger2-6.1h {
  execsql {
    SELECT * from tbl;
  }
} {}
execsql {DELETE FROM tbl}


# Handling of ON CONFLICT by UPDATE statements inside triggers
execsql {
  INSERT INTO tbl values (4, 2, 3);
  INSERT INTO tbl values (6, 3, 4);
  CREATE TRIGGER au_tbl AFTER UPDATE ON tbl BEGIN
    UPDATE OR IGNORE tbl SET a = new.a, c = 10;
  END;
}
do_test trigger2-6.2a {
  execsql {
    BEGIN;
    UPDATE tbl SET a = 1 WHERE a = 4;
    SELECT * from tbl;
  }
} {1 2 10 6 3 4}
do_test trigger2-6.2b {
  catchsql {
    UPDATE OR ABORT tbl SET a = 4 WHERE a = 1;
  }
} {1 {column a is not unique}}
do_test trigger2-6.2c {
  execsql {
    SELECT * from tbl;
  }
} {1 2 10 6 3 4}
do_test trigger2-6.2d {
  catchsql {
    UPDATE OR FAIL tbl SET a = 4 WHERE a = 1;
  }
} {1 {column a is not unique}}
do_test trigger2-6.2e {
  execsql {
    SELECT * from tbl;
  }
} {4 2 10 6 3 4}
do_test trigger2-6.2f.1 {
  execsql {
    UPDATE OR REPLACE tbl SET a = 1 WHERE a = 4;
    SELECT * from tbl;
  }
} {1 3 10}
do_test trigger2-6.2f.2 {
  execsql {
    INSERT INTO tbl VALUES (2, 3, 4);
    SELECT * FROM tbl;
  }
} {1 3 10 2 3 4}
do_test trigger2-6.2g {
  catchsql {
    UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1;
  }
} {1 {column a is not unique}}
do_test trigger2-6.2h {
  execsql {
    SELECT * from tbl;
  }
} {4 2 3 6 3 4}
execsql {
  DROP TABLE tbl;
}

# 7. Triggers on views
do_test trigger2-7.1 {
  execsql {
  CREATE TABLE ab(a, b);
  CREATE TABLE cd(c, d);
  INSERT INTO ab VALUES (1, 2);
  INSERT INTO ab VALUES (0, 0);
  INSERT INTO cd VALUES (3, 4);

  CREATE TABLE tlog(ii INTEGER PRIMARY KEY, 
      olda, oldb, oldc, oldd, newa, newb, newc, newd);

  CREATE VIEW abcd AS SELECT a, b, c, d FROM ab, cd;

  CREATE TRIGGER before_update INSTEAD OF UPDATE ON abcd BEGIN
    INSERT INTO tlog VALUES(NULL, 
	old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d);
  END;
  CREATE TRIGGER after_update INSTEAD OF UPDATE ON abcd BEGIN
    INSERT INTO tlog VALUES(NULL, 
	old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d);
  END;

  CREATE TRIGGER before_delete INSTEAD OF DELETE ON abcd BEGIN
    INSERT INTO tlog VALUES(NULL, 
	old.a, old.b, old.c, old.d, 0, 0, 0, 0);
  END;
  CREATE TRIGGER after_delete INSTEAD OF DELETE ON abcd BEGIN
    INSERT INTO tlog VALUES(NULL, 
	old.a, old.b, old.c, old.d, 0, 0, 0, 0);
  END;

  CREATE TRIGGER before_insert INSTEAD OF INSERT ON abcd BEGIN
    INSERT INTO tlog VALUES(NULL, 
	0, 0, 0, 0, new.a, new.b, new.c, new.d);
  END;
   CREATE TRIGGER after_insert INSTEAD OF INSERT ON abcd BEGIN
    INSERT INTO tlog VALUES(NULL, 
	0, 0, 0, 0, new.a, new.b, new.c, new.d);
   END;
  }
} {};

do_test trigger2-7.2 {
  execsql {
    UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
    DELETE FROM abcd WHERE a = 1;
    INSERT INTO abcd VALUES(10, 20, 30, 40);
    SELECT * FROM tlog;
  }
} [ list 1 1 2 3 4 100 25 3 4 \
         2 1 2 3 4 100 25 3 4 \
	 3 1 2 3 4 0 0 0 0 \
	 4 1 2 3 4 0 0 0 0 \
	 5 0 0 0 0 10 20 30 40 \
	 6 0 0 0 0 10 20 30 40 ]

do_test trigger2-7.3 {
  execsql {
    DELETE FROM tlog;
    INSERT INTO abcd VALUES(10, 20, 30, 40);
    UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
    DELETE FROM abcd WHERE a = 1;
    SELECT * FROM tlog;
  }
} [ list \
   1 0 0 0 0 10 20 30 40 \
   2 0 0 0 0 10 20 30 40 \
   3 1 2 3 4 100 25 3 4 \
   4 1 2 3 4 100 25 3 4 \
   5 1 2 3 4 0 0 0 0 \
   6 1 2 3 4 0 0 0 0 \
]
do_test trigger2-7.4 {
  execsql {
    DELETE FROM tlog;
    DELETE FROM abcd WHERE a = 1;
    INSERT INTO abcd VALUES(10, 20, 30, 40);
    UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
    SELECT * FROM tlog;
  }
} [ list \
   1 1 2 3 4 0 0 0 0 \
   2 1 2 3 4 0 0 0 0 \
   3 0 0 0 0 10 20 30 40 \
   4 0 0 0 0 10 20 30 40 \
   5 1 2 3 4 100 25 3 4 \
   6 1 2 3 4 100 25 3 4 \
]

do_test trigger2-8.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    CREATE VIEW v1 AS
      SELECT a+b AS x, b+c AS y, a+c AS z FROM t1;
    SELECT * FROM v1;
  }
} {3 5 4}
do_test trigger2-8.2 {
  execsql {
    CREATE TABLE v1log(a,b,c,d,e,f);
    CREATE TRIGGER r1 INSTEAD OF DELETE ON v1 BEGIN
      INSERT INTO v1log VALUES(OLD.x,NULL,OLD.y,NULL,OLD.z,NULL);
    END;
    DELETE FROM v1 WHERE x=1;
    SELECT * FROM v1log;
  }
} {}
do_test trigger2-8.3 {
  execsql {
    DELETE FROM v1 WHERE x=3;
    SELECT * FROM v1log;
  }
} {3 {} 5 {} 4 {}}
do_test trigger2-8.4 {
  execsql {
    INSERT INTO t1 VALUES(4,5,6);
    DELETE FROM v1log;
    DELETE FROM v1 WHERE y=11;
    SELECT * FROM v1log;
  }
} {9 {} 11 {} 10 {}}
do_test trigger2-8.5 {
  execsql {
    CREATE TRIGGER r2 INSTEAD OF INSERT ON v1 BEGIN
      INSERT INTO v1log VALUES(NULL,NEW.x,NULL,NEW.y,NULL,NEW.z);
    END;
    DELETE FROM v1log;
    INSERT INTO v1 VALUES(1,2,3);
    SELECT * FROM v1log;
  }
} {{} 1 {} 2 {} 3}
do_test trigger2-8.6 {
  execsql {
    CREATE TRIGGER r3 INSTEAD OF UPDATE ON v1 BEGIN
      INSERT INTO v1log VALUES(OLD.x,NEW.x,OLD.y,NEW.y,OLD.z,NEW.z);
    END;
    DELETE FROM v1log;
    UPDATE v1 SET x=x+100, y=y+200, z=z+300;
    SELECT * FROM v1log;
  }
} {3 103 5 205 4 304 9 109 11 211 10 310}

do_test trigger2-9.9 {
  execsql {PRAGMA integrity_check}
} {ok}

finish_test

--- NEW FILE: trigger3.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests the RAISE() function.
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Test that we can cause ROLLBACK, FAIL and ABORT correctly
# catchsql { DROP TABLE tbl; }
catchsql { CREATE TABLE tbl (a, b, c) }

execsql {
    CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE 
	WHEN (new.a = 4) THEN RAISE(IGNORE) END;
    END;

    CREATE TRIGGER after_tbl_insert AFTER INSERT ON tbl BEGIN SELECT CASE 
	WHEN (new.a = 1) THEN RAISE(ABORT,    'Trigger abort') 
	WHEN (new.a = 2) THEN RAISE(FAIL,     'Trigger fail') 
	WHEN (new.a = 3) THEN RAISE(ROLLBACK, 'Trigger rollback') END;
    END;
}
# ABORT
do_test trigger3-1.1 {
    catchsql {
	BEGIN;
        INSERT INTO tbl VALUES (5, 5, 6);
        INSERT INTO tbl VALUES (1, 5, 6);
    }
} {1 {Trigger abort}}
do_test trigger3-1.2 {
    execsql {
	SELECT * FROM tbl;
	ROLLBACK;
    }
} {5 5 6}
do_test trigger3-1.3 {
    execsql {SELECT * FROM tbl}
} {}

# FAIL
do_test trigger3-2.1 {
    catchsql {
	BEGIN;
        INSERT INTO tbl VALUES (5, 5, 6);
        INSERT INTO tbl VALUES (2, 5, 6);
    }
} {1 {Trigger fail}}
do_test trigger3-2.2 {
    execsql {
	SELECT * FROM tbl;
	ROLLBACK;
    }
} {5 5 6 2 5 6}
# ROLLBACK
do_test trigger3-3.1 {
    catchsql {
	BEGIN;
        INSERT INTO tbl VALUES (5, 5, 6);
        INSERT INTO tbl VALUES (3, 5, 6);
    }
} {1 {Trigger rollback}}
do_test trigger3-3.2 {
    execsql {
	SELECT * FROM tbl;
    }
} {}
# IGNORE
do_test trigger3-4.1 {
    catchsql {
	BEGIN;
        INSERT INTO tbl VALUES (5, 5, 6);
        INSERT INTO tbl VALUES (4, 5, 6);
    }
} {0 {}}
do_test trigger3-4.2 {
    execsql {
	SELECT * FROM tbl;
	ROLLBACK;
    }
} {5 5 6}

# Check that we can also do RAISE(IGNORE) for UPDATE and DELETE
execsql {DROP TABLE tbl;}
execsql {CREATE TABLE tbl (a, b, c);}
execsql {INSERT INTO tbl VALUES(1, 2, 3);}
execsql {INSERT INTO tbl VALUES(4, 5, 6);}
execsql {
    CREATE TRIGGER before_tbl_update BEFORE UPDATE ON tbl BEGIN
	SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END;
    END;

    CREATE TRIGGER before_tbl_delete BEFORE DELETE ON tbl BEGIN
	SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END;
    END;
}
do_test trigger3-5.1 {
    execsql {
	UPDATE tbl SET c = 10;
	SELECT * FROM tbl;
    }
} {1 2 3 4 5 10}
do_test trigger3-5.2 {
    execsql {
	DELETE FROM tbl;
	SELECT * FROM tbl;
    }
} {1 2 3}

# Check that RAISE(IGNORE) works correctly for nested triggers:
execsql {CREATE TABLE tbl2(a, b, c)}
execsql {
    CREATE TRIGGER after_tbl2_insert AFTER INSERT ON tbl2 BEGIN
	UPDATE tbl SET c = 10;
        INSERT INTO tbl2 VALUES (new.a, new.b, new.c);
    END;
}
do_test trigger3-6 {
    execsql {
	INSERT INTO tbl2 VALUES (1, 2, 3);
	SELECT * FROM tbl2;
	SELECT * FROM tbl;
    }
} {1 2 3 1 2 3 1 2 3}

# Check that things also work for view-triggers
execsql {CREATE VIEW tbl_view AS SELECT * FROM tbl}
execsql {
    CREATE TRIGGER tbl_view_insert INSTEAD OF INSERT ON tbl_view BEGIN
	SELECT CASE WHEN (new.a = 1) THEN RAISE(ROLLBACK, 'View rollback')
	            WHEN (new.a = 2) THEN RAISE(IGNORE) 
	            WHEN (new.a = 3) THEN RAISE(ABORT, 'View abort') END;
    END;
}

do_test trigger3-7.1 {
    catchsql {
	INSERT INTO tbl_view VALUES(1, 2, 3);
    }
} {1 {View rollback}}
do_test trigger3-7.2 {
    catchsql {
	INSERT INTO tbl_view VALUES(2, 2, 3);
    }
} {0 {}}
do_test trigger3-7.3 {
    catchsql {
	INSERT INTO tbl_view VALUES(3, 2, 3);
    }
} {1 {View abort}}

integrity_check trigger3-8.1

catchsql { DROP TABLE tbl; } 
catchsql { DROP TABLE tbl2; } 
catchsql { DROP VIEW tbl_view; }

finish_test

--- NEW FILE: trigger4.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests the triggers of views.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test trigger4-1.1 {
  execsql {
    create table test1(id integer primary key,a);
    create table test2(id integer,b);
    create view test as
      select test1.id as id,a as a,b as b
      from test1 join test2 on test2.id =  test1.id;
    create trigger I_test instead of insert on test
      begin
        insert into test1 (id,a) values (NEW.id,NEW.a);
        insert into test2 (id,b) values (NEW.id,NEW.b);
      end;
    insert into test values(1,2,3);
    select * from test1;
  }
} {1 2}
do_test trigger4-1.2 {
  execsql {
    select * from test2;
  }
} {1 3}
do_test trigger4-1.3 {
  db close
  sqlite3 db test.db
  execsql {
    insert into test values(4,5,6);
    select * from test1;
  }
} {1 2 4 5}
do_test trigger4-1.4 {
  execsql {
    select * from test2;
  }
} {1 3 4 6}

do_test trigger4-2.1 {
  execsql {
    create trigger U_test instead of update on test
      begin
        update test1 set a=NEW.a where id=NEW.id;
        update test2 set b=NEW.b where id=NEW.id;
      end;
    update test set a=22 where id=1;
    select * from test1;
  }
} {1 22 4 5}
do_test trigger4-2.2 {
  execsql {
    select * from test2;
  }
} {1 3 4 6}
do_test trigger4-2.3 {
  db close
  sqlite3 db test.db
  execsql {
    update test set b=66 where id=4;
    select * from test1;
  }
} {1 22 4 5}
do_test trigger4-2.4 {
  execsql {
    select * from test2;
  }
} {1 3 4 66}

do_test trigger4-3.1 {
  catchsql {
    drop table test2;
    insert into test values(7,8,9);
  }
} {1 {no such table: main.test2}}
do_test trigger4-3.2 {
  db close
  sqlite3 db test.db
  catchsql {
    insert into test values(7,8,9);
  }
} {1 {no such table: main.test2}}
do_test trigger4-3.3 {
  catchsql {
    update test set a=222 where id=1;
  }
} {1 {no such table: main.test2}}
do_test trigger4-3.4 {
  execsql {
    select * from test1;
  }
} {1 22 4 5}
do_test trigger4-3.5 {
  execsql {
    create table test2(id,b);
    insert into test values(7,8,9);
    select * from test1;
  }
} {1 22 4 5 7 8}
do_test trigger4-3.6 {
  execsql {
    select * from test2;
  }
} {7 9}
do_test trigger4-3.7 {
  db close
  sqlite3 db test.db
  execsql {
    update test set b=99 where id=7;
    select * from test2;
  }
} {7 99}

integrity_check trigger4-4.1

finish_test

--- NEW FILE: trigger5.test ---
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests the triggers of views.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Ticket #844
#
do_test trigger5-1.1 {
  execsql {
    CREATE TABLE Item(
       a integer PRIMARY KEY NOT NULL ,
       b double NULL ,
       c int NOT NULL DEFAULT 0
    );
    CREATE TABLE Undo(UndoAction TEXT);
    INSERT INTO Item VALUES (1,38205.60865,340);
    CREATE TRIGGER trigItem_UNDO_AD AFTER DELETE ON Item FOR EACH ROW
    BEGIN
      INSERT INTO Undo SELECT 'INSERT INTO Item (a,b,c) VALUES ('
       || coalesce(old.a,'NULL') || ',' || quote(old.b) || ',' || old.c || ');';
    END;
    DELETE FROM Item WHERE a = 1;
    SELECT * FROM Undo;
  }
} {{INSERT INTO Item (a,b,c) VALUES (1,38205.60865,340);}}

integrity_check trigger5-99.9

finish_test

--- NEW FILE: types.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. Specfically
# it tests that the different storage classes (integer, real, text etc.)
# all work correctly.
#
# $Id: types.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests in this file are organized roughly as follows:
#
# types-1.*.*: Test that values are stored using the expected storage
#              classes when various forms of literals are inserted into
#              columns with different affinities.
# types-1.1.*: INSERT INTO <table> VALUES(...)
# types-1.2.*: INSERT INTO <table> SELECT...
# types-1.3.*: UPDATE <table> SET...
#
# types-2.*.*: Check that values can be stored and retrieving using the
#              various storage classes.
# types-2.1.*: INTEGER
# types-2.2.*: REAL
# types-2.3.*: NULL
# types-2.4.*: TEXT
# types-2.5.*: Records with a few different storage classes.
#
# types-3.*: Test that the '=' operator respects manifest types.
#

# Disable encryption on the database for this test.
db close
set DB [sqlite3 db test.db]
sqlite3_rekey $DB {}

# Create a table with one column for each type of affinity
do_test types-1.1.0 {
  execsql {
    CREATE TABLE t1(i integer, n numeric, t text, o blob);
  }
} {}

# Each element of the following list represents one test case.
#
# The first value of each sub-list is an SQL literal. The following
# four value are the storage classes that would be used if the
# literal were inserted into a column with affinity INTEGER, NUMERIC, TEXT
# or NONE, respectively.
set values {
  { 5.0    integer real    text real    }
  { 5      integer integer text integer }
  { '5.0'  integer real    text text    }
  { '-5.0' integer real    text text    }
  { '-5.0' integer real    text text    }
  { '5'    integer integer text text    }
  { 'abc'  text    text    text text    }
  { NULL   null    null    null null    }
  { X'00'  blob    blob    blob blob    }
}

# This code tests that the storage classes specified above (in the $values
# table) are correctly assigned when values are inserted using a statement
# of the form:
#
# INSERT INTO <table> VALUE(<values>);
#
set tnum 1
foreach val $values {
  set lit [lindex $val 0]
  execsql "DELETE FROM t1;"
  execsql "INSERT INTO t1 VALUES($lit, $lit, $lit, $lit);"
  do_test types-1.1.$tnum {
    execsql {
      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
    }
  } [lrange $val 1 end]
  incr tnum
}

# This code tests that the storage classes specified above (in the $values
# table) are correctly assigned when values are inserted using a statement
# of the form:
#
# INSERT INTO t1 SELECT ....
#
set tnum 1
foreach val $values {
  set lit [lindex $val 0]
  execsql "DELETE FROM t1;"
  execsql "INSERT INTO t1 SELECT $lit, $lit, $lit, $lit;"
  do_test types-1.2.$tnum {
    execsql {
      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
    }
  } [lrange $val 1 end]
  incr tnum
}

# This code tests that the storage classes specified above (in the $values
# table) are correctly assigned when values are inserted using a statement
# of the form:
#
# UPDATE <table> SET <column> = <value>;
#
set tnum 1
foreach val $values {
  set lit [lindex $val 0]
  execsql "UPDATE t1 SET i = $lit, n = $lit, t = $lit, o = $lit;"
  do_test types-1.3.$tnum {
    execsql {
      SELECT typeof(i), typeof(n), typeof(t), typeof(o) FROM t1;
    }
  } [lrange $val 1 end]
  incr tnum
}

execsql {
  DROP TABLE t1;
}

# Open the table with root-page $rootpage at the btree
# level. Return a list that is the length of each record
# in the table, in the tables default scanning order.
proc record_sizes {rootpage} {
  set bt [btree_open test.db 10 0]
  set c [btree_cursor $bt $rootpage 0]
  btree_first $c
  while 1 {
    lappend res [btree_payload_size $c]
    if {[btree_next $c]} break
  }
  btree_close_cursor $c
  btree_close $bt
  set res
}


# Create a table and insert some 1-byte integers. Make sure they 
# can be read back OK. These should be 3 byte records.
do_test types-2.1.1 {
  execsql {
    CREATE TABLE t1(a integer);
    INSERT INTO t1 VALUES(0);
    INSERT INTO t1 VALUES(120);
    INSERT INTO t1 VALUES(-120);
  }
} {}
do_test types-2.1.2 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120}

# Try some 2-byte integers (4 byte records)
do_test types-2.1.3 {
  execsql {
    INSERT INTO t1 VALUES(30000);
    INSERT INTO t1 VALUES(-30000);
  }
} {}
do_test types-2.1.4 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120 30000 -30000}

# 4-byte integers (6 byte records)
do_test types-2.1.5 {
  execsql {
    INSERT INTO t1 VALUES(2100000000);
    INSERT INTO t1 VALUES(-2100000000);
  }
} {}
do_test types-2.1.6 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120 30000 -30000 2100000000 -2100000000}

# 8-byte integers (10 byte records)
do_test types-2.1.7 {
  execsql {
    INSERT INTO t1 VALUES(9000000*1000000*1000000);
    INSERT INTO t1 VALUES(-9000000*1000000*1000000);
  }
} {}
do_test types-2.1.8 {
  execsql {
    SELECT a FROM t1;
  }
} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
        9000000000000000000 -9000000000000000000]

# Check that all the record sizes are as we expected.
do_test types-2.1.9 {
  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
  record_sizes $root
} {3 3 3 4 4 6 6 10 10}

# Insert some reals. These should be 10 byte records.
do_test types-2.2.1 {
  execsql {
    CREATE TABLE t2(a float);
    INSERT INTO t2 VALUES(0.0);
    INSERT INTO t2 VALUES(12345.678);
    INSERT INTO t2 VALUES(-12345.678);
  }
} {}
do_test types-2.2.2 {
  execsql {
    SELECT a FROM t2;
  }
} {0.0 12345.678 -12345.678}

# Check that all the record sizes are as we expected.
do_test types-2.2.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
  record_sizes $root
} {10 10 10}

# Insert a NULL. This should be a two byte record.
do_test types-2.3.1 {
  execsql {
    CREATE TABLE t3(a nullvalue);
    INSERT INTO t3 VALUES(NULL);
  }
} {}
do_test types-2.3.2 {
  execsql {
    SELECT a ISNULL FROM t3;
  }
} {1}

# Check that all the record sizes are as we expected.
do_test types-2.3.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't3'}]
  record_sizes $root
} {2}

# Insert a couple of strings.
do_test types-2.4.1 {
  set string10 abcdefghij
  set string500 [string repeat $string10 50]
  set string500000 [string repeat $string10 50000]

  execsql "
    CREATE TABLE t4(a string);
    INSERT INTO t4 VALUES('$string10');
    INSERT INTO t4 VALUES('$string500');
    INSERT INTO t4 VALUES('$string500000');
  "
} {}
do_test types-2.4.2 {
  execsql {
    SELECT a FROM t4;
  }
} [list $string10 $string500 $string500000]

# Check that all the record sizes are as we expected. This is dependant on
# the database encoding.
if { [execsql {pragma encoding}] == "UTF-8" } {
  do_test types-2.4.3 {
    set root [db eval {select rootpage from sqlite_master where name = 't4'}]
    record_sizes $root
  } {12 503 500004}
} else {
  do_test types-2.4.3 {
    set root [db eval {select rootpage from sqlite_master where name = 't4'}]
    record_sizes $root
  } {22 1003 1000004}
}

do_test types-2.5.1 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    DROP TABLE t3;
    DROP TABLE t4;
    CREATE TABLE t1(a, b, c);
  }
} {}
do_test types-2.5.2 {
  set string10 abcdefghij
  set string500 [string repeat $string10 50]
  set string500000 [string repeat $string10 50000]

  execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);"
  execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
  execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
} {}
do_test types-2.5.3 {
  execsql {
    SELECT * FROM t1;
  }
} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]

finish_test

--- NEW FILE: types2.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# of this file is testing the interaction of manifest types, type affinity
# and comparison expressions.
#
# $Id: types2.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests in this file are organized roughly as follows:
#
# types2-1.*: The '=' operator in the absence of an index.
# types2-2.*: The '=' operator implemented using an index.
# types2-3.*: The '<' operator implemented using an index.
# types2-4.*: The '>' operator in the absence of an index.
# types2-5.*: The 'IN(x, y...)' operator in the absence of an index.
# types2-6.*: The 'IN(x, y...)' operator with an index.
# types2-7.*: The 'IN(SELECT...)' operator in the absence of an index.
# types2-8.*: The 'IN(SELECT...)' operator with an index.
#
# All tests test the operators using literals and columns, but no
# other types of expressions. All expressions except columns are
# handled similarly in the implementation.

execsql {
  CREATE TABLE t1(
    i1 INTEGER,
    i2 INTEGER,
    n1 NUMERIC,
    n2 NUMERIC,
    t1 TEXT,
    t2 TEXT,
    o1 BLOB,
    o2 BLOB
  );
  INSERT INTO t1 VALUES(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}

proc test_bool {testname vars expr res} {
  if { $vars != "" } {
    execsql "UPDATE t1 SET $vars"
  }

  foreach {t e r} [list $testname $expr $res] {}

  do_test $t.1 "execsql {SELECT $e FROM t1}" $r
  do_test $t.2 "execsql {SELECT 1 FROM t1 WHERE $expr}" [expr $r?"1":""]
  do_test $t.3 "execsql {SELECT 1 FROM t1 WHERE NOT ($e)}" [expr $r?"":"1"]
}

# Compare literals against literals. This should always use a numeric
# comparison.
#
# Changed by ticket #805:  Use no affinity for literal comparisons.
#
test_bool types2-1.1 "" {500 = 500.0} 1
test_bool types2-1.2 "" {'500' = 500.0} 0
test_bool types2-1.3 "" {500 = '500.0'} 0
test_bool types2-1.4 "" {'500' = '500.0'} 0

# Compare literals against a column with TEXT affinity
test_bool types2-1.5 {t1=500} {500 = t1} 1
test_bool types2-1.6 {t1=500} {'500' = t1} 1
test_bool types2-1.7 {t1=500} {500.0 = t1} 0
test_bool types2-1.8 {t1=500} {'500.0' = t1} 0
test_bool types2-1.9 {t1='500'} {500 = t1} 1
test_bool types2-1.10 {t1='500'} {'500' = t1} 1
test_bool types2-1.11 {t1='500'} {500.0 = t1} 0
test_bool types2-1.12 {t1='500'} {'500.0' = t1} 0

# Compare literals against a column with NUMERIC affinity
test_bool types2-1.13 {n1=500} {500 = n1} 1
test_bool types2-1.14 {n1=500} {'500' = n1} 1
test_bool types2-1.15 {n1=500} {500.0 = n1} 1
test_bool types2-1.16 {n1=500} {'500.0' = n1} 1
test_bool types2-1.17 {n1='500'} {500 = n1} 1
test_bool types2-1.18 {n1='500'} {'500' = n1} 1
test_bool types2-1.19 {n1='500'} {500.0 = n1} 1
test_bool types2-1.20 {n1='500'} {'500.0' = n1} 1

# Compare literals against a column with affinity NONE
test_bool types2-1.21 {o1=500} {500 = o1} 1
test_bool types2-1.22 {o1=500} {'500' = o1} 0
test_bool types2-1.23 {o1=500} {500.0 = o1} 1
test_bool types2-1.24 {o1=500} {'500.0' = o1} 0
test_bool types2-1.25 {o1='500'} {500 = o1} 0
test_bool types2-1.26 {o1='500'} {'500' = o1} 1
test_bool types2-1.27 {o1='500'} {500.0 = o1} 0
test_bool types2-1.28 {o1='500'} {'500.0' = o1} 0

set vals [list 10 10.0 '10' '10.0' 20 20.0 '20' '20.0' 30 30.0 '30' '30.0']
#              1  2    3    4      5  6    7    8      9  10   11   12

execsql {
  CREATE TABLE t2(i INTEGER, n NUMERIC, t TEXT, o XBLOBY);
  CREATE INDEX t2i1 ON t2(i);
  CREATE INDEX t2i2 ON t2(n);
  CREATE INDEX t2i3 ON t2(t);
  CREATE INDEX t2i4 ON t2(o);
}
foreach v $vals {
  execsql "INSERT INTO t2 VALUES($v, $v, $v, $v);"
}

proc test_boolset {testname where set} {
  set ::tb_sql "SELECT rowid FROM t2 WHERE $where"
  do_test $testname {
    lsort -integer [execsql $::tb_sql]
  } $set
}

test_boolset types2-2.1 {i = 10} {1 2 3 4}
test_boolset types2-2.2 {i = 10.0} {1 2 3 4}
test_boolset types2-2.3 {i = '10'} {1 2 3 4}
test_boolset types2-2.4 {i = '10.0'} {1 2 3 4}

test_boolset types2-2.5 {n = 20} {5 6 7 8}
test_boolset types2-2.6 {n = 20.0} {5 6 7 8}
test_boolset types2-2.7 {n = '20'} {5 6 7 8}
test_boolset types2-2.8 {n = '20.0'} {5 6 7 8}

test_boolset types2-2.9 {t = 20} {5 7}
test_boolset types2-2.10 {t = 20.0} {6 8}
test_boolset types2-2.11 {t = '20'} {5 7}
test_boolset types2-2.12 {t = '20.0'} {6 8}

test_boolset types2-2.10 {o = 30} {9 10}
test_boolset types2-2.11 {o = 30.0} {9 10}
test_boolset types2-2.12 {o = '30'} 11
test_boolset types2-2.13 {o = '30.0'} 12

test_boolset types2-3.1 {i < 20} {1 2 3 4}
test_boolset types2-3.2 {i < 20.0} {1 2 3 4}
test_boolset types2-3.3 {i < '20'} {1 2 3 4}
test_boolset types2-3.4 {i < '20.0'} {1 2 3 4}

test_boolset types2-3.1 {n < 20} {1 2 3 4}
test_boolset types2-3.2 {n < 20.0} {1 2 3 4}
test_boolset types2-3.3 {n < '20'} {1 2 3 4}
test_boolset types2-3.4 {n < '20.0'} {1 2 3 4}

test_boolset types2-3.1 {t < 20} {1 2 3 4}
test_boolset types2-3.2 {t < 20.0} {1 2 3 4 5 7}
test_boolset types2-3.3 {t < '20'} {1 2 3 4}
test_boolset types2-3.4 {t < '20.0'} {1 2 3 4 5 7}

test_boolset types2-3.1 {o < 20} {1 2}
test_boolset types2-3.2 {o < 20.0} {1 2}
test_boolset types2-3.3 {o < '20'} {1 2 3 4 5 6 9 10}
test_boolset types2-3.3 {o < '20.0'} {1 2 3 4 5 6 7 9 10}

# Compare literals against literals (always a numeric comparison).
# Change (by ticket #805):  No affinity in comparisons
test_bool types2-4.1 "" {500 > 60.0} 1
test_bool types2-4.2 "" {'500' > 60.0} 1
test_bool types2-4.3 "" {500 > '60.0'} 0
test_bool types2-4.4 "" {'500' > '60.0'} 0

# Compare literals against a column with TEXT affinity
test_bool types2-4.5 {t1=500.0} {t1 > 500} 1
test_bool types2-4.6 {t1=500.0} {t1 > '500' } 1
test_bool types2-4.7 {t1=500.0} {t1 > 500.0 } 0
test_bool types2-4.8 {t1=500.0} {t1 > '500.0' } 0
test_bool types2-4.9 {t1='500.0'} {t1 > 500 } 1
test_bool types2-4.10 {t1='500.0'} {t1 > '500' } 1
test_bool types2-4.11 {t1='500.0'} {t1 > 500.0 } 0
test_bool types2-4.12 {t1='500.0'} {t1 > '500.0' } 0

# Compare literals against a column with NUMERIC affinity
test_bool types2-4.13 {n1=400} {500 > n1} 1
test_bool types2-4.14 {n1=400} {'500' > n1} 1
test_bool types2-4.15 {n1=400} {500.0 > n1} 1
test_bool types2-4.16 {n1=400} {'500.0' > n1} 1
test_bool types2-4.17 {n1='400'} {500 > n1} 1
test_bool types2-4.18 {n1='400'} {'500' > n1} 1
test_bool types2-4.19 {n1='400'} {500.0 > n1} 1
test_bool types2-4.20 {n1='400'} {'500.0' > n1} 1

# Compare literals against a column with affinity NONE
test_bool types2-4.21 {o1=500} {500 > o1} 0
test_bool types2-4.22 {o1=500} {'500' > o1} 1
test_bool types2-4.23 {o1=500} {500.0 > o1} 0
test_bool types2-4.24 {o1=500} {'500.0' > o1} 1
test_bool types2-4.25 {o1='500'} {500 > o1} 0
test_bool types2-4.26 {o1='500'} {'500' > o1} 0
test_bool types2-4.27 {o1='500'} {500.0 > o1} 0
test_bool types2-4.28 {o1='500'} {'500.0' > o1} 1

# types2-5.* - The 'IN (x, y....)' operator with no index.
# 
# Compare literals against literals (always a numeric comparison).
test_bool types2-5.1 {} {(NULL IN ('10.0', 20)) ISNULL} 1
test_bool types2-5.2 {} {10 IN ('10.0', 20)} 1
test_bool types2-5.3 {} {'10' IN ('10.0', 20)} 1
test_bool types2-5.4 {} {10 IN (10.0, 20)} 1
test_bool types2-5.5 {} {'10.0' IN (10, 20)} 1

# Compare literals against a column with TEXT affinity
test_bool types2-5.6 {t1='10.0'} {t1 IN (10.0, 20)} 1
test_bool types2-5.7 {t1='10.0'} {t1 IN (10, 20)} 0
test_bool types2-5.8 {t1='10'} {t1 IN (10.0, 20)} 0
test_bool types2-5.9 {t1='10'} {t1 IN (20, '10.0')} 0
test_bool types2-5.10 {t1=10} {t1 IN (20, '10')} 1

# Compare literals against a column with NUMERIC affinity
test_bool types2-5.11 {n1='10.0'} {n1 IN (10.0, 20)} 1
test_bool types2-5.12 {n1='10.0'} {n1 IN (10, 20)} 1
test_bool types2-5.13 {n1='10'} {n1 IN (10.0, 20)} 1
test_bool types2-5.14 {n1='10'} {n1 IN (20, '10.0')} 1
test_bool types2-5.15 {n1=10} {n1 IN (20, '10')} 1

# Compare literals against a column with affinity NONE
test_bool types2-5.16 {o1='10.0'} {o1 IN (10.0, 20)} 0
test_bool types2-5.17 {o1='10.0'} {o1 IN (10, 20)} 0
test_bool types2-5.18 {o1='10'} {o1 IN (10.0, 20)} 0
test_bool types2-5.19 {o1='10'} {o1 IN (20, '10.0')} 0
test_bool types2-5.20 {o1=10} {o1 IN (20, '10')} 0
test_bool types2-5.21 {o1='10.0'} {o1 IN (10, 20, '10.0')} 1
test_bool types2-5.22 {o1='10'} {o1 IN (10.0, 20, '10')} 1
test_bool types2-5.23 {o1=10} {n1 IN (20, '10', 10)} 1

# Tests named types2-6.* use the same infrastructure as the types2-2.*
# tests. The contents of the vals array is repeated here for easy 
# reference.
# 
# set vals [list 10 10.0 '10' '10.0' 20 20.0 '20' '20.0' 30 30.0 '30' '30.0']
#                1  2    3    4      5  6    7    8      9  10   11   12

test_boolset types2-6.1 {o IN ('10', 30)} {3 9 10}
test_boolset types2-6.2 {o IN (20.0, 30.0)} {5 6 9 10}
test_boolset types2-6.3 {t IN ('10', 30)} {1 3 9 11}
test_boolset types2-6.4 {t IN (20.0, 30.0)} {6 8 10 12}
test_boolset types2-6.5 {n IN ('10', 30)} {1 2 3 4 9 10 11 12}
test_boolset types2-6.6 {n IN (20.0, 30.0)} {5 6 7 8 9 10 11 12}
test_boolset types2-6.7 {i IN ('10', 30)} {1 2 3 4 9 10 11 12}
test_boolset types2-6.8 {i IN (20.0, 30.0)} {5 6 7 8 9 10 11 12}

# Also test than IN(x, y, z) works on a rowid:
test_boolset types2-6.9 {rowid IN (1, 6, 10)} {1 6 10}

# Tests types2-7.* concentrate on expressions of the form 
# "x IN (SELECT...)" with no index.
execsql {
  CREATE TABLE t3(i INTEGER, n NUMERIC, t TEXT, o BLOB);
  INSERT INTO t3 VALUES(1, 1, 1, 1);
  INSERT INTO t3 VALUES(2, 2, 2, 2);
  INSERT INTO t3 VALUES(3, 3, 3, 3);
  INSERT INTO t3 VALUES('1', '1', '1', '1');
  INSERT INTO t3 VALUES('1.0', '1.0', '1.0', '1.0');
}

test_bool types2-7.1 {i1=1} {i1 IN (SELECT i FROM t3)} 1
test_bool types2-7.2 {i1='2.0'} {i1 IN (SELECT i FROM t3)} 1
test_bool types2-7.3 {i1='2.0'} {i1 IN (SELECT n FROM t3)} 1
test_bool types2-7.4 {i1='2.0'} {i1 IN (SELECT t FROM t3)} 1
test_bool types2-7.5 {i1='2.0'} {i1 IN (SELECT o FROM t3)} 1

test_bool types2-7.6 {n1=1} {n1 IN (SELECT n FROM t3)} 1
test_bool types2-7.7 {n1='2.0'} {n1 IN (SELECT i FROM t3)} 1
test_bool types2-7.8 {n1='2.0'} {n1 IN (SELECT n FROM t3)} 1
test_bool types2-7.9 {n1='2.0'} {n1 IN (SELECT t FROM t3)} 1
test_bool types2-7.10 {n1='2.0'} {n1 IN (SELECT o FROM t3)} 1

test_bool types2-7.6 {t1=1} {t1 IN (SELECT t FROM t3)} 1
test_bool types2-7.7 {t1='2.0'} {t1 IN (SELECT t FROM t3)} 0
test_bool types2-7.8 {t1='2.0'} {t1 IN (SELECT n FROM t3)} 1
test_bool types2-7.9 {t1='2.0'} {t1 IN (SELECT i FROM t3)} 1
test_bool types2-7.10 {t1='2.0'} {t1 IN (SELECT o FROM t3)} 0
test_bool types2-7.11 {t1='1.0'} {t1 IN (SELECT t FROM t3)} 1
test_bool types2-7.12 {t1='1.0'} {t1 IN (SELECT o FROM t3)} 1

test_bool types2-7.13 {o1=2} {o1 IN (SELECT o FROM t3)} 1
test_bool types2-7.14 {o1='2'} {o1 IN (SELECT o FROM t3)} 0
test_bool types2-7.15 {o1='2'} {o1 IN (SELECT o||'' FROM t3)} 1

# set vals [list 10 10.0 '10' '10.0' 20 20.0 '20' '20.0' 30 30.0 '30' '30.0']
#                1  2    3    4      5  6    7    8      9  10   11   12
execsql {
  CREATE TABLE t4(i INTEGER, n NUMERIC, t VARCHAR(20), o LARGE BLOB);
  INSERT INTO t4 VALUES(10, 20, 20, 30);
}
test_boolset types2-8.1 {i IN (SELECT i FROM t4)} {1 2 3 4}
test_boolset types2-8.2 {n IN (SELECT i FROM t4)} {1 2 3 4}
test_boolset types2-8.3 {t IN (SELECT i FROM t4)} {1 2 3 4}
test_boolset types2-8.4 {o IN (SELECT i FROM t4)} {1 2 3 4}
test_boolset types2-8.5 {i IN (SELECT t FROM t4)} {5 6 7 8}
test_boolset types2-8.6 {n IN (SELECT t FROM t4)} {5 6 7 8}
test_boolset types2-8.7 {t IN (SELECT t FROM t4)} {5 7}
test_boolset types2-8.8 {o IN (SELECT t FROM t4)} {7}
test_boolset types2-8.9 {i IN (SELECT o FROM t4)} {9 10 11 12}
test_boolset types2-8.6 {n IN (SELECT o FROM t4)} {9 10 11 12}
test_boolset types2-8.7 {t IN (SELECT o FROM t4)} {9 11}
test_boolset types2-8.8 {o IN (SELECT o FROM t4)} {9 10}

finish_test

--- NEW FILE: unique.test ---
# 2001 September 27
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE UNIQUE INDEX statement,
# and primary keys, and the UNIQUE constraint on table columns
#
# $Id: unique.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to create a table with two primary keys.
# (This is allowed in SQLite even that it is not valid SQL)
#
do_test unique-1.1 {
  catchsql {
    CREATE TABLE t1(
       a int PRIMARY KEY,
       b int PRIMARY KEY,
       c text
    );
  }
} {1 {table "t1" has more than one primary key}}
do_test unique-1.1b {
  catchsql {
    CREATE TABLE t1(
       a int PRIMARY KEY,
       b int UNIQUE,
       c text
    );
  }
} {0 {}}
do_test unique-1.2 {
  catchsql {
    INSERT INTO t1(a,b,c) VALUES(1,2,3)
  }
} {0 {}}
do_test unique-1.3 {
  catchsql {
    INSERT INTO t1(a,b,c) VALUES(1,3,4)
  }
} {1 {column a is not unique}}
do_test unique-1.4 {
  execsql {
    SELECT * FROM t1 ORDER BY a;
  }
} {1 2 3}
do_test unique-1.5 {
  catchsql {
    INSERT INTO t1(a,b,c) VALUES(3,2,4)
  }
} {1 {column b is not unique}}
do_test unique-1.6 {
  execsql {
    SELECT * FROM t1 ORDER BY a;
  }
} {1 2 3}
do_test unique-1.7 {
  catchsql {
    INSERT INTO t1(a,b,c) VALUES(3,4,5)
  }
} {0 {}}
do_test unique-1.8 {
  execsql {
    SELECT * FROM t1 ORDER BY a;
  }
} {1 2 3 3 4 5}
integrity_check unique-1.9

do_test unique-2.0 {
  execsql {
    DROP TABLE t1;
    CREATE TABLE t2(a int, b int);
    INSERT INTO t2(a,b) VALUES(1,2);
    INSERT INTO t2(a,b) VALUES(3,4);
    SELECT * FROM t2 ORDER BY a;
  }
} {1 2 3 4}
do_test unique-2.1 {
  catchsql {
    CREATE UNIQUE INDEX i2 ON t2(a)
  }
} {0 {}}
do_test unique-2.2 {
  catchsql {
    SELECT * FROM t2 ORDER BY a
  }
} {0 {1 2 3 4}}
do_test unique-2.3 {
  catchsql {
    INSERT INTO t2 VALUES(1,5);
  }
} {1 {column a is not unique}}
do_test unique-2.4 {
  catchsql {
    SELECT * FROM t2 ORDER BY a
  }
} {0 {1 2 3 4}}
do_test unique-2.5 {
  catchsql {
    DROP INDEX i2;
    SELECT * FROM t2 ORDER BY a;
  }
} {0 {1 2 3 4}}
do_test unique-2.6 {
  catchsql {
    INSERT INTO t2 VALUES(1,5)
  }
} {0 {}}
do_test unique-2.7 {
  catchsql {
    SELECT * FROM t2 ORDER BY a, b;
  }
} {0 {1 2 1 5 3 4}}
do_test unique-2.8 {
  catchsql {
    CREATE UNIQUE INDEX i2 ON t2(a);
  }
} {1 {indexed columns are not unique}}
do_test unique-2.9 {
  catchsql {
    CREATE INDEX i2 ON t2(a);
  }
} {0 {}}
integrity_check unique-2.10

# Test the UNIQUE keyword as used on two or more fields.
#
do_test unique-3.1 {
  catchsql {
    CREATE TABLE t3(
       a int,
       b int,
       c int,
       d int,
       unique(a,c,d)
     );
  }
} {0 {}}
do_test unique-3.2 {
  catchsql {
    INSERT INTO t3(a,b,c,d) VALUES(1,2,3,4);
    SELECT * FROM t3 ORDER BY a,b,c,d;
  }
} {0 {1 2 3 4}}
do_test unique-3.3 {
  catchsql {
    INSERT INTO t3(a,b,c,d) VALUES(1,2,3,5);
    SELECT * FROM t3 ORDER BY a,b,c,d;
  }
} {0 {1 2 3 4 1 2 3 5}}
do_test unique-3.4 {
  catchsql {
    INSERT INTO t3(a,b,c,d) VALUES(1,4,3,5);
    SELECT * FROM t3 ORDER BY a,b,c,d;
  }
} {1 {columns a, c, d are not unique}}
integrity_check unique-3.5

# Make sure NULLs are distinct as far as the UNIQUE tests are
# concerned.
#
do_test unique-4.1 {
  execsql {
    CREATE TABLE t4(a UNIQUE, b, c, UNIQUE(b,c));
    INSERT INTO t4 VALUES(1,2,3);
    INSERT INTO t4 VALUES(NULL, 2, NULL);
    SELECT * FROM t4;
  }
} {1 2 3 {} 2 {}}
do_test unique-4.2 {
  catchsql {
    INSERT INTO t4 VALUES(NULL, 3, 4);
  }
} {0 {}}
do_test unique-4.3 {
  execsql {
    SELECT * FROM t4
  }
} {1 2 3 {} 2 {} {} 3 4}
do_test unique-4.4 {
  catchsql {
    INSERT INTO t4 VALUES(2, 2, NULL);
  }
} {0 {}}
do_test unique-4.5 {
  execsql {
    SELECT * FROM t4
  }
} {1 2 3 {} 2 {} {} 3 4 2 2 {}}
integrity_check unique-4.6

# Test the error message generation logic.  In particular, make sure we
# do not overflow the static buffer used to generate the error message.
#
do_test unique-5.1 {
  execsql {
    CREATE TABLE t5(
      first_column_with_long_name,
      second_column_with_long_name,
      third_column_with_long_name,
      fourth_column_with_long_name,
      fifth_column_with_long_name,
      sixth_column_with_long_name,
      UNIQUE(
        first_column_with_long_name,
        second_column_with_long_name,
        third_column_with_long_name,
        fourth_column_with_long_name,
        fifth_column_with_long_name,
        sixth_column_with_long_name
      )
    );
    INSERT INTO t5 VALUES(1,2,3,4,5,6);
    SELECT * FROM t5;
  }
} {1 2 3 4 5 6}
do_test unique-5.2 {
  catchsql {
    INSERT INTO t5 VALUES(1,2,3,4,5,6);
  }
} {1 {columns first_column_with_long_name, second_column_with_long_name, third_column_with_long_name, fourth_column_with_long_name, fifth_column_with_long_name, ... are not unique}}

finish_test

--- NEW FILE: update.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the UPDATE statement.
#
# $Id: update.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to update an non-existent table
#
do_test update-1.1 {
  set v [catch {execsql {UPDATE test1 SET f2=5 WHERE f1<1}} msg]
  lappend v $msg
} {1 {no such table: test1}}

# Try to update a read-only table
#
do_test update-2.1 {
  set v [catch \
       {execsql {UPDATE sqlite_master SET name='xyz' WHERE name='123'}} msg]
  lappend v $msg
} {1 {table sqlite_master may not be modified}}

# Create a table to work with
#
do_test update-3.1 {
  execsql {CREATE TABLE test1(f1 int,f2 int)}
  for {set i 1} {$i<=10} {incr i} {
    set sql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
    execsql $sql
  }
  execsql {SELECT * FROM test1 ORDER BY f1}
} {1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024}

# Unknown column name in an expression
#
do_test update-3.2 {
  set v [catch {execsql {UPDATE test1 SET f1=f3*2 WHERE f2==32}} msg]
  lappend v $msg
} {1 {no such column: f3}}
do_test update-3.3 {
  set v [catch {execsql {UPDATE test1 SET f1=test2.f1*2 WHERE f2==32}} msg]
  lappend v $msg
} {1 {no such column: test2.f1}}
do_test update-3.4 {
  set v [catch {execsql {UPDATE test1 SET f3=f1*2 WHERE f2==32}} msg]
  lappend v $msg
} {1 {no such column: f3}}

# Actually do some updates
#
do_test update-3.5 {
  execsql {UPDATE test1 SET f2=f2*3}
} {}
do_test update-3.6 {
  execsql {SELECT * FROM test1 ORDER BY f1}
} {1 6 2 12 3 24 4 48 5 96 6 192 7 384 8 768 9 1536 10 3072}
do_test update-3.7 {
  execsql {PRAGMA count_changes=on}
  execsql {UPDATE test1 SET f2=f2/3 WHERE f1<=5}
} {5}
do_test update-3.8 {
  execsql {SELECT * FROM test1 ORDER BY f1}
} {1 2 2 4 3 8 4 16 5 32 6 192 7 384 8 768 9 1536 10 3072}
do_test update-3.9 {
  execsql {UPDATE test1 SET f2=f2/3 WHERE f1>5}
} {5}
do_test update-3.10 {
  execsql {SELECT * FROM test1 ORDER BY f1}
} {1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024}

# Swap the values of f1 and f2 for all elements
#
do_test update-3.11 {
  execsql {UPDATE test1 SET F2=f1, F1=f2}
} {10}
do_test update-3.12 {
  execsql {SELECT * FROM test1 ORDER BY F1}
} {2 1 4 2 8 3 16 4 32 5 64 6 128 7 256 8 512 9 1024 10}
do_test update-3.13 {
  execsql {PRAGMA count_changes=off}
  execsql {UPDATE test1 SET F2=f1, F1=f2}
} {}
do_test update-3.14 {
  execsql {SELECT * FROM test1 ORDER BY F1}
} {1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024}

# Create duplicate entries and make sure updating still
# works.
#
do_test update-4.0 {
  execsql {
    DELETE FROM test1 WHERE f1<=5;
    INSERT INTO test1(f1,f2) VALUES(8,88);
    INSERT INTO test1(f1,f2) VALUES(8,888);
    INSERT INTO test1(f1,f2) VALUES(77,128);
    INSERT INTO test1(f1,f2) VALUES(777,128);
  }
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-4.1 {
  execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_test update-4.2 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_test update-4.3 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-4.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
do_test update-4.5 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
do_test update-4.6 {
  execsql {
    PRAGMA count_changes=on;
    UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128;
  }
} {2}
do_test update-4.7 {
  execsql {
    PRAGMA count_changes=off;
    SELECT * FROM test1 ORDER BY f1,f2
  }
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}

# Repeat the previous sequence of tests with an index.
#
do_test update-5.0 {
  execsql {CREATE INDEX idx1 ON test1(f1)}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-5.1 {
  execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_test update-5.2 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_test update-5.3 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-5.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
do_test update-5.4.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-5.4.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {778 128}
do_test update-5.4.3 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-5.5 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
} {}
do_test update-5.5.1 {
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
do_test update-5.5.2 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-5.5.3 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-5.5.4 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-5.5.5 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-5.6 {
  execsql {
    PRAGMA count_changes=on;
    UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128;
  }
} {2}
do_test update-5.6.1 {
  execsql {
    PRAGMA count_changes=off;
    SELECT * FROM test1 ORDER BY f1,f2
  }
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-5.6.2 {
  execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
} {77 128}
do_test update-5.6.3 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-5.6.4 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-5.6.5 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}

# Repeat the previous sequence of tests with a different index.
#
execsql {PRAGMA synchronous=FULL}
do_test update-6.0 {
  execsql {DROP INDEX idx1}
  execsql {CREATE INDEX idx1 ON test1(f2)}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.1 {
  execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_test update-6.1.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 89 8 257 8 889}
do_test update-6.1.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {8 89}
do_test update-6.1.3 {
  execsql {SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2}
} {}
do_test update-6.2 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.3 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.3.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}
do_test update-6.3.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {}
do_test update-6.3.3 {
  execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
} {8 88}
do_test update-6.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
do_test update-6.4.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-6.4.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {778 128}
do_test update-6.4.3 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-6.5 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
do_test update-6.5.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-6.5.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-6.5.3 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-6.5.4 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-6.6 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.6.1 {
  execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
} {77 128}
do_test update-6.6.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-6.6.3 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-6.6.4 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}

# Repeat the previous sequence of tests with multiple
# indices
#
do_test update-7.0 {
  execsql {CREATE INDEX idx2 ON test1(f2)}
  execsql {CREATE INDEX idx3 ON test1(f1,f2)}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.1 {
  execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_test update-7.1.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 89 8 257 8 889}
do_test update-7.1.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {8 89}
do_test update-7.1.3 {
  execsql {SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2}
} {}
do_test update-7.2 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.3 {
  # explain {UPDATE test1 SET f2=f2-1 WHERE f1==8 and F2<300}
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.3.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}
do_test update-7.3.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {}
do_test update-7.3.3 {
  execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
} {8 88}
do_test update-7.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
do_test update-7.4.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-7.4.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {778 128}
do_test update-7.4.3 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-7.5 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
do_test update-7.5.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-7.5.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-7.5.3 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-7.5.4 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-7.6 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.6.1 {
  execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
} {77 128}
do_test update-7.6.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-7.6.3 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-7.6.4 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}

# Error messages
#
do_test update-9.1 {
  set v [catch {execsql {
    UPDATE test1 SET x=11 WHERE f1=1025
  }} msg]
  lappend v $msg
} {1 {no such column: x}}
do_test update-9.2 {
  set v [catch {execsql {
    UPDATE test1 SET f1=x(11) WHERE f1=1025
  }} msg]
  lappend v $msg
} {1 {no such function: x}}
do_test update-9.3 {
  set v [catch {execsql {
    UPDATE test1 SET f1=11 WHERE x=1025
  }} msg]
  lappend v $msg
} {1 {no such column: x}}
do_test update-9.4 {
  set v [catch {execsql {
    UPDATE test1 SET f1=11 WHERE x(f1)=1025
  }} msg]
  lappend v $msg
} {1 {no such function: x}}

# Try doing updates on a unique column where the value does not
# really change.
#
do_test update-10.1 {
  execsql {
    DROP TABLE test1;
    CREATE TABLE t1(
       a integer primary key,
       b UNIQUE, 
       c, d,
       e, f,
       UNIQUE(c,d)
    );
    INSERT INTO t1 VALUES(1,2,3,4,5,6);
    INSERT INTO t1 VALUES(2,3,4,4,6,7);
    SELECT * FROM t1
  }
} {1 2 3 4 5 6 2 3 4 4 6 7}
do_test update-10.2 {
  catchsql {
    UPDATE t1 SET a=1, e=9 WHERE f=6;
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}
do_test update-10.3 {
  catchsql {
    UPDATE t1 SET a=1, e=10 WHERE f=7;
    SELECT * FROM t1;
  }
} {1 {PRIMARY KEY must be unique}}
do_test update-10.4 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}
do_test update-10.5 {
  catchsql {
    UPDATE t1 SET b=2, e=11 WHERE f=6;
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 11 6 2 3 4 4 6 7}}
do_test update-10.6 {
  catchsql {
    UPDATE t1 SET b=2, e=12 WHERE f=7;
    SELECT * FROM t1;
  }
} {1 {column b is not unique}}
do_test update-10.7 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 11 6 2 3 4 4 6 7}}
do_test update-10.8 {
  catchsql {
    UPDATE t1 SET c=3, d=4, e=13 WHERE f=6;
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 13 6 2 3 4 4 6 7}}
do_test update-10.9 {
  catchsql {
    UPDATE t1 SET c=3, d=4, e=14 WHERE f=7;
    SELECT * FROM t1;
  }
} {1 {columns c, d are not unique}}
do_test update-10.10 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 13 6 2 3 4 4 6 7}}

# Make sure we can handle a subquery in the where clause.
#
do_test update-11.1 {
  execsql {
    UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);
    SELECT b,e FROM t1;
  }
} {2 14 3 7}
do_test update-11.2 {
  execsql {
    UPDATE t1 SET e=e+1 WHERE a IN (SELECT a FROM t1);
    SELECT a,e FROM t1;
  }
} {1 15 2 8}

integrity_check update-12.1

# Ticket 602.  Updates should occur in the same order as the records
# were discovered in the WHERE clause.
#
do_test update-13.1 {
  execsql {
    BEGIN;
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
    INSERT INTO t2 SELECT a+2 FROM t2;
    INSERT INTO t2 SELECT a+4 FROM t2;
    INSERT INTO t2 SELECT a+8 FROM t2;
    INSERT INTO t2 SELECT a+16 FROM t2;
    INSERT INTO t2 SELECT a+32 FROM t2;
    INSERT INTO t2 SELECT a+64 FROM t2;
    INSERT INTO t2 SELECT a+128 FROM t2;
    INSERT INTO t2 SELECT a+256 FROM t2;
    INSERT INTO t2 SELECT a+512 FROM t2;
    INSERT INTO t2 SELECT a+1024 FROM t2;
    COMMIT;
    SELECT count(*) FROM t2;
  }
} {2048}
do_test update-13.2 {
  execsql {
    SELECT count(*) FROM t2 WHERE a=rowid;
  }
} {2048}
do_test update-13.3 {
  execsql {
    UPDATE t2 SET rowid=rowid-1;
    SELECT count(*) FROM t2 WHERE a=rowid+1;
  }
} {2048}
do_test update-13.3 {
  execsql {
    UPDATE t2 SET rowid=rowid+10000;
    UPDATE t2 SET rowid=rowid-9999;
    SELECT count(*) FROM t2 WHERE a=rowid;
  }
} {2048}
do_test update-13.4 {
  execsql {
    BEGIN;
    INSERT INTO t2 SELECT a+2048 FROM t2;
    INSERT INTO t2 SELECT a+4096 FROM t2;
    INSERT INTO t2 SELECT a+8192 FROM t2;
    SELECT count(*) FROM t2 WHERE a=rowid;
    COMMIT;
  }
} 16384
do_test update-13.5 {
  execsql {
    UPDATE t2 SET rowid=rowid-1;
    SELECT count(*) FROM t2 WHERE a=rowid+1;
  }
} 16384

integrity_check update-13.6


finish_test

--- NEW FILE: utf16.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: utf16.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test2
proc finish_test {} {}
set ISQUICK 1

if { [llength $argv]>0 } {
  set FILES $argv
  set argv [list]
} else {
  set F {
    auth.test bind.test blob.test capi2.test capi3.test collate1.test
    collate2.test collate3.test collate4.test collate5.test collate6.test
    conflict.test date.test delete.test expr.test fkey1.test func.test
    hook.test index.test insert2.test insert.test interrupt.test in.test
    intpkey.test ioerr.test join2.test join.test lastinsert.test
    laststmtchanges.test limit.test lock2.test lock.test main.test 
    memdb.test minmax.test misc1.test misc2.test misc3.test notnull.test
    null.test progress.test quote.test rowid.test select1.test select2.test
    select3.test select4.test select5.test select6.test sort.test 
    subselect.test tableapi.test table.test temptable.test
    trace.test trigger1.test trigger2.test trigger3.test
    trigger4.test types2.test types.test unique.test update.test
    vacuum.test view.test where.test
  }
  foreach f $F {lappend FILES $testdir/$f}
}

rename sqlite3 real_sqlite3
proc sqlite3 {args} {
  set r [eval "real_sqlite3 $args"]
  if { [llength $args] == 2 } {
    [lindex $args 0] eval {pragma encoding = 'UTF-16'}
  }
  set r
}

rename do_test really_do_test
proc do_test {args} {
  set sc [concat really_do_test "utf16-[lindex $args 0]" [lrange $args 1 end]]
  eval $sc
}

foreach f $FILES {
  source $f
  catch {db close}
  if {$sqlite_open_file_count>0} {
    puts "$tail did not close all files: $sqlite_open_file_count"
    incr nErr
    lappend ::failList $tail
  }
}

rename sqlite3 ""
rename real_sqlite3 sqlite3
rename finish_test ""
rename really_finish_test2 finish_test
rename do_test ""
rename really_do_test do_test
finish_test


--- NEW FILE: vacuum.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the VACUUM statement.
#
# $Id: vacuum.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set fcnt 1
proc cksum {{db db}} {
  set sql "SELECT name, type, sql FROM sqlite_master ORDER BY name, type"
  set txt [$db eval $sql]\n
  set sql "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
  foreach tbl [$db eval $sql] {
    append txt [$db eval "SELECT * FROM $tbl"]\n
  }
  foreach prag {default_cache_size} {
    append txt $prag-[$db eval "PRAGMA $prag"]\n
  }
  if 1 {
    global fcnt
    set fd [open dump$fcnt.txt w]
    puts -nonewline $fd $txt
    close $fd
    incr fcnt
  }
  set cksum [string length $txt]-[md5 $txt]
  # puts $cksum-[file size test.db]
  return $cksum
}
do_test vacuum-1.1 {
  execsql {
    BEGIN;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
    INSERT INTO t1 VALUES(NULL,randstr(10,100),randstr(5,50));
    INSERT INTO t1 VALUES(123456,randstr(10,100),randstr(5,50));
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
    CREATE INDEX i1 ON t1(b,c);
    CREATE UNIQUE INDEX i2 ON t1(c,a);
    CREATE TABLE t2 AS SELECT * FROM t1;
    COMMIT;
    DROP TABLE t2;
  }
  set ::size1 [file size test.db]
  set ::cksum [cksum]
  expr {$::cksum!=""}
} {1}
do_test vacuum-1.2 {
  execsql {
    VACUUM;
  }
  cksum
} $cksum
do_test vacuum-1.3 {
  expr {[file size test.db]<$::size1}
} {1}
do_test vacuum-1.4 {
  execsql {
    BEGIN;
    CREATE TABLE t2 AS SELECT * FROM t1;
    CREATE TABLE t3 AS SELECT * FROM t1;
    CREATE VIEW v1 AS SELECT b, c FROM t3;
    CREATE TRIGGER r1 AFTER DELETE ON t2 BEGIN
      SELECT 1;
    END;
    COMMIT;
    DROP TABLE t2;
  }
  set ::size1 [file size test.db]
  set ::cksum [cksum]
  expr {$::cksum!=""}
} {1}
do_test vacuum-1.5 {
  execsql {
    VACUUM;
  }
  cksum
} $cksum
do_test vacuum-1.6 {
  expr {[file size test.db]<$::size1}
} {1}

do_test vacuum-2.1 {
  catchsql {
    BEGIN;
    VACUUM;
    COMMIT;
  }
} {1 {cannot VACUUM from within a transaction}}
catch {db eval COMMIT}
do_test vacuum-2.2 {
  sqlite3 db2 test.db
  execsql {
    BEGIN;
    CREATE TABLE t4 AS SELECT * FROM t1;
    CREATE TABLE t5 AS SELECT * FROM t1;
    COMMIT;
    DROP TABLE t4;
    DROP TABLE t5;
  } db2
  set ::cksum [cksum db2]
  catchsql {
    VACUUM
  }
} {0 {}}
do_test vacuum-2.3 {
  cksum
} $cksum
do_test vacuum-2.4 {
  catch {db2 eval {SELECT count(*) FROM sqlite_master}}
  cksum db2
} $cksum

# Ticket #427.  Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS
# pragma is turned on.
#
do_test vacuum-3.1 {
  db close
  db2 close
  file delete test.db
  sqlite3 db test.db
  execsql {
    PRAGMA empty_result_callbacks=on;
    VACUUM;
  }
} {}

# Ticket #464.  Make sure VACUUM works with the sqlite3_prepare() API.
#
do_test vacuum-4.1 {
  db close
  set DB [sqlite3 db test.db]
  set VM [sqlite3_prepare $DB {VACUUM} -1 TAIL]
  sqlite3_step $VM
} {SQLITE_DONE}
do_test vacuum-4.2 {
  sqlite3_finalize $VM
} SQLITE_OK

# Ticket #515.  VACUUM after deleting and recreating the table that
# a view refers to.
#
do_test vacuum-5.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  catchsql {
    CREATE TABLE Test (TestID int primary key);
    INSERT INTO Test VALUES (NULL);
    CREATE VIEW viewTest AS SELECT * FROM Test;

    BEGIN;
    CREATE TEMP TABLE tempTest (TestID int primary key, Test2 int NULL);
    INSERT INTO tempTest SELECT TestID, 1 FROM Test;
    DROP TABLE Test;
    CREATE TABLE Test(TestID int primary key, Test2 int NULL);
    INSERT INTO Test SELECT * FROM tempTest;
    COMMIT;
    VACUUM;
  }
} {0 {}}
do_test vacuum-5.2 {
  catchsql {
    VACUUM;
  }
} {0 {}}

# Ensure vacuum works with complicated tables names.
do_test vacuum-6.1 {
  execsql {
    CREATE TABLE "abc abc"(a, b, c);
    INSERT INTO "abc abc" VALUES(1, 2, 3);
    VACUUM;
  }
} {}
do_test vacuum-6.2 {
  execsql {
    select * from "abc abc";
  }
} {1 2 3}

# Also ensure that blobs survive a vacuum.
do_test vacuum-6.3 {
  execsql {
    DELETE FROM "abc abc";
    INSERT INTO "abc abc" VALUES(X'00112233', NULL, NULL);
    VACUUM;
  }
} {}
do_test vacuum-6.4 {
  execsql {
    select count(*) from "abc abc" WHERE a = X'00112233';
  }
} {1}

# Check what happens when an in-memory database is vacuumed.
do_test vacuum-7.0 {
  sqlite3 db2 :memory:
  execsql {
    CREATE TABLE t1(t);
    VACUUM;
  } db2
} {}
db2 close

# Ticket #873.  VACUUM a database that has ' in its name.
#
do_test vacuum-8.1 {
  file delete -force a'z.db
  file delete -force a'z.db-journal
  sqlite3 db2 a'z.db
  execsql {
    CREATE TABLE t1(t);
    VACUUM;
  } db2
} {}
db2 close

# finish_test

--- NEW FILE: varint.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is variable-length integer encoding scheme.
#
# $Id: varint.test,v 1.1 2004/11/15 14:42:04 anthm Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Test reading and writing of varints.
#
set cnt 0
foreach start {0 100 10000 1000000 0x10000000} {
  foreach mult {1 0x10 0x100 0x1000 0x10000 0x100000 0x1000000 0x10000000} {
    foreach incr {1 500 10000 50000000} {
      incr cnt
      do_test varint-1.$cnt {
        btree_varint_test $start $mult 5000 $incr
      } {}
    }
  }
}

--- NEW FILE: view.test ---
# 2002 February 26
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing VIEW statements.
#
# $Id: view.test,v 1.1 2004/11/15 14:42:04 anthm Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test view-1.0 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 VALUES(4,5,6);
    INSERT INTO t1 VALUES(7,8,9);
    SELECT * FROM t1;
  }
} {1 2 3 4 5 6 7 8 9}

do_test view-1.1 {
  execsql {
    BEGIN;
    CREATE VIEW v1 AS SELECT a,b FROM t1;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 2 4 5 7 8}
do_test view-1.2 {
  catchsql {
    ROLLBACK;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 {no such table: v1}}
do_test view-1.3 {
  execsql {
    CREATE VIEW v1 AS SELECT a,b FROM t1;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 2 4 5 7 8}
do_test view-1.3.1 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM v1 ORDER BY a;
  }
} {1 2 4 5 7 8}
do_test view-1.4 {
  catchsql {
    DROP VIEW v1;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 {no such table: v1}}
do_test view-1.5 {
  execsql {
    CREATE VIEW v1 AS SELECT a,b FROM t1;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 2 4 5 7 8}
do_test view-1.6 {
  catchsql {
    DROP TABLE t1;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 {no such table: main.t1}}
do_test view-1.7 {
  execsql {
    CREATE TABLE t1(x,a,b,c);
    INSERT INTO t1 VALUES(1,2,3,4);
    INSERT INTO t1 VALUES(4,5,6,7);
    INSERT INTO t1 VALUES(7,8,9,10);
    SELECT * FROM v1 ORDER BY a;
  }
} {2 3 5 6 8 9}
do_test view-1.8 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM v1 ORDER BY a;
  }
} {2 3 5 6 8 9}

do_test view-2.1 {
  execsql {
    CREATE VIEW v2 AS SELECT * FROM t1 WHERE a>5
  };  # No semicolon
  execsql2 {
    SELECT * FROM v2;
  }
} {x 7 a 8 b 9 c 10}
do_test view-2.2 {
  catchsql {
    INSERT INTO v2 VALUES(1,2,3,4);
  }
} {1 {cannot modify v2 because it is a view}}
do_test view-2.3 {
  catchsql {
    UPDATE v2 SET a=10 WHERE a=5;
  }
} {1 {cannot modify v2 because it is a view}}
do_test view-2.4 {
  catchsql {
    DELETE FROM v2;
  }
} {1 {cannot modify v2 because it is a view}}
do_test view-2.5 {
  execsql {
    INSERT INTO t1 VALUES(11,12,13,14);
    SELECT * FROM v2 ORDER BY x;
  }
} {7 8 9 10 11 12 13 14}
do_test view-2.6 {
  execsql {
    SELECT x FROM v2 WHERE a>10
  }
} {11}

# Test that column name of views are generated correctly.
#
do_test view-3.1 {
  execsql2 {
    SELECT * FROM v1 LIMIT 1
  }
} {a 2 b 3}
do_test view-3.2 {
  execsql2 {
    SELECT * FROM v2 LIMIT 1
  }
} {x 7 a 8 b 9 c 10}
do_test view-3.3 {
  execsql2 {
    DROP VIEW v1;
    CREATE VIEW v1 AS SELECT a AS 'xyz', b+c AS 'pqr', c-b FROM t1;
    SELECT * FROM v1 LIMIT 1
  }
} {xyz 2 pqr 7 c-b 1}
do_test  view-3.4 {
  execsql2 {
    CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY b;
    SELECT * FROM v3 LIMIT 4;
  }
} {b 2 b 3 b 5 b 6}
do_test  view-3.5 {
  execsql2 {
    CREATE VIEW v4 AS 
      SELECT a, b FROM t1 
      UNION
      SELECT b AS 'x', a AS 'y' FROM t1
      ORDER BY x, y;
    SELECT y FROM v4 ORDER BY y LIMIT 4;
  }
} {y 2 y 3 y 5 y 6}


do_test view-4.1 {
  catchsql {
    DROP VIEW t1;
  }
} {1 {use DROP TABLE to delete table t1}}
do_test view-4.2 {
  execsql {
    SELECT 1 FROM t1 LIMIT 1;
  }
} 1
do_test view-4.3 {
  catchsql {
    DROP TABLE v1;
  }
} {1 {use DROP VIEW to delete view v1}}
do_test view-4.4 {
  execsql {
     SELECT 1 FROM v1 LIMIT 1;
  }
} {1}
do_test view-4.5 {
  catchsql {
    CREATE INDEX i1v1 ON v1(xyz);
  }
} {1 {views may not be indexed}}

do_test view-5.1 {
  execsql {
    CREATE TABLE t2(y,a);
    INSERT INTO t2 VALUES(22,2);
    INSERT INTO t2 VALUES(33,3);
    INSERT INTO t2 VALUES(44,4);
    INSERT INTO t2 VALUES(55,5);
    SELECT * FROM t2;
  }
} {22 2 33 3 44 4 55 5}
do_test view-5.2 {
  execsql {
    CREATE VIEW v5 AS
      SELECT t1.x AS v, t2.y AS w FROM t1 JOIN t2 USING(a);
    SELECT * FROM v5;
  }
} {1 22 4 55}

# Verify that the view v5 gets flattened.  see sqliteFlattenSubquery().
# Ticket #272
do_test view-5.3 {
  lsearch [execsql {
    EXPLAIN SELECT * FROM v5;
  }] OpenTemp
} {-1}
do_test view-5.4 {
  execsql {
    SELECT * FROM v5 AS a, t2 AS b WHERE a.w=b.y;
  }
} {1 22 22 2 4 55 55 5}
do_test view-5.5 {
  lsearch [execsql {
    EXPLAIN SELECT * FROM v5 AS a, t2 AS b WHERE a.w=b.y;
  }] OpenTemp
} {-1}
do_test view-5.6 {
  execsql {
    SELECT * FROM t2 AS b, v5 AS a WHERE a.w=b.y;
  }
} {22 2 1 22 55 5 4 55}
do_test view-5.7 {
  lsearch [execsql {
    EXPLAIN SELECT * FROM t2 AS b, v5 AS a WHERE a.w=b.y;
  }] OpenTemp
} {-1}
do_test view-5.8 {
  execsql {
    SELECT * FROM t1 AS a, v5 AS b, t2 AS c WHERE a.x=b.v AND b.w=c.y;
  }
} {1 2 3 4 1 22 22 2 4 5 6 7 4 55 55 5}
do_test view-5.9 {
  lsearch [execsql {
    EXPLAIN SELECT * FROM t1 AS a, v5 AS b, t2 AS c WHERE a.x=b.v AND b.w=c.y;
  }] OpenTemp
} {-1}

do_test view-6.1 {
  execsql {
    SELECT min(x), min(a), min(b), min(c), min(a+b+c) FROM v2;
  }
} {7 8 9 10 27}
do_test view-6.2 {
  execsql {
    SELECT max(x), max(a), max(b), max(c), max(a+b+c) FROM v2;
  }
} {11 12 13 14 39}

do_test view-7.1 {
  execsql {
    CREATE TABLE test1(id integer primary key, a);
    CREATE TABLE test2(id integer, b);
    INSERT INTO test1 VALUES(1,2);
    INSERT INTO test2 VALUES(1,3);
    CREATE VIEW test AS
      SELECT test1.id, a, b
      FROM test1 JOIN test2 ON test2.id=test1.id;
    SELECT * FROM test;
  }
} {1 2 3}
do_test view-7.2 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM test;
  }
} {1 2 3}
do_test view-7.3 {
  execsql {
    DROP VIEW test;
    CREATE VIEW test AS
      SELECT test1.id, a, b
      FROM test1 JOIN test2 USING(id);
    SELECT * FROM test;
  }
} {1 2 3}
do_test view-7.4 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM test;
  }
} {1 2 3}
do_test view-7.5 {
  execsql {
    DROP VIEW test;
    CREATE VIEW test AS
      SELECT test1.id, a, b
      FROM test1 NATURAL JOIN test2;
    SELECT * FROM test;
  }
} {1 2 3}
do_test view-7.6 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM test;
  }
} {1 2 3}

do_test view-8.1 {
  execsql {
    CREATE VIEW v6 AS SELECT pqr, xyz FROM v1;
    SELECT * FROM v6 ORDER BY xyz;
  }
} {7 2 13 5 19 8 27 12}
do_test view-8.2 {
  db close
  sqlite3 db test.db
  execsql {
    SELECT * FROM v6 ORDER BY xyz;
  }
} {7 2 13 5 19 8 27 12}
do_test view-8.3 {
  execsql {
    CREATE VIEW v7 AS SELECT pqr+xyz AS a FROM v6;
    SELECT * FROM v7 ORDER BY a;
  }
} {9 18 27 39}
do_test view-8.4 {
  execsql {
    CREATE VIEW v8 AS SELECT max(cnt) AS mx FROM
      (SELECT a%2 AS eo, count(*) AS cnt FROM t1 GROUP BY eo);
    SELECT * FROM v8;
  }
} 3
do_test view-8.5 {
  execsql {
    SELECT mx+10, mx*2 FROM v8;
  }
} {13 6}
do_test view-8.6 {
  execsql {
    SELECT mx+10, pqr FROM v6, v8 WHERE xyz=2;
  }
} {13 7}
do_test view-8.7 {
  execsql {
    SELECT mx+10, pqr FROM v6, v8 WHERE xyz>2;
  }
} {13 13 13 19 13 27}

# Tests for a bug found by Michiel de Wit involving ORDER BY in a VIEW.
#
do_test view-9.1 {
  execsql {
    INSERT INTO t2 SELECT * FROM t2 WHERE a<5;
    INSERT INTO t2 SELECT * FROM t2 WHERE a<4;
    INSERT INTO t2 SELECT * FROM t2 WHERE a<3;
    SELECT DISTINCT count(*) FROM t2 GROUP BY a ORDER BY 1;
  }
} {1 2 4 8}
do_test view-9.2 {
  execsql {
    SELECT DISTINCT count(*) FROM t2 GROUP BY a ORDER BY 1 LIMIT 3;
  }
} {1 2 4}
do_test view-9.3 {
  execsql {
    CREATE VIEW v9 AS 
       SELECT DISTINCT count(*) FROM t2 GROUP BY a ORDER BY 1 LIMIT 3;
    SELECT * FROM v9;
  }
} {1 2 4}
do_test view-9.4 {
  execsql {
    SELECT * FROM v9 ORDER BY 1 DESC;
  }
} {4 2 1}
do_test view-9.5 {
  execsql {
    CREATE VIEW v10 AS 
       SELECT DISTINCT a, count(*) FROM t2 GROUP BY a ORDER BY 2 LIMIT 3;
    SELECT * FROM v10;
  }
} {5 1 4 2 3 4}
do_test view-9.6 {
  execsql {
    SELECT * FROM v10 ORDER BY 1;
  }
} {3 4 4 2 5 1}

# Tables with columns having peculiar quoted names used in views
# Ticket #756.
#
do_test view-10.1 {
  execsql {
    CREATE TABLE t3("9" integer, [4] text);
    INSERT INTO t3 VALUES(1,2);
    CREATE VIEW v_t3_a AS SELECT a.[9] FROM t3 AS a;
    CREATE VIEW v_t3_b AS SELECT "4" FROM t3;
    SELECT * FROM v_t3_a;
  }
} {1}
do_test view-10.2 {
  execsql {
    SELECT * FROM v_t3_b;
  }
} {2}

finish_test

--- NEW FILE: where.test ---
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clases.
#
# $Id: where.test,v 1.1 2004/11/15 14:42:04 anthm Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where-1.0 {
  execsql {
    CREATE TABLE t1(w int, x int, y int);
    CREATE TABLE t2(p int, q int, r int, s int);
  }
  for {set i 1} {$i<=100} {incr i} {
    set w $i
    set x [expr {int(log($i)/log(2))}]
    set y [expr {$i*$i + 2*$i + 1}]
    execsql "INSERT INTO t1 VALUES($w,$x,$y)"
  }
  execsql {
    INSERT INTO t2 SELECT 101-w, x, (SELECT max(y) FROM t1)+1-y, y FROM t1;
    CREATE INDEX i1w ON t1(w);
    CREATE INDEX i1xy ON t1(x,y);
    CREATE INDEX i2p ON t2(p);
    CREATE INDEX i2r ON t2(r);
    CREATE INDEX i2qs ON t2(q, s);
  }
} {}

# Do an SQL statement.  Append the search count to the end of the result.
#
proc count sql {
  set ::sqlite_search_count 0
  return [concat [execsql $sql] $::sqlite_search_count]
}

# Verify that queries use an index.  We are using the special variable
# "sqlite_search_count" which tallys the number of executions of MoveTo
# and Next operators in the VDBE.  By verifing that the search count is
# small we can be assured that indices are being used properly.
#
do_test where-1.1 {
  count {SELECT x, y FROM t1 WHERE w=10}
} {3 121 3}
do_test where-1.2 {
  count {SELECT x, y FROM t1 WHERE w=11}
} {3 144 3}
do_test where-1.3 {
  count {SELECT x, y FROM t1 WHERE 11=w}
} {3 144 3}
do_test where-1.4 {
  count {SELECT x, y FROM t1 WHERE 11=w AND x>2}
} {3 144 3}
do_test where-1.5 {
  count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
} {3 144 3}
do_test where-1.6 {
  count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
} {3 144 3}
do_test where-1.7 {
  count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2}
} {3 144 3}
do_test where-1.8 {
  count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
} {3 144 3}
do_test where-1.9 {
  count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}
do_test where-1.10 {
  count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
} {3 121 3}
do_test where-1.11 {
  count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10}
} {3 100 3}

# New for SQLite version 2.1: Verify that that inequality constraints
# are used correctly.
#
do_test where-1.12 {
  count {SELECT w FROM t1 WHERE x=3 AND y<100}
} {8 3}
do_test where-1.13 {
  count {SELECT w FROM t1 WHERE x=3 AND 100>y}
} {8 3}
do_test where-1.14 {
  count {SELECT w FROM t1 WHERE 3=x AND y<100}
} {8 3}
do_test where-1.15 {
  count {SELECT w FROM t1 WHERE 3=x AND 100>y}
} {8 3}
do_test where-1.16 {
  count {SELECT w FROM t1 WHERE x=3 AND y<=100}
} {8 9 5}
do_test where-1.17 {
  count {SELECT w FROM t1 WHERE x=3 AND 100>=y}
} {8 9 5}
do_test where-1.18 {
  count {SELECT w FROM t1 WHERE x=3 AND y>225}
} {15 3}
do_test where-1.19 {
  count {SELECT w FROM t1 WHERE x=3 AND 225<y}
} {15 3}
do_test where-1.20 {
  count {SELECT w FROM t1 WHERE x=3 AND y>=225}
} {14 15 5}
do_test where-1.21 {
  count {SELECT w FROM t1 WHERE x=3 AND 225<=y}
} {14 15 5}
do_test where-1.22 {
  count {SELECT w FROM t1 WHERE x=3 AND y>121 AND y<196}
} {11 12 5}
do_test where-1.23 {
  count {SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196}
} {10 11 12 13 9}
do_test where-1.24 {
  count {SELECT w FROM t1 WHERE x=3 AND 121<y AND 196>y}
} {11 12 5}
do_test where-1.25 {
  count {SELECT w FROM t1 WHERE x=3 AND 121<=y AND 196>=y}
} {10 11 12 13 9}

# Need to work on optimizing the BETWEEN operator.  
#
# do_test where-1.26 {
#   count {SELECT w FROM t1 WHERE x=3 AND y BETWEEN 121 AND 196}
# } {10 11 12 13 9}

do_test where-1.27 {
  count {SELECT w FROM t1 WHERE x=3 AND y+1==122}
} {10 17}

do_test where-1.28 {
  count {SELECT w FROM t1 WHERE x+1=4 AND y+1==122}
} {10 99}
do_test where-1.29 {
  count {SELECT w FROM t1 WHERE y==121}
} {10 99}


do_test where-1.30 {
  count {SELECT w FROM t1 WHERE w>97}
} {98 99 100 6}
do_test where-1.31 {
  count {SELECT w FROM t1 WHERE w>=97}
} {97 98 99 100 8}
do_test where-1.33 {
  count {SELECT w FROM t1 WHERE w==97}
} {97 3}
do_test where-1.34 {
  count {SELECT w FROM t1 WHERE w+1==98}
} {97 99}
do_test where-1.35 {
  count {SELECT w FROM t1 WHERE w<3}
} {1 2 4}
do_test where-1.36 {
  count {SELECT w FROM t1 WHERE w<=3}
} {1 2 3 6}
do_test where-1.37 {
  count {SELECT w FROM t1 WHERE w+1<=4 ORDER BY w}
} {1 2 3 199}

do_test where-1.38 {
  count {SELECT (w) FROM t1 WHERE (w)>(97)}
} {98 99 100 6}
do_test where-1.39 {
  count {SELECT (w) FROM t1 WHERE (w)>=(97)}
} {97 98 99 100 8}
do_test where-1.40 {
  count {SELECT (w) FROM t1 WHERE (w)==(97)}
} {97 3}
do_test where-1.41 {
  count {SELECT (w) FROM t1 WHERE ((w)+(1))==(98)}
} {97 99}


# Do the same kind of thing except use a join as the data source.
#
do_test where-2.1 {
  count {
    SELECT w, p FROM t2, t1
    WHERE x=q AND y=s AND r=8977
  }
} {34 67 6}
do_test where-2.2 {
  count {
    SELECT w, p FROM t2, t1
    WHERE x=q AND s=y AND r=8977
  }
} {34 67 6}
do_test where-2.3 {
  count {
    SELECT w, p FROM t2, t1
    WHERE x=q AND s=y AND r=8977 AND w>10
  }
} {34 67 6}
do_test where-2.4 {
  count {
    SELECT w, p FROM t2, t1
    WHERE p<80 AND x=q AND s=y AND r=8977 AND w>10
  }
} {34 67 6}
do_test where-2.5 {
  count {
    SELECT w, p FROM t2, t1
    WHERE p<80 AND x=q AND 8977=r AND s=y AND w>10
  }
} {34 67 6}
do_test where-2.6 {
  count {
    SELECT w, p FROM t2, t1
    WHERE x=q AND p=77 AND s=y AND w>5
  }
} {24 77 6}
do_test where-2.7 {
  count {
    SELECT w, p FROM t1, t2
    WHERE x=q AND p>77 AND s=y AND w=5
  }
} {5 96 6}

# Lets do a 3-way join.
#
do_test where-3.1 {
  count {
    SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
    WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=11
  }
} {11 90 11 9}
do_test where-3.2 {
  count {
    SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
    WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=12
  }
} {12 89 12 9}
do_test where-3.3 {
  count {
    SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
    WHERE A.w=15 AND B.p=C.w AND B.r=10202-A.y
  }
} {15 86 86 9}

# Test to see that the special case of a constant WHERE clause is
# handled.
#
do_test where-4.1 {
  count {
    SELECT * FROM t1 WHERE 0
  }
} {0}
do_test where-4.2 {
  count {
    SELECT * FROM t1 WHERE 1 LIMIT 1
  }
} {1 0 4 1}
do_test where-4.3 {
  execsql {
    SELECT 99 WHERE 0
  }
} {}
do_test where-4.4 {
  execsql {
    SELECT 99 WHERE 1
  }
} {99}

# Verify that IN operators in a WHERE clause are handled correctly.
#
do_test where-5.1 {
  count {
    SELECT * FROM t1 WHERE rowid IN (1,2,3,1234) order by 1;
  }
} {1 0 4 2 1 9 3 1 16 3}
do_test where-5.2 {
  count {
    SELECT * FROM t1 WHERE rowid+0 IN (1,2,3,1234) order by 1;
  }
} {1 0 4 2 1 9 3 1 16 199}
do_test where-5.3 {
  count {
    SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1;
  }
} {1 0 4 2 1 9 3 1 16 13}
do_test where-5.4 {
  count {
    SELECT * FROM t1 WHERE w+0 IN (-1,1,2,3) order by 1;
  }
} {1 0 4 2 1 9 3 1 16 199}
do_test where-5.5 {
  count {
    SELECT * FROM t1 WHERE rowid IN 
       (select rowid from t1 where rowid IN (-1,2,4))
    ORDER BY 1;
  }
} {2 1 9 4 2 25 3}
do_test where-5.6 {
  count {
    SELECT * FROM t1 WHERE rowid+0 IN 
       (select rowid from t1 where rowid IN (-1,2,4))
    ORDER BY 1;
  }
} {2 1 9 4 2 25 201}
do_test where-5.7 {
  count {
    SELECT * FROM t1 WHERE w IN 
       (select rowid from t1 where rowid IN (-1,2,4))
    ORDER BY 1;
  }
} {2 1 9 4 2 25 9}
do_test where-5.8 {
  count {
    SELECT * FROM t1 WHERE w+0 IN 
       (select rowid from t1 where rowid IN (-1,2,4))
    ORDER BY 1;
  }
} {2 1 9 4 2 25 201}
do_test where-5.9 {
  count {
    SELECT * FROM t1 WHERE x IN (1,7) ORDER BY 1;
  }
} {2 1 9 3 1 16 7}
do_test where-5.10 {
  count {
    SELECT * FROM t1 WHERE x+0 IN (1,7) ORDER BY 1;
  }
} {2 1 9 3 1 16 199}
do_test where-5.11 {
  count {
    SELECT * FROM t1 WHERE y IN (6400,8100) ORDER BY 1;
  }
} {79 6 6400 89 6 8100 199}
do_test where-5.12 {
  count {
    SELECT * FROM t1 WHERE x=6 AND y IN (6400,8100) ORDER BY 1;
  }
} {79 6 6400 89 6 8100 74}
do_test where-5.13 {
  count {
    SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1;
  }
} {2 1 9 3 1 16 7}
do_test where-5.14 {
  count {
    SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
  }
} {2 1 9 7}

# This procedure executes the SQL.  Then it checks the generated program
# for the SQL and appends a "nosort" to the result if the program contains the
# SortCallback opcode.  If the program does not contain the SortCallback
# opcode it appends "sort"
#
proc cksort {sql} {
  set data [execsql $sql]
  set prog [execsql "EXPLAIN $sql"]
  if {[regexp Sort $prog]} {set x sort} {set x nosort}
  lappend data $x
  return $data
}
# Check out the logic that attempts to implement the ORDER BY clause
# using an index rather than by sorting.
#
do_test where-6.1 {
  execsql {
    CREATE TABLE t3(a,b,c);
    CREATE INDEX t3a ON t3(a);
    CREATE INDEX t3bc ON t3(b,c);
    CREATE INDEX t3acb ON t3(a,c,b);
    INSERT INTO t3 SELECT w, 101-w, y FROM t1;
    SELECT count(*), sum(a), sum(b), sum(c) FROM t3;
  }
} {100 5050.0 5050.0 348550.0}
do_test where-6.2 {
  cksort {
    SELECT * FROM t3 ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 nosort}
do_test where-6.3 {
  cksort {
    SELECT * FROM t3 ORDER BY a+1 LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 sort}
do_test where-6.4 {
  cksort {
    SELECT * FROM t3 WHERE a<10 ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 nosort}
do_test where-6.5 {
  cksort {
    SELECT * FROM t3 WHERE a>0 AND a<10 ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 nosort}
do_test where-6.6 {
  cksort {
    SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 nosort}
do_test where-6.7 {
  cksort {
    SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 sort}
do_test where-6.8 {
  cksort {
    SELECT * FROM t3 WHERE a IN (3,5,7,1,9,4,2) ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 sort}
do_test where-6.9.1 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.9.2 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.9.3 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY c LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.9.4 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a DESC LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.9.5 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a DESC, c DESC LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.9.6 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY c DESC LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.9.7 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY c,a LIMIT 3
  }
} {1 100 4 sort}
do_test where-6.9.8 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a DESC, c ASC LIMIT 3
  }
} {1 100 4 sort}
do_test where-6.9.9 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a ASC, c DESC LIMIT 3
  }
} {1 100 4 sort}
do_test where-6.10 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.11 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.12 {
  cksort {
    SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c,b LIMIT 3
  }
} {1 100 4 nosort}
do_test where-6.13 {
  cksort {
    SELECT * FROM t3 WHERE a>0 ORDER BY a DESC LIMIT 3
  }
} {100 1 10201 99 2 10000 98 3 9801 nosort}
do_test where-6.13.1 {
  cksort {
    SELECT * FROM t3 WHERE a>0 ORDER BY -a LIMIT 3
  }
} {100 1 10201 99 2 10000 98 3 9801 sort}
do_test where-6.14 {
  cksort {
    SELECT * FROM t3 ORDER BY b LIMIT 3
  }
} {100 1 10201 99 2 10000 98 3 9801 nosort}
do_test where-6.15 {
  cksort {
    SELECT t3.a, t1.x FROM t3, t1 WHERE t3.a=t1.w ORDER BY t3.a LIMIT 3
  }
} {1 0 2 1 3 1 nosort}
do_test where-6.16 {
  cksort {
    SELECT t3.a, t1.x FROM t3, t1 WHERE t3.a=t1.w ORDER BY t1.x, t3.a LIMIT 3
  }
} {1 0 2 1 3 1 sort}
#### Version 3 does not work this way:
#do_test where-6.17 {
#  cksort {
#    SELECT y FROM t1 ORDER BY w COLLATE text LIMIT 3;
#  }
#} {4 121 10201 sort}
#do_test where-6.18 {
#  cksort {
#    SELECT y FROM t1 ORDER BY w COLLATE numeric LIMIT 3;
#  }
#} {4 9 16 sort}
do_test where-6.19 {
  cksort {
    SELECT y FROM t1 ORDER BY w LIMIT 3;
  }
} {4 9 16 nosort}

# Tests for reverse-order sorting.
#
do_test where-7.1 {
  cksort {
    SELECT w FROM t1 WHERE x=3 ORDER BY y;
  }
} {8 9 10 11 12 13 14 15 nosort}
do_test where-7.2 {
  cksort {
    SELECT w FROM t1 WHERE x=3 ORDER BY y DESC;
  }
} {15 14 13 12 11 10 9 8 nosort}
do_test where-7.3 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>100 ORDER BY y LIMIT 3;
  }
} {10 11 12 nosort}
do_test where-7.4 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>100 ORDER BY y DESC LIMIT 3;
  }
} {15 14 13 nosort}
do_test where-7.5 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>121 ORDER BY y DESC;
  }
} {15 14 13 12 11 nosort}
do_test where-7.6 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=121 ORDER BY y DESC;
  }
} {15 14 13 12 11 10 nosort}
do_test where-7.7 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<196 ORDER BY y DESC;
  }
} {12 11 10 nosort}
do_test where-7.8 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196 ORDER BY y DESC;
  }
} {13 12 11 10 nosort}
do_test where-7.9 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>121 AND y<=196 ORDER BY y DESC;
  }
} {13 12 11 nosort}
do_test where-7.10 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>100 AND y<196 ORDER BY y DESC;
  }
} {12 11 10 nosort}
do_test where-7.11 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<196 ORDER BY y;
  }
} {10 11 12 nosort}
do_test where-7.12 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196 ORDER BY y;
  }
} {10 11 12 13 nosort}
do_test where-7.13 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>121 AND y<=196 ORDER BY y;
  }
} {11 12 13 nosort}
do_test where-7.14 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>100 AND y<196 ORDER BY y;
  }
} {10 11 12 nosort}
do_test where-7.15 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y<81 ORDER BY y;
  }
} {nosort}
do_test where-7.16 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y<=81 ORDER BY y;
  }
} {8 nosort}
do_test where-7.17 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>256 ORDER BY y;
  }
} {nosort}
do_test where-7.18 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=256 ORDER BY y;
  }
} {15 nosort}
do_test where-7.19 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y<81 ORDER BY y DESC;
  }
} {nosort}
do_test where-7.20 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y<=81 ORDER BY y DESC;
  }
} {8 nosort}
do_test where-7.21 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>256 ORDER BY y DESC;
  }
} {nosort}
do_test where-7.22 {
  cksort {
    SELECT w FROM t1 WHERE x=3 AND y>=256 ORDER BY y DESC;
  }
} {15 nosort}
do_test where-7.23 {
  cksort {
    SELECT w FROM t1 WHERE x=0 AND y<4 ORDER BY y;
  }
} {nosort}
do_test where-7.24 {
  cksort {
    SELECT w FROM t1 WHERE x=0 AND y<=4 ORDER BY y;
  }
} {1 nosort}
do_test where-7.25 {
  cksort {
    SELECT w FROM t1 WHERE x=6 AND y>10201 ORDER BY y;
  }
} {nosort}
do_test where-7.26 {
  cksort {
    SELECT w FROM t1 WHERE x=6 AND y>=10201 ORDER BY y;
  }
} {100 nosort}
do_test where-7.27 {
  cksort {
    SELECT w FROM t1 WHERE x=0 AND y<4 ORDER BY y DESC;
  }
} {nosort}
do_test where-7.28 {
  cksort {
    SELECT w FROM t1 WHERE x=0 AND y<=4 ORDER BY y DESC;
  }
} {1 nosort}
do_test where-7.29 {
  cksort {
    SELECT w FROM t1 WHERE x=6 AND y>10201 ORDER BY y DESC;
  }
} {nosort}
do_test where-7.30 {
  cksort {
    SELECT w FROM t1 WHERE x=6 AND y>=10201 ORDER BY y DESC;
  }
} {100 nosort}

do_test where-8.1 {
  execsql {
    CREATE TABLE t4 AS SELECT * FROM t1;
    CREATE INDEX i4xy ON t4(x,y);
  }
  cksort {
    SELECT w FROM t4 WHERE x=4 and y<1000 ORDER BY y DESC limit 3;
  }
} {30 29 28 nosort}
do_test where-8.2 {
  execsql {
    DELETE FROM t4;
  }
  cksort {
    SELECT w FROM t4 WHERE x=4 and y<1000 ORDER BY y DESC limit 3;
  }
} {nosort}

# Make sure searches with an index work with an empty table.
#
do_test where-9.1 {
  execsql {
    CREATE TABLE t5(x PRIMARY KEY);
    SELECT * FROM t5 WHERE x<10;
  }
} {}
do_test where-9.2 {
  execsql {
    SELECT * FROM t5 WHERE x<10 ORDER BY x DESC;
  }
} {}
do_test where-9.3 {
  execsql {
    SELECT * FROM t5 WHERE x=10;
  }
} {}

do_test where-10.1 {
  execsql {
    SELECT 1 WHERE abs(random())<0
  }
} {}
do_test where-10.2 {
  proc tclvar_func {vname} {return [set ::$vname]}
  db function tclvar tclvar_func
  set ::v1 0
  execsql {
    SELECT count(*) FROM t1 WHERE tclvar('v1');
  }
} {0}
do_test where-10.3 {
  set ::v1 1
  execsql {
    SELECT count(*) FROM t1 WHERE tclvar('v1');
  }
} {100}
do_test where-10.4 {
  set ::v1 1
  proc tclvar_func {vname} {
    upvar #0 $vname v
    set v [expr {!$v}]
    return $v
  }
  execsql {
    SELECT count(*) FROM t1 WHERE tclvar('v1');
  }
} {50}

integrity_check {where-99.0}

finish_test




More information about the svn-commits mailing list