# 機能設計書 43-sqlite

## 概要

本ドキュメントは、Node.jsの`sqlite`モジュールの機能設計を記載する。SQLiteは軽量で自己完結型のリレーショナルデータベースエンジンであり、このモジュールはNode.jsからSQLiteデータベースへの同期的なアクセスを提供する。

### 本機能の処理概要

sqliteモジュールは、Node.js組み込みのSQLiteデータベースインターフェースを提供する。サーバーレスかつファイルベースのSQLデータベースへのアクセスを可能にし、設定不要でローカルデータの永続化を実現する。

**業務上の目的・背景**：アプリケーション開発において、軽量なローカルデータストレージが必要なケースは多い。従来はBetter-SQLite3やsqlite3などのnpmパッケージに依存していたが、Node.jsにSQLiteを組み込むことで、追加のネイティブモジュールのコンパイルなしにSQLiteを利用できるようになる。これにより、設定ファイルの保存、キャッシュ、ローカルデータの永続化、開発・テスト環境でのデータベース利用などが容易になる。

**機能の利用シーン**：
- Electronアプリケーションでのローカルデータ保存
- CLIツールでの設定・状態管理
- テスト時のインメモリデータベース利用
- 組み込みシステムやIoTデバイスでのデータ保存
- サーバーレス関数でのセッション管理

**主要な処理内容**：
1. データベース接続の作成と管理
2. SQLクエリの実行（SELECT、INSERT、UPDATE、DELETE）
3. プリペアドステートメントの作成と実行
4. トランザクション管理
5. インメモリデータベースの利用

**関連システム・外部連携**：
- SQLiteエンジン（C++バインディング経由）
- ファイルシステム（データベースファイルの永続化）

**権限による制御**：
- ファイルシステムへのアクセス権限に依存
- Node.jsパーミッションシステムとの連携

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当なし |

## 機能種別

データ連携 / CRUD操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| filename | String | Yes | データベースファイルのパス、または':memory:'（インメモリ） | 有効なファイルパス |
| options | Object | No | データベースオプション | - |
| sql | String | Yes | 実行するSQLクエリ | 有効なSQL文 |
| params | Array/Object | No | SQLパラメータ（バインド変数） | - |

### 入力データソース

JavaScriptコード内からの直接呼び出し、SQLiteデータベースファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Database | Class | データベース接続オブジェクト |
| Statement | Class | プリペアドステートメントオブジェクト |
| rows | Array | SELECTクエリの結果行 |
| changes | Number | 変更された行数（INSERT/UPDATE/DELETE） |
| lastInsertRowid | BigInt | 最後に挿入された行のROWID |

### 出力先

呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

