# Row not saving with ATTACH from another DB in WAL mode

**URL:** <https://discuss.zetetic.net/t/row-not-saving-with-attach-from-another-db-in-wal-mode/6546>\
**Category:** Issues\
**Created:** [July 20, 2024, 8:03pm UTC](https://discuss.zetetic.net/t/row-not-saving-with-attach-from-another-db-in-wal-mode/6546 "2024-07-20T20:03:15Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ojuswi](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/ojuswi/32/2269_2.png) [@Ojuswi](https://discuss.zetetic.net/u/Ojuswi)\
**Post date:** [July 20, 2024, 8:03pm UTC](https://discuss.zetetic.net/t/row-not-saving-with-attach-from-another-db-in-wal-mode/6546/1 "2024-07-20T20:03:16Z")

</div>

Hi, I noticed something interesting and want to understand if it’s expected.

There are two DBs `plain.db` and `cipher.db` (encrypted)

1. Create a sqlite connection to `plain.db` and a sqlcipher connection to `cipher.db`
2. Attach and detach the `plain.db` with `cipher.db` in the sqlicipher connection
3. Insert a value in the `plain.db` via the plain sqlite connection created in step 1, and check if the value is there.
4. Kill the process with the connection open.

### Expected Behavior

When we reopen the `plain.db`, the value should still be present in it.

### Actual Behavior

The value is not found anymore in `plain.db`, with sqlite version \>= 3.44 and both DBs in WAL mode.

### Steps to Reproduce

This issue can only be reproduced when:

- sqlite version \>= 3.44
- DBs are in WAL mode
- `cipher.db` is encrypted
- ATTACH is done
- Process is killed

Python scripts to reproduce the issue. Usage `python test.py`

`test.py`

```py
import os
import sqlite3
import subprocess
from time import sleep

def main():
    if os.path.exists('plain.db'):
        os.remove('plain.db')
    if os.path.exists('cipher.db'):
        os.remove('cipher.db')

    process = subprocess.Popen(
        [
            'python',
            'insert_attach_kill.py',
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True,
    )
    sleep(1)
    process.kill()
    stdout, stderr = process.communicate()
    assert stdout == '', stdout
    assert stderr == '', stderr

    conn_plain = sqlite3.connect("plain.db")
    cursor_plain = conn_plain.cursor()
    
    db_value = cursor_plain.execute("SELECT * FROM A;").fetchone()
    assert db_value == (1,), f'{db_value} != (1,)' # this fails

if __name__ == " __main__":
    main()

```

`insert_attach_kill.py`

````py
import sqlite3
from time import sleep
from pysqlcipher3 import dbapi2 as sqlcipher

def main():
    conn_plain = sqlite3.connect("plain.db")
    cursor_plain = conn_plain.cursor()
    cursor_plain.execute("PRAGMA journal_mode=WAL;")
    cursor_plain.execute("CREATE TABLE IF NOT EXISTS A(a);")

    conn_cipher = sqlcipher.connect("cipher.db")
    cursor_cipher = conn_cipher.cursor()
    cursor_cipher.execute('PRAGMA key="password";')
    cursor_cipher.execute("PRAGMA journal_mode=WAL;")
    cursor_cipher.execute('ATTACH DATABASE "plain.db" AS plain KEY "";')
    cursor_cipher.execute('DETACH DATABASE plain;')
    
    cursor_plain.execute('INSERT INTO A VALUES(1);')
    conn_plain.commit()

    db_value = cursor_plain.execute("SELECT * FROM A;").fetchone()
    assert db_value == (1,), f'{db_value} != (1,)'

    sleep(10)

if __name__ == " __main__":
    main()```
````

---

<div class="post-metadata">

**Author:** ![sjlombardo](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/sjlombardo/32/3_2.png) [@sjlombardo](https://discuss.zetetic.net/u/sjlombardo)\
**Post date:** [September 17, 2024, 5:23pm UTC](https://discuss.zetetic.net/t/row-not-saving-with-attach-from-another-db-in-wal-mode/6546/2 "2024-09-17T17:23:38Z")

</div>

@Ojuswi the problem in this case is that you are using two different SQLite libraries. This is not supported and know to [cause locking and corruption issues](https://www.sqlite.org/howtocorrupt.html#multiple_copies_of_sqlite_linked_into_the_same_application). Remove all references to `sqlite3`, and only use `sqlcipher`. You can still create plaintext databases with sqlcipher, just don’t set a key. If you make that change everything will work as expected.
