SQLite

Check-in [82cd837e72]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add extra tests and a fix for rollbacks of UNLOCKED transactions.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA1: 82cd837e72ed4cf5821be717369694be29a2997e
User & Date: dan 2015-08-21 14:21:22.365
Context
2015-08-21
16:22
Merge trunk changes with this branch. (check-in: deaf3b1856 user: dan tags: begin-concurrent)
14:21
Add extra tests and a fix for rollbacks of UNLOCKED transactions. (check-in: 82cd837e72 user: dan tags: begin-concurrent)
2015-08-20
20:25
Fix a problem causing corruption when an UNLOCKED transaction is rolled back. (check-in: 7c36147846 user: dan tags: begin-concurrent)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/wal.c.
2631
2632
2633
2634
2635
2636
2637















2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
            }else if( sqlite3BitvecTestNotNull(pAllRead, aPgno[i]) ){
              sqlite3_log(SQLITE_OK,
                  "cannot commit UNLOCKED transaction (conflict at page %d)",
                  (int)aPgno[i]
              );
              rc = SQLITE_BUSY_SNAPSHOT;
            }else if( (pPg = sqlite3PagerLookup(pPager, aPgno[i])) ){















              if( sqlite3PagerIswriteable(pPg)==0 ){
                sqlite3PcacheDrop(pPg);
              }else{
                sqlite3PagerUnref(pPg);
              }
            }
          }
        }
        if( rc!=SQLITE_OK ) break;
      }
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

|







2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
            }else if( sqlite3BitvecTestNotNull(pAllRead, aPgno[i]) ){
              sqlite3_log(SQLITE_OK,
                  "cannot commit UNLOCKED transaction (conflict at page %d)",
                  (int)aPgno[i]
              );
              rc = SQLITE_BUSY_SNAPSHOT;
            }else if( (pPg = sqlite3PagerLookup(pPager, aPgno[i])) ){
              /* Page aPgno[i], which is present in the pager cache, has been
              ** modified since the current UNLOCKED transaction was started.
              ** However it was not read by the current transaction, so is not
              ** a conflict. There are two possibilities: (a) the page was
              ** allocated at the of the file by the current transaction or 
              ** (b) was present in the cache at the start of the transaction.
              **
              ** For case (a), do nothing. This page will be moved within the
              ** database file by the commit code to avoid the conflict. The
              ** call to PagerUnref() is to release the reference grabbed by
              ** the sqlite3PagerLookup() above.  
              **
              ** In case (b), drop the page from the cache - otherwise
              ** following the snapshot upgrade the cache would be inconsistent
              ** with the database as stored on disk. */
              if( sqlite3PagerIswriteable(pPg) ){
                sqlite3PagerUnref(pPg);
              }else{
                sqlite3PcacheDrop(pPg);
              }
            }
          }
        }
        if( rc!=SQLITE_OK ) break;
      }
    }
Changes to test/unlocked2.test.
127
128
129
130
131
132
133












134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151



152

153
154











155
156


157




158

159
160
161

    sql1 COMMIT
  } {}

  do_test 2.$tn.7 { sql3 { PRAGMA integrity_check } } {ok}
}













reset_db
do_execsql_test 3.0 {
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(x, y);
  INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500));
  DELETE FROM t1;
} {wal}

db close
sqlite3 db test.db
breakpoint

do_execsql_test 3.1 {
  BEGIN UNLOCKED;
    INSERT INTO t1 VALUES(1, 2);
  ROLLBACK;
}




do_execsql_test 3.2 {

  PRAGMA integrity_check;
} {ok}












do_execsql_test 3.3 {


  PRAGMA freelist_count;




} {2}


finish_test








>
>
>
>
>
>
>
>
>
>
>
>








<
<
<
<






>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>

|
>
>
|
>
>
>
>

>



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153




154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

    sql1 COMMIT
  } {}

  do_test 2.$tn.7 { sql3 { PRAGMA integrity_check } } {ok}
}

#-------------------------------------------------------------------------
# When an UNLOCKED transaction is opened on a database, the nFree and 
# iTrunk header fields of the cached version of page 1 are both set 
# to 0. This allows an UNLOCKED transaction to use its own private 
# free-page-list, which is merged with the main database free-list when
# the transaction is committed.
#
# The following tests check that nFree/iTrunk are correctly restored if
# an UNLOCKED transaction is rolled back, and that savepoint rollbacks
# that occur within UNLOCKED transactions do not incorrectly restore
# these fields to their on-disk values.
#
reset_db
do_execsql_test 3.0 {
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(x, y);
  INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500));
  DELETE FROM t1;
} {wal}





do_execsql_test 3.1 {
  BEGIN UNLOCKED;
    INSERT INTO t1 VALUES(1, 2);
  ROLLBACK;
}

do_execsql_test 3.2 { PRAGMA integrity_check } {ok}
do_execsql_test 3.3 { PRAGMA freelist_count } {2}

do_execsql_test 3.4.1 {
  BEGIN UNLOCKED;
    PRAGMA freelist_count;
} {2}
do_execsql_test 3.4.2 {
  SAVEPOINT xyz;
    INSERT INTO t1 VALUES(randomblob(1500), NULL);
    PRAGMA freelist_count;
} {0}
do_execsql_test 3.4.3 {
  ROLLBACK TO xyz;
} {}
do_execsql_test 3.4.4 { PRAGMA freelist_count } {0}
do_execsql_test 3.4.5 { COMMIT; PRAGMA freelist_count } {2}
do_execsql_test 3.4.6 { PRAGMA integrity_check } {ok}

do_execsql_test 3.5.1 {
  BEGIN UNLOCKED;
    UPDATE t1 SET x=randomblob(10) WHERE y=555;
    PRAGMA freelist_count;
} {0}
do_execsql_test 3.5.2 {
  ROLLBACK;
  PRAGMA freelist_count;
} {2}
do_execsql_test 3.5.3 { PRAGMA integrity_check } {ok}

finish_test