# 機能設計書 18-D1 SQLite アダプター

## 概要

本ドキュメントは、Payload CMSにおけるCloudflare D1 SQLite アダプター（`@payloadcms/db-d1-sqlite`）の設計を定義する。Cloudflare Workers上でのD1データベースとの接続、CRUD操作、スキーマ管理をDrizzle ORMを通じて提供する。

### 本機能の処理概要

D1 SQLite アダプターは、Payload CMSとCloudflare D1間のインターフェースを提供するデータベースアダプターである。Cloudflare Workersのエッジ環境に最適化されており、D1バインディングを通じてSQLiteデータベースにアクセスする。

**業務上の目的・背景**：Cloudflare D1は、Cloudflare Workers上で動作するサーバーレスSQLiteデータベースである。エッジコンピューティング環境でのグローバルな低レイテンシアクセスを実現し、サーバーレスアプリケーションのデータ永続化を提供する。

**機能の利用シーン**：
- Cloudflare Workersへのデプロイ
- エッジコンピューティング環境でのCMS運用
- グローバルに分散したアプリケーション
- サーバーレス環境での軽量データストア

**主要な処理内容**：
1. 接続管理：D1バインディング経由の接続
2. リードレプリカ：first-primaryストラテジーのサポート
3. CRUD操作：Drizzle ORM経由のデータ操作
4. マイグレーション：スキーマ変更のマイグレーション生成・実行

**関連システム・外部連携**：
- Cloudflare D1
- Cloudflare Workers
- Drizzle ORM
- @payloadcms/drizzle

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （該当なし） | - | データベース層のため画面連携なし |

## 機能種別

データベースアダプター / ORM統合 / エッジコンピューティング対応

## 入力仕様

### アダプター設定パラメータ

| パラメータ名 | 型 | 必須 | 説明 | デフォルト |
|-------------|-----|-----|------|-----------|
| binding | AnyD1Database | Yes | D1データベースバインディング | - |
| idType | 'number' / 'uuid' | No | ID生成タイプ | 'number' |
| allowIDOnCreate | boolean | No | create時にカスタムIDを許可 | false |
| autoIncrement | boolean | No | 自動インクリメントID | false |
| blocksAsJSON | boolean | No | ブロックをJSON列で保存 | false |
| readReplicas | 'first-primary' | No | リードレプリカストラテジー（実験的） | undefined |
| localesSuffix | string | No | ロケールテーブルの接尾辞 | '_locales' |
| relationshipsSuffix | string | No | リレーションテーブルの接尾辞 | '_rels' |
| versionsSuffix | string | No | バージョンテーブルの接尾辞 | '_v' |
| transactionOptions | TransactionConfig / false | No | トランザクションオプション | undefined |
| logger | DrizzleConfig['logger'] | No | ロガー設定 | false |
| prodMigrations | MigrationConfig[] | No | 本番用マイグレーション定義 | undefined |

### D1バインディング

```typescript
// wrangler.tomlでの設定例
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

// Payload設定での使用
import { sqliteD1Adapter } from '@payloadcms/db-d1-sqlite'

export default buildConfig({
  db: sqliteD1Adapter({
    binding: env.DB, // Cloudflare Workersの環境変数から取得
  }),
})
```

## 出力仕様

PayloadのドキュメントフォーマットでJSON形式のデータを返却。

## 処理フロー

### 初期化処理

```
1. sqliteD1Adapter()呼び出し
   └─ binding（D1バインディング）を必須で受け取る

2. IDタイプ設定
   └─ number→'number'、uuid→'text'に変換

3. 演算子オーバーライド
   └─ SQLiteのlikeは大文字小文字区別なし

4. createDatabaseAdapter()
   └─ limitedBoundParameters: true を設定
   └─ 共通アダプターインターフェースでラップ

5. connect()実行
   └─ readReplicasストラテジー判定
   └─ drizzle(binding)でDrizzleインスタンス生成
```

### リードレプリカ設定

```
リードレプリカ設定（実験的）:
1. readReplicas = 'first-primary' の場合
   └─ binding.withSession('first-primary')を使用
   └─ D1のfirst-primaryストラテジーでセッション確立

2. readReplicas未設定の場合
   └─ 通常のバインディングを使用
```

## ビジネスルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | IDタイプデフォルト | idType='number'がデフォルト | 全コレクション |
| BR-02 | バインディング必須 | D1バインディングは必須パラメータ | 常時 |
| BR-03 | limitedBoundParameters | D1はバインドパラメータ数に制限あり | 常時 |
| BR-04 | like演算子 | SQLiteのlikeは大文字小文字を区別しない | contains、like操作 |
| BR-05 | upsert制限 | upsertはupdateOneにフォールバック | D1固有の制限 |

