# データベース設計書

## 概要

本ドキュメントは、Node.jsランタイムに組み込まれているSQLiteベースのデータベース機能のスキーマ設計を記述したものです。Node.jsはv22.5.0以降、`node:sqlite`モジュールを通じてSQLiteデータベースへの同期的なアクセスを提供しています。また、Web Storage API（localStorage）の永続化ストレージとしてもSQLiteを使用しています。

本プロジェクトはNode.jsランタイム自体であり、アプリケーション固有のビジネスデータベースを持つものではありません。代わりに、ランタイム機能として提供されるWeb Storage API用の内部スキーマが定義されています。

## テーブル一覧

| テーブル名 | 対応エンティティ | 説明 |
| --- | --- | --- |
| nodejs_webstorage | Web Storage データ | localStorage APIで保存されるキー・バリューペアを格納 |
| nodejs_webstorage_state | ストレージ状態管理 | ストレージの容量制限、使用量、スキーマバージョンを管理 |

## 各テーブル定義

### 1. nodejs_webstorage

localStorageおよびsessionStorage APIで使用されるキー・バリューストアのメインテーブルです。Web Storage仕様に準拠したデータ永続化を実現します。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| key | BLOB | NOT NULL | ストレージキー（UTF-16LEエンコード）。主キー |
| value | BLOB | NOT NULL | ストレージ値（UTF-16LEエンコード） |

**制約:**
- PRIMARY KEY(key)
- STRICTモード有効（型の厳密チェック）

**関連トリガー:**
- `nodejs_quota_insert`: INSERT時に容量チェック
- `nodejs_quota_update`: UPDATE時に容量チェック
- `nodejs_quota_delete`: DELETE時に使用量を減算

### 2. nodejs_webstorage_state

Web Storageの状態を管理するシングルトンテーブルです。ストレージ容量の制限と現在の使用量を追跡し、クォータ超過を防止します。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| max_size | INTEGER | NOT NULL | 最大容量（バイト）。デフォルト: 10,485,760（10MB） |
| total_size | INTEGER | NOT NULL | 現在の使用量（バイト） |
| schema_version | INTEGER | NOT NULL | スキーマバージョン。デフォルト: 0 |
| single_row_ | INTEGER | NOT NULL | シングルトン制約用。常に1。デフォルト: 1 |

**制約:**
- PRIMARY KEY(single_row_)
- CHECK(single_row_ = 1) - 単一行のみ許可
- STRICTモード有効

## トリガー定義

### nodejs_quota_insert

INSERT操作後に実行され、新しいエントリのサイズを使用量に加算し、クォータを超過した場合は操作をアボートします。

```sql
CREATE TRIGGER IF NOT EXISTS nodejs_quota_insert
AFTER INSERT ON nodejs_webstorage
FOR EACH ROW
BEGIN
  UPDATE nodejs_webstorage_state
    SET total_size = total_size + OCTET_LENGTH(NEW.key) + OCTET_LENGTH(NEW.value);
  SELECT RAISE(ABORT, 'QuotaExceeded') WHERE EXISTS (
    SELECT 1 FROM nodejs_webstorage_state WHERE total_size > max_size
  );
END;
```

### nodejs_quota_update

UPDATE操作後に実行され、値の変更分を使用量に反映し、クォータを超過した場合は操作をアボートします。

```sql
CREATE TRIGGER IF NOT EXISTS nodejs_quota_update
AFTER UPDATE ON nodejs_webstorage
FOR EACH ROW
BEGIN
  UPDATE nodejs_webstorage_state
    SET total_size = total_size +
      ((OCTET_LENGTH(NEW.key) + OCTET_LENGTH(NEW.value)) -
      (OCTET_LENGTH(OLD.key) + OCTET_LENGTH(OLD.value)));
  SELECT RAISE(ABORT, 'QuotaExceeded') WHERE EXISTS (
    SELECT 1 FROM nodejs_webstorage_state WHERE total_size > max_size
  );
END;
```

### nodejs_quota_delete

DELETE操作後に実行され、削除されたエントリのサイズを使用量から減算します。

```sql
CREATE TRIGGER IF NOT EXISTS nodejs_quota_delete
AFTER DELETE ON nodejs_webstorage
FOR EACH ROW
BEGIN
  UPDATE nodejs_webstorage_state
    SET total_size = total_size - (OCTET_LENGTH(OLD.key) + OCTET_LENGTH(OLD.value));
END;
```

## データベース設定

### PRAGMAの設定

Web Storageデータベースは以下のPRAGMA設定で初期化されます:

| PRAGMA | 設定値 | 説明 |
| --- | --- | --- |
| encoding | UTF-16le | 文字エンコーディング |
| busy_timeout | 3000 | ビジータイムアウト（ミリ秒） |
| journal_mode | WAL | ライトアヘッドロギングモード |
| synchronous | NORMAL | 同期モード |
| temp_store | memory | 一時ストレージをメモリに配置 |

### スキーマバージョン管理

現在のスキーマバージョンは **1** です。スキーマのマイグレーションは`schema_version`カラムを参照して実行されます。

## node:sqlite モジュールについて

`node:sqlite`モジュールはSQLiteデータベースへの汎用的なアクセスを提供するAPIであり、固定のスキーマを持ちません。ユーザーは任意のテーブル構造を作成できます。

### サポートされるデータ型変換

| SQLite | JavaScript |
| --- | --- |
| NULL | null |
| INTEGER | number または bigint |
| REAL | number |
| TEXT | string |
| BLOB | TypedArray または DataView |

### 主要クラス

- **DatabaseSync**: データベース接続を表すクラス
- **StatementSync**: プリペアドステートメントを表すクラス
- **Session**: 変更セットを追跡するセッションクラス
- **SQLTagStore**: プリペアドステートメントのLRUキャッシュ

## 備考

- 本データベーススキーマはNode.jsランタイムの内部実装であり、アプリケーション開発者が直接操作することは想定されていません
- Web Storage APIの容量制限（10MB）は将来的に設定可能になる可能性があります
- `node:sqlite`モジュールはv22.5.0で追加され、v23.4.0以降は`--experimental-sqlite`フラグなしで利用可能です（ただし依然として実験的機能）
- データベースファイルの場所はローカルストレージの設定に依存しますが、インメモリデータベース（`:memory:`）もサポートされています
