/ Check-in [6c7bec1b]
Login

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

Overview
Comment:Fix an assertion failure due to interaction between the count_changes pragma and triggers. (CVS 2187)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6c7bec1b3aee0287e30f43c1d6a7b67b1c47e774
User & Date: danielk1977 2005-01-10 02:48:49
Context
2005-01-10
06:39
Update some documentation for version 3.1. (CVS 2188) check-in: 5b7a5a4d user: danielk1977 tags: trunk
02:48
Fix an assertion failure due to interaction between the count_changes pragma and triggers. (CVS 2187) check-in: 6c7bec1b user: danielk1977 tags: trunk
2005-01-08
18:42
Tcl interface does as sqlite3 or as sqlite. A compile-time option allows duel linking. Also fix a bug in the pragma change from earlier today. (CVS 2186) check-in: ad109537 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.94 2004/12/25 01:03:14 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
  }

  /*
  ** Return the number of rows that were deleted. If this routine is 
  ** generating code because of a call to sqlite3NestedParse(), do not
  ** invoke the callback function.
  */
  if( db->flags & SQLITE_CountRows && pParse->nested==0 ){
    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC);
  }

delete_from_cleanup:
  sqlite3AuthContextPop(&sContext);







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.95 2005/01/10 02:48:49 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
  }

  /*
  ** Return the number of rows that were deleted. If this routine is 
  ** generating code because of a call to sqlite3NestedParse(), do not
  ** invoke the callback function.
  */
  if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC);
  }

delete_from_cleanup:
  sqlite3AuthContextPop(&sContext);

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.128 2004/12/07 15:41:49 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
#endif

  /*
  ** Return the number of rows inserted. If this routine is 
  ** generating code because of a call to sqlite3NestedParse(), do not
  ** invoke the callback function.
  */
  if( db->flags & SQLITE_CountRows && pParse->nested==0 ){
    sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC);
  }

insert_cleanup:







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.129 2005/01/10 02:48:49 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
#endif

  /*
  ** Return the number of rows inserted. If this routine is 
  ** generating code because of a call to sqlite3NestedParse(), do not
  ** invoke the callback function.
  */
  if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
    sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC);
  }

insert_cleanup:

Changes to test/pragma.test.

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
...
650
651
652
653
654
655
656



















































657


#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma.test,v 1.30 2005/01/08 15:44:26 drh Exp $

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

# Test organization:
#
# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db.
# pragma-2.*: Test synchronous on attached db.
# pragma-3.*: Test detection of table/index inconsistency by integrity_check.
# pragma-4.*: Test cache_size and default_cache_size on attached db.
# pragma-5.*: Test that pragma synchronous may not be used inside of a
#             transaction.



# pragma-9.*: Test temp_store and temp_store_directory.

#

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
file delete test.db
................................................................................
  catchsql "
    PRAGMA temp_store_directory='$pwd';
    SELECT * FROM temp_store_directory_test;
  "
} {1 {no such table: temp_store_directory_test}}
} ;# ifcapable pager_pragmas




















































finish_test









|












>
>
>

>







 







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

>
>
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
...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma.test,v 1.31 2005/01/10 02:48:49 danielk1977 Exp $

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

# Test organization:
#
# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db.
# pragma-2.*: Test synchronous on attached db.
# pragma-3.*: Test detection of table/index inconsistency by integrity_check.
# pragma-4.*: Test cache_size and default_cache_size on attached db.
# pragma-5.*: Test that pragma synchronous may not be used inside of a
#             transaction.
# pragma-6.*: Test schema-query pragmas.
# pragma-7.*: Miscellaneous tests.
# pragma-8.*: Test user_version and schema_version pragmas.
# pragma-9.*: Test temp_store and temp_store_directory.
# pragma-10.*: Test the count_changes pragma in the presence of triggers.
#

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
file delete test.db
................................................................................
  catchsql "
    PRAGMA temp_store_directory='$pwd';
    SELECT * FROM temp_store_directory_test;
  "
} {1 {no such table: temp_store_directory_test}}
} ;# ifcapable pager_pragmas

ifcapable trigger {

do_test pragma-10.0 {
  catchsql {
    DROP TABLE main.t1;
  }
  execsql {
    PRAGMA count_changes = 1;

    CREATE TABLE t1(a PRIMARY KEY);
    CREATE TABLE t1_mirror(a);
    CREATE TABLE t1_mirror2(a);
    CREATE TRIGGER t1_bi BEFORE INSERT ON t1 BEGIN 
      INSERT INTO t1_mirror VALUES(new.a);
    END;
    CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN 
      INSERT INTO t1_mirror2 VALUES(new.a);
    END;
    CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN 
      UPDATE t1_mirror SET a = new.a WHERE a = old.a;
    END;
    CREATE TRIGGER t1_au AFTER UPDATE ON t1 BEGIN 
      UPDATE t1_mirror2 SET a = new.a WHERE a = old.a;
    END;
    CREATE TRIGGER t1_bd BEFORE DELETE ON t1 BEGIN 
      DELETE FROM t1_mirror WHERE a = old.a;
    END;
    CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN 
      DELETE FROM t1_mirror2 WHERE a = old.a;
    END;
  }
} {}

do_test pragma-10.1 {
  execsql {
    INSERT INTO t1 VALUES(randstr(10,10));
  }
} {1}
do_test pragma-10.2 {
  execsql {
    UPDATE t1 SET a = randstr(10,10);
  }
} {1}
do_test pragma-10.3 {
  execsql {
    DELETE FROM t1;
  }
} {1}

} ;# ifcapable trigger

finish_test