SQLite Forum

checkpointing 9th attached database checkpoints all databases
Login

checkpointing 9th attached database checkpoints all databases

(1) By Richard PArkins (rparkins) on 2021-03-10 14:11:15 [source]

The problem is in the interface to sqlite3Checkpoint(), where the value SQLITE_MAX_ATTACHED for the argument iDb is used to indicate that all databases are to be checkpointed.

Presumably the assumption of the writer of this code was that index into the array aDb in a struct sqlite3 must be less than SQLITE_MAX_ATTACHED. Unfortunately this is incorrect.

As stated in the comment on the definition of struct Db, aDb[0] and aDb[1] are reserved for the main and temp databases respectively, and SQLITE_MAX_ATTACHED further databases can be attached, making the maximum possible index SQLITE_MAX_ATTACHED+1.

I think that line 103198
assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
is a bit dubious as well. sqlite3SchemaToIndex() can validly return SQLITE_MAX_ATTACHED or SQLITE_MAX_ATTACHED+1 as noted above.

This is a script that demonstrates the problem (assuming that sqlite is compiled with the default SQLITE_MAX_ATTACHED of 10):- gdb sqlite3 start break sqlite3.c:166381 c .open main.sqlite ATTACH 'attach1.sqlite' AS 'attach1'; ATTACH 'attach2.sqlite' AS 'attach2'; ATTACH 'attach3.sqlite' AS 'attach3'; ATTACH 'attach4.sqlite' AS 'attach4'; ATTACH 'attach5.sqlite' AS 'attach5'; ATTACH 'attach6.sqlite' AS 'attach6'; ATTACH 'attach7.sqlite' AS 'attach7'; ATTACH 'attach8.sqlite' AS 'attach8'; ATTACH 'attach9.sqlite' AS 'attach9'; PRAGMA attach8.wal_checkpoint; -- checkpoints one database display i display db->aDb[i].zDbSName c PRAGMA attach9.wal_checkpoint; -- checkpoints all of them c c c c c c c c c c c .quit q This is suggested diff that fixes the problem. It isn't the simplest possible patch, but it has in my opinion better maintainability because any change to the set of reserved slots in the aDb array is propagated to all places in the code that are affected.

    16740,16741c16740,16741
    < ** aDb[1] is the database file used to hold temporary tables.  Additional
    < ** databases may be attached.
    ---
    > ** aDb[1] is the database file used to hold temporary tables.
    > ** SQLITE_LIMIT_ATTACHED additional databases may be attached.
    16742a16743
    > #define SQLITE_MAX_DATABASES (SQLITE_MAX_ATTACHED + 2)
    103198c103199
    <     assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
    ---
    >     assert( iDb>=0 && iDb<SQLITE_MAX_DATABASES );
    116369c116370
    <   assert( iDb<SQLITE_MAX_ATTACHED+2 );
    ---
    >   assert( iDb<SQLITE_MAX_DATABASES);
    129425c129426
    <     int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
    ---
    >     int iBt = (pId2->z?iDb:SQLITE_MAX_DATABASES);
    166292c166293
    <   int iDb = SQLITE_MAX_ATTACHED;  /* sqlite3.aDb[] index of db to checkpoint */
    ---
    >   int iDb = SQLITE_MAX_DATABASES; /* sqlite3.aDb[] index of db to checkpoint */
    166363c166364
    < ** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
    ---
    > ** If iDb is passed SQLITE_MAX_DATABASES, then all attached databases are
    166380c166381
    <     if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
    ---
    >     if( i==iDb || iDb==SQLITE_MAX_DATABASES ){