SQLite

Check-in [1f8f4fdf3f]
Login

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

Overview
Comment:Obtain the required shared-cache write-lock when executing "DELETE FROM tbl" statements. Fix for [1e1321ee98].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1f8f4fdf3ff2b8de27e167a44a19b0f479f5ee1a
User & Date: dan 2013-09-26 15:21:16.149
Context
2013-09-28
12:40
Updates to the sqlite3_analyzer utility: Change the names of some labels, especially change "Fragmentation" to "Non-sequential pages". Revise the computation of non-sequential pages so that it ignores itercalated non-leaf pages (overflow and index pages). (check-in: 3e5c7771fa user: drh tags: trunk)
2013-09-26
15:21
Obtain the required shared-cache write-lock when executing "DELETE FROM tbl" statements. Fix for [1e1321ee98]. (check-in: 1f8f4fdf3f user: dan tags: trunk)
11:04
Fix a faulty assert() in sqlite3BtreeBeginTrans() that may fail in shared-cache mode. (check-in: 1e1321ee98 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/delete.c.
346
347
348
349
350
351
352

353
354
355
356
357
358
359
  ** It is easier just to erase the whole table. Prior to version 3.6.5,
  ** this optimization caused the row change count (the value returned by 
  ** API function sqlite3_count_changes) to be set incorrectly.  */
  if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
   && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
  ){
    assert( !isView );

    sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
                      pTab->zName, P4_STATIC);
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
      sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
    }
  }else







>







346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  ** It is easier just to erase the whole table. Prior to version 3.6.5,
  ** this optimization caused the row change count (the value returned by 
  ** API function sqlite3_count_changes) to be set incorrectly.  */
  if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
   && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
  ){
    assert( !isView );
    sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
    sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
                      pTab->zName, P4_STATIC);
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
      sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
    }
  }else
Changes to test/sharedlock.test.
9
10
11
12
13
14
15

16
17
18
19
20
21
22
#
#***********************************************************************
#
# $Id: sharedlock.test,v 1.1 2009/07/02 17:21:58 danielk1977 Exp $

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

db close

ifcapable !shared_cache {
  finish_test
  return
}








>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
#
# $Id: sharedlock.test,v 1.1 2009/07/02 17:21:58 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sharedlock
db close

ifcapable !shared_cache {
  finish_test
  return
}

42
43
44
45
46
47
48
49




























50
51
52
53
54
    # prevent connection [db2] from obtaining the write-lock it needs to
    # modify t1. At one point there was a bug causing the previous INSERT
    # to drop the read-lock belonging to [db].
    if {$a == 2} { catch { db2 eval "INSERT INTO t1 VALUES(4, 'four')"  } }
  }
  set res
} {1 one 2 two 3 three}





























db close
db2 close

sqlite3_enable_shared_cache $::enable_shared_cache
finish_test








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


<


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
    # prevent connection [db2] from obtaining the write-lock it needs to
    # modify t1. At one point there was a bug causing the previous INSERT
    # to drop the read-lock belonging to [db].
    if {$a == 2} { catch { db2 eval "INSERT INTO t1 VALUES(4, 'four')"  } }
  }
  set res
} {1 one 2 two 3 three}


#-------------------------------------------------------------------------
# Test that a write-lock is taken on a table when its entire contents
# are deleted using the OP_Clear optimization.
#
foreach {tn delete_sql} {
  1 { DELETE FROM t2 WHERE 1 }
  2 { DELETE FROM t2 }
} {
  do_execsql_test 2.1 {
    DROP TABLE IF EXISTS t2;
    CREATE TABLE t2(x, y);
    INSERT INTO t2 VALUES(1, 2);
    INSERT INTO t2 VALUES(3, 4);
  }

  do_test 2.2 { execsql { SELECT * FROM t2 } db2 } {1 2 3 4}

  do_execsql_test 2.3 " BEGIN; $delete_sql; "

  do_test 2.4 { 
    catchsql { SELECT * FROM t2 } db2 
  } {1 {database table is locked: t2}}

  do_execsql_test 2.5 COMMIT
}


db close
db2 close

sqlite3_enable_shared_cache $::enable_shared_cache
finish_test