package models // DeferralClause returns the SQL deferral clause for a foreign key constraint // ("DEFERRABLE", "DEFERRABLE INITIALLY DEFERRED" or "NOT DEFERRABLE"), or "" // when the model does not specify one. InitiallyDeferred without Deferrable // implies DEFERRABLE; InitiallyDeferred=false alone specifies nothing. func (d *Constraint) DeferralClause() string { deferrable, initially, set := d.effectiveDeferral() switch { case !set: return "" case !deferrable: return "NOT DEFERRABLE" case initially != nil && *initially: return "DEFERRABLE INITIALLY DEFERRED" default: return "DEFERRABLE" } } // effectiveDeferral resolves the optional flags. set is false when the model says nothing // about deferral; initially is nil when the initial mode is unspecified. func (d *Constraint) effectiveDeferral() (deferrable bool, initially *bool, set bool) { switch { case d.Deferrable != nil: return *d.Deferrable, d.InitiallyDeferred, true case d.InitiallyDeferred != nil && *d.InitiallyDeferred: return true, d.InitiallyDeferred, true } return false, nil, false } // DeferralMatches reports whether two constraints agree on deferral. An unspecified side // matches anything, and the initial mode is only compared when both sides specify it. func DeferralMatches(a, b *Constraint) bool { da, ia, aSet := a.effectiveDeferral() db, ib, bSet := b.effectiveDeferral() if !aSet || !bSet { return true } if da != db { return false } if !da || ia == nil || ib == nil { return true } return *ia == *ib }