/ Check-in [0e422580]
Login

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

Overview
Comment:Allow statements like "REPLACE INTO tbl(rowid) VALUES(...)" to run without a statement journal as long as there are no triggers, foreign keys or indexes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0e4225804010cb0e3f254e2dbffc4fe0e7d982ce
User & Date: dan 2010-02-18 08:19:20
Context
2010-02-18
18:45
Add a new, experimental logging interface designed to aid in debugging of deeply embedded projects that use SQLite. check-in: 103321e3 user: drh tags: trunk
08:19
Allow statements like "REPLACE INTO tbl(rowid) VALUES(...)" to run without a statement journal as long as there are no triggers, foreign keys or indexes. check-in: 0e422580 user: dan tags: trunk
2010-02-17
17:48
Consistent use of #ifdef for SQLITE_HAS_CODEC to avoid confusion. check-in: 34a3413a user: shaneh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/insert.c.

1257
1258
1259
1260
1261
1262
1263

1264
1265
1266












1267
1268
1269
1270
1271
1272

1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
      case OE_Replace: {
        /* If there are DELETE triggers on this table and the
        ** recursive-triggers flag is set, call GenerateRowDelete() to
        ** remove the conflicting row from the the table. This will fire
        ** the triggers and remove both the table and index b-tree entries.
        **
        ** Otherwise, if there are no triggers or the recursive-triggers

        ** flag is not set, call GenerateRowIndexDelete(). This removes
        ** the index b-tree entries only. The table b-tree entry will be 
        ** replaced by the new entry when it is inserted.  */












        Trigger *pTrigger = 0;
        if( pParse->db->flags&SQLITE_RecTriggers ){
          pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
        }
        sqlite3MultiWrite(pParse);
        if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){

          sqlite3GenerateRowDelete(
              pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
          );
        }else{

          sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );







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




<

>



|
>







1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283

1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
      case OE_Replace: {
        /* If there are DELETE triggers on this table and the
        ** recursive-triggers flag is set, call GenerateRowDelete() to
        ** remove the conflicting row from the the table. This will fire
        ** the triggers and remove both the table and index b-tree entries.
        **
        ** Otherwise, if there are no triggers or the recursive-triggers
        ** flag is not set, but the table has one or more indexes, call 
        ** GenerateRowIndexDelete(). This removes the index b-tree entries 
        ** only. The table b-tree entry will be replaced by the new entry 
        ** when it is inserted.  
        **
        ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
        ** also invoke MultiWrite() to indicate that this VDBE may require
        ** statement rollback (if the statement is aborted after the delete
        ** takes place). Earlier versions called sqlite3MultiWrite() regardless,
        ** but being more selective here allows statements like:
        **
        **   REPLACE INTO t(rowid) VALUES($newrowid)
        **
        ** to run without a statement journal if there are no indexes on the
        ** table.
        */
        Trigger *pTrigger = 0;
        if( pParse->db->flags&SQLITE_RecTriggers ){
          pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
        }

        if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
          sqlite3MultiWrite(pParse);
          sqlite3GenerateRowDelete(
              pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
          );
        }else if( pTab->pIndex ){
          sqlite3MultiWrite(pParse);
          sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );

Changes to test/fts3snippet.test.

338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
    for {set i 1} {$i < 150} {incr i} {
      set commas [string repeat , $i]
      execsql {INSERT INTO ft VALUES('one' || $commas || 'two')}
      lappend testresults "{one}$commas{two}"
    }
    execsql COMMIT
  } {}
  do_snippet_test $T.7.2 {one two} -1 3 {*}$testresults
  
  ##########################################################################
  # Test the matchinfo function.
  #
  proc mit {blob} {
    set scan(littleEndian) i*
    set scan(bigEndian) I*







|







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
    for {set i 1} {$i < 150} {incr i} {
      set commas [string repeat , $i]
      execsql {INSERT INTO ft VALUES('one' || $commas || 'two')}
      lappend testresults "{one}$commas{two}"
    }
    execsql COMMIT
  } {}
  eval [list do_snippet_test $T.7.2 {one two} -1 3] $testresults
  
  ##########################################################################
  # Test the matchinfo function.
  #
  proc mit {blob} {
    set scan(littleEndian) i*
    set scan(bigEndian) I*

Added test/stmt.test.

































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# 2010 February 18
#
# 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.
#
#***********************************************************************
#
# The tests in this file check that SQLite uses (or does not use) a
# statement journal for various SQL statements.
#

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

do_test stmt-1.1 {
  execsql { CREATE TABLE t1(a integer primary key, b INTEGER NOT NULL) }
} {}

# The following tests verify the method used for the tests in this file -
# that if a statement journal is required by a statement it is opened and
# remains open until the current transaction is committed or rolled back.
#
do_test stmt-1.2 {
  set sqlite_open_file_count
} {1}
do_test stmt-1.3 {
  execsql {
    BEGIN;
      INSERT INTO t1 VALUES(1, 1);
  }
  set sqlite_open_file_count
} {2}
do_test stmt-1.4 {
  execsql {
    INSERT INTO t1 SELECT a+1, b+1 FROM t1;
  }
  set sqlite_open_file_count
} {3}
do_test stmt-1.5 {
  execsql COMMIT
  set sqlite_open_file_count
} {1}
do_test stmt-1.6 {
  execsql {
    BEGIN;
      INSERT INTO t1 SELECT a+2, b+2 FROM t1;
  }
  set sqlite_open_file_count
} {3}
do_test stmt-1.7 {
  execsql COMMIT
  set sqlite_open_file_count
} {1}


proc filecount {testname sql expected} {
  uplevel [list do_test $testname [subst -nocommand {
    execsql BEGIN
    execsql { $sql }
    set ret [set sqlite_open_file_count]
    execsql ROLLBACK
    set ret
  }] $expected]
}

filecount stmt-2.1 { INSERT INTO t1 VALUES(5, 5)  } 2
filecount stmt-2.2 { REPLACE INTO t1 VALUES(5, 5) } 2
filecount stmt-2.3 { INSERT INTO t1 SELECT 5, 5   } 3

do_test stmt-2.4 {
  execsql { CREATE INDEX i1 ON t1(b) }
} {}
filecount stmt-2.5 { REPLACE INTO t1 VALUES(5, 5) } 3

finish_test