SQLite

Check-in [12c7a83f8e]
Login

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

Overview
Comment:Always reload the schema after a rollback. Ticket #594. (CVS 1229)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 12c7a83f8e4055c4590983ef212648c781ebd963
User & Date: drh 2004-02-12 15:31:21.000
Context
2004-02-12
15:32
Remove unused variable. (CVS 1230) (check-in: 74b234264b user: drh tags: trunk)
15:31
Always reload the schema after a rollback. Ticket #594. (CVS 1229) (check-in: 12c7a83f8e user: drh tags: trunk)
13:02
VACUUM returns SQLITE_INTERRUPT when interrupted. Ticket #593. (CVS 1228) (check-in: 2fe9f5101c user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree_rb.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2003 Feb 4
**
** 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_rb.c,v 1.22 2004/02/11 02:18:06 drh Exp $
**
** This file implements an in-core database using Red-Black balanced
** binary trees.
** 
** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
*/
#include "btree.h"











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2003 Feb 4
**
** 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_rb.c,v 1.23 2004/02/12 15:31:21 drh Exp $
**
** This file implements an in-core database using Red-Black balanced
** binary trees.
** 
** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
*/
#include "btree.h"
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
734
735
736
737
738
739
  RbtCursor **ppCur
){
  RbtCursor *pCur;
  assert(tree);
  pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
  pCur->pTree  = sqliteHashFind(&tree->tblHash, 0, iTable);

  pCur->pRbtree = tree;
  pCur->iTree  = iTable;
  pCur->pOps = &sqliteRbtreeCursorOps;
  pCur->wrFlag = wrFlag;
  pCur->pShared = pCur->pTree->pCursors;
  pCur->pTree->pCursors = pCur;
  

  assert( (*ppCur)->pTree );
  return SQLITE_OK;
}

/*
 * Insert a new record into the Rbtree.  The key is given by (pKey,nKey)







>






<







719
720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
  RbtCursor **ppCur
){
  RbtCursor *pCur;
  assert(tree);
  pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
  pCur->pTree  = sqliteHashFind(&tree->tblHash, 0, iTable);
  assert( pCur->pTree );
  pCur->pRbtree = tree;
  pCur->iTree  = iTable;
  pCur->pOps = &sqliteRbtreeCursorOps;
  pCur->wrFlag = wrFlag;
  pCur->pShared = pCur->pTree->pCursors;
  pCur->pTree->pCursors = pCur;


  assert( (*ppCur)->pTree );
  return SQLITE_OK;
}

/*
 * Insert a new record into the Rbtree.  The key is given by (pKey,nKey)
Changes to src/main.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.147 2004/02/10 02:27:04 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.148 2004/02/12 15:31:21 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
383
384
385
386
387
388
389



390
391
392
393
394
395
396
  
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
    assert( i!=1 );  /* Should have been initialized together with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);



  }
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to







>
>
>







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
  
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
    assert( i!=1 );  /* Should have been initialized together with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
      sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
      sqlite_exec(db, "COMMIT", 0, 0, 0);
    }
    if( rc!=SQLITE_OK ){
      sqliteSetString(pzErrMsg, 
        "unable to upgrade database to the version 2.6 format",
        zErr ? ": " : 0, zErr, (char*)0);
      sqliteStrRealloc(pzErrMsg);
    }
    sqlite_freemem(zErr);
  }

  if( rc!=SQLITE_OK ){
    db->flags &= ~SQLITE_Initialized;
  }







<







421
422
423
424
425
426
427

428
429
430
431
432
433
434
      sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
      sqlite_exec(db, "COMMIT", 0, 0, 0);
    }
    if( rc!=SQLITE_OK ){
      sqliteSetString(pzErrMsg, 
        "unable to upgrade database to the version 2.6 format",
        zErr ? ": " : 0, zErr, (char*)0);

    }
    sqlite_freemem(zErr);
  }

  if( rc!=SQLITE_OK ){
    db->flags &= ~SQLITE_Initialized;
  }
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
  int i;
  for(i=0; i<db->nDb; i++){
    if( db->aDb[i].pBt ){
      sqliteBtreeRollback(db->aDb[i].pBt);
      db->aDb[i].inTrans = 0;
    }
  }

  sqliteRollbackInternalChanges(db);
}

/*
** This routine does the work of either sqlite_exec() or sqlite_compile().
** It works like sqlite_exec() if pVm==NULL and it works like sqlite_compile()
** otherwise.
*/







