-
Notifications
You must be signed in to change notification settings - Fork 154
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
server: implement referential integrity
Implement referential integrity and garbage collection as described in RFC7047. This is achieved keeping track of inverse references. A reference tracker is used in the transaction to keep these references updated, to check for referential integrity related violations and to add additional updates to the transaction resulting from reference garbage collection. The inverse references are stored in the database on commit. The updates resulting from reference garbage collection are also sent to any monitoring clients as expected. Signed-off-by: Jaime Caamaño Ruiz <[email protected]>
- Loading branch information
Showing
9 changed files
with
3,011 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package database | ||
|
||
// References tracks the references to rows from other rows at specific | ||
// locations in the schema. | ||
type References map[ReferenceSpec]Reference | ||
|
||
// ReferenceSpec specifies details about where in the schema a reference occurs. | ||
type ReferenceSpec struct { | ||
// ToTable is the table of the row to which the reference is made | ||
ToTable string | ||
|
||
// FromTable is the table of the row from which the reference is made | ||
FromTable string | ||
|
||
// FromColumn is the column of the row from which the reference is made | ||
FromColumn string | ||
|
||
// FromValue flags if the reference is made on a map key or map value when | ||
// the column is a map | ||
FromValue bool | ||
} | ||
|
||
// Reference maps the UUIDs of rows to which the reference is made to the | ||
// rows it is made from | ||
type Reference map[string][]string | ||
|
||
// GetReferences gets references to a row | ||
func (rs References) GetReferences(table, uuid string) References { | ||
refs := References{} | ||
for spec, values := range rs { | ||
if spec.ToTable != table { | ||
continue | ||
} | ||
if _, ok := values[uuid]; ok { | ||
refs[spec] = Reference{uuid: values[uuid]} | ||
} | ||
} | ||
return refs | ||
} | ||
|
||
// UpdateReferences updates the references with the provided ones. Dangling | ||
// references, that is, the references of rows that are no longer referenced | ||
// from anywhere, are cleaned up. | ||
func (rs References) UpdateReferences(other References) { | ||
for spec, otherRefs := range other { | ||
for to, from := range otherRefs { | ||
rs.updateReference(spec, to, from) | ||
} | ||
} | ||
} | ||
|
||
// updateReference updates the references to a row at a specific location in the | ||
// schema | ||
func (rs References) updateReference(spec ReferenceSpec, to string, from []string) { | ||
thisRefs, ok := rs[spec] | ||
if !ok && len(from) > 0 { | ||
// add references from a previously untracked location | ||
rs[spec] = Reference{to: from} | ||
return | ||
} | ||
if len(from) > 0 { | ||
// replace references to this row at this specific location | ||
thisRefs[to] = from | ||
return | ||
} | ||
// otherwise remove previously tracked references | ||
delete(thisRefs, to) | ||
if len(thisRefs) == 0 { | ||
delete(rs, spec) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.