## 特殊制約

### limitedBoundParameters

D1データベースはバインドパラメータ数に制限があるため、`limitedBoundParameters: true`が設定されている。これにより、大量のパラメータを使用するクエリは自動的に分割される。

```typescript
// index.ts 128行目
limitedBoundParameters: true,
```

### upsert制限

D1アダプターでは`upsert`操作が`updateOne`にフォールバックされる。

```typescript
// index.ts 204行目
upsert: updateOne,
```

## パフォーマンス要件

- エッジロケーションでの低レイテンシアクセス
- Cloudflare D1の制限（ストレージ、クエリ数）を考慮
- first-primaryストラテジーによる読み取り最適化

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

- Cloudflare Workersの環境変数によるバインディング管理
- D1の認証・認可はCloudflareプラットフォームが管理
- 接続文字列不要（バインディング経由）

---

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

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/db-d1-sqlite/src/index.ts` | ソース | アダプターエントリーポイント |
| types.ts | `packages/db-d1-sqlite/src/types.ts` | ソース | 型定義 |
| connect.ts | `packages/db-d1-sqlite/src/connect.ts` | ソース | D1接続処理 |
| execute.ts | `packages/db-d1-sqlite/src/execute.ts` | ソース | SQL実行処理 |

### 推奨リーディング順序

1. **types.ts** - Args型（binding必須）とSQLiteD1Adapter型の定義を確認
2. **index.ts** - sqliteD1Adapter()関数でアダプター構造を理解
3. **connect.ts** - D1バインディング経由の接続処理を確認

### 主要処理フロー

#### index.ts

- **65行目**: sqliteD1Adapter関数（エントリーポイント）
- **66-68行目**: IDタイプ初期化（number→'number'、uuid→'text'）
- **80-86行目**: SQLite用演算子オーバーライド（like、contains、not_like）
- **102-205行目**: createDatabaseAdapterでアダプター生成
- **108行目**: binding設定（D1バインディング）
- **128行目**: limitedBoundParameters: true（D1固有）
- **137行目**: readReplicasオプション
- **193行目**: packageNameは'@payloadcms/db-d1-sqlite'
- **204行目**: upsert: updateOne（D1制限によるフォールバック）
- **217行目**: name: 'd1-sqlite'（アダプター名）

#### connect.ts

- **17-20行目**: スキーマ構築（tables + relations）
- **26-31行目**: readReplicasストラテジー判定
- **28-30行目**: first-primaryストラテジーでwithSession()使用
- **33-36行目**: drizzle(binding)でDrizzleインスタンス生成
- **38行目**: client設定（drizzle.$client）
- **58-64行目**: 開発環境でpushDevSchema実行
- **70-72行目**: 本番環境でprodMigrationsによるマイグレーション実行

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

```
sqliteD1Adapter()
├── createDatabaseAdapter() - 共通アダプターラッパー
│   └── limitedBoundParameters: true
├── connect()
│   ├── binding.withSession() - リードレプリカ（オプション）
│   ├── drizzle(binding) - Drizzleインスタンス生成
│   ├── pushDevSchema() - 開発環境スキーマ同期
│   └── migrate() - 本番マイグレーション実行
└── @payloadcms/drizzle - CRUD操作群
    ├── find()
    ├── create()
    ├── update()
    └── delete()
```

### データフロー図

```
[Payload CMS]
     │
     ▼
[sqliteD1Adapter]
     │
     ├──[binding取得]
     │      │
     │      ▼
     │  [D1 Binding]
     │      │
     │      ├──[readReplicas設定]──┐
     │      │                      │
     │      ▼                      ▼
     │  [通常]              [withSession]
     │      │                      │
     │      └──────────┬───────────┘
     │                 ▼
     │         [drizzle-orm/d1]
     │                 │
     └─────────────────┘
                       │
                       ▼
          [Cloudflare D1 Database]
```

### SQLiteアダプターとの違い

| 機能 | SQLiteアダプター | D1 SQLiteアダプター |
|------|-----------------|-------------------|
| パッケージ | @payloadcms/db-sqlite | @payloadcms/db-d1-sqlite |
| クライアント | @libsql/client | D1バインディング |
| 接続方法 | createClient() | Cloudflare環境変数 |
| WALモード | サポート | 非対応（D1管理） |
| busyTimeout | サポート | 非対応 |
| limitedBoundParameters | false | true |
| upsert | 通常サポート | updateOneフォールバック |
| readReplicas | - | first-primary（実験的） |
