|
10 | 10 | * ``enforced_keys`` — supported records, all ENFORCED + ALL_ROWS: |
11 | 11 | ``items`` PRIMARY KEY (id) |
12 | 12 | ``items_no_returning`` PRIMARY KEY (id), UNIQUE (name) |
| 13 | + ``items_insert_only`` PRIMARY KEY (id) (declares INSERT only) |
13 | 14 | * ``rowid_keys`` — ENFORCED + ALL_ROWS records that name the rowid column: |
14 | 15 | ``items`` PRIMARY KEY (rowid) |
15 | 16 | ``items_no_returning`` PRIMARY KEY (id, rowid), UNIQUE (rowid, name) |
|
57 | 58 | (ConstraintKind.PRIMARY_KEY, ["id"], _TRUSTED), |
58 | 59 | (ConstraintKind.UNIQUE, ["name"], _TRUSTED), |
59 | 60 | ], |
| 61 | + "items_insert_only": [(ConstraintKind.PRIMARY_KEY, ["id"], _TRUSTED)], |
60 | 62 | }, |
61 | 63 | ), |
62 | 64 | "rowid_keys": ( |
|
83 | 85 | raise RuntimeError("vgi.worker.validate_constraint_records moved; update this fixture") |
84 | 86 | vgi.worker.validate_constraint_records = lambda *args, **kwargs: None |
85 | 87 |
|
| 88 | +# vgi-python also serves a table with constraint records read-only (drops its |
| 89 | +# write functions and modes) unless the attachment selected |
| 90 | +# vgi.constraint.enforce.v1. Keep the declared writes, so the extension's own |
| 91 | +# planning check is what refuses them. Same loud failure if the hook moves. |
| 92 | +if not hasattr(vgi.worker.Worker, "_table_for_capabilities"): |
| 93 | + raise RuntimeError("vgi.worker.Worker._table_for_capabilities moved; update this fixture") |
| 94 | + |
86 | 95 |
|
87 | 96 | class RowidConstraintCatalog(SimpleWritableCatalog): |
88 | 97 | """SimpleWritableCatalog whose tables carry the records of the attached mode.""" |
89 | 98 |
|
90 | 99 | def catalog_capabilities(self, *, attach_opaque_data): # type: ignore[no-untyped-def,override] |
91 | | - """Serve constraint records; writes are not offered, so the tables are read-only.""" |
| 100 | + """Serve constraint records but never negotiate vgi.constraint.enforce.v1. |
| 101 | +
|
| 102 | + The tables keep their simple_writable writes (see |
| 103 | + ``RowidConstraintWorker._table_for_capabilities``), so a write a table |
| 104 | + declares fails on the missing enforcement profile and one it does not |
| 105 | + declare fails as unsupported. |
| 106 | + """ |
92 | 107 | del attach_opaque_data |
93 | 108 | return CatalogCapabilities(read=[CONSTRAINT_RECORDS_READ]) |
94 | 109 |
|
@@ -136,6 +151,17 @@ class RowidConstraintWorker(SimpleWritableWorker): |
136 | 151 |
|
137 | 152 | catalog_interface = RowidConstraintCatalog |
138 | 153 |
|
| 154 | + @staticmethod |
| 155 | + def _table_for_capabilities(info, selected): # type: ignore[no-untyped-def,override] |
| 156 | + served = SimpleWritableWorker._table_for_capabilities(info, selected) |
| 157 | + return dataclasses.replace( |
| 158 | + served, |
| 159 | + write_result_modes=info.write_result_modes, |
| 160 | + insert_function=info.insert_function, |
| 161 | + update_function=info.update_function, |
| 162 | + delete_function=info.delete_function, |
| 163 | + ) |
| 164 | + |
139 | 165 |
|
140 | 166 | if __name__ == "__main__": |
141 | 167 | RowidConstraintWorker.main() |
0 commit comments