github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/schema/constraint.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  	"fmt"
    19  
    20  	"github.com/dolthub/dolt/go/store/types"
    21  )
    22  
    23  // ColConstraint is an interface used for evaluating whether a columns value is valid
    24  type ColConstraint interface {
    25  	// SatisfiesConstraint takes in a value and returns true if the value satisfies the constraint
    26  	SatisfiesConstraint(value types.Value) bool
    27  
    28  	// GetConstraintType returns a string representation of the type of constraint.  This is used for serialization and
    29  	// deserialization of constraints (see ColConstraintFromTypeAndParams).
    30  	GetConstraintType() string
    31  
    32  	// GetConstraintParams returns a map[string]string containing the constraints parameters.  This is used for
    33  	// serialization and deserialization of constraints, and a deserialized constraint must be able to reproduce the same
    34  	// behavior based on the parameters in this map (See ColConstraintFromTypeAndParams).
    35  	GetConstraintParams() map[string]string
    36  
    37  	// Stringer results are used to inform users of the constraint's properties.
    38  	fmt.Stringer
    39  }
    40  
    41  const (
    42  	NotNullConstraintType = "not_null"
    43  )
    44  
    45  // ColConstraintFromTypeAndParams takes in a string representing the type of the constraint and a map of parameters
    46  // that can be used to determine the behavior of the constraint.  An example might be a constraint which validated
    47  // a value is in a given range.  For this the constraint type might by "in_range_constraint", and the parameters might
    48  // be {"min": -10, "max": 10}
    49  func ColConstraintFromTypeAndParams(colCnstType string, params map[string]string) ColConstraint {
    50  	switch colCnstType {
    51  	case NotNullConstraintType:
    52  		return NotNullConstraint{}
    53  	}
    54  	panic("Unknown column constraint type: " + colCnstType)
    55  }
    56  
    57  // NotNullConstraint validates that a value is not null.  It does not restrict 0 length strings, or 0 valued ints, or
    58  // anything other than non nil values
    59  type NotNullConstraint struct{}
    60  
    61  // SatisfiesConstraint returns true if value is not nil and not types.NullValue
    62  func (nnc NotNullConstraint) SatisfiesConstraint(value types.Value) bool {
    63  	return !types.IsNull(value)
    64  }
    65  
    66  // GetConstraintType returns "not_null"
    67  func (nnc NotNullConstraint) GetConstraintType() string {
    68  	return NotNullConstraintType
    69  }
    70  
    71  // GetConstraintParams returns nil as this constraint does not require any parameters.
    72  func (nnc NotNullConstraint) GetConstraintParams() map[string]string {
    73  	return nil
    74  }
    75  
    76  // String returns a useful description of the constraint
    77  func (nnc NotNullConstraint) String() string {
    78  	return "Not null"
    79  }
    80  
    81  // IndexOfConstraint returns the index in the supplied slice of the first constraint of matching type.  If none are
    82  // found then -1 is returned
    83  func IndexOfConstraint(constraints []ColConstraint, constraintType string) int {
    84  	for i, c := range constraints {
    85  		if c.GetConstraintType() == constraintType {
    86  			return i
    87  		}
    88  	}
    89  
    90  	return -1
    91  }
    92  
    93  // ColConstraintsAreEqual validates two ColConstraint slices are identical.
    94  func ColConstraintsAreEqual(a, b []ColConstraint) bool {
    95  	if len(a) != len(b) {
    96  		return false
    97  	} else if len(a) == 0 {
    98  		return true
    99  	}
   100  
   101  	// kinda shitty.  Probably shouldn't require order to be identital
   102  	for i := 0; i < len(a); i++ {
   103  		ca, cb := a[i], b[i]
   104  
   105  		if ca.GetConstraintType() != cb.GetConstraintType() {
   106  			return false
   107  		} else {
   108  			pa := ca.GetConstraintParams()
   109  			pb := cb.GetConstraintParams()
   110  
   111  			if len(pa) != len(pb) {
   112  				return false
   113  			} else if len(pa) != 0 {
   114  				for k, va := range pa {
   115  					vb, ok := pb[k]
   116  
   117  					if !ok {
   118  						return false
   119  					} else if va != vb {
   120  						return false
   121  					}
   122  				}
   123  			}
   124  		}
   125  	}
   126  
   127  	return true
   128  }