# データベース設計書

## 概要

本ドキュメントは、serve-d（D言語向けLanguage Server Protocol実装）プロジェクトにおけるデータストレージ設計を記述する。serve-dは従来のリレーショナルデータベース（SQL、MySQL、PostgreSQLなど）を使用していない。代わりに、インメモリデータ構造とファイルベースのバイナリキャッシュによるデータ永続化の仕組みを採用している。

本設計書では、serve-dが管理する主要なデータストア（インメモリストア及びファイルベースストア）をテーブルに見立てて定義する。

## テーブル一覧

| テーブル名 | 対応エンティティ | 説明 |
| --- | --- | --- |
| IndexCache (symbolindex.bin) | IndexCache / IndexedFile | ファイルベースのシンボルインデックスキャッシュ。バイナリ形式でディスクに永続化される |
| ImportCacheEntry | ImportCacheEntry | インメモリのモジュール別インポート・定義キャッシュ |
| DefinitionElement | DefinitionElement | シンボル定義の詳細情報。IndexCache及びImportCacheEntryの子要素 |
| TextDocumentManager (documentStore) | Document | LSPクライアントから受信したドキュメントのインメモリストア |
| Configuration (UserConfiguration) | Configuration | ワークスペース毎のユーザ設定情報 |
| Configuration (Backend) | workspaced.backend.Configuration | コンポーネント設定のキーバリューストア |
| ProfileGCCache | ProfileGCCache / ProfileGCEntry | GCプロファイル情報のインメモリキャッシュ |
| PerDocumentCache | PerDocumentCache(T) | ドキュメント単位の汎用キャッシュ構造 |
| CompileCache | CompileCache | インポートコンパイル時間のインメモリキャッシュ |
| Workspace | Workspace | ワークスペース管理情報 |
| WorkspaceD.Instance | WorkspaceD.Instance | ワークスペースインスタンスとコンポーネント管理 |

## 各テーブル定義

### 1. IndexCache (symbolindex.bin)

ファイルベースのシンボルインデックスキャッシュ。`symbolindex.bin` としてユーザのキャッシュディレクトリ（`$XDG_CACHE_HOME/serve-d/` 等）に保存される。バイナリフォーマットで、ヘッダ（マジックバイト "SvDx" + フォーマットバージョン）に続き、各ファイルのインデックス情報が格納される。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| fileName | string | 不可 | インデックス対象のファイルパス（ルックアップキーとして使用） |
| modName | ModuleRef (string) | 不可 | D言語モジュール名 |
| lastModified | SysTime (long) | 不可 | ファイルの最終更新日時（キャッシュ有効性判定に使用） |
| fileSize | ulong | 不可 | ファイルサイズ（キャッシュ有効性判定に使用） |
| hasMixin | bool (ubyte) | 不可 | mixin文を含むかどうか（不完全なインデックスの判定に使用） |
| elements | DefinitionElement[] | 不可 | シンボル定義のリスト（msgpackでシリアライズ） |

### 2. ImportCacheEntry

インメモリのモジュール別キャッシュエントリ。ModuleRef（モジュール名）をキーとする連想配列で管理される。インデックスコンポーネント（IndexComponent）が保持する。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| success | bool | 不可 | インデックスが成功したかどうか |
| fileName | string | 不可 | ソースファイルのパス |
| lastModified | SysTime | 不可 | ファイルの最終更新日時 |
| fileSize | ulong | 不可 | ファイルサイズ |
| isIncomplete | bool | 不可 | mixin等により不完全なインデックスかどうか |
| _allImports | DefinitionElement[] | 可 | インポート定義のリスト（内部的に_definitionsから抽出） |
| _definitions | DefinitionElement[] | 可 | シンボル定義のリスト |

### 3. DefinitionElement

