書く
チェックアウト、コミット、push。作業カタログ、書き込みの順番、push が断られるとき。
作業カタログ
書き手は作業カタログに書きます。リポジトリの外にある、SQLite の DuckLake カタログです。手元のパソコンでもホストのコンテナでも、作業カタログは 1 種類です。
DATA_INLINING_ROW_LIMIT 0で ATTACH し、すべての行をデータファイルに書かなければならない- データパスはリポジトリのデータフォルダ(
<root><data_dir>)。新しいデータファイルはリポジトリに書かれる。HTTP 越しのリポジトリだけは例外で、新しいデータファイルは書き手のマシンのフォルダに書き、push がそれを上げる(HTTP での push) ducklake_expire_snapshotsとducklake_cleanup_old_filesを流してはいけない
段階
| 段階 | すること |
|---|---|
| チェックアウト | ブランチのバージョンのカタログから作業カタログを作り、そのバージョンを覚える。最初のバージョンの前は空のものを作る |
| コミット | 作業カタログの最後のスナップショットを新しいバージョンに固める。親は覚えておいたバージョン。中身を dataset.json で説明する |
| push | データファイルを確かめ、カタログ、dataset.json と files.json、version.json の順にアップロードし、条件付きで ref を動かす |
チェックアウトでは、DuckLake の管理用の表を、固めたカタログから SQLite へそのまま写します。固めるときはその逆で、最後のスナップショットまでの行を残します。どちらもデータファイルは書き換えません。
固めるとき、書き手は次のことをしなければなりません。
- 行をカタログの中に持つ作業カタログを断る
- 固めたカタログの
data_pathを<root><data_dir>の絶対 URL にする - 絶対パスで記録されたデータファイルや、
data_dirの外のデータファイルがあれば断る
変更がないとき
書き手は、親と同じ中身のバージョンを作らないようにするべきです。Git が親と同じ tree のコミットを作らないのと同じです。次のどちらかなら、親と同じ中身です。
- 最後のスナップショットが親のもの(
ducklake.snapshot_id)と同じ - 同じ表とビューがあり、どの表も列の名前と型が同じで、行が同じ(重複を数え、順番は問わない)。さらに
dataset.jsonの sha256 が親と同じ
同じ入力から作り直した表は新しいデータファイルに書かれるので、ファイルやカタログのバイトを比べても判定できません。書き手はまずファイルを比べ、ファイルが違う表だけ行を読みます。行を読めないときはバージョンを作ります。頼まれたときは、git commit --allow-empty と同じく、変更がなくても作ってかまいません。
書き込みの順番
- データファイル
versions/<ID>/ducklake.duckdb(とcatalogs/)versions/<ID>/dataset.jsonとversions/<ID>/files.jsonversions/<ID>/version.json- ref(条件付き)
途中で止まった書き手は、読み手に見えるものを何も変えていません。残ったファイルはどの ref からも参照されず、その中のデータファイルは猶予期間のあとに消されます。
バージョンのファイルは一度だけ書きます。既に同じ中身のファイルがあれば先へ進み、違う中身なら止まります。
push が断られるとき
古い作業カタログからの push は、次の 2 つの確認で断られます。
- いまブランチが指すバージョンが、新しいバージョンの
parentsに無い。ほかの人が先に push した - カタログが参照するデータファイルがリポジトリに無い。書いたまま猶予期間より長く参照されなかったファイルは、消されていることがある
どちらの場合も、書き手はチェックアウトし直し、作業をやり直して、もう一度 push します。リポジトリを片付ける必要はありません。断られたバージョンはどの ref からも参照されていません。