diff options
| author | Marcos Magueta <maguetamarcos@gmail.com> | 2026-03-14 11:39:04 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-14 11:39:04 -0300 |
| commit | e6661bfa6a3d7dc477d0b7717c80bd536eca2d68 (patch) | |
| tree | 12510963feeed03221defa690e73edd4135b65e1 /docs/icl.org | |
| parent | 0ad04e638baa8f283150d3c2809cdb9bf21e2995 (diff) | |
| download | Sakura-e6661bfa6a3d7dc477d0b7717c80bd536eca2d68.tar.gz Sakura-e6661bfa6a3d7dc477d0b7717c80bd536eca2d68.zip | |
Branching and naïve merge strategies
* AGPL license
* branching and merging
* Delete LICENSE in favor of separate PR
Signed-off-by: Marcos Magueta <maguetamarcos@gmail.com>
* add unmonitored tests and docs
---------
Signed-off-by: Marcos Magueta <maguetamarcos@gmail.com>
Diffstat (limited to 'docs/icl.org')
| -rw-r--r-- | docs/icl.org | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/docs/icl.org b/docs/icl.org new file mode 100644 index 0000000..c2258bf --- /dev/null +++ b/docs/icl.org @@ -0,0 +1,108 @@ +#+TITLE: ICL — Integrity Control Language + +ICL registers integrity constraints on relations. A constraint is a +membership check: before any tuple is inserted, Sakura verifies that +the tuple belongs to every constraint-relation attached to the target +relation. + +Constraints are expressed as S-expressions and sent over the wire like +any other command. + +* Syntax + +#+begin_src +(RegisterConstraint + (constraint_name "<name>") + (relation_name "<target-relation>") + (body <constraint-body>)) +#+end_src + +A ~<constraint-body>~ is one of: + +| Form | Meaning | +|-------------------------------------------------+--------------------------------| +| ~(MemberOf (target R) (binding (...)))~ | Tuple must be in relation R | +| ~(Not (body B) (universe R))~ | Negation (closed-world over R) | +| ~(And (B1 B2 ...))~ | All must hold | +| ~(Or (B1 B2 ...))~ | At least one must hold | +| ~(Exists (variable v) (quantifier R) (body B))~ | ∃ v ∈ R such that B holds | +| ~(Forall (variable v) (quantifier R) (body B))~ | ∀ v ∈ R, B holds | + +Bindings map target-relation attribute names to values drawn from the +tuple being checked: + +| Binding expr | Meaning | +|---------------------+--------------------------------| +| ~(Var "attr")~ | Value of ~attr~ from the tuple | +| ~(Const (Int N))~ | Literal integer N | +| ~(Const (Str "s"))~ | Literal string s | +| ~(Const (Float f))~ | Literal float f | + +* Examples + +** Foreign key + +#+begin_src sexp +(CreateRelation (name "Department") (schema ((dept_id "integer") (dept_name "string")))) +(CreateRelation (name "Employee") (schema ((emp_id "integer") (emp_name "string") (dept_id "integer")))) + +(RegisterConstraint + (constraint_name "fk_employee_dept") + (relation_name "Employee") + (body (MemberOf + (target "Department") + (binding ((dept_id (Var "dept_id"))))))) +#+end_src + +** Range check + +#+begin_src sexp +(CreateRelation (name "Result") (schema ((student_id "integer") (score "integer")))) + +(RegisterConstraint + (constraint_name "score_range") + (relation_name "Result") + (body (And + ((MemberOf (target "greater_than_or_equal_natural") + (binding ((left (Var "score")) (right (Const (Int 0)))))) + (MemberOf (target "less_than_or_equal_natural") + (binding ((left (Var "score")) (right (Const (Int 100)))))))))) +#+end_src + +** Existential (FK through a join) + +A ~Suite~ is only valid if its room belongs to a building with more +than 3 floors: + +#+begin_src sexp +(CreateRelation (name "Building") (schema ((building_id "integer") (building_name "string") (floors "integer")))) +(CreateRelation (name "Room") (schema ((room_id "integer") (building_id "integer") (floor "integer")))) +(CreateRelation (name "Suite") (schema ((suite_id "integer") (room_id "integer") (suite_name "string")))) + +(RegisterConstraint + (constraint_name "suite_in_tall_building") + (relation_name "Suite") + (body + (Exists (variable "r") (quantifier "Room") + (body + (Exists (variable "b") (quantifier "Building") + (body + (And + ((MemberOf (target "Room") + (binding ((room_id (Var "room_id"))))) + (MemberOf (target "Building") + (binding ((building_id (Var "r.building_id"))))) + (MemberOf (target "greater_than_natural") + (binding ((left (Var "b.floors")) + (right (Const (Int 3)))))))))))))) +#+end_src + +Note: quantifier variables are namespaced — attributes from variable +~r~ are accessed as ~r.attr_name~ inside nested scopes. + +* See also + +- ~lib/icl/~ — AST, parser, executor +- ~lib/constraint.ml~ — runtime constraint representation and evaluator +- ~docs/icl-quantification.org~ — full runtime model for ~Exists~/~Forall~ +- ~docs/constraints.org~ — conceptual background |
