same_dimension_reference
same_dimension_reference 讓原生 link 不會跨越邊界。連結到上層任務的任務必須屬於同一個專案;連結到價格的發票明細必須使用同一家公司的價格。這條規則指定三個 cardinality one 的 link:這一列選取的參照、這一列所屬的維度,以及被選取紀錄的維度。每一列都必須剛好連結一個目標,兩邊都必須剛好連結一個維度紀錄,而且兩個維度紀錄必須是同一筆 live 列。
Payload
{
"type": "same_dimension_reference",
"name": "上層任務必須在同一專案",
"reference_column": "上層任務",
"source_dimension": "專案",
"target_dimension": "專案"
}| 欄位 | 契約 |
|---|---|
reference_column | 本表的 cardinality one link 欄位,用來選取目標紀錄。 |
source_dimension | 本表的 cardinality one link 欄位,指向這一列的維度紀錄。 |
target_dimension | reference_column 所連結資料表上的 cardinality one link 欄位,必須與 source_dimension 連到同一張維度表。 |
參照可以用顯示名稱或內部鍵。when 只能是 null 或 [],未知的鍵也會被拒絕;兩者都是 422 request 驗證錯誤。id 必須符合 rule_<8–32 hex>,name 最多 128 字。這條規則計入 10 條規則的上限,不計入 unique 上限。GET 會以顯示名稱回傳 reference_column 與 source_dimension;target_dimension 屬於目標表,會維持其內部 col_<hex> 鍵。
設定錯誤是 400,detail 為純字串:
detail | 原因 |
|---|---|
Reference fields must be native cardinality-one links | 三個欄位之一不是 link、沒有 link 定義,或 cardinality 是 many |
Reference target table is not accessible | 被參照的資料表不存在、在垃圾桶或不在同一公司 |
Both dimensions must link to the same dimension table | source_dimension 與 target_dimension 指向不同的資料表 |
Dimension table is not accessible | 維度表不存在、在垃圾桶或不在同一公司 |
來源 → 目標、來源 → 維度與目標 → 維度這三組也都適用一般的 link 範圍規則(相同範圍,或同一公司內較廣的範圍)。
伺服器強制執行的內容
對來源表的每一筆 live 列:
reference_column剛好有一個目標,且該目標是 live 資料表中的 live 列;source_dimension剛好有一筆 live 的維度列;- 目標的
target_dimension剛好有一筆,而且就是同一筆 live 維度列。
沒有 null 豁免:沒有參照或沒有維度的列會被拒絕。沒有維度的目標列可以存在,直到有來源列選取它為止。檢查不看 principal(會穿過所有 ACL 與 room 篩選),並在所有相關資料表的排序鎖之下進行,因此不會被競態繞過。
被拒絕的寫入回傳不含值的 409:
{
"detail": {
"error": "same_dimension_reference_violation",
"message": "Reference must share a live required dimension."
}
}這條規則同時守護三張表,而不只是來源表:
| 寫入 | 何時被拒絕 |
|---|---|
| 建立、更新、還原(revert)或復原(restore)來源列 | 它的參照或維度違反不變條件 |
| 刪除來源列 | 永遠不會(這只是移除一項義務) |
修改目標列的 target_dimension,或刪除被參照的目標列 | 仍有 live 來源列依賴它 |
| 刪除維度列 | 仍有 live 來源列直接或透過其選取的目標依賴它 |
| 把目標表或維度表丟到垃圾桶 | 仍有 live 來源列依賴它 |
| 復原來源表 | 它的目標表或維度表在垃圾桶中 |
規則 closure 內的每一次寫入——來源、目標與維度表,加上透過其他 same_dimension_reference 規則與它們相連的任何資料表——都會重新驗證該 closure 中每個 binding 的 live 來源列。公司內的每一次資料列寫入也都會讀取該公司的參照 binding,所以公司內任何一個結構已損壞的 binding(規則的 link 不再是指向同一張維度表的 cardinality one link)都會讓資料列寫入以同樣的 409 fail closed,直到移除該規則為止;下方的欄位與 purge 保護就是為了避免這種情況。
啟用規則
PUT 在儲存前會檢查每一筆既有的 live 來源列:只要有一列違反不變條件,整份清單就以同樣的 409 拒絕,不會儲存任何東西。與其他所有規則型別不同,rules.preview 也會執行這個既有列檢查(在交易範圍的 guard 下進行,之後回滾),並回相同的 409——發布新的 binding 前請先預覽。
相關欄位與資料表的保護
| 操作 | 回應 |
|---|---|
刪除或變更型別:reference_column/source_dimension(來源表)或 target_dimension(目標表) | 409 衝突 {"type": "dependent_rule", "field": "<欄位鍵>", "code": "same_dimension_reference_dependency", "message": "Remove the dependent reference rule before changing this link column."} |
| 永久清除目標表或維度表 | Purge 預覽的 blocker {"code": "same_dimension_reference_dependency", "table_id": "<來源表>", "message": "Remove the dependent reference rule before purging its target or dimension table."};仍然執行到的 purge 會回 409 {"error": "same_dimension_reference_dependency"} |
其他寫入路徑
- 核准:套用已核准的變更時會重新檢查這條規則;違反時該變更以
apply_failed結束,原因為refused at apply (same_dimension_reference_violation): Reference must share a live required dimension. - Bulk 與匯入:不會逐列預檢這條規則,而是在寫入資料列時失敗。非同步 bulk ticket 會在該 chunk 提交時失敗(先前的 chunk 仍保留),同步 bulk 請求或 publish 提交則整批回滾。
- 指令:碰到 binding 中任何一張表的指令,會把整個 closure 納入其 dependency contract,所以修改這條規則會讓那些指令變成 stale(見指令)。
請把規則放進完整的 rules 清單,透過 rules.set 發布。