SQLite

Check-in [bebf8d2f88]
Login

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

Overview
Comment:Make sure the sqlite3BtreePrevious() routine terminates properly if the table is deleted out from under it. Ticket #2286. This bug was discovered while trying to increase test coverage from 98.5% to 99% - once again showing the value of full coverage testing. (CVS 3818)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bebf8d2f886ed9fe1b96e4cb11ab3de2f2f7d2c8
User & Date: drh 2007-04-06 01:03:33.000
Context
2007-04-06
01:04
Changes to increase test coverage. (CVS 3819) (check-in: fd4da6b134 user: drh tags: trunk)
01:03
Make sure the sqlite3BtreePrevious() routine terminates properly if the table is deleted out from under it. Ticket #2286. This bug was discovered while trying to increase test coverage from 98.5% to 99% - once again showing the value of full coverage testing. (CVS 3818) (check-in: bebf8d2f88 user: drh tags: trunk)
2007-04-05
21:58
Fix the amalgamation so that it works with -DSQLITE_ENABLE_REDEF_IO. Change tclsqlite.c so that it can be appended to the amalgamation. Create a new amalgamation of header files for use by projects that want to redefine their own I/O interface using -DSQLITE_ENABLE_REDEF_IO. (CVS 3817) (check-in: f2caff870c user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 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.
**
*************************************************************************
** $Id: btree.c,v 1.350 2007/04/02 05:07:47 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 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.
**
*************************************************************************
** $Id: btree.c,v 1.351 2007/04/06 01:03:33 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
3516
3517
3518
3519
3520
3521
3522








3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
  MemPage *pPage;

#ifndef SQLITE_OMIT_SHARED_CACHE
  rc = restoreOrClearCursorPosition(pCur);
  if( rc!=SQLITE_OK ){
    return rc;
  }








  if( pCur->skip>0 ){
    pCur->skip = 0;
    *pRes = 0;
    return SQLITE_OK;
  }
  pCur->skip = 0;
#endif 

  assert( pRes!=0 );
  pPage = pCur->pPage;
  if( CURSOR_INVALID==pCur->eState ){
    *pRes = 1;
    return SQLITE_OK;
  }
  assert( pPage->isInit );
  assert( pCur->idx<pPage->nCell );

  pCur->idx++;
  pCur->info.nSize = 0;
  if( pCur->idx>=pPage->nCell ){
    if( !pPage->leaf ){







>
>
>
>
>
>
>
>








<
<
<
<
<
<







3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538






3539
3540
3541
3542
3543
3544
3545
  MemPage *pPage;

#ifndef SQLITE_OMIT_SHARED_CACHE
  rc = restoreOrClearCursorPosition(pCur);
  if( rc!=SQLITE_OK ){
    return rc;
  }
#endif 
  assert( pRes!=0 );
  pPage = pCur->pPage;
  if( CURSOR_INVALID==pCur->eState ){
    *pRes = 1;
    return SQLITE_OK;
  }
#ifndef SQLITE_OMIT_SHARED_CACHE
  if( pCur->skip>0 ){
    pCur->skip = 0;
    *pRes = 0;
    return SQLITE_OK;
  }
  pCur->skip = 0;
#endif 







  assert( pPage->isInit );
  assert( pCur->idx<pPage->nCell );

  pCur->idx++;
  pCur->info.nSize = 0;
  if( pCur->idx>=pPage->nCell ){
    if( !pPage->leaf ){
3584
3585
3586
3587
3588
3589
3590






3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
  MemPage *pPage;

#ifndef SQLITE_OMIT_SHARED_CACHE
  rc = restoreOrClearCursorPosition(pCur);
  if( rc!=SQLITE_OK ){
    return rc;
  }






  if( pCur->skip<0 ){
    pCur->skip = 0;
    *pRes = 0;
    return SQLITE_OK;
  }
  pCur->skip = 0;
#endif

  if( CURSOR_INVALID==pCur->eState ){
    *pRes = 1;
    return SQLITE_OK;
  }

  pPage = pCur->pPage;
  assert( pPage->isInit );
  assert( pCur->idx>=0 );
  if( !pPage->leaf ){
    pgno = get4byte( findCell(pPage, pCur->idx) );
    rc = moveToChild(pCur, pgno);
    if( rc ) return rc;







>
>
>
>
>
>








<
<
<
<
<







3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606





3607
3608
3609
3610
3611
3612
3613
  MemPage *pPage;

#ifndef SQLITE_OMIT_SHARED_CACHE
  rc = restoreOrClearCursorPosition(pCur);
  if( rc!=SQLITE_OK ){
    return rc;
  }
#endif
  if( CURSOR_INVALID==pCur->eState ){
    *pRes = 1;
    return SQLITE_OK;
  }
#ifndef SQLITE_OMIT_SHARED_CACHE
  if( pCur->skip<0 ){
    pCur->skip = 0;
    *pRes = 0;
    return SQLITE_OK;
  }
  pCur->skip = 0;
#endif






  pPage = pCur->pPage;
  assert( pPage->isInit );
  assert( pCur->idx>=0 );
  if( !pPage->leaf ){
    pgno = get4byte( findCell(pPage, pCur->idx) );
    rc = moveToChild(pCur, pgno);
    if( rc ) return rc;
Changes to test/misc2.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# 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.26 2006/09/29 14:01:07 drh Exp $

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

ifcapable {trigger} {
# Test for ticket #360
#







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# 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.27 2007/04/06 01:03:34 drh Exp $

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

ifcapable {trigger} {
# Test for ticket #360
#
245
246
247
248
249
250
251




































































































252
253
254
255
256
257
258
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1);
  }
  db eval {SELECT rowid, x FROM t1} {
    if {$x<10} {
      db eval {INSERT INTO t1 VALUES($x+1)}
    }




































































































  }
  execsql {SELECT * FROM t1}
} {1 2 3 4 5 6 7 8 9 10}

db close
file delete -force test.db
sqlite3 db test.db







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







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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1);
  }
  db eval {SELECT rowid, x FROM t1} {
    if {$x<10} {
      db eval {INSERT INTO t1 VALUES($x+1)}
    }
  }
  execsql {SELECT * FROM t1}
} {1 2 3 4 5 6 7 8 9 10}

# Repeat the tests 7.1 through 7.8 about but this time do the SELECTs
# in reverse order so that we exercise the sqlite3BtreePrev() routine
# instead of sqlite3BtreeNext()
#
do_test misc2-7.11 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    SELECT * FROM t1;
  }
} {1 2 3}
do_test misc2-7.12 {
  set rc [catch {
    db eval {SELECT rowid FROM t1 ORDER BY rowid DESC} {} {
      db eval "DELETE FROM t1 WHERE rowid=$rowid"
    }
  } msg]
  lappend rc $msg
} {0 {}}
do_test misc2-7.13 {
  execsql {SELECT * FROM t1}
} {}
do_test misc2-7.14 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    INSERT INTO t1 VALUES(4);
  }
  db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} {
    if {$x & 1} {
      db eval {DELETE FROM t1 WHERE rowid=$rowid}
    }
  }
  execsql {SELECT * FROM t1}
} {2 4}
do_test misc2-7.15 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    INSERT INTO t1 VALUES(4);
  }
  db eval {SELECT rowid, x FROM t1} {
    if {$x & 1} {
      db eval {DELETE FROM t1 WHERE rowid=$rowid+1}
    }
  }
  execsql {SELECT * FROM t1}
} {1 3}
do_test misc2-7.16 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    INSERT INTO t1 VALUES(4);
  }
  db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} {
    if {$x & 1} {
      db eval {DELETE FROM t1}
    }
  }
  execsql {SELECT * FROM t1}
} {}
do_test misc2-7.17 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    INSERT INTO t1 VALUES(4);
  }
  db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} {
    if {$x & 1} {
      db eval {UPDATE t1 SET x=x+100 WHERE rowid=$rowid}
    }
  }
  execsql {SELECT * FROM t1}
} {101 2 103 4}
do_test misc2-7.18 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1(rowid,x) VALUES(10,10);
  }
  db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} {
    if {$x>1} {
      db eval {INSERT INTO t1(rowid,x) VALUES($x-1,$x-1)}
    }
  }
  execsql {SELECT * FROM t1}
} {1 2 3 4 5 6 7 8 9 10}

db close
file delete -force test.db
sqlite3 db test.db