SQLite3 CLIで複数のデータベース接続を可能にする .CONNECTIONドットコマンド

# はじめに

[SQLite3 Command Line Shell dot-commands マニュアル(完全版)](https://www.sqlite.org/cli.html) を更新した際、バージョン3.37.0（2021-11-27）からCLIが複数のデータベース接続を同時にオープンできるようになったことが分かりました。しかし、公式ドキュメントには詳細が記載されていなかったため、使い方を備忘録としてまとめました。

SQLite という OSS データベースは、ユーザーが SQLite データベースで SQL ステートメントを入力して実行できるようにする、sqlite3 (Windowsでは sqlite3.exe) というコマンドラインシェルプログラム(以下、CLI)を提供しています。Oracle の SQL*Plus や PostgreSQL の psql に相当します。

この CLI は、通常、入力された SQL ステートメントを実行しますが、"." で始まる ドットコマンド と呼ばれる特別なコマンドも存在します。

# 複数のデータベース接続の操作

バージョン3.37.0 以降、CLIは複数のデータベース接続を同時にオープンできます。一度にアクティブにできるのは 1つのデータベース接続のみで、非アクティブな接続はオープンしたままですが、アイドル状態です。

".connection" ドットコマンド (.conn と省略可能) を使用すると、データベース接続リストと現在アクティブな接続を表示できます。".conn" ドットコマンドの後に番号を入力することで、異なるデータベース接続に切り替え可能です。データベース接続がまだない場合、新たな接続を作成してから切り替えます。

```bash
$ sqlite3 test0.db
SQLite version 3.45.1 2024-01-30 16:01:20
Enter ".help" for usage hints.
sqlite> .conn
ACTIVE 0: test0.db
sqlite> .conn 1
sqlite> .conn
ACTIVE 1: (memory)
```

".conn" ドットコマンドは接続を作成するのみです。そのため、メモリデータベースではなくデータベースファイルを使用したい場合は、".open" ドットコマンドを使用してデータベースファイルを開きます。

```sql
sqlite> .open test1.db
sqlite> .conn
ACTIVE 1: test1.db
```

データベース接続をクローズするには、".conn close N"と入力します。(Nは接続番号)

```sql
sqlite> .conn 0
sqlite> .conn
ACTIVE 0: test0.db
       1: test1.db
sqlite> .conn close 1
sqlite> .conn
ACTIVE 0: test0.db
```

# 最大データベース接続数

同時接続数について、公式サイトには「各データベース接続は0から9までの整数で識別されます。同時に開くことができる接続は最大10個です」と公式サイトには書いています。以下のように接続番号は0～9までエラーとなりません。しかし、接続リストを確認すると、2つの接続しかありません。

```sql
sqlite> .conn 0
sqlite> .conn 1
sqlite> .conn 2
sqlite> .conn 3
sqlite> .conn 4
sqlite> .conn 5
sqlite> .conn 6
sqlite> .conn 7
sqlite> .conn 8
sqlite> .conn 9
sqlite> .conn 10
Usage: .connection [close] [CONNECTION-NUMBER]
sqlite> .conn
       0: test0.db
ACTIVE 4: (memory)
```

動作確認の結果、実際の最大接続数は5つであることがわかりました。shell.cのコードを見ると、データベース接続(aAuxDb)のサイズが5に設定されているため、コードを見ても最大接続数は5つであると確認できます。

```sql
sqlite> .conn 1
sqlite> .open test1.db
sqlite> .conn 2
sqlite> .open test2.db
sqlite> .conn 3
sqlite> .open test3.db
sqlite> .conn 4
sqlite> .open test4.db
sqlite> .conn
       0: test0.db
       1: test1.db
       2: test2.db
       3: test3.db
ACTIVE 4: test4.db
sqlite> .conn 5
sqlite> .open test5.db
sqlite> .conn
       0: test0.db
       1: test1.db
       2: test2.db
       3: test3.db
ACTIVE 4: test5.db
```

shell.cのコードを見ると、データベース接続(aAuxDb)のサイズが5に設定されているため、コードを見ても最大接続数は5つであると確認できます。
ソースコードからインストールしている場合は、aAuxDb配列の要素数を変更してビルドすることで最大接続数を変更することが可能です。

```c
struct ShellState {
  sqlite3 *db;           /* The database */
  ...
  struct AuxDb {         /* Storage space for auxiliary database connections */
    sqlite3 *db;         /* Connection pointer */
    ...
  } aAuxDb[5],           /* Array of all database connections */
    *pAuxDb;             /* Currently active database connection */
  ...
}
```

# CLI設定と.CONNECTION

SQLiteデータベースの接続は互いに独立しているものの、出力形式を含む多くのCLI設定が全ての接続で共有されています。そのため、一つの接続で出力モードを変更すると、他の全ての接続にもその変更が適用されます。

.show ドットコマンドで現在、設定されている値を表示します。次に接続を切り替えて、設定されている値を表示します。オープンしているデータベースファイル名以外の設定は同じ表示となります。

```sql
sqlite> .conn 0
sqlite> .show
        echo: off
         eqp: off
     explain: auto
     headers: off
        mode: list
   nullvalue: ""
      output: stdout
colseparator: "|"
rowseparator: "\n"
       stats: off
       width:
    filename: test0.db
sqlite> .conn 1
sqlite> .show
        echo: off
         eqp: off
     explain: auto
     headers: off
        mode: list
   nullvalue: ""
      output: stdout
colseparator: "|"
rowseparator: "\n"
       stats: off
       width:
    filename: test1.db
```

# 注意点

新しい接続を作成した後、データベースが作成されていない場合、接続を切り替えるとその接続は失われるため注意が必要です。例えば、接続1と3でデータベースが作成されていない場合、接続0、2 のみが保持されます。

```sql
$ sqlite3 test0.db
SQLite version 3.45.1 2024-01-30 16:01:20
Enter ".help" for usage hints.
sqlite> .conn 1
sqlite> .conn
       0: test0.db
ACTIVE 1: (memory)
sqlite> .conn 2
sqlite> .open :memory:
sqlite> .conn 
       0: test0.db
ACTIVE 2: :memory:
sqlite> .conn 3
sqlite> .conn
       0: db0.db
       2: :memory:
ACTIVE 3: (memory)
sqlite> .conn 0
sqlite> .conn
ACTIVE 0: test0.db
       2: :memory:
```

# ところで .CONNECTION ドットコマンドは何に使うのか?

.CONNECTION ドットコマンドは、SQLite3の複数のデータベース接続を開いたり閉じたりするために使用されます。これまで、SQLite3のthreading_modeの動作を確認する際には専用のプログラムが必要でしたが、.CONNECTIONドットコマンドを使うことで、より簡単にこれを行うことができます。例えば、複数データベース接続環境でのトランザクション排他制御を確認する際、より簡単に行えると考えます。

詳細については [Using SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html) をご参照ください。

# まとめ
バージョン3.37.0 以降、追加された .CONNECTIONドットコマンドについて、SQLite3 CLIで複数のデータベース接続ができることを確認しました。公式サイトだけで不明だった点についても確認してまとめました。

この "dot commands" は、バージョン毎に改善されて、さまざまコマンドがサポートされています。特にバッチ実行で効果を発揮すると思われ、知っていると自動化に大きな違いが出てくると思います。

もし、記述について誤りがあったり、気になることがあれば、編集リクエストやコメントでフィードバックしていただけると助かります。