>
|







582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
  int i;
  for(i=0; i<db->nDb; i++){
    if( db->aDb[i].pBt ){
      sqliteBtreeRollback(db->aDb[i].pBt);
      db->aDb[i].inTrans = 0;
    }
  }
  sqliteResetInternalSchema(db, 0);
  /* sqliteRollbackInternalChanges(db); */
}

/*
** This routine does the work of either sqlite_exec() or sqlite_compile().
** It works like sqlite_exec() if pVm==NULL and it works like sqlite_compile()
** otherwise.
*/
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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 SELECT statements in SQLite.
**
** $Id: select.c,v 1.151 2004/02/09 14:37:50 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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 SELECT statements in SQLite.
**
** $Id: select.c,v 1.152 2004/02/12 15:31:21 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
      if( sqliteExprType(p)==SQLITE_SO_TEXT ){
        zType = "TEXT";
      }else{
        zType = "NUMERIC";
      }
    }
    sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);
    sqliteVdbeChangeP3(v, -1, zType, P3_STATIC);
  }
}

/*
** Generate code that will tell the VDBE the names of columns
** in the result set.  This information is used to provide the
** azCol[] vaolues in the callback.







|







672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
      if( sqliteExprType(p)==SQLITE_SO_TEXT ){
        zType = "TEXT";
      }else{
        zType = "NUMERIC";
      }
    }
    sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);
    sqliteVdbeChangeP3(v, -1, zType, 0);
  }
}

/*
** Generate code that will tell the VDBE the names of columns
** in the result set.  This information is used to provide the
** azCol[] vaolues in the callback.
Changes to src/vdbeaux.c.
825
826
827
828
829
830
831

832
833
834
835
836
837
838
    }else{
      sqliteFree(p->zErrMsg);
    }
    p->zErrMsg = 0;
  }
  Cleanup(p);
  if( p->rc!=SQLITE_OK ){

    switch( p->errorAction ){
      case OE_Abort: {
        if( !p->undoTransOnError ){
          for(i=0; i<db->nDb; i++){
            if( db->aDb[i].pBt ){
              sqliteBtreeRollbackCkpt(db->aDb[i].pBt);
            }







>







825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
    }else{
      sqliteFree(p->zErrMsg);
    }
    p->zErrMsg = 0;
  }
  Cleanup(p);
  if( p->rc!=SQLITE_OK ){
    int saved_flags;
    switch( p->errorAction ){
      case OE_Abort: {
        if( !p->undoTransOnError ){
          for(i=0; i<db->nDb; i++){
            if( db->aDb[i].pBt ){
              sqliteBtreeRollbackCkpt(db->aDb[i].pBt);
            }
Changes to test/attach.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.11 2003/07/18 01:25:35 drh Exp $
#

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

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.12 2004/02/12 15:31:22 drh Exp $
#

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

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
360
361
362
363
364
365
366



367
368

369
370
371
372
373
374
375
do_test attach-3.12 {
  execsql {SELECT * FROM t1}
} {2 2 4 4}
do_test attach-3.13 {
  catchsql {UPDATE t2 SET x=x+1 WHERE x=50}
} {1 {database is locked}}
do_test attach-3.14 {



  # the "database is locked" error on the previous test should have
  # caused a rollback.

  execsql {SELECT * FROM t1}
} {1 2 3 4}

# Ticket #323
do_test attach-4.1 {
  execsql {DETACH db2}
  db2 close







>
>
>
|
|
>







360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
do_test attach-3.12 {
  execsql {SELECT * FROM t1}
} {2 2 4 4}
do_test attach-3.13 {
  catchsql {UPDATE t2 SET x=x+1 WHERE x=50}
} {1 {database is locked}}
do_test attach-3.14 {
  # Unable to reinitialize the schema tables because the aux database
  # is still locked.
  catchsql {SELECT * FROM t1}
} {1 {database is locked}}
do_test attach-3.15 {
  execsql COMMIT db2
  execsql {SELECT * FROM t1}
} {1 2 3 4}

# Ticket #323
do_test attach-4.1 {
  execsql {DETACH db2}
  db2 close
Changes to test/attach2.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach2.test,v 1.4 2004/01/20 11:54:03 drh Exp $
#


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

# Ticket #354







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach2.test,v 1.5 2004/02/12 15:31:22 drh Exp $
#


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

# Ticket #354
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  catchsql {
    INSERT INTO t2.t1 VALUES(1,2);
  }
} {1 {database is locked}}
do_test attach2-2.11 {
  # when the write failed in the previous test, the transaction should
  # have rolled back.

  execsql {
    SELECT * FROM t1
  }
} {}
do_test attach2-2.12 {
  catchsql {
    COMMIT
  }
} {1 {cannot commit - no transaction is active}}

# Ticket #574:  Make sure it works usingi the non-callback API
#
do_test attach2-3.1 {
  db close
  db2 eval ROLLBACK
  set DB [sqlite db test.db]
  set rc [catch {sqlite_compile $DB "ATTACH 'test2.db' AS t2" TAIL} VM]
  if {$rc} {lappend rc $VM}
  sqlite_finalize $VM
  set rc
} {0}
do_test attach2-3.2 {







>














<







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
  catchsql {
    INSERT INTO t2.t1 VALUES(1,2);
  }
} {1 {database is locked}}
do_test attach2-2.11 {
  # when the write failed in the previous test, the transaction should
  # have rolled back.
  db2 eval ROLLBACK
  execsql {
    SELECT * FROM t1
  }
} {}
do_test attach2-2.12 {
  catchsql {
    COMMIT
  }
} {1 {cannot commit - no transaction is active}}

# Ticket #574:  Make sure it works usingi the non-callback API
#
do_test attach2-3.1 {
  db close

  set DB [sqlite db test.db]
  set rc [catch {sqlite_compile $DB "ATTACH 'test2.db' AS t2" TAIL} VM]
  if {$rc} {lappend rc $VM}
  sqlite_finalize $VM
  set rc
} {0}
do_test attach2-3.2 {
Changes to test/interrupt.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2004 Feb 8
#
# 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 regression tests for SQLite library.  The
# focus of this script is the sqlite_interrupt() API.
#
# $Id: interrupt.test,v 1.1 2004/02/12 13:02:57 drh Exp $


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

# Compute a checksum on the entire database.
#













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2004 Feb 8
#
# 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 regression tests for SQLite library.  The
# focus of this script is the sqlite_interrupt() API.
#
# $Id: interrupt.test,v 1.2 2004/02/12 15:31:22 drh Exp $


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

# Compute a checksum on the entire database.
#
101
102
103
104
105
106
107



108
































109
  }
} $cksum
do_test interrupt-2.4 {
  expr {$::origsize>[file size test.db]}
} 1
integrity_check interrupt-2.5





































finish_test







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

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  }
} $cksum
do_test interrupt-2.4 {
  expr {$::origsize>[file size test.db]}
} 1
integrity_check interrupt-2.5

# Ticket #594.  If an interrupt occurs in the middle of a transaction
# and that transaction is later rolled back, the internal schema tables do
# not reset.
#
for {set i 1} {$i<50} {incr i 5} {
  do_test interrupt-3.$i.1 {
    execsql {
      BEGIN;
      CREATE TEMP TABLE t2(x,y);
      SELECT name FROM sqlite_temp_master;
    }
  } {t2}
  do_test interrupt-3.$i.2 {
    set ::sqlite_interrupt_count $::i
    catchsql {
      INSERT INTO t2 SELECT * FROM t1;
    }
  } {1 interrupted}
  do_test interrupt-3.$i.3 {
    execsql {
      SELECT name FROM sqlite_temp_master;
    }
  } {t2}
  do_test interrupt-3.$i.4 {
    catchsql {
      ROLLBACK
    }
  } {0 {}}
  do_test interrupt-3.$i.5 {
    catchsql {SELECT name FROM sqlite_temp_master};
    execsql {
      SELECT name FROM sqlite_temp_master;
    }
  } {}
}

finish_test