Project Database — 構造化した成果を保存・検索する
schemaの作成から行の保存・検索・WebUIでの確認、SQL制限、migration競合、書き込み結果不明時の復旧までを説明します。
Project Databaseは、顧客記録、調査結果、在庫など、agentと人間が再利用する構造化データの保存先です。行の背景や判断はShared Documentsに残します。通常Projectごとにserver管理のCloudflare D1 databaseを持ち、最初のmigrationで必要になった時点で作成されます。schemaを読むだけでは作成されません。ローカルSQLiteファイルや、HTMLに自動接続されるbackendではありません。
前提と権限
active Projectをcoverageに持つrunning Sessionのagentへ操作を依頼します。SessionのProject roleがViewerならschemaとSELECTを読めます。CollaboratorとAdminはmigration、INSERT、UPDATE、DELETEも実行できます。archived、completed、deletingのProjectは新規Database操作を受け付けません。
chat dbはSession内のコマンドです。Team、Project、Database ID、Sessionを選ぶflagはありません。schemaとqueryは現在のディレクトリ、migrateはcanonical migration file pathからProjectを解決します。例はProject rootで実行してください。外側のaachat project databaseはcatalogの取得用であり、任意SQLの実行口ではありません。agentへD1のcredentialを直接渡す必要はありません。
tableを作り、成果を1件保存する
acme/customer-researchをSessionのcoverageにある実在Projectへ置き換え、まず現在のschemaを読みます。
cd aachat/projects/acme/customer-research
chat db schemaread-onlyのdb/schema.sql投影は、空のDBなら-- aachat-schema-version: root、migration後ならsha256:...のversionで始まります。このファイルは編集しません。以下は空のDBであることを確認してから、db/migrations/add_customer.sqlへそのまま保存する例です。既存schemaがある場合は、parent headerへ現在のversion全体を正確にコピーし、既存tableに合わせてSQLを修正してください。rootを再利用しません。
-- aachat-parent: root
CREATE TABLE customer (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
status TEXT NOT NULL
);
CREATE INDEX customer_status ON customer(status);parent headerはbyte 0から始めます。BOMやNULを含まないUTF-8の通常ファイルを使い、symlinkは使いません。migration IDは英小文字・数字・_・-、先頭は英小文字または数字、最大128文字です。ファイル同期はSQL sourceの保存であり、DBへの適用ではありません。明示的に適用してから行を書き、読んで確認します。
chat db migrate db/migrations/add_customer.sql
chat db schema
chat db query --sql 'INSERT INTO customer (id, name, status) VALUES (?, ?, ?)' --params '["c1", "Ada", "active"]'
chat db query --sql 'SELECT id, name, status FROM customer WHERE status = ? ORDER BY id LIMIT 100' --params '["active"]'
chat db query --sql 'UPDATE customer SET status = ? WHERE id = ?' --params '["reviewed", "c1"]'
chat db query --sql 'SELECT id, name, status FROM customer WHERE id = ?' --params '["c1"]'migration成功後はschemaのversionが変わり、tableとindexが現れます。最初のSELECTはc1、Ada、activeを返し、UPDATE後の最後のSELECTはc1、Ada、reviewedを返します。各段階の実際のJSON応答を読んでから次へ進みます。同じ主キーでINSERTを繰り返しても新しい記録にはなりません。捨ててよい練習用の行なら、chat db query --sql 'DELETE FROM customer WHERE id = ?' --params '["c1"]'で削除し、同じキーのSELECTで不在を確認します。
queryとmigrationのSQL規則は異なる
両方ともSQLは最大100 KiBです。予約された_aachat_、sqlite_、_cf_、pragma_のrelation、database名で修飾したobject名、任意のSQLite拡張は使えません。
| 操作 | 許可する入力 | 主な制限 |
|---|---|---|
chat db query | SELECT、INSERT、UPDATE、DELETEのいずれか1文。RETURNINGとOUTPUTは不可 | placeholderは位置指定?のみ。--paramsは最大100個のstringのJSON配列で、placeholder数と一致させる |
chat db migrate | 下記allowlistの1〜100文 | parameter bindingは不可。現在のparent versionが必要 |
queryでDDLやPRAGMAは実行できません。SELECT結果は最大1,000行かつdecoded 1 MiBで、超過は部分結果ではなくエラーです。必要なcolumn、WHERE、小さなLIMITを指定します。LIMITを指定するなら静的な非負整数を使い、placeholderや式にしません。queryのUPDATEとDELETEではORDER BYやLIMITを使えません。
migrationのallowlistは、通常のCREATE TABLEとCREATE INDEX、columnの追加・削除・改名またはtable改名のALTER TABLE、単一objectのDROP TABLEまたはDROP INDEX、RETURNINGとOUTPUTを伴わないINSERT・UPDATE・DELETE、そして**PRAGMA defer_foreign_keys = ON**です。このPRAGMAはmigrationだけの例外です。SELECT、任意PRAGMA、view、trigger、明示的なtransaction制御scriptはmigration操作ではありません。allowlistに含まれていてもSQLiteの全方言を許可するわけではありません。
WebUIで結果を見る
ProjectのDatabaseタブを開き、tableを選んでcolumnと行を確認します。閲覧専用で、SQL editorや更新操作はありません。column見出しをクリックするとsortが切り替わり、1ページ25・50・100行(既定100行)で移動できます。table、page、page size、sortはURLに保持されます。
データ変更時はUpdates availableが表示され、refreshで新しい行を読み込みます。schema変更時はcatalogを再取得します。空文字、NULL、BLOBは別の値として表示されます。1 MiB超過なら25行へ減らし、それでも失敗する場合はagentへcolumnや値を絞ったSELECTを依頼します。
書き込みを重複させずに復旧する
応答のerror、reason、次のactionを読みます。timeoutだけでは書き込み失敗と判断できません。
| 症状 | 次の操作 |
|---|---|
| Projectを解決できない・権限がない | Project-rootのcwd、Session coverage、active状態、agentのroleを確認します。ファイルを移しても権限は増えません。 |
| migration sourceが拒否された・見つからない | db/_errors.mdを読み、path、header、encoding、SQLを修正し、同期が受理してから適用します。 |
| parent versionが古い | current schemaを読み、そのversion向けにmigrationを作り直します。1つのparentを進める子は1つで、force操作はありません。受理済みsourceは変更しません。 |
| migrationがreconciling | 応答のread・復旧案内に従います。serverがoperationとprovider ledgerを照合し、解決までschema読取と次のmigrationを待たせます。SELECT/DMLは通常の受付条件で続行できる場合があります。 |
DML後にOPERATION_OUTCOME_UNKNOWN | 既知の主キーと現在値を読んで、追加書き込みが必要か判断します。INSERT・UPDATE・DELETEを盲目的に再送しません。 |
| queryがbusy | 他のlive queryがProject leaseを保持しています。retry案内に従い、並列書き込みで回避しません。 |
| 結果が大きすぎる | columnと行を絞り、区切って読みます。途中までのデータを全件と見なしません。 |
ローカルのmigrationやschemaファイルを消しても適用済みデータは戻りません。Project削除は受理済みqueryと未解決migration、物理DB削除の完了を待ちます。即時rollbackやbackupの仕組みではありません。信頼境界とProjectsも確認してください。
空の状態とセルの全文
WebUIのDatabaseでNo database yetと表示されたら、最初のmigrationでDBを初期化していません。上の手順でAgentにmigrationの作成と適用を依頼します。No tables yetならuser tableがない状態なので、migrationでtableを作成して表示を更新します。schemaを読むだけではDBは初期化されません。
NULL以外のセルを押すと値の全文を開け、必要ならCopyを使えます。空文字はNULLと区別され、詳細を開けますが、NULLのセルには詳細buttonがありません。ここはread-onlyの確認面であり編集画面ではありません。Agentが行やschemaを変更した後は、Refresh/Updates availableで現在の状態を読み直します。