github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/schema/schema.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 "github.com/dolthub/dolt/go/store/types"
    18  
    19  // Schema is an interface for retrieving the columns that make up a schema
    20  type Schema interface {
    21  	// GetPKCols gets the collection of columns which make the primary key.
    22  	GetPKCols() *ColCollection
    23  
    24  	// GetNonPKCols gets the collection of columns which are not part of the primary key.
    25  	GetNonPKCols() *ColCollection
    26  
    27  	// GetAllCols gets the collection of all columns (pk and non-pk)
    28  	GetAllCols() *ColCollection
    29  
    30  	// Indexes returns a collection of all indexes on the table that this schema belongs to.
    31  	Indexes() IndexCollection
    32  
    33  	// Checks returns a collection of all check constraints on the table that this schema belongs to.
    34  	Checks() CheckCollection
    35  }
    36  
    37  // ColFromTag returns a schema.Column from a schema and a tag
    38  func ColFromTag(sch Schema, tag uint64) (Column, bool) {
    39  	return sch.GetAllCols().GetByTag(tag)
    40  }
    41  
    42  // ColFromName returns a schema.Column from a schema from it's name
    43  func ColFromName(sch Schema, name string) (Column, bool) {
    44  	return sch.GetAllCols().GetByName(name)
    45  }
    46  
    47  // ExtractAllColNames returns a map of tag to column name, with one map entry for every column in the schema.
    48  func ExtractAllColNames(sch Schema) (map[uint64]string, error) {
    49  	colNames := make(map[uint64]string)
    50  	err := sch.GetAllCols().Iter(func(tag uint64, col Column) (stop bool, err error) {
    51  		colNames[tag] = col.Name
    52  		return false, nil
    53  	})
    54  
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	return colNames, nil
    60  }
    61  
    62  func IsKeyless(sch Schema) bool {
    63  	return sch.GetPKCols().Size() == 0 &&
    64  		sch.GetAllCols().Size() != 0
    65  }
    66  
    67  func HasAutoIncrement(sch Schema) (ok bool) {
    68  	_ = sch.GetAllCols().Iter(func(tag uint64, col Column) (stop bool, err error) {
    69  		if col.AutoIncrement {
    70  			ok = true
    71  			stop = true
    72  		}
    73  		return
    74  	})
    75  	return
    76  }
    77  
    78  // SchemasAreEqual tests equality of two schemas.
    79  func SchemasAreEqual(sch1, sch2 Schema) bool {
    80  	if sch1 == nil && sch2 == nil {
    81  		return true
    82  	} else if sch1 == nil || sch2 == nil {
    83  		return false
    84  	}
    85  	colCollIsEqual := ColCollsAreEqual(sch1.GetAllCols(), sch2.GetAllCols())
    86  	if !colCollIsEqual {
    87  		return false
    88  	}
    89  	return sch1.Indexes().Equals(sch2.Indexes())
    90  }
    91  
    92  // TODO: this function never returns an error
    93  // VerifyInSchema tests that the incoming schema matches the schema from the original table
    94  // based on the presence of the column name in the original schema.
    95  func VerifyInSchema(inSch, outSch Schema) (bool, error) {
    96  	inSchCols := inSch.GetAllCols()
    97  	outSchCols := outSch.GetAllCols()
    98  
    99  	if inSchCols.Size() != outSchCols.Size() {
   100  		return false, nil
   101  	}
   102  
   103  	match := true
   104  	err := inSchCols.Iter(func(tag uint64, inCol Column) (stop bool, err error) {
   105  		_, isValid := outSchCols.GetByNameCaseInsensitive(inCol.Name)
   106  
   107  		if !isValid {
   108  			match = false
   109  			return true, nil
   110  		}
   111  
   112  		return false, nil
   113  	})
   114  
   115  	if err != nil {
   116  		return false, err
   117  	}
   118  
   119  	return match, nil
   120  }
   121  
   122  // GetSharedCols returns a name -> tag mapping for name/kind matches
   123  func GetSharedCols(schema Schema, cmpNames []string, cmpKinds []types.NomsKind) map[string]uint64 {
   124  	existingColKinds := make(map[string]types.NomsKind)
   125  	existingColTags := make(map[string]uint64)
   126  
   127  	_ = schema.GetAllCols().Iter(func(tag uint64, col Column) (stop bool, err error) {
   128  		existingColKinds[col.Name] = col.Kind
   129  		existingColTags[col.Name] = col.Tag
   130  		return false, nil
   131  	})
   132  
   133  	reuseTags := make(map[string]uint64)
   134  	for i, col := range cmpNames {
   135  		if val, ok := existingColKinds[col]; ok {
   136  			if val == cmpKinds[i] {
   137  				reuseTags[col] = existingColTags[col]
   138  			}
   139  		}
   140  	}
   141  	return reuseTags
   142  }