|
| 1 | +--- |
| 2 | +description: 323-database-url-for-connectionブランチでの開発時に読み込む |
| 3 | +alwaysApply: false |
| 4 | +--- |
| 5 | +dbOpen Database URL 対応 ブランチルール |
| 6 | +=== |
| 7 | + |
| 8 | +このブランチで実装することは以下の通りです。 |
| 9 | +- `dbOpen` に database URL を使って接続できる新しいオーバーロードを追加し、既存の引数シグネチャは後方互換のため残す。 |
| 10 | +- SQLite / MySQL / MariaDB / PostgreSQL は一般的な database URL 仕様に従い、scheme・認証情報・host・port・database path・query を解釈できる設計に整える。 |
| 11 | +- URL 解析責務を各 driver の `dbOpen` 実装にベタ書きせず、共通化できる層へ寄せて公開 API を汚さない。 |
| 12 | +- 既存の URL 文字列 1 引数版 `dbOpen` と、新しく追加する引数デザインの役割分担を明確にし、曖昧なオーバーロード解決を避ける。 |
| 13 | +- 既存テスト・example・README・`documents/rdb/query_builder.md` を、最終仕様と齟齬がない状態へ同期する。 |
| 14 | + |
| 15 | +## 進捗 |
| 16 | +- [x] `.cursor/rules/project.mdc` と `.cursor/rules/branch.mdc` を確認した |
| 17 | +- [x] 現在のブランチ名に対応するブランチルールファイルが未作成であることを確認した |
| 18 | +- [x] 既存 `dbOpen` 実装が SQLite / MySQL / MariaDB / PostgreSQL / SurrealDB でどう分かれているか確認した |
| 19 | +- [x] MySQL / MariaDB / PostgreSQL にはすでに URL 文字列 1 引数版 `dbOpen` があり、SQLite には未整備であることを確認した |
| 20 | +- [x] 既存 URL 実装が `split` ベースの簡易パーサであり、一般的な URL 仕様を十分に扱えていないことを確認した |
| 21 | +- [x] 今回のブランチでは SurrealDB を対象外とする方針を反映した |
| 22 | +- [x] ブランチルールに改修方針・進捗粒度・参考資料を整理した |
| 23 | +- [x] 一般的な database URL 仕様として採用する範囲を整理する |
| 24 | +- [x] 新しい `dbOpen` オーバーロードの引数デザインを確定する |
| 25 | +- [x] URL 解析の共通 helper / 型配置を決め、driver 差分の閉じ込め方を整理する |
| 26 | +- [x] SQLite の URL 受け口を追加し、ファイルパス指定との意味論を衝突させない |
| 27 | +- [x] MySQL / MariaDB / PostgreSQL の URL 解析を一般仕様に合わせて強化する |
| 28 | +- [x] 正常系・異常系・後方互換のテストを driver ごとに追加または更新する |
| 29 | +- [x] example / README / documents を同期する |
| 30 | +- [x] 実装途中で設計認識に誤りが見つかった場合は、本ファイルの `調査結果・設計まとめ` を更新する |
| 31 | + |
| 32 | +## 参考資料 |
| 33 | +- `src/allographer/connection.nim` |
| 34 | +- `src/allographer/query_builder/models/sqlite/sqlite_open.nim` |
| 35 | +- `src/allographer/query_builder/models/mysql/mysql_open.nim` |
| 36 | +- `src/allographer/query_builder/models/mariadb/mariadb_open.nim` |
| 37 | +- `src/allographer/query_builder/models/postgres/postgres_open.nim` |
| 38 | +- `src/allographer/query_builder/models/surreal/surreal_open.nim` |
| 39 | +- `tests/mysql/test_open.nim` |
| 40 | +- `tests/mariadb/test_open.nim` |
| 41 | +- `tests/postgres/test_open.nim` |
| 42 | +- `tests/sqlite/connections.nim` |
| 43 | +- `tests/postgres/connections.nim` |
| 44 | +- `tests/mysql/connections.nim` |
| 45 | +- `tests/mariadb/connections.nim` |
| 46 | +- `example/connections.nim` |
| 47 | +- `README.md` |
| 48 | +- `documents/rdb/query_builder.md` |
| 49 | +- RFC 3986: Uniform Resource Identifier (URI): Generic Syntax |
| 50 | +- PostgreSQL Documentation: Connection URIs |
| 51 | +- MySQL / MariaDB ecosystem documentation for connection URI / DSN conventions |
| 52 | + |
| 53 | +## 調査結果・設計まとめ |
| 54 | + |
| 55 | +### 背景 |
| 56 | + |
| 57 | +現状の `dbOpen` は、RDB 系では「分解済みの接続情報を個別引数で渡す形」が基本で、一部 driver にだけ URL 文字列 1 引数版が追加されている。 |
| 58 | + |
| 59 | +ただし既存の URL 版は `split` を重ねた簡易実装で、一般的な URL で登場する予約文字・query・省略可能項目・scheme 差異に弱い。API としては URL 対応を名乗りつつ、仕様が狭く不均一な状態である。 |
| 60 | + |
| 61 | +今回の目的は、既存 API を壊さずに、database URL を正式な接続入力として扱える `dbOpen` オーバーロード群を整備し、RDB driver 間の設計を揃えることである。SurrealDB は今回の対象外とする。 |
| 62 | + |
| 63 | +### 現状の問題 |
| 64 | + |
| 65 | +1. SQLite はファイルパス引数のみで、URL ベース接続の入口がない |
| 66 | +2. MySQL / MariaDB / PostgreSQL の URL 版は実装されているが、一般的な URL 仕様を十分に扱えない |
| 67 | +3. driver ごとに URL の扱いがバラバラで、共通 API として学習コストが高い |
| 68 | +4. 既存の URL 文字列 1 引数版と、新たな「database url を使う関数」の住み分けを設計しないと、将来の拡張で曖昧さが増える |
| 69 | + |
| 70 | +### 設計目標 |
| 71 | + |
| 72 | +1. 既存 `dbOpen` シグネチャを残しつつ、新しいオーバーロードで URL ベース接続を自然に表現できる |
| 73 | +2. SQLite / MySQL / MariaDB / PostgreSQL は一般的な URI 記法を優先する |
| 74 | +3. URL 解析と driver ごとの接続情報変換を責務分離し、公開 API へ場当たり的分岐を持ち込まない |
| 75 | +4. 後方互換・テスト・文書更新まで含めて、利用者が迷わない状態を作る |
| 76 | + |
| 77 | +### 非目標 |
| 78 | + |
| 79 | +1. 既存の個別引数版 `dbOpen` を削除または非推奨化すること |
| 80 | +2. 接続 URL と無関係な query builder / schema builder API を同時に変更すること |
| 81 | +3. SurrealDB の接続モデルや URL 設計をこのブランチで見直すこと |
| 82 | +4. このブランチで ORM 的な接続設定 abstraction を全面導入すること |
| 83 | + |
| 84 | +### API 方針 |
| 85 | + |
| 86 | +#### 1. 新しいオーバーロードは「URL であることが呼び出し側から明確に分かる」形を優先する |
| 87 | + |
| 88 | +候補: |
| 89 | +1. `dbOpen(MySQL, url = "...", maxConnections = ..., timeout = ...)` |
| 90 | +2. `dbOpen(MySQL, databaseUrl = "...", maxConnections = ..., timeout = ...)` |
| 91 | +3. URL 専用の薄い型を導入して `dbOpen(MySQL, DatabaseUrl("..."), ...)` |
| 92 | + |
| 93 | +採用した設計: |
| 94 | +- URL 専用の薄い型 `DatabaseUrl` を導入し、`dbOpen(driver, databaseUrl = asDatabaseUrl("..."), ...)` で呼べるようにした |
| 95 | +- 既存の `dbOpen(driver, url: string, ...)` は後方互換のため残し、内部では共通 parser に委譲する |
| 96 | +- SQLite の既存 `dbOpen(SQLite3, path: string, ...)` はそのまま維持し、URL 文字列が渡された場合のみ URL ルートへ寄せる |
| 97 | + |
| 98 | +理由: |
| 99 | +- SQLite では単なる `string` がファイルパスと URL の両方になり得る |
| 100 | +- `DatabaseUrl` に分けることで、既存の string overload と overload 解決が衝突しない |
| 101 | +- 将来の拡張でも、URL 専用の入口を安全に追加しやすい |
| 102 | + |
| 103 | +#### 2. RDB の URL 仕様は一般的な形式を優先する |
| 104 | + |
| 105 | +最低限そろえる対象: |
| 106 | +1. `sqlite:///absolute/path/to/db.sqlite3` |
| 107 | +2. `sqlite://relative/path.db` またはこの扱いを不採用とするなら明文化する |
| 108 | +3. `mysql://user:pass@host:3306/database` |
| 109 | +4. `mariadb://user:pass@host:3306/database` |
| 110 | +5. `postgresql://user:pass@host:5432/database` |
| 111 | + |
| 112 | +設計メモ: |
| 113 | +- `postgres://...` は `postgresql://...` の alias として受ける |
| 114 | +- percent-encoding の decode 要否を明確にする |
| 115 | +- query parameter は現段階で未使用でも、少なくとも破壊的に誤解釈しない方針を取る |
| 116 | +- database 名や password に `:` `/` `@` が含まれるケースを、単純 `split` で壊さない |
| 117 | + |
| 118 | +### 実装方針 |
| 119 | + |
| 120 | +#### 1. URL 解析は共通 helper 化を優先する |
| 121 | + |
| 122 | +方針: |
| 123 | +- `scheme`, `user`, `password`, `host`, `port`, `path`, `query` を扱える共通 parser を用意する |
| 124 | +- URL 専用の `DatabaseUrl` を導入し、driver ごとの差分は「解析結果からどう接続情報へ落とすか」に限定する |
| 125 | +- 既存 driver ファイルの `split` ベース処理は置き換え対象とする |
| 126 | + |
| 127 | +#### 2. SQLite は URL とファイルパスの意味論を分ける |
| 128 | + |
| 129 | +要点: |
| 130 | +- 既存 `dbOpen(SQLite3, "/path/to/file.db")` はそのまま維持する |
| 131 | +- URL 版は `asDatabaseUrl(...)` で「これは URL」と明示できる形を優先する |
| 132 | +- `:memory:` や相対パスとの整合を壊さない |
| 133 | + |
| 134 | +#### 3. 既存 URL 1 引数版は互換維持しつつ内部実装を新 parser に寄せる |
| 135 | + |
| 136 | +要点: |
| 137 | +- MySQL / MariaDB / PostgreSQL の既存テストは維持する |
| 138 | +- 既存の `ValueError` / `DbError` の期待が妥当なら保つ |
| 139 | +- 公開 API は残しつつ、仕様の狭さだけを改善する |
| 140 | + |
| 141 | +#### 4. テストは「構文解析」と「実接続」を分けて考える |
| 142 | + |
| 143 | +候補: |
| 144 | +1. URL から接続情報へ正しく分解されることを確認する軽量テスト |
| 145 | +2. 既存の integration 系 `dbOpen(...).isConnected()` テスト |
| 146 | +3. 不正 scheme・不足情報・不正 port・予約文字を含む入力の異常系テスト |
| 147 | +4. SQLite の URL 指定とファイルパス指定の後方互換テスト |
| 148 | +5. SurrealDB の namespace / database 解決規則テスト |
| 149 | + |
| 150 | +### 受け入れ基準 |
| 151 | + |
| 152 | +1. 既存の `dbOpen` 呼び出しを壊さずに、新しい URL ベースのオーバーロードを追加できている |
| 153 | +2. SQLite / MySQL / MariaDB / PostgreSQL の URL 設計が一般的な仕様と整合している |
| 154 | +3. SurrealDB の URL 設計が独自要件を満たしつつ、他 driver と読後感が大きく乖離していない |
| 155 | +4. 既存の簡易 `split` 実装を置き換え、予約文字や query を誤解釈しにくい構造になっている |
| 156 | +5. driver ごとの正常系・異常系・後方互換テストが追加または更新されている |
| 157 | +6. example / README / documents / ブランチルールが最終仕様と一致している |
| 158 | + |
| 159 | +### リスク |
| 160 | + |
| 161 | +1. Nim 標準ライブラリだけで URL 解析を行う場合、RFC 3986 の細部を十分に扱えない可能性がある |
| 162 | +2. SQLite の URL 仕様を曖昧にすると、既存のファイルパス API と混同されやすい |
| 163 | +3. SurrealDB の namespace / database の載せ方を誤ると、RDB に寄せたつもりで逆に分かりにくくなる |
| 164 | +4. 既存の `dbOpen(driver, urlString)` と新オーバーロードが衝突すると、Nim の overload 解決で利用者体験が悪化する |
| 165 | +5. 文字列解析だけでなく実接続テストも必要なため、driver 横断で確認コストが上がる |
| 166 | + |
| 167 | +### 段階導入案 |
| 168 | + |
| 169 | +1. 採用する URL 仕様と新オーバーロードの表面 API を確定する |
| 170 | +2. 共通 URL parser / 接続情報変換レイヤを用意する |
| 171 | +3. MySQL / MariaDB / PostgreSQL の既存 URL 実装を載せ替える |
| 172 | +4. SQLite の URL 入口を追加する |
| 173 | +5. テストを整備して後方互換と異常系を固める |
| 174 | +6. example / README / documents を同期する |
0 commit comments