xref: /sqlite-3.40.0/test/malloc3.test (revision eee4c8ca)
11a485fcaSdanielk1977# 2005 November 30
21a485fcaSdanielk1977#
31a485fcaSdanielk1977# The author disclaims copyright to this source code.  In place of
41a485fcaSdanielk1977# a legal notice, here is a blessing:
51a485fcaSdanielk1977#
61a485fcaSdanielk1977#    May you do good and not evil.
71a485fcaSdanielk1977#    May you find forgiveness for yourself and forgive others.
81a485fcaSdanielk1977#    May you share freely, never taking more than you give.
91a485fcaSdanielk1977#
101a485fcaSdanielk1977#***********************************************************************
111a485fcaSdanielk1977#
1200fd957bSdanielk1977# This file contains tests to ensure that the library handles malloc() failures
1300fd957bSdanielk1977# correctly. The emphasis of these tests are the _prepare(), _step() and
1400fd957bSdanielk1977# _finalize() calls.
1500fd957bSdanielk1977#
16*eee4c8caSdrh# $Id: malloc3.test,v 1.20 2008/02/18 22:24:58 drh Exp $
171a485fcaSdanielk1977
181a485fcaSdanielk1977set testdir [file dirname $argv0]
191a485fcaSdanielk1977source $testdir/tester.tcl
20*eee4c8caSdrhsource $testdir/malloc_common.tcl
211a485fcaSdanielk1977
221a485fcaSdanielk1977# Only run these tests if memory debugging is turned on.
23ed138fb3Sdrh#
24*eee4c8caSdrhif {!$MEMDEBUG} {
255a3032b3Sdrh   puts "Skipping malloc3 tests: not compiled with -DSQLITE_MEMDEBUG..."
261a485fcaSdanielk1977   finish_test
271a485fcaSdanielk1977   return
281a485fcaSdanielk1977}
291a485fcaSdanielk1977
301a485fcaSdanielk1977#--------------------------------------------------------------------------
311a485fcaSdanielk1977# NOTES ON RECOVERING FROM A MALLOC FAILURE
321a485fcaSdanielk1977#
331a485fcaSdanielk1977# The tests in this file test the behaviours described in the following
341a485fcaSdanielk1977# paragraphs. These tests test the behaviour of the system when malloc() fails
351a485fcaSdanielk1977# inside of a call to _prepare(), _step(), _finalize() or _reset(). The
361a485fcaSdanielk1977# handling of malloc() failures within ancillary procedures is tested
371a485fcaSdanielk1977# elsewhere.
381a485fcaSdanielk1977#
391a485fcaSdanielk1977# Overview:
401a485fcaSdanielk1977#
411a485fcaSdanielk1977# Executing a statement is done in three stages (prepare, step and finalize). A
421a485fcaSdanielk1977# malloc() failure may occur within any stage. If a memory allocation fails
431a485fcaSdanielk1977# during statement preparation, no statement handle is returned. From the users
441a485fcaSdanielk1977# point of view the system state is as if _prepare() had never been called.
451a485fcaSdanielk1977#
461a485fcaSdanielk1977# If the memory allocation fails during the _step() or _finalize() calls, then
471a485fcaSdanielk1977# the database may be left in one of two states (after finalize() has been
481a485fcaSdanielk1977# called):
491a485fcaSdanielk1977#
501a485fcaSdanielk1977#     * As if the neither _step() nor _finalize() had ever been called on
511a485fcaSdanielk1977#       the statement handle (i.e. any changes made by the statement are
521a485fcaSdanielk1977#       rolled back).
531a485fcaSdanielk1977#     * The current transaction may be rolled back. In this case a hot-journal
541a485fcaSdanielk1977#       may or may not actually be present in the filesystem.
551a485fcaSdanielk1977#
561a485fcaSdanielk1977# The caller can tell the difference between these two scenarios by invoking
571a485fcaSdanielk1977# _get_autocommit().
581a485fcaSdanielk1977#
591a485fcaSdanielk1977#
601a485fcaSdanielk1977# Handling of sqlite3_reset():
611a485fcaSdanielk1977#
621a485fcaSdanielk1977# If a malloc() fails while executing an sqlite3_reset() call, this is handled
631a485fcaSdanielk1977# in the same way as a failure within _finalize(). The statement handle
641a485fcaSdanielk1977# is not deleted and must be passed to _finalize() for resource deallocation.
651a485fcaSdanielk1977# Attempting to _step() or _reset() the statement after a failed _reset() will
661a485fcaSdanielk1977# always return SQLITE_NOMEM.
671a485fcaSdanielk1977#
681a485fcaSdanielk1977#
691a485fcaSdanielk1977# Other active SQL statements:
701a485fcaSdanielk1977#
711a485fcaSdanielk1977# The effect of a malloc failure on concurrently executing SQL statements,
721a485fcaSdanielk1977# particularly when the statement is executing with READ_UNCOMMITTED set and
731a485fcaSdanielk1977# the malloc() failure mandates statement rollback only. Currently, if
741a485fcaSdanielk1977# transaction rollback is required, all other vdbe's are aborted.
751a485fcaSdanielk1977#
761a485fcaSdanielk1977#     Non-transient mallocs in btree.c:
771a485fcaSdanielk1977#         * The Btree structure itself
781a485fcaSdanielk1977#         * Each BtCursor structure
791a485fcaSdanielk1977#
801a485fcaSdanielk1977#     Mallocs in pager.c:
811a485fcaSdanielk1977#         readMasterJournal()  - Space to read the master journal name
821a485fcaSdanielk1977#         pager_delmaster()    - Space for the entire master journal file
831a485fcaSdanielk1977#
841a485fcaSdanielk1977#         sqlite3pager_open()  - The pager structure itself
851a485fcaSdanielk1977#         sqlite3_pagerget()   - Space for a new page
861a485fcaSdanielk1977#         pager_open_journal() - Pager.aInJournal[] bitmap
871a485fcaSdanielk1977#         sqlite3pager_write() - For in-memory databases only: history page and
881a485fcaSdanielk1977#                                statement history page.
891a485fcaSdanielk1977#         pager_stmt_begin()   - Pager.aInStmt[] bitmap
901a485fcaSdanielk1977#
911a485fcaSdanielk1977# None of the above are a huge problem. The most troublesome failures are the
921a485fcaSdanielk1977# transient malloc() calls in btree.c, which can occur during the tree-balance
931a485fcaSdanielk1977# operation. This means the tree being balanced will be internally inconsistent
941a485fcaSdanielk1977# after the malloc() fails. To avoid the corrupt tree being read by a
951a485fcaSdanielk1977# READ_UNCOMMITTED query, we have to make sure the transaction or statement
961a485fcaSdanielk1977# rollback occurs before sqlite3_step() returns, not during a subsequent
971a485fcaSdanielk1977# sqlite3_finalize().
981a485fcaSdanielk1977#--------------------------------------------------------------------------
991a485fcaSdanielk1977
1001a485fcaSdanielk1977#--------------------------------------------------------------------------
1011a485fcaSdanielk1977# NOTES ON TEST IMPLEMENTATION
1021a485fcaSdanielk1977#
1031a485fcaSdanielk1977# The tests in this file are implemented differently from those in other
1041a485fcaSdanielk1977# files. Instead, tests are specified using three primitives: SQL, PREP and
1051a485fcaSdanielk1977# TEST. Each primitive has a single argument. Primitives are processed in
1061a485fcaSdanielk1977# the order they are specified in the file.
1071a485fcaSdanielk1977#
10885b623f2Sdrh# A TEST primitive specifies a TCL script as its argument. When a TEST
1091a485fcaSdanielk1977# directive is encountered the Tcl script is evaluated. Usually, this Tcl
1101a485fcaSdanielk1977# script contains one or more calls to [do_test].
1111a485fcaSdanielk1977#
11285b623f2Sdrh# A PREP primitive specifies an SQL script as its argument. When a PREP
1131a485fcaSdanielk1977# directive is encountered the SQL is evaluated using database connection
1141a485fcaSdanielk1977# [db].
1151a485fcaSdanielk1977#
1161a485fcaSdanielk1977# The SQL primitives are where the action happens. An SQL primitive must
11785b623f2Sdrh# contain a single, valid SQL statement as its argument. When an SQL
1181a485fcaSdanielk1977# primitive is encountered, it is evaluated one or more times to test the
1191a485fcaSdanielk1977# behaviour of the system when malloc() fails during preparation or
1201a485fcaSdanielk1977# execution of said statement. The Nth time the statement is executed,
1211a485fcaSdanielk1977# the Nth malloc is said to fail. The statement is executed until it
1221a485fcaSdanielk1977# succeeds, i.e. (M+1) times, where M is the number of mallocs() required
1231a485fcaSdanielk1977# to prepare and execute the statement.
1241a485fcaSdanielk1977#
1251a485fcaSdanielk1977# Each time an SQL statement fails, the driver program (see proc [run_test]
1261a485fcaSdanielk1977# below) figures out if a transaction has been automatically rolled back.
1271a485fcaSdanielk1977# If not, it executes any TEST block immediately proceeding the SQL
1281a485fcaSdanielk1977# statement, then reexecutes the SQL statement with the next value of N.
1291a485fcaSdanielk1977#
1301a485fcaSdanielk1977# If a transaction has been automatically rolled back, then the driver
1311a485fcaSdanielk1977# program executes all the SQL specified as part of SQL or PREP primitives
1321a485fcaSdanielk1977# between the current SQL statement and the most recent "BEGIN". Any
1331a485fcaSdanielk1977# TEST block immediately proceeding the SQL statement is evaluated, and
1341a485fcaSdanielk1977# then the SQL statement reexecuted with the incremented N value.
1351a485fcaSdanielk1977#
1361a485fcaSdanielk1977# That make any sense? If not, read the code in [run_test] and it might.
1371a485fcaSdanielk1977#
1381a485fcaSdanielk1977# Extra restriction imposed by the implementation:
1391a485fcaSdanielk1977#
1401a485fcaSdanielk1977# * If a PREP block starts a transaction, it must finish it.
1411a485fcaSdanielk1977# * A PREP block may not close a transaction it did not start.
1421a485fcaSdanielk1977#
1431a485fcaSdanielk1977#--------------------------------------------------------------------------
1441a485fcaSdanielk1977
1451a485fcaSdanielk1977
1461a485fcaSdanielk1977# These procs are used to build up a "program" in global variable
1471a485fcaSdanielk1977# ::run_test_script. At the end of this file, the proc [run_test] is used
1481a485fcaSdanielk1977# to execute the program (and all test cases contained therein).
1491a485fcaSdanielk1977#
150da717982Sdanielk1977set ::run_test_script [list]
1511a485fcaSdanielk1977proc TEST {id t} {lappend ::run_test_script -test [list $id $t]}
1521a485fcaSdanielk1977proc PREP {p} {lappend ::run_test_script -prep [string trim $p]}
15393aed5a1Sdrhproc DEBUG {s} {lappend ::run_test_script -debug $s}
1541a485fcaSdanielk1977
1551a485fcaSdanielk1977# SQL --
1561a485fcaSdanielk1977#
1571a485fcaSdanielk1977#     SQL ?-norollback? <sql-text>
1581a485fcaSdanielk1977#
1591a485fcaSdanielk1977# Add an 'SQL' primitive to the program (see notes above). If the -norollback
1601a485fcaSdanielk1977# switch is present, then the statement is not allowed to automatically roll
1611a485fcaSdanielk1977# back any active transaction if malloc() fails. It must rollback the statement
1621a485fcaSdanielk1977# transaction only.
1631a485fcaSdanielk1977#
1641a485fcaSdanielk1977proc SQL  {a1 {a2 ""}} {
1651a485fcaSdanielk1977  # An SQL primitive parameter is a list of two elements, a boolean value
1661a485fcaSdanielk1977  # indicating if the statement may cause transaction rollback when malloc()
1671a485fcaSdanielk1977  # fails, and the sql statement itself.
1681a485fcaSdanielk1977  if {$a2 == ""} {
1691a485fcaSdanielk1977    lappend ::run_test_script -sql [list true [string trim $a1]]
1701a485fcaSdanielk1977  } else {
1711a485fcaSdanielk1977    lappend ::run_test_script -sql [list false [string trim $a2]]
1721a485fcaSdanielk1977  }
1731a485fcaSdanielk1977}
1741a485fcaSdanielk1977
1751a485fcaSdanielk1977# TEST_AUTOCOMMIT --
1761a485fcaSdanielk1977#
1771a485fcaSdanielk1977#     A shorthand test to see if a transaction is active or not. The first
1781a485fcaSdanielk1977#     argument - $id - is the integer number of the test case. The second
1791a485fcaSdanielk1977#     argument is either 1 or 0, the expected value of the auto-commit flag.
1801a485fcaSdanielk1977#
1811a485fcaSdanielk1977proc TEST_AUTOCOMMIT {id a} {
18237f0d221Sdanielk1977    TEST $id "do_test \$testid { sqlite3_get_autocommit \$::DB } {$a}"
1831a485fcaSdanielk1977}
1841a485fcaSdanielk1977
1851a485fcaSdanielk1977#--------------------------------------------------------------------------
1861a485fcaSdanielk1977# Start of test program declaration
1871a485fcaSdanielk1977#
1881a485fcaSdanielk1977
1891a485fcaSdanielk1977
1901a485fcaSdanielk1977# Warm body test. A malloc() fails in the middle of a CREATE TABLE statement
1911a485fcaSdanielk1977# in a single-statement transaction on an empty database. Not too much can go
1921a485fcaSdanielk1977# wrong here.
1931a485fcaSdanielk1977#
1941a485fcaSdanielk1977TEST 1 {
1951a485fcaSdanielk1977  do_test $testid {
1961a485fcaSdanielk1977    execsql {SELECT tbl_name FROM sqlite_master;}
1971a485fcaSdanielk1977  } {}
1981a485fcaSdanielk1977}
1991a485fcaSdanielk1977SQL {
2001a485fcaSdanielk1977  CREATE TABLE abc(a, b, c);
2011a485fcaSdanielk1977}
2021a485fcaSdanielk1977TEST 2 {
2031a485fcaSdanielk1977  do_test $testid.1 {
2041a485fcaSdanielk1977    execsql {SELECT tbl_name FROM sqlite_master;}
2051a485fcaSdanielk1977  } {abc}
2061a485fcaSdanielk1977}
2071a485fcaSdanielk1977
20885b623f2Sdrh# Insert a couple of rows into the table. each insert is in its own
2091a485fcaSdanielk1977# transaction. test that the table is unpopulated before running the inserts
2101a485fcaSdanielk1977# (and hence after each failure of the first insert), and that it has been
2111a485fcaSdanielk1977# populated correctly after the final insert succeeds.
2121a485fcaSdanielk1977#
2131a485fcaSdanielk1977TEST 3 {
2141a485fcaSdanielk1977  do_test $testid.2 {
2151a485fcaSdanielk1977    execsql {SELECT * FROM abc}
2161a485fcaSdanielk1977  } {}
2171a485fcaSdanielk1977}
2181a485fcaSdanielk1977SQL {INSERT INTO abc VALUES(1, 2, 3);}
2191a485fcaSdanielk1977SQL {INSERT INTO abc VALUES(4, 5, 6);}
2201a485fcaSdanielk1977SQL {INSERT INTO abc VALUES(7, 8, 9);}
2211a485fcaSdanielk1977TEST 4 {
2221a485fcaSdanielk1977  do_test $testid {
2231a485fcaSdanielk1977    execsql {SELECT * FROM abc}
2241a485fcaSdanielk1977  } {1 2 3 4 5 6 7 8 9}
2251a485fcaSdanielk1977}
2261a485fcaSdanielk1977
2271a485fcaSdanielk1977# Test a CREATE INDEX statement. Because the table 'abc' is so small, the index
2281a485fcaSdanielk1977# will all fit on a single page, so this doesn't test too much that the CREATE
2291a485fcaSdanielk1977# TABLE statement didn't test. A few of the transient malloc()s in btree.c
2301a485fcaSdanielk1977# perhaps.
2311a485fcaSdanielk1977#
2321a485fcaSdanielk1977SQL {CREATE INDEX abc_i ON abc(a, b, c);}
2331a485fcaSdanielk1977TEST 4 {
2341a485fcaSdanielk1977  do_test $testid {
2351a485fcaSdanielk1977    execsql {
2361a485fcaSdanielk1977      SELECT * FROM abc ORDER BY a DESC;
2371a485fcaSdanielk1977    }
2381a485fcaSdanielk1977  } {7 8 9 4 5 6 1 2 3}
2391a485fcaSdanielk1977}
2401a485fcaSdanielk1977
2411a485fcaSdanielk1977# Test a DELETE statement. Also create a trigger and a view, just to make sure
2421a485fcaSdanielk1977# these statements don't have any obvious malloc() related bugs in them. Note
2431a485fcaSdanielk1977# that the test above will be executed each time the DELETE fails, so we're
2441a485fcaSdanielk1977# also testing rollback of a DELETE from a table with an index on it.
2451a485fcaSdanielk1977#
2461a485fcaSdanielk1977SQL {DELETE FROM abc WHERE a > 2;}
2471a485fcaSdanielk1977SQL {CREATE TRIGGER abc_t AFTER INSERT ON abc BEGIN SELECT 'trigger!'; END;}
2481a485fcaSdanielk1977SQL {CREATE VIEW abc_v AS SELECT * FROM abc;}
2491a485fcaSdanielk1977TEST 5 {
2501a485fcaSdanielk1977  do_test $testid {
2511a485fcaSdanielk1977    execsql {
2521a485fcaSdanielk1977      SELECT name, tbl_name FROM sqlite_master ORDER BY name;
2531a485fcaSdanielk1977      SELECT * FROM abc;
2541a485fcaSdanielk1977    }
2551a485fcaSdanielk1977  } {abc abc abc_i abc abc_t abc abc_v abc_v 1 2 3}
2561a485fcaSdanielk1977}
2571a485fcaSdanielk1977
2581a485fcaSdanielk1977set sql {
2591a485fcaSdanielk1977  BEGIN;DELETE FROM abc;
2601a485fcaSdanielk1977}
26193aed5a1Sdrhfor {set i 1} {$i < 15} {incr i} {
2621a485fcaSdanielk1977  set a $i
2631a485fcaSdanielk1977  set b "String value $i"
2641a485fcaSdanielk1977  set c [string repeat X $i]
2651a485fcaSdanielk1977  append sql "INSERT INTO abc VALUES ($a, '$b', '$c');"
2661a485fcaSdanielk1977}
2671a485fcaSdanielk1977append sql {COMMIT;}
2681a485fcaSdanielk1977PREP $sql
2691a485fcaSdanielk1977
2701a485fcaSdanielk1977SQL {
2711a485fcaSdanielk1977  DELETE FROM abc WHERE oid IN (SELECT oid FROM abc ORDER BY random() LIMIT 5);
2721a485fcaSdanielk1977}
2731a485fcaSdanielk1977TEST 6 {
2741a485fcaSdanielk1977  do_test $testid.1 {
2751a485fcaSdanielk1977    execsql {SELECT count(*) FROM abc}
2761a485fcaSdanielk1977  } {94}
2771a485fcaSdanielk1977  do_test $testid.2 {
2781a485fcaSdanielk1977    execsql {
2791a485fcaSdanielk1977      SELECT min(
2801a485fcaSdanielk1977          (oid == a) AND 'String value ' || a == b AND a == length(c)
2811a485fcaSdanielk1977      ) FROM abc;
2821a485fcaSdanielk1977    }
2831a485fcaSdanielk1977  } {1}
2841a485fcaSdanielk1977}
2851a485fcaSdanielk1977SQL {
2861a485fcaSdanielk1977  DELETE FROM abc WHERE oid IN (SELECT oid FROM abc ORDER BY random() LIMIT 5);
2871a485fcaSdanielk1977}
2881a485fcaSdanielk1977TEST 7 {
2891a485fcaSdanielk1977  do_test $testid {
2901a485fcaSdanielk1977    execsql {SELECT count(*) FROM abc}
2911a485fcaSdanielk1977  } {89}
2921a485fcaSdanielk1977  do_test $testid {
2931a485fcaSdanielk1977    execsql {
2941a485fcaSdanielk1977      SELECT min(
2951a485fcaSdanielk1977          (oid == a) AND 'String value ' || a == b AND a == length(c)
2961a485fcaSdanielk1977      ) FROM abc;
2971a485fcaSdanielk1977    }
2981a485fcaSdanielk1977  } {1}
2991a485fcaSdanielk1977}
3001a485fcaSdanielk1977SQL {
3011a485fcaSdanielk1977  DELETE FROM abc WHERE oid IN (SELECT oid FROM abc ORDER BY random() LIMIT 5);
3021a485fcaSdanielk1977}
3031a485fcaSdanielk1977TEST 9 {
3041a485fcaSdanielk1977  do_test $testid {
3051a485fcaSdanielk1977    execsql {SELECT count(*) FROM abc}
3061a485fcaSdanielk1977  } {84}
3071a485fcaSdanielk1977  do_test $testid {
3081a485fcaSdanielk1977    execsql {
3091a485fcaSdanielk1977      SELECT min(
3101a485fcaSdanielk1977          (oid == a) AND 'String value ' || a == b AND a == length(c)
3111a485fcaSdanielk1977      ) FROM abc;
3121a485fcaSdanielk1977    }
3131a485fcaSdanielk1977  } {1}
3141a485fcaSdanielk1977}
3151a485fcaSdanielk1977
3161a485fcaSdanielk1977set padding [string repeat X 500]
3171a485fcaSdanielk1977PREP [subst {
3181a485fcaSdanielk1977  DROP TABLE abc;
3191a485fcaSdanielk1977  CREATE TABLE abc(a PRIMARY KEY, padding, b, c);
3201a485fcaSdanielk1977  INSERT INTO abc VALUES(0, '$padding', 2, 2);
3211a485fcaSdanielk1977  INSERT INTO abc VALUES(3, '$padding', 5, 5);
3221a485fcaSdanielk1977  INSERT INTO abc VALUES(6, '$padding', 8, 8);
3231a485fcaSdanielk1977}]
3241a485fcaSdanielk1977
3251a485fcaSdanielk1977TEST 10 {
3261a485fcaSdanielk1977  do_test $testid {
3271a485fcaSdanielk1977    execsql {SELECT a, b, c FROM abc}
3281a485fcaSdanielk1977  } {0 2 2 3 5 5 6 8 8}
3291a485fcaSdanielk1977}
3301a485fcaSdanielk1977
3311a485fcaSdanielk1977SQL {BEGIN;}
3321a485fcaSdanielk1977SQL {INSERT INTO abc VALUES(9, 'XXXXX', 11, 12);}
3331a485fcaSdanielk1977TEST_AUTOCOMMIT 11 0
3341a485fcaSdanielk1977SQL -norollback {UPDATE abc SET a = a + 1, c = c + 1;}
3351a485fcaSdanielk1977TEST_AUTOCOMMIT 12 0
3361a485fcaSdanielk1977SQL {DELETE FROM abc WHERE a = 10;}
3371a485fcaSdanielk1977TEST_AUTOCOMMIT 13 0
3381a485fcaSdanielk1977SQL {COMMIT;}
3391a485fcaSdanielk1977
3401a485fcaSdanielk1977TEST 14 {
3411a485fcaSdanielk1977  do_test $testid.1 {
3421a485fcaSdanielk1977    sqlite3_get_autocommit $::DB
3431a485fcaSdanielk1977  } {1}
3441a485fcaSdanielk1977  do_test $testid.2 {
3451a485fcaSdanielk1977    execsql {SELECT a, b, c FROM abc}
3461a485fcaSdanielk1977  } {1 2 3 4 5 6 7 8 9}
3471a485fcaSdanielk1977}
3481a485fcaSdanielk1977
3491a485fcaSdanielk1977PREP [subst {
3501a485fcaSdanielk1977  DROP TABLE abc;
3511a485fcaSdanielk1977  CREATE TABLE abc(a, padding, b, c);
3521a485fcaSdanielk1977  INSERT INTO abc VALUES(1, '$padding', 2, 3);
3531a485fcaSdanielk1977  INSERT INTO abc VALUES(4, '$padding', 5, 6);
3541a485fcaSdanielk1977  INSERT INTO abc VALUES(7, '$padding', 8, 9);
3551a485fcaSdanielk1977  CREATE INDEX abc_i ON abc(a, padding, b, c);
3561a485fcaSdanielk1977}]
3571a485fcaSdanielk1977
3581a485fcaSdanielk1977TEST 15 {
3591a485fcaSdanielk1977  db eval {PRAGMA cache_size = 10}
3601a485fcaSdanielk1977}
3611a485fcaSdanielk1977
3621a485fcaSdanielk1977SQL {BEGIN;}
3631a485fcaSdanielk1977SQL -norllbck {INSERT INTO abc (oid, a, padding, b, c) SELECT NULL, * FROM abc}
3641a485fcaSdanielk1977TEST 16 {
3651a485fcaSdanielk1977  do_test $testid {
3661a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
3671a485fcaSdanielk1977  } {1 2 4 2 7 2}
3681a485fcaSdanielk1977}
3691a485fcaSdanielk1977SQL -norllbck {INSERT INTO abc (oid, a, padding, b, c) SELECT NULL, * FROM abc}
3701a485fcaSdanielk1977TEST 17 {
3711a485fcaSdanielk1977  do_test $testid {
3721a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
3731a485fcaSdanielk1977  } {1 4 4 4 7 4}
3741a485fcaSdanielk1977}
3751a485fcaSdanielk1977SQL -norllbck {INSERT INTO abc (oid, a, padding, b, c) SELECT NULL, * FROM abc}
3761a485fcaSdanielk1977TEST 18 {
3771a485fcaSdanielk1977  do_test $testid {
3781a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
3791a485fcaSdanielk1977  } {1 8 4 8 7 8}
3801a485fcaSdanielk1977}
3811a485fcaSdanielk1977SQL -norllbck {INSERT INTO abc (oid, a, padding, b, c) SELECT NULL, * FROM abc}
3821a485fcaSdanielk1977TEST 19 {
3831a485fcaSdanielk1977  do_test $testid {
3841a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
3851a485fcaSdanielk1977  } {1 16 4 16 7 16}
3861a485fcaSdanielk1977}
3871a485fcaSdanielk1977SQL {COMMIT;}
3881a485fcaSdanielk1977TEST 21 {
3891a485fcaSdanielk1977  do_test $testid {
3901a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
3911a485fcaSdanielk1977  } {1 16 4 16 7 16}
3921a485fcaSdanielk1977}
3931a485fcaSdanielk1977
3941a485fcaSdanielk1977SQL {BEGIN;}
3951a485fcaSdanielk1977SQL {DELETE FROM abc WHERE oid %2}
3961a485fcaSdanielk1977TEST 22 {
3971a485fcaSdanielk1977  do_test $testid {
3981a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
3991a485fcaSdanielk1977  } {1 8 4 8 7 8}
4001a485fcaSdanielk1977}
4011a485fcaSdanielk1977SQL {DELETE FROM abc}
4021a485fcaSdanielk1977TEST 23 {
4031a485fcaSdanielk1977  do_test $testid {
4041a485fcaSdanielk1977    execsql {SELECT * FROM abc}
4051a485fcaSdanielk1977  } {}
4061a485fcaSdanielk1977}
4071a485fcaSdanielk1977SQL {ROLLBACK;}
4081a485fcaSdanielk1977TEST 24 {
4091a485fcaSdanielk1977  do_test $testid {
4101a485fcaSdanielk1977    execsql {SELECT a, count(*) FROM abc GROUP BY a;}
4111a485fcaSdanielk1977  } {1 16 4 16 7 16}
4121a485fcaSdanielk1977}
4131a485fcaSdanielk1977
4141a485fcaSdanielk1977# Test some schema modifications inside of a transaction. These should all
4151a485fcaSdanielk1977# cause transaction rollback if they fail. Also query a view, to cover a bit
4161a485fcaSdanielk1977# more code.
4171a485fcaSdanielk1977#
4181a485fcaSdanielk1977PREP {DROP VIEW abc_v;}
4191a485fcaSdanielk1977TEST 25 {
4201a485fcaSdanielk1977  do_test $testid {
4211a485fcaSdanielk1977    execsql {
4221a485fcaSdanielk1977      SELECT name, tbl_name FROM sqlite_master;
4231a485fcaSdanielk1977    }
4241a485fcaSdanielk1977  } {abc abc abc_i abc}
4251a485fcaSdanielk1977}
4261a485fcaSdanielk1977SQL {BEGIN;}
4271a485fcaSdanielk1977SQL {CREATE TABLE def(d, e, f);}
4281a485fcaSdanielk1977SQL {CREATE TABLE ghi(g, h, i);}
4291a485fcaSdanielk1977TEST 26 {
4301a485fcaSdanielk1977  do_test $testid {
4311a485fcaSdanielk1977    execsql {
4321a485fcaSdanielk1977      SELECT name, tbl_name FROM sqlite_master;
4331a485fcaSdanielk1977    }
4341a485fcaSdanielk1977  } {abc abc abc_i abc def def ghi ghi}
4351a485fcaSdanielk1977}
4361a485fcaSdanielk1977SQL {CREATE VIEW v1 AS SELECT * FROM def, ghi}
4371a485fcaSdanielk1977SQL {CREATE UNIQUE INDEX ghi_i1 ON ghi(g);}
4381a485fcaSdanielk1977TEST 27 {
4391a485fcaSdanielk1977  do_test $testid {
4401a485fcaSdanielk1977    execsql {
4411a485fcaSdanielk1977      SELECT name, tbl_name FROM sqlite_master;
4421a485fcaSdanielk1977    }
4431a485fcaSdanielk1977  } {abc abc abc_i abc def def ghi ghi v1 v1 ghi_i1 ghi}
4441a485fcaSdanielk1977}
4451a485fcaSdanielk1977SQL {INSERT INTO def VALUES('a', 'b', 'c')}
4461a485fcaSdanielk1977SQL {INSERT INTO def VALUES(1, 2, 3)}
4471a485fcaSdanielk1977SQL -norollback {INSERT INTO ghi SELECT * FROM def}
4481a485fcaSdanielk1977TEST 28 {
4491a485fcaSdanielk1977  do_test $testid {
4501a485fcaSdanielk1977    execsql {
4511a485fcaSdanielk1977      SELECT * FROM def, ghi WHERE d = g;
4521a485fcaSdanielk1977    }
4531a485fcaSdanielk1977  } {a b c a b c 1 2 3 1 2 3}
4541a485fcaSdanielk1977}
4551a485fcaSdanielk1977SQL {COMMIT}
4561a485fcaSdanielk1977TEST 29 {
4571a485fcaSdanielk1977  do_test $testid {
4581a485fcaSdanielk1977    execsql {
4591a485fcaSdanielk1977      SELECT * FROM v1 WHERE d = g;
4601a485fcaSdanielk1977    }
4611a485fcaSdanielk1977  } {a b c a b c 1 2 3 1 2 3}
4621a485fcaSdanielk1977}
4631a485fcaSdanielk1977
4641a485fcaSdanielk1977# Test a simple multi-file transaction
4651a485fcaSdanielk1977#
4661a485fcaSdanielk1977file delete -force test2.db
4675a8f9374Sdanielk1977ifcapable attach {
468f4208043Sdanielk1977  SQL {ATTACH 'test2.db' AS aux;}
4691a485fcaSdanielk1977  SQL {BEGIN}
4701a485fcaSdanielk1977  SQL {CREATE TABLE aux.tbl2(x, y, z)}
4711a485fcaSdanielk1977  SQL {INSERT INTO tbl2 VALUES(1, 2, 3)}
4721a485fcaSdanielk1977  SQL {INSERT INTO def VALUES(4, 5, 6)}
4731a485fcaSdanielk1977  TEST 30 {
4741a485fcaSdanielk1977    do_test $testid {
4751a485fcaSdanielk1977      execsql {
4761a485fcaSdanielk1977        SELECT * FROM tbl2, def WHERE d = x;
4771a485fcaSdanielk1977      }
4781a485fcaSdanielk1977    } {1 2 3 1 2 3}
4791a485fcaSdanielk1977  }
4801a485fcaSdanielk1977  SQL {COMMIT}
4811a485fcaSdanielk1977  TEST 31 {
4821a485fcaSdanielk1977    do_test $testid {
4831a485fcaSdanielk1977      execsql {
4841a485fcaSdanielk1977        SELECT * FROM tbl2, def WHERE d = x;
4851a485fcaSdanielk1977      }
4861a485fcaSdanielk1977    } {1 2 3 1 2 3}
4871a485fcaSdanielk1977  }
4885a8f9374Sdanielk1977}
4891a485fcaSdanielk1977
49007cb560bSdanielk1977# Test what happens when a malloc() fails while there are other active
49107cb560bSdanielk1977# statements. This changes the way sqlite3VdbeHalt() works.
49207cb560bSdanielk1977TEST 32 {
49307cb560bSdanielk1977  if {![info exists ::STMT32]} {
49407cb560bSdanielk1977    set sql "SELECT name FROM sqlite_master"
49507cb560bSdanielk1977    set ::STMT32 [sqlite3_prepare $::DB $sql -1 DUMMY]
49607cb560bSdanielk1977    do_test $testid {
49707cb560bSdanielk1977      sqlite3_step $::STMT32
49807cb560bSdanielk1977    } {SQLITE_ROW}
49907cb560bSdanielk1977  }
50007cb560bSdanielk1977}
50197a227c9Sdanielk1977SQL BEGIN
50297a227c9Sdanielk1977TEST 33 {
50397a227c9Sdanielk1977  do_test $testid {
50497a227c9Sdanielk1977    execsql {SELECT * FROM ghi}
50597a227c9Sdanielk1977  } {a b c 1 2 3}
50607cb560bSdanielk1977}
50797a227c9Sdanielk1977SQL -norollback {
50897a227c9Sdanielk1977  -- There is a unique index on ghi(g), so this statement may not cause
50997a227c9Sdanielk1977  -- an automatic ROLLBACK. Hence the "-norollback" switch.
51097a227c9Sdanielk1977  INSERT INTO ghi SELECT '2'||g, h, i FROM ghi;
51197a227c9Sdanielk1977}
51297a227c9Sdanielk1977TEST 34 {
51397a227c9Sdanielk1977  if {[info exists ::STMT32]} {
51497a227c9Sdanielk1977    do_test $testid {
51597a227c9Sdanielk1977      sqlite3_finalize $::STMT32
51697a227c9Sdanielk1977    } {SQLITE_OK}
51797a227c9Sdanielk1977    unset ::STMT32
51897a227c9Sdanielk1977  }
51997a227c9Sdanielk1977}
52097a227c9Sdanielk1977SQL COMMIT
52107cb560bSdanielk1977
5221a485fcaSdanielk1977#
5231a485fcaSdanielk1977# End of test program declaration
5241a485fcaSdanielk1977#--------------------------------------------------------------------------
5251a485fcaSdanielk1977
52637f0d221Sdanielk1977proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} {
5271a485fcaSdanielk1977  if {[llength $arglist] %2} {
5281a485fcaSdanielk1977    error "Uneven number of arguments to TEST"
5291a485fcaSdanielk1977  }
5301a485fcaSdanielk1977
5311a485fcaSdanielk1977  for {set i 0} {$i < $pcstart} {incr i} {
5321a485fcaSdanielk1977    set k2 [lindex $arglist [expr 2 * $i]]
5331a485fcaSdanielk1977    set v2 [lindex $arglist [expr 2 * $i + 1]]
5341a485fcaSdanielk1977    set ac [sqlite3_get_autocommit $::DB]        ;# Auto-Commit
5351a485fcaSdanielk1977    switch -- $k2 {
5361a485fcaSdanielk1977      -sql  {db eval [lindex $v2 1]}
5371a485fcaSdanielk1977      -prep {db eval $v2}
5381a485fcaSdanielk1977    }
5391a485fcaSdanielk1977    set nac [sqlite3_get_autocommit $::DB]       ;# New Auto-Commit
5401a485fcaSdanielk1977    if {$ac && !$nac} {set begin_pc $i}
5411a485fcaSdanielk1977  }
5421a485fcaSdanielk1977
543f3f06bb3Sdanielk1977  db rollback_hook [list incr ::rollback_hook_count]
544f3f06bb3Sdanielk1977
5451a485fcaSdanielk1977  set iFail $iFailStart
5461a485fcaSdanielk1977  set pc $pcstart
5471a485fcaSdanielk1977  while {$pc*2 < [llength $arglist]} {
5481a485fcaSdanielk1977
5491a485fcaSdanielk1977    # Id of this iteration:
5501a485fcaSdanielk1977    set k [lindex $arglist [expr 2 * $pc]]
55193aed5a1Sdrh    set iterid "pc=$pc.iFail=$iFail$k"
5521a485fcaSdanielk1977    set v [lindex $arglist [expr 2 * $pc + 1]]
5531a485fcaSdanielk1977
5541a485fcaSdanielk1977    switch -- $k {
5551a485fcaSdanielk1977
5561a485fcaSdanielk1977      -test {
5571a485fcaSdanielk1977        foreach {id script} $v {}
5581a485fcaSdanielk1977        incr pc
5591a485fcaSdanielk1977      }
5601a485fcaSdanielk1977
5611a485fcaSdanielk1977      -sql {
562f3f06bb3Sdanielk1977        set ::rollback_hook_count 0
563f3f06bb3Sdanielk1977
5641a485fcaSdanielk1977        set ac [sqlite3_get_autocommit $::DB]        ;# Auto-Commit
56537f0d221Sdanielk1977        sqlite3_memdebug_fail $iFail -repeat 0
5661a485fcaSdanielk1977        set rc [catch {db eval [lindex $v 1]} msg]   ;# True error occurs
5671a485fcaSdanielk1977        set nac [sqlite3_get_autocommit $::DB]       ;# New Auto-Commit
5681a485fcaSdanielk1977
569f3f06bb3Sdanielk1977        if {$rc != 0 && $nac && !$ac} {
570f3f06bb3Sdanielk1977          # Before [db eval] the auto-commit flag was clear. Now it
571f3f06bb3Sdanielk1977          # is set. Since an error occured we assume this was not a
572f3f06bb3Sdanielk1977	  # commit - therefore a rollback occured. Check that the
573f3f06bb3Sdanielk1977	  # rollback-hook was invoked.
574f3f06bb3Sdanielk1977          do_test malloc3-rollback_hook.$iterid {
575f3f06bb3Sdanielk1977            set ::rollback_hook_count
576f3f06bb3Sdanielk1977          } {1}
577f3f06bb3Sdanielk1977        }
578f3f06bb3Sdanielk1977
579ae72d982Sdanielk1977        set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
5801a485fcaSdanielk1977        if {$rc == 0} {
581ae72d982Sdanielk1977            # Successful execution of sql. The number of failed malloc()
582ae72d982Sdanielk1977            # calls should be equal to the number of benign failures.
583ae72d982Sdanielk1977            # Otherwise a malloc() failed and the error was not reported.
584ae72d982Sdanielk1977            #
585ae72d982Sdanielk1977            if {$nFail!=$nBenign} {
5861a485fcaSdanielk1977              error "Unreported malloc() failure"
5871a485fcaSdanielk1977            }
588f3f06bb3Sdanielk1977
5891a485fcaSdanielk1977            if {$ac && !$nac} {
590f3f06bb3Sdanielk1977              # Before the [db eval] the auto-commit flag was set, now it
591f3f06bb3Sdanielk1977              # is clear. We can deduce that a "BEGIN" statement has just
592f3f06bb3Sdanielk1977              # been successfully executed.
5931a485fcaSdanielk1977              set begin_pc $pc
5941a485fcaSdanielk1977            }
595f3f06bb3Sdanielk1977
5961a485fcaSdanielk1977            incr pc
5971a485fcaSdanielk1977            set iFail 1
5981a485fcaSdanielk1977            integrity_check "malloc3-(integrity).$iterid"
599ae72d982Sdanielk1977        } elseif {[regexp {.*out of memory} $msg] || [db errorcode] == 3082} {
600ae72d982Sdanielk1977            # Out of memory error, as expected.
601ae72d982Sdanielk1977            #
6021a485fcaSdanielk1977            integrity_check "malloc3-(integrity).$iterid"
6031a485fcaSdanielk1977            incr iFail
6041a485fcaSdanielk1977            if {$nac && !$ac} {
605f3f06bb3Sdanielk1977
606ae72d982Sdanielk1977              if {![lindex $v 0] && [db errorcode] != 3082} {
607ae72d982Sdanielk1977                # error "Statement \"[lindex $v 1]\" caused a rollback"
6081a485fcaSdanielk1977              }
609f3f06bb3Sdanielk1977
6101a485fcaSdanielk1977              for {set i $begin_pc} {$i < $pc} {incr i} {
6111a485fcaSdanielk1977                set k2 [lindex $arglist [expr 2 * $i]]
6121a485fcaSdanielk1977                set v2 [lindex $arglist [expr 2 * $i + 1]]
6131a485fcaSdanielk1977                set catchupsql ""
6141a485fcaSdanielk1977                switch -- $k2 {
6151a485fcaSdanielk1977                  -sql  {set catchupsql [lindex $v2 1]}
6161a485fcaSdanielk1977                  -prep {set catchupsql $v2}
6171a485fcaSdanielk1977                }
6181a485fcaSdanielk1977                db eval $catchupsql
6191a485fcaSdanielk1977              }
6201a485fcaSdanielk1977            }
6211a485fcaSdanielk1977        } else {
6221a485fcaSdanielk1977            error $msg
6231a485fcaSdanielk1977        }
6241a485fcaSdanielk1977
6251a485fcaSdanielk1977        while {[lindex $arglist [expr 2 * ($pc -1)]] == "-test"} {
6261a485fcaSdanielk1977          incr pc -1
6271a485fcaSdanielk1977        }
6281a485fcaSdanielk1977      }
6291a485fcaSdanielk1977
6301a485fcaSdanielk1977      -prep {
6311a485fcaSdanielk1977        db eval $v
6321a485fcaSdanielk1977        incr pc
6331a485fcaSdanielk1977      }
6341a485fcaSdanielk1977
63593aed5a1Sdrh      -debug {
63693aed5a1Sdrh        eval $v
63793aed5a1Sdrh        incr pc
63893aed5a1Sdrh      }
63993aed5a1Sdrh
6401a485fcaSdanielk1977      default { error "Unknown switch: $k" }
6411a485fcaSdanielk1977    }
6421a485fcaSdanielk1977  }
6431a485fcaSdanielk1977}
6441a485fcaSdanielk1977
64537f0d221Sdanielk1977# Turn of the Tcl interface's prepared statement caching facility. Then
64637f0d221Sdanielk1977# run the tests with "persistent" malloc failures.
647ae72d982Sdanielk1977sqlite3_extended_result_codes db 1
6481a485fcaSdanielk1977db cache size 0
64937f0d221Sdanielk1977run_test $::run_test_script 1
6501a485fcaSdanielk1977
65137f0d221Sdanielk1977# Close and reopen the db.
6522e588c75Sdanielk1977db close
65385378228Sdanielk1977file delete -force test.db test.db-journal test2.db test2.db-journal
65437f0d221Sdanielk1977sqlite3 db test.db
655ae72d982Sdanielk1977sqlite3_extended_result_codes db 1
65637f0d221Sdanielk1977set ::DB [sqlite3_connection_pointer db]
6572e588c75Sdanielk1977
65837f0d221Sdanielk1977# Turn of the Tcl interface's prepared statement caching facility in
65937f0d221Sdanielk1977# the new connnection. Then run the tests with "transient" malloc failures.
66037f0d221Sdanielk1977db cache size 0
66137f0d221Sdanielk1977run_test $::run_test_script 0
66237f0d221Sdanielk1977
66337f0d221Sdanielk1977sqlite3_memdebug_fail -1
6641a485fcaSdanielk1977finish_test
665