github.com/dolthub/go-mysql-server@v0.18.0/sql/constraints.go (about) 1 // Copyright 2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sql 16 17 import ( 18 "fmt" 19 "strings" 20 ) 21 22 // ForeignKeyConstraint declares a constraint between the columns of two tables. 23 type ForeignKeyConstraint struct { 24 Name string 25 Database string 26 Table string 27 Columns []string 28 ParentDatabase string 29 ParentTable string 30 ParentColumns []string 31 OnUpdate ForeignKeyReferentialAction 32 OnDelete ForeignKeyReferentialAction 33 IsResolved bool 34 } 35 36 // ForeignKeyReferentialAction is the behavior for this foreign key with the relevant action is performed on the foreign 37 // table. 38 type ForeignKeyReferentialAction string 39 40 const ( 41 ForeignKeyReferentialAction_DefaultAction ForeignKeyReferentialAction = "DEFAULT" // No explicit action was specified 42 ForeignKeyReferentialAction_Restrict ForeignKeyReferentialAction = "RESTRICT" 43 ForeignKeyReferentialAction_Cascade ForeignKeyReferentialAction = "CASCADE" 44 ForeignKeyReferentialAction_NoAction ForeignKeyReferentialAction = "NO ACTION" 45 ForeignKeyReferentialAction_SetNull ForeignKeyReferentialAction = "SET NULL" 46 ForeignKeyReferentialAction_SetDefault ForeignKeyReferentialAction = "SET DEFAULT" 47 ) 48 49 // IsSelfReferential returns whether this foreign key represents a self-referential foreign key. 50 func (f ForeignKeyConstraint) IsSelfReferential() bool { 51 return strings.ToLower(f.Database) == strings.ToLower(f.ParentDatabase) && 52 strings.ToLower(f.Table) == strings.ToLower(f.ParentTable) 53 } 54 55 func (f *ForeignKeyConstraint) DebugString() string { 56 return fmt.Sprintf( 57 "FOREIGN KEY %s (%s) REFERENCES %s (%s)", 58 f.Name, 59 strings.Join(f.Columns, ","), 60 f.ParentTable, 61 strings.Join(f.ParentColumns, ","), 62 ) 63 } 64 65 // IsEquivalentToRestrict returns whether the referential action is equivalent to RESTRICT. In MySQL, although there are 66 // a number of referential actions, the majority of them are functionally ignored and default to RESTRICT. 67 func (f ForeignKeyReferentialAction) IsEquivalentToRestrict() bool { 68 switch f { 69 case ForeignKeyReferentialAction_Cascade, ForeignKeyReferentialAction_SetNull: 70 return false 71 default: 72 return true 73 } 74 } 75 76 // CheckDefinition defines a trigger. Integrators are not expected to parse or understand the trigger definitions, 77 // but must store and return them when asked. 78 type CheckDefinition struct { 79 Name string // The name of this check. Check names in a database are unique. 80 CheckExpression string // String serialization of the check expression 81 Enforced bool // Whether this constraint is enforced 82 } 83 84 // CheckConstraint declares a boolean-eval constraint. 85 type CheckConstraint struct { 86 Name string 87 Expr Expression 88 Enforced bool 89 } 90 91 type CheckConstraints []*CheckConstraint 92 93 type CheckConstraintNode interface { 94 Node 95 Checks() CheckConstraints 96 WithChecks(CheckConstraints) Node 97 } 98 99 // ToExpressions returns the check expressions in these constraints as a slice of sql.Expression 100 func (checks CheckConstraints) ToExpressions() []Expression { 101 exprs := make([]Expression, len(checks)) 102 for i := range checks { 103 exprs[i] = checks[i].Expr 104 } 105 return exprs 106 } 107 108 // FromExpressions takes a slice of sql.Expression in the same order as these constraints, and returns a new slice of 109 // constraints with the expressions given, holding names and other properties constant. 110 func (checks CheckConstraints) FromExpressions(exprs []Expression) (CheckConstraints, error) { 111 if len(checks) != len(exprs) { 112 return nil, ErrInvalidChildrenNumber.New(checks, len(exprs), len(checks)) 113 } 114 115 newChecks := make(CheckConstraints, len(checks)) 116 for i := range exprs { 117 nc := *checks[i] 118 newChecks[i] = &nc 119 newChecks[i].Expr = exprs[i] 120 } 121 122 return newChecks, nil 123 } 124 125 func (c CheckConstraint) DebugString() string { 126 name := c.Name 127 if len(name) > 0 { 128 name += " " 129 } 130 not := "" 131 if !c.Enforced { 132 not = "not " 133 } 134 return fmt.Sprintf("%sCHECK %s %sENFORCED", name, DebugString(c.Expr), not) 135 }