SQLite Forum

checkpointing 9th attached database checkpoints all databases
Login
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
<br><code>assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );</code><br>
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):-
<code>
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
</code>
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 ){
```