シンボル（関数、クラス、構造体、列挙型など）の定義情報。IndexCacheおよびImportCacheEntryの子要素として格納される。msgpackによるシリアライズ/デシリアライズに対応している。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| name | string | 不可 | シンボル名 |
| line | int | 不可 | 定義行番号（1始まり） |
| type | char | 不可 | シンボル種別（c=class, s=struct, i=interface, T=template, f=function, g=enum{}, u=union, e=enum member, v=variable, a=alias, I=import 等） |
| attributes | string[string] | 可 | シンボル固有の属性データ |
| range | int[2] | 不可 | ソースコード内の範囲（開始・終了） |
| insideFunction | bool | 不可 | 関数内部で定義されているかどうか |
| insideAggregate | bool | 不可 | 集約型（クラス・構造体等）内部で定義されているかどうか |
| visibility | Visibility (SumType) | 不可 | 可視性（default_, export_, public_, protected_, private_ またはパッケージ名） |
| versioned | VersionCondition[] | 可 | version条件のリスト |
| debugVersioned | VersionCondition[] | 可 | debug条件のリスト |
| hasOtherConditional | bool | 不可 | static if等のコンパイル時条件内にあるかどうか |

### 4. TextDocumentManager (documentStore)

LSPクライアントから送信されるテキストドキュメントのインメモリストア。DocumentUri をキーとする連想配列で管理される。`textDocument/didOpen`、`textDocument/didChange`、`textDocument/didClose` イベントにより更新される。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| uri | DocumentUri (string) | 不可 | ドキュメントURI（主キー） |
| languageId | string | 可 | 言語識別子（d, dpp, c, cpp, sdl, json 等。未設定時は拡張子から推測） |
| version_ | long | 不可 | ドキュメントバージョン（クライアントから報告される） |
| text | char[] | 可 | ドキュメントの内容（テキストバッファ） |

### 5. Configuration (UserConfiguration)

エディタから受信するユーザ設定情報。ワークスペース毎にperWorkspaceConfigurationStoreで管理される。ネストした構造体で複数のセクション（D, DFmt, DScanner, SDL, Editor, Git）を持つ。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| d | D (struct) | 不可 | D言語関連設定（stdlibPath, dcdClientPath, dcdServerPath, dubPath, enableLinting, enableAutoComplete 等多数） |
| dfmt | DFmt (struct) | 不可 | dfmtフォーマッタ設定（alignSwitchStatements, braceStyle, outdentAttributes 等） |
| dscanner | DScanner (struct) | 不可 | D-Scanner設定（ignoredKeys, excludedFiles） |
| sdl | SDL (struct) | 不可 | SDL関連設定（enableFormatting, whitespaceAroundEquals 等） |
| editor | Editor (struct) | 不可 | エディタ設定（rulers, tabSize） |
| git | Git (struct) | 不可 | Git設定（path） |

### 6. Configuration (Backend)

workspace-dバックエンドのコンポーネント設定。キーバリュー形式で、コンポーネント名とキーの組み合わせで値を格納する。SumType（null, string, bool, long, double, 配列, 連想配列）の値を保持できる。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| base | Section[string] | 可 | コンポーネント名をキーとするセクション連想配列 |
| Section.values | ValueT[string] | 可 | キー名をキーとする設定値の連想配列 |

### 7. ProfileGCCache

GCプロファイラ（profilegc.log）の解析結果をインメモリにキャッシュする構造。DocumentUri をキーとして、ドキュメント毎のキャッシュを管理する。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| caches | PerDocumentCache[DocumentUri] | 可 | URI毎のキャッシュエントリ |

ProfileGCEntry（キャッシュの各エントリ）：

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| bytesAllocated | size_t | 不可 | 割り当てられたバイト数 |
| allocationCount | size_t | 不可 | 割り当て回数 |
| type | string | 不可 | 関数名/型名 |
| uri | DocumentUri | 不可 | 正規化されたファイルURI |
| displayFile | string | 不可 | 表示用ファイルパス |
| line | uint | 不可 | 行番号（1始まり） |

### 8. PerDocumentCache(T)

