Documentation
¶
Overview ¶
Package refintegrity implements referential integrity for xolu's entity references, per docs/proposals/referential-integrity.md (@R).
Stage 2 (this file + the delete-time restrict check) delivers the safety half of RI: a ref field annotated with x-ref and an on_delete policy of "restrict" causes a DELETE of the referenced entity to be refused while live referrers exist — the SQL ON DELETE RESTRICT behaviour. Cascade and nullify (stage 3) are not yet implemented; a policy of cascade or nullify parses correctly but is treated as unenforced-today by the stage-2 delete path, which is documented at the call site rather than silently swallowed.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type FieldXRefMeta ¶
type FieldXRefMeta struct {
Field string
// Raw is the value of the field's "x-ref" metadata key, or nil if the
// field carries no x-ref annotation.
Raw interface{}
}
FieldXRefMeta is the field name paired with its raw x-ref annotation value (as returned by a schema introspector's Meta("x-ref") lookup, or nil if the field has none). The caller — pkg/storage or the server, which own the concrete schema types — extracts these and hands them to CollectXRefs, keeping refintegrity free of any schema-package import and the import cycle that would create.
func FieldsFromRawSchema ¶
func FieldsFromRawSchema(raw map[string]interface{}) []FieldXRefMeta
FieldsFromRawSchema extracts field/x-ref pairs from a raw JSON Schema map of the shape {"properties": {"<field>": {"x-ref": {...}}}} — the form pkg/validation's GetSchema returns. Fields without an x-ref key are omitted (only annotated fields matter to the collector). A schema with no "properties" object yields nil, not an error: an entity may legitimately have no reference fields.
type OnDelete ¶
type OnDelete string
OnDelete is the delete-time policy for a reference field (@R02.1).
const ( // OnDeleteRestrict refuses to delete a referenced entity while any // live referrer names it. The default when x-ref is present, because // it is the only policy that destroys nothing: refusal is // recoverable, deletion is not. OnDeleteRestrict OnDelete = "restrict" // OnDeleteCascade deletes referrers along with the target. Stage 3. OnDeleteCascade OnDelete = "cascade" // OnDeleteNullify sets the referring field to null. Stage 3. OnDeleteNullify OnDelete = "nullify" )
type ReferrerPolicy ¶
type ReferrerPolicy struct {
// ReferringEntity is the entity type that carries the ref field.
ReferringEntity string
// Field is the ref field's name on the referring entity.
Field string
// OnDelete is the policy governing a delete of the referenced entity.
OnDelete OnDelete
}
ReferrerPolicy names one field on one entity type that references a target entity, and the on_delete policy governing that reference. It is the unit the delete path consults: "who points at E, and what must happen to them when E is deleted."
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry maps a referenced entity type to the set of referrer policies that target it. It is built once from the loaded schemas and consulted at delete time. A nil or empty registry enforces nothing — the safe default for a deployment that has adopted no x-ref annotations.
func (*Registry) AddEntitySchema ¶
func (r *Registry) AddEntitySchema(referringEntity string, fields []FieldXRefMeta) error
AddEntitySchema records every x-ref on referringEntity's schema, indexing each by the entity it targets. Call once per entity type as schemas load. `fields` is the entity's field-name/x-ref-meta pairs, which the caller extracts from its concrete schema type. Returns an error if the schema carries a malformed x-ref.
func (*Registry) HasAnyPolicy ¶ added in v0.16.16
HasAnyPolicy reports whether the registry holds any referential- integrity policy at all. Used by the startup parity guard: if any schema carries an x-ref but the graph subsystem is disabled, enforcement would silently not run — the guard turns that into a loud failure rather than a data-integrity gap discovered later.
func (*Registry) HasRestrictReferrers ¶
HasRestrictReferrers reports whether any referrer of targetEntity carries the restrict policy — the cheap pre-check the delete path uses to decide whether an inbound-edge query is even necessary.
func (*Registry) ReferrersOf ¶
func (r *Registry) ReferrersOf(targetEntity string) []ReferrerPolicy
ReferrersOf returns the policies whose reference targets the given entity type. The result is read-only; callers must not mutate it. Returns nil when nothing references the entity.
type XRef ¶
type XRef struct {
// Field is the ref field's name on the referring entity.
Field string
// Entity is the referenced entity type. Required.
Entity string
// OnDelete is the delete policy; defaults to restrict when x-ref is
// present but on_delete is omitted.
OnDelete OnDelete
// Validate is the write-time target-existence check (stage 4). Parsed
// here so the annotation round-trips, but not enforced until stage 4.
Validate bool
}
XRef is a parsed x-ref annotation on a schema field (@R02.1).
func CollectXRefs ¶
func CollectXRefs(fields []FieldXRefMeta) ([]XRef, error)
CollectXRefs parses every x-ref annotation from a schema's fields, sorted by field name for determinism. A malformed annotation aborts the whole collection with an error — a schema with a broken x-ref must not load as if the annotation were absent, because that would silently disable an enforcement the author asked for.
func ParseXRef ¶
ParseXRef reads an x-ref annotation from a field's raw metadata map (as returned by the schema browser's GetMeta("x-ref")). It returns ok=false when the field has no x-ref annotation. A malformed annotation (missing entity, unknown policy) is an error, not a silent skip — a schema author who wrote x-ref meant to enforce something.