```
1. データベースを開く
   └─ new Database(filename, options)
   └─ SQLiteエンジンの初期化
2. プリペアドステートメントの作成（オプション）
   └─ db.prepare(sql)
3. クエリの実行
   └─ stmt.run(params) - INSERT/UPDATE/DELETE
   └─ stmt.get(params) - 1行取得
   └─ stmt.all(params) - 全行取得
4. トランザクション処理（オプション）
   └─ db.exec('BEGIN')
   └─ 複数のクエリ実行
   └─ db.exec('COMMIT') または db.exec('ROLLBACK')
5. データベースを閉じる
   └─ db.close()
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[new Database]
    B --> C{インメモリ?}
    C -->|Yes| D[メモリ上にDB作成]
    C -->|No| E[ファイルを開く/作成]
    D --> F[db.prepare SQL]
    E --> F
    F --> G{クエリ種別}
    G -->|SELECT| H[stmt.all/get]
    G -->|INSERT/UPDATE/DELETE| I[stmt.run]
    G -->|DDL| J[db.exec]
    H --> K[結果を返却]
    I --> L[changes/lastInsertRowidを返却]
    J --> M[実行完了]
    K --> N{継続?}
    L --> N
    M --> N
    N -->|Yes| F
    N -->|No| O[db.close]
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 同期API | すべてのAPIは同期的に実行される | 常時 |
| BR-02 | インメモリDB | ':memory:'指定でインメモリデータベースを作成 | filename指定時 |
| BR-03 | 自動クローズ | プロセス終了時にデータベースは自動的に閉じられる | 常時 |
| BR-04 | WALモード | 書き込み性能向上のためWALモードをサポート | PRAGMA設定時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| stmt.run() | 任意 | INSERT/UPDATE/DELETE | データの変更操作 |
| stmt.get() | 任意 | SELECT | 1行の取得 |
| stmt.all() | 任意 | SELECT | 全行の取得 |
| db.exec() | 任意 | 任意 | 複数SQL文の実行 |

### テーブル別操作詳細

#### 任意のテーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | ユーザー定義 | バインドパラメータ | lastInsertRowid取得可 |
| UPDATE | ユーザー定義 | バインドパラメータ | changes取得可 |
| DELETE | ユーザー定義 | バインドパラメータ | changes取得可 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_ERROR | SQLエラー | SQL構文エラー | クエリの修正 |
| SQLITE_BUSY | ロックエラー | データベースがロック中 | リトライまたは待機 |
| SQLITE_CONSTRAINT | 制約違反 | UNIQUE/FK制約違反 | データの確認 |
| SQLITE_NOTFOUND | 未検出 | テーブル/カラムが存在しない | スキーマの確認 |

### リトライ仕様

SQLITE_BUSYエラー時はbusy_timeoutの設定に応じて自動リトライ

## トランザクション仕様

- BEGINで開始、COMMIT/ROLLBACKで終了
- デフォルトは自動コミットモード
- ネストされたトランザクションはSAVEPOINTで対応

## パフォーマンス要件

- 同期APIのためイベントループをブロック
- 大量データ処理時はワーカースレッドでの実行を推奨
- WALモードで書き込み性能向上

## セキュリティ考慮事項

- **実験的機能**：セキュリティレビューが完了していない可能性
- **SQLインジェクション**：プリペアドステートメントとバインドパラメータを使用
- **ファイルアクセス**：データベースファイルの適切なパーミッション設定

## 備考

- 実験的機能のため、起動時に警告が発行される
- Node.jsに同梱されたSQLiteライブラリを使用
- C++バインディング経由でSQLiteエンジンにアクセス

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

sqliteモジュールのエントリーポイントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqlite.js | `lib/sqlite.js` | 1-6行目のモジュール全体構造 |

**読解のコツ**: このモジュールは非常にシンプルで、C++バインディングを直接エクスポートしている。主要な実装はC++側にあり、JavaScriptはラッパーとして機能する。

#### Step 2: エントリーポイントを理解する

モジュールのエクスポートを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sqlite.js | `lib/sqlite.js` | 2行目の実験的警告 |
| 2-2 | sqlite.js | `lib/sqlite.js` | 4行目のemitExperimentalWarning |
| 2-3 | sqlite.js | `lib/sqlite.js` | 6行目のinternalBinding('sqlite') |

**主要処理フロー**:
1. **2行目**: internal/utilからemitExperimentalWarningをインポート
2. **4行目**: 'SQLite'の実験的警告を発行
3. **6行目**: C++バインディング'sqlite'をそのままエクスポート

#### Step 3: C++バインディングの構造を理解する

実際の実装はC++側にあるため、バインディングの概要を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | (C++ソース) | `src/node_sqlite.cc` | DatabaseクラスとStatementクラスの実装（存在する場合） |

**読解のコツ**:
- JavaScriptレイヤーは薄いラッパーに過ぎない
- 実際のSQLite操作ロジックはC++で実装
- `internalBinding('sqlite')`が返すオブジェクトに主要なクラスとメソッドが含まれる

### プログラム呼び出し階層図

```
require('node:sqlite')
    │
    └─ lib/sqlite.js
           │
           ├─ emitExperimentalWarning('SQLite')
           │
           └─ module.exports = internalBinding('sqlite')
                  │
                  └─ C++ バインディング
                         │
                         ├─ Database クラス
                         │      ├─ constructor(filename, options)
                         │      ├─ prepare(sql)
                         │      ├─ exec(sql)
                         │      └─ close()
                         │
                         └─ Statement クラス
                                ├─ run(...params)
                                ├─ get(...params)
                                └─ all(...params)
```

### データフロー図

```
[入力]                     [処理]                              [出力]

filename              ┌───────────────────────┐
"./data.db"      ───▶│  new Database()       │
or ":memory:"         │  └─ SQLite エンジン   │───▶  Databaseオブジェクト
                      └───────────────────────┘

SQL文                 ┌───────────────────────┐
"SELECT * FROM ..." ─▶│  db.prepare(sql)      │───▶  Statementオブジェクト
                      └───────────────────────┘

params               ┌───────────────────────┐
[1, 'value']    ───▶│  stmt.all(params)     │───▶  結果配列
                     │  └─ SQLite 実行       │      [{id: 1, name: '...'}]
                     └───────────────────────┘

params               ┌───────────────────────┐
[1, 'value']    ───▶│  stmt.run(params)     │───▶  { changes, lastInsertRowid }
                     │  └─ SQLite 実行       │
                     └───────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sqlite.js | `lib/sqlite.js` | ソース | SQLiteモジュールのエントリーポイント |
| util.js | `lib/internal/util.js` | ソース | emitExperimentalWarning関数の提供 |
| (node_sqlite.cc) | `src/node_sqlite.cc` | C++ソース | SQLiteへのC++バインディング（推定） |
