github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/schema/column.go (about) 1 // Copyright 2019 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 schema 16 17 import ( 18 "errors" 19 "math" 20 "strings" 21 22 "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" 23 "github.com/dolthub/dolt/go/store/types" 24 ) 25 26 // InvalidTag is used as an invalid tag 27 const InvalidTag uint64 = math.MaxUint64 28 29 var ( 30 // KindToLwrStr maps a noms kind to the kinds lowercased name 31 KindToLwrStr = make(map[types.NomsKind]string) 32 33 // LwrStrToKind maps a lowercase string to the noms kind it is referring to 34 LwrStrToKind = make(map[string]types.NomsKind) 35 ) 36 37 var ( 38 // InvalidCol is a Column instance that is returned when there is nothing to return and can be tested against. 39 InvalidCol = Column{ 40 Name: "invalid", 41 Tag: InvalidTag, 42 Kind: types.NullKind, 43 TypeInfo: typeinfo.UnknownType, 44 } 45 ) 46 47 func init() { 48 for t, s := range types.KindToString { 49 KindToLwrStr[t] = strings.ToLower(s) 50 LwrStrToKind[strings.ToLower(s)] = t 51 } 52 } 53 54 // Column is a structure containing information about a column in a row in a table. 55 type Column struct { 56 // Name is the name of the column 57 Name string 58 59 // Tag should be unique per versioned schema and allows 60 Tag uint64 61 62 // Kind is the types.NomsKind that values of this column will be 63 Kind types.NomsKind 64 65 // IsPartOfPK says whether this column is part of the primary key 66 IsPartOfPK bool 67 68 // TypeInfo states the type of this column. 69 TypeInfo typeinfo.TypeInfo 70 71 // Default is the default value of this column. This is the string representation of a sql.Expression. 72 Default string 73 74 // Generated is the generated value of this column. This is the string representation of a sql.Expression. 75 Generated string 76 77 // OnUpdate is the on update value of this column. This is the string representation of a sql.Expression. 78 OnUpdate string 79 80 // Virtual is true if this is a virtual column. 81 Virtual bool 82 83 // AutoIncrement says whether this column auto increments. 84 AutoIncrement bool 85 86 // Comment is the comment for this column. 87 Comment string 88 89 // Constraints are rules that can be checked on each column to say if the columns value is valid 90 Constraints []ColConstraint 91 } 92 93 // NewColumn creates a Column instance with the default type info for the NomsKind 94 func NewColumn(name string, tag uint64, kind types.NomsKind, partOfPK bool, constraints ...ColConstraint) Column { 95 typeInfo := typeinfo.FromKind(kind) 96 col, err := NewColumnWithTypeInfo(name, tag, typeInfo, partOfPK, "", false, "", constraints...) 97 if err != nil { 98 panic(err) 99 } 100 return col 101 } 102 103 // NewColumnWithTypeInfo creates a Column instance with the given type info. 104 // Callers are encouraged to construct schema.Column structs directly instead of using this method, then call 105 // ValidateColumn. 106 func NewColumnWithTypeInfo(name string, tag uint64, typeInfo typeinfo.TypeInfo, partOfPK bool, defaultVal string, autoIncrement bool, comment string, constraints ...ColConstraint) (Column, error) { 107 c := Column{ 108 Name: name, 109 Tag: tag, 110 Kind: typeInfo.NomsKind(), 111 IsPartOfPK: partOfPK, 112 TypeInfo: typeInfo, 113 Default: defaultVal, 114 AutoIncrement: autoIncrement, 115 Comment: comment, 116 Constraints: constraints, 117 } 118 119 err := ValidateColumn(c) 120 if err != nil { 121 return InvalidCol, err 122 } 123 124 return c, nil 125 } 126 127 // ValidateColumn validates the given column. 128 func ValidateColumn(c Column) error { 129 for _, c := range c.Constraints { 130 if c == nil { 131 return errors.New("nil passed as a constraint") 132 } 133 } 134 135 if c.TypeInfo == nil { 136 return errors.New("cannot instantiate column with nil type info") 137 } 138 139 if c.TypeInfo.NomsKind() != c.Kind { 140 return errors.New("type info and kind do not match") 141 } 142 143 return nil 144 } 145 146 // IsNullable returns whether the column can be set to a null value. 147 func (c Column) IsNullable() bool { 148 if c.IsPartOfPK { 149 return false 150 } 151 if c.AutoIncrement { 152 return false 153 } 154 for _, cnst := range c.Constraints { 155 if cnst.GetConstraintType() == NotNullConstraintType { 156 return false 157 } 158 } 159 return true 160 } 161 162 // Equals tests equality between two columns. 163 func (c Column) Equals(other Column) bool { 164 return c.Name == other.Name && 165 c.Tag == other.Tag && 166 c.Kind == other.Kind && 167 c.IsPartOfPK == other.IsPartOfPK && 168 c.TypeInfo.Equals(other.TypeInfo) && 169 c.Default == other.Default && 170 ColConstraintsAreEqual(c.Constraints, other.Constraints) 171 } 172 173 // EqualsWithoutTag tests equality between two columns, but does not check the columns' tags. 174 func (c Column) EqualsWithoutTag(other Column) bool { 175 return c.Name == other.Name && 176 c.Kind == other.Kind && 177 c.IsPartOfPK == other.IsPartOfPK && 178 c.TypeInfo.Equals(other.TypeInfo) && 179 c.Default == other.Default && 180 ColConstraintsAreEqual(c.Constraints, other.Constraints) 181 } 182 183 // Compatible tests compatibility between two columns. Compatible columns have the same tag and can store the same 184 // kinds of values at the storage layer, but may have different constraints or type parameters. 185 func (c Column) Compatible(other Column) bool { 186 return c.Tag == other.Tag && 187 c.Kind == other.Kind && 188 c.IsPartOfPK == other.IsPartOfPK 189 } 190 191 // KindString returns the string representation of the NomsKind stored in the column. 192 func (c Column) KindString() string { 193 return KindToLwrStr[c.Kind] 194 }