summaryrefslogtreecommitdiffstats
path: root/test/capi3b.test
blob: 72bbbaf65678938bcfb9fe072c55f675f00db2b8 (plain)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# 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.4 2007/08/10 19:46:14 drh Exp $
#

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


# These tests depend on the pager holding changes in cache
# until it is time to commit.  But that won't happen if the
# soft-heap-limit is set too low.  So disable the soft heap limit
# for the duration of this test.
#
sqlite3_soft_heap_limit 0


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

# 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}

sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
finish_test