ドキュメント単位の汎用キャッシュ構造。テンプレートパラメータTで任意のデータ型を格納できる。ドキュメントのバージョンを基にキャッシュの有効性を判定する。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| entries | Entry[] | 可 | キャッシュエントリの配列 |
| Entry.document | Document | 不可 | 対応するドキュメント（URIとバージョンを保持） |
| Entry.data | T | 可 | キャッシュされたデータ |

### 9. CompileCache

インポート文のコンパイル時間をキャッシュする構造。コードレンズ機能で使用され、一定時間（2分～20分、コンパイル時間に応じて変動）有効なインメモリキャッシュとして機能する。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| at | SysTime | 不可 | キャッシュ生成時刻 |
| code | string | 不可 | インポート文のコード |
| ret | int | 不可 | コンパイル時間（ミリ秒） |

### 10. Workspace

LSPワークスペースの管理情報。複数ワークスペース対応で、配列として管理される。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| folder | WorkspaceFolder | 不可 | ワークスペースフォルダ情報（URI、名前） |
| initialized | bool | 不可 | 初期化済みかどうか |
| disabled | bool | 不可 | 無効化されているかどうか |
| startupErrorNotifications | string[string] | 可 | 起動時エラー通知（フォルダURI→エラーメッセージ） |
| selected | bool | 不可 | 現在アクティブなワークスペースかどうか |
| useGlobalConfig | bool | 不可 | グローバル設定を使用するかどうか |

### 11. WorkspaceD.Instance

workspace-dバックエンドのインスタンス。各ワークスペースに対応し、コンポーネントの管理と設定を行う。

| カラム名 | データ型 | NULL | 説明 |
| --- | --- | --- | --- |
| cwd | string | 不可 | 作業ディレクトリ（正規化パス） |
| instanceComponents | ComponentWrapperInstance[] | 可 | アタッチされたコンポーネントのリスト |
| config | Configuration | 不可 | バックエンド設定 |
| importPathProvider | ImportPathProvider (delegate) | 可 | インポートパスプロバイダ |
| stringImportPathProvider | ImportPathProvider (delegate) | 可 | 文字列インポートパスプロバイダ |
| importFilesProvider | ImportPathProvider (delegate) | 可 | インポートファイルプロバイダ |
| projectVersionsProvider | IdentifierListProvider (delegate) | 可 | プロジェクトバージョンプロバイダ |
| debugSpecificationsProvider | IdentifierListProvider (delegate) | 可 | デバッグ仕様プロバイダ |

## 備考

### データ永続化方式

serve-dは以下の2層のデータストレージ方式を採用している。

1. **ファイルベース永続化**: IndexCache（symbolindex.bin）のみがディスクに永続化される。バイナリ形式で、ヘッダのマジックバイト "SvDx" とフォーマットバージョンを持つ独自フォーマットを使用する。保存先はOSのキャッシュディレクトリ（`$XDG_CACHE_HOME/serve-d/` または `%LOCALAPPDATA%/serve-d/`）である。

2. **インメモリストア**: その他のデータストア（TextDocumentManager, ImportCacheEntry, ProfileGCCache, Configuration等）は全てインメモリで管理され、プロセス終了時に破棄される。

### スレッドセーフティ

- IndexComponent内のキャッシュ（cache, reverseImports, reverseDefinitions, allGlobals）はMutex（cachesMutex）で保護されている。
- IndexCacheのlookupはMutex（lookupMutex）で保護されている。
- TextDocumentManagerはスレッドセーフではなく、単一スレッドからのアクセスを前提としている。

### シリアライズ方式

- DefinitionElementはmsgpackによるシリアライズ/デシリアライズに対応し、serializeVersionフィールド（現在: 2）によるバージョン管理が行われている。
- IndexCacheのファイルフォーマットはリトルエンディアンのバイナリ形式で、追記モード（append）に対応している。
- UserConfigurationはJSON形式でLSPクライアントとの間でやり取りされる（mir.serdeによるデシリアライズ）。
