SQLite

Check-in [3a6e2afe40]
Login

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

Overview
Comment:Add a few simple test cases for SQLITE_TESTCTRL_INITMODE - cases which also test PRAGMA integrity_check.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | initmode-testctrl
Files: files | file ages | folders
SHA1: 3a6e2afe408d2b0c8166d00def2048568169d87a
User & Date: drh 2015-01-30 15:40:15.485
Context
2015-01-30
15:52
Added SQLITE_TESTCTRL_INITMODE for improved testability. (check-in: 98e029134d user: drh tags: trunk)
15:40
Add a few simple test cases for SQLITE_TESTCTRL_INITMODE - cases which also test PRAGMA integrity_check. (Closed-Leaf check-in: 3a6e2afe40 user: drh tags: initmode-testctrl)
2015-01-29
17:54
Add the INITMODE test-control. (check-in: 5940af8e78 user: drh tags: initmode-testctrl)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/test1.c.
5910
5911
5912
5913
5914
5915
5916
5917

5918
5919
5920
5921
5922
5923
5924
  Tcl_Obj *CONST objv[]
){
  struct Verb {
    const char *zName;
    int i;
  } aVerb[] = {
    { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 
    { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, 

  };
  int iVerb;
  int iFlag;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");







|
>







5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
  Tcl_Obj *CONST objv[]
){
  struct Verb {
    const char *zName;
    int i;
  } aVerb[] = {
    { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 
    { "SQLITE_TESTCTRL_SORTER_MMAP",     SQLITE_TESTCTRL_SORTER_MMAP     }, 
    { "SQLITE_TESTCTRL_INITMODE",        SQLITE_TESTCTRL_INITMODE        },
  };
  int iVerb;
  int iFlag;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
5951
5952
5953
5954
5955
5956
5957















5958
5959
5960
5961
5962
5963
5964
        return TCL_ERROR;
      }
      if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
      if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
      sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
      break;
    }















  }

  Tcl_ResetResult(interp);
  return TCL_OK;
}

#if SQLITE_OS_UNIX







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







5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
        return TCL_ERROR;
      }
      if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
      if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
      sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
      break;
    }

    case SQLITE_TESTCTRL_INITMODE: {
      int fBusy, iDb, newTnum;
      sqlite3 *db;
      if( objc!=6 ){
        Tcl_WrongNumArgs(interp, 2, objv, "DB fBusy iDb newTnum");
        return TCL_ERROR;
      }
      if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
      if( Tcl_GetIntFromObj(interp, objv[3], &fBusy) ) return TCL_ERROR;
      if( Tcl_GetIntFromObj(interp, objv[4], &iDb) ) return TCL_ERROR;
      if( Tcl_GetIntFromObj(interp, objv[5], &newTnum) ) return TCL_ERROR;
      sqlite3_test_control(SQLITE_TESTCTRL_INITMODE, db, fBusy, iDb, newTnum);
      break;
    }
  }

  Tcl_ResetResult(interp);
  return TCL_OK;
}

#if SQLITE_OS_UNIX
Added test/initmode.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 2015-01-30
#
# 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.
#
#***********************************************************************
#
# This file implements tests for SQLite library.
#
# The focus of this file is adding extra entries in the symbol table
# using sqlite3_test_control(SQLITE_TESTCTRL_INITMODE) and verifying that
# SQLite handles those as expected.
#

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

# Create a bunch of data to sort against
#
do_test initmode-1.0 {
  execsql {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d NOT NULL);
    CREATE INDEX t1b ON t1(b);
    CREATE UNIQUE INDEX t1c ON t1(c);
    WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<30)
      INSERT INTO t1(a,b,c,d) SELECT i,1000+i,2000+i,3000+i FROM c;
  }
  set t1_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1'}]
  set t1a_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1a'}]
  set t1b_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1b'}]

  # Create a shadow table that uses the same b-tree as t1 but which does
  # not have the indexes
  #
  sqlite3_test_control SQLITE_TESTCTRL_INITMODE db 1 0 $t1_root
  db eval {CREATE TABLE xt1(a,b,c,d)}
  sqlite3_test_control SQLITE_TESTCTRL_INITMODE db 0 0 0

  # Create triggers to record changes to xt1.
  #
  db eval {
    CREATE TEMP TABLE chnglog(desc TEXT);
    CREATE TEMP TRIGGER xt1_del AFTER DELETE ON xt1 BEGIN
      INSERT INTO chnglog VALUES(
           printf('DELETE t1: rowid=%d, a=%s, b=%s, c=%s, d=%s',
                  old.rowid, quote(old.a), quote(old.b), quote(old.c),
                  quote(old.d)));
    END;
    CREATE TEMP TRIGGER xt1_ins AFTER INSERT ON xt1 BEGIN
      INSERT INTO chnglog VALUES(
           printf('INSERT t1:  rowid=%d, a=%s, b=%s, c=%s, d=%s',
                  new.rowid, quote(new.a), quote(new.b), quote(new.c),
                  quote(new.d)));
    END;
  }
} {}

# The xt1 table has separate xt1.rowid and xt1.a columns.  The xt1.rowid
# column corresponds to t1.rowid and t1.a, but the xt1.a column is always
# NULL
#
do_execsql_test initmode-1.1 {
  SELECT rowid FROM xt1 WHERE a IS NOT NULL;
} {}
do_execsql_test initmode-1.2 {
  SELECT a,b,c,d FROM t1 EXCEPT SELECT rowid,b,c,d FROM xt1;
  SELECT rowid,b,c,d FROM xt1 EXCEPT SELECT a,b,c,d FROM t1;
} {}


# Make changes via the xt1 shadow table.  This will not update the
# indexes on t1 nor check the uniqueness constraint on t1.c nor check
# the NOT NULL constraint on t1.d, resulting in a logically inconsistent
# database.
#
do_execsql_test initmode-1.3 {
  DELETE FROM xt1 WHERE rowid=5;
  INSERT INTO xt1(rowid,a,b,c,d) VALUES(99,'hello',1099,2022,NULL);
  SELECT * FROM chnglog ORDER BY rowid;
} [list \
  {DELETE t1: rowid=5, a=NULL, b=1005, c=2005, d=3005} \
  {INSERT t1:  rowid=99, a='hello', b=1099, c=2022, d=NULL} \
]

do_execsql_test initmode-1.4a {
  PRAGMA integrity_check;
} {/NULL value in t1.d/}
do_execsql_test initmode-1.4b {
  PRAGMA integrity_check;
} {/row # missing from index t1b/}
do_execsql_test initmode-1.4c {
  PRAGMA integrity_check;
} {/row # missing from index t1c/}

finish_test