github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/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  		"invalid",
    41  		InvalidTag,
    42  		types.NullKind,
    43  		false,
    44  		typeinfo.UnknownType,
    45  		"",
    46  		false,
    47  		"",
    48  		nil,
    49  	}
    50  )
    51  
    52  func init() {
    53  	for t, s := range types.KindToString {
    54  		KindToLwrStr[t] = strings.ToLower(s)
    55  		LwrStrToKind[strings.ToLower(s)] = t
    56  	}
    57  }
    58  
    59  // Column is a structure containing information about a column in a row in a table.
    60  type Column struct {
    61  	// Name is the name of the column
    62  	Name string
    63  
    64  	// Tag should be unique per versioned schema and allows
    65  	Tag uint64
    66  
    67  	// Kind is the types.NomsKind that values of this column will be
    68  	Kind types.NomsKind
    69  
    70  	// IsPartOfPK says whether this column is part of the primary key
    71  	IsPartOfPK bool
    72  
    73  	// TypeInfo states the type of this column.
    74  	TypeInfo typeinfo.TypeInfo
    75  
    76  	// Default is the default value of this column. This is the string representation of a sql.Expression.
    77  	Default string
    78  
    79  	// AutoIncrement says whether this column auto increments.
    80  	AutoIncrement bool
    81  
    82  	// Comment is the comment for this column.
    83  	Comment string
    84  
    85  	// Constraints are rules that can be checked on each column to say if the columns value is valid
    86  	Constraints []ColConstraint
    87  }
    88  
    89  // NewColumn creates a Column instance with the default type info for the NomsKind
    90  func NewColumn(name string, tag uint64, kind types.NomsKind, partOfPK bool, constraints ...ColConstraint) Column {
    91  	typeInfo := typeinfo.FromKind(kind)
    92  	col, err := NewColumnWithTypeInfo(name, tag, typeInfo, partOfPK, "", false, "", constraints...)
    93  	if err != nil {
    94  		panic(err)
    95  	}
    96  	return col
    97  }
    98  
    99  // NewColumnWithTypeInfo creates a Column instance with the given type info.
   100  func NewColumnWithTypeInfo(name string, tag uint64, typeInfo typeinfo.TypeInfo, partOfPK bool, defaultVal string, autoIncrement bool, comment string, constraints ...ColConstraint) (Column, error) {
   101  	for _, c := range constraints {
   102  		if c == nil {
   103  			return Column{}, errors.New("nil passed as a constraint")
   104  		}
   105  	}
   106  
   107  	if typeInfo == nil {
   108  		return Column{}, errors.New("cannot instantiate column with nil type info")
   109  	}
   110  
   111  	return Column{
   112  		name,
   113  		tag,
   114  		typeInfo.NomsKind(),
   115  		partOfPK,
   116  		typeInfo,
   117  		defaultVal,
   118  		autoIncrement,
   119  		comment,
   120  		constraints,
   121  	}, nil
   122  }
   123  
   124  // IsNullable returns whether the column can be set to a null value.
   125  func (c Column) IsNullable() bool {
   126  	if c.IsPartOfPK {
   127  		return false
   128  	}
   129  	for _, cnst := range c.Constraints {
   130  		if cnst.GetConstraintType() == NotNullConstraintType {
   131  			return false
   132  		}
   133  	}
   134  	return true
   135  }
   136  
   137  // Equals tests equality between two columns.
   138  func (c Column) Equals(other Column) bool {
   139  	return c.Name == other.Name &&
   140  		c.Tag == other.Tag &&
   141  		c.Kind == other.Kind &&
   142  		c.IsPartOfPK == other.IsPartOfPK &&
   143  		c.TypeInfo.Equals(other.TypeInfo) &&
   144  		c.Default == other.Default &&
   145  		ColConstraintsAreEqual(c.Constraints, other.Constraints)
   146  }
   147  
   148  // Compatible tests compatibility between two columns. Compatible columns have the same tag and can store the same
   149  // kinds of values at the storage layer, but may have different constraints or type parameters.
   150  func (c Column) Compatible(other Column) bool {
   151  	return c.Tag == other.Tag &&
   152  		c.Kind == other.Kind &&
   153  		c.IsPartOfPK == other.IsPartOfPK
   154  }
   155  
   156  // KindString returns the string representation of the NomsKind stored in the column.
   157  func (c Column) KindString() string {
   158  	return KindToLwrStr[c.Kind]
   159  }