github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/doltdb/root_val.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 doltdb
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"errors"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    25  	"github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding"
    26  	"github.com/dolthub/dolt/go/libraries/utils/set"
    27  	"github.com/dolthub/dolt/go/store/hash"
    28  	"github.com/dolthub/dolt/go/store/types"
    29  )
    30  
    31  const (
    32  	ddbRootStructName = "dolt_db_root"
    33  
    34  	tablesKey       = "tables"
    35  	superSchemasKey = "super_schemas"
    36  	foreignKeyKey   = "foreign_key"
    37  	featureVersKey  = "feature_ver"
    38  )
    39  
    40  type FeatureVersion int64
    41  
    42  // DoltFeatureVersion is described in feature_version.md.
    43  // only variable for testing.
    44  var DoltFeatureVersion FeatureVersion = 1 // last bumped for CHECK constraint storage
    45  
    46  // RootValue defines the structure used inside all Dolthub noms dbs
    47  type RootValue struct {
    48  	vrw     types.ValueReadWriter
    49  	valueSt types.Struct
    50  	fkc     *ForeignKeyCollection // cache the first load
    51  }
    52  
    53  func newRootValue(vrw types.ValueReadWriter, st types.Struct) (*RootValue, error) {
    54  	v, ok, err := st.MaybeGet(featureVersKey)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	if ok {
    59  		ver := FeatureVersion(v.(types.Int))
    60  		if DoltFeatureVersion < ver {
    61  			return nil, ErrClientOutOfDate{
    62  				ClientVer: DoltFeatureVersion,
    63  				RepoVer:   ver,
    64  			}
    65  		}
    66  	}
    67  
    68  	return &RootValue{vrw, st, nil}, nil
    69  }
    70  
    71  func EmptyRootValue(ctx context.Context, vrw types.ValueReadWriter) (*RootValue, error) {
    72  	empty, err := types.NewMap(ctx, vrw)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	sd := types.StructData{
    78  		tablesKey:       empty,
    79  		superSchemasKey: empty,
    80  		foreignKeyKey:   empty,
    81  		featureVersKey:  types.Int(DoltFeatureVersion),
    82  	}
    83  
    84  	st, err := types.NewStruct(vrw.Format(), ddbRootStructName, sd)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	return newRootValue(vrw, st)
    90  }
    91  
    92  func (root *RootValue) VRW() types.ValueReadWriter {
    93  	return root.vrw
    94  }
    95  
    96  // GetFeatureVersion returns the feature version of this root, if one is written
    97  func (root *RootValue) GetFeatureVersion(ctx context.Context) (ver FeatureVersion, ok bool, err error) {
    98  	v, ok, err := root.valueSt.MaybeGet(featureVersKey)
    99  	if err != nil || !ok {
   100  		return ver, ok, err
   101  	}
   102  	ver = FeatureVersion(v.(types.Int))
   103  	return ver, ok, err
   104  }
   105  
   106  func (root *RootValue) HasTable(ctx context.Context, tName string) (bool, error) {
   107  	val, found, err := root.valueSt.MaybeGet(tablesKey)
   108  
   109  	if err != nil {
   110  		return false, err
   111  	}
   112  
   113  	if !found {
   114  		return false, nil
   115  	}
   116  
   117  	tableMap := val.(types.Map)
   118  	return tableMap.Has(ctx, types.String(tName))
   119  }
   120  
   121  // TableNameInUse checks if a name can be used to create a new table. The most recent
   122  // names of all current tables and all previously existing tables cannot be used.
   123  func (root *RootValue) TableNameInUse(ctx context.Context, tName string) (bool, error) {
   124  	_, ok, err := root.GetSuperSchema(ctx, tName)
   125  	if err != nil {
   126  		return false, err
   127  	}
   128  	return ok, nil
   129  }
   130  
   131  // GetSuperSchema returns the SuperSchema for the table name specified if that table exists.
   132  func (root *RootValue) GetSuperSchema(ctx context.Context, tName string) (*schema.SuperSchema, bool, error) {
   133  	// SuperSchema is only persisted on Commit()
   134  	ss, found, err := root.getSuperSchemaAtLastCommit(ctx, tName)
   135  
   136  	if err != nil {
   137  		return nil, false, err
   138  	}
   139  	if !found {
   140  		ss, _ = schema.NewSuperSchema()
   141  	}
   142  
   143  	t, tblFound, err := root.GetTable(ctx, tName)
   144  	if err != nil {
   145  		return nil, false, err
   146  	}
   147  
   148  	if !found && !tblFound {
   149  		// table doesn't exist in current commit or in history
   150  		return nil, false, nil
   151  	}
   152  
   153  	if tblFound {
   154  		sch, err := t.GetSchema(ctx)
   155  		if err != nil {
   156  			return nil, false, err
   157  		}
   158  
   159  		err = ss.AddSchemas(sch)
   160  		if err != nil {
   161  			return nil, false, err
   162  		}
   163  	}
   164  
   165  	return ss, true, err
   166  }
   167  
   168  func (root *RootValue) GenerateTagsForNewColColl(ctx context.Context, tableName string, cc *schema.ColCollection) (*schema.ColCollection, error) {
   169  	newColNames := make([]string, 0, cc.Size())
   170  	newColKinds := make([]types.NomsKind, 0, cc.Size())
   171  	_ = cc.Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
   172  		newColNames = append(newColNames, col.Name)
   173  		newColKinds = append(newColKinds, col.Kind)
   174  		return false, nil
   175  	})
   176  
   177  	newTags, err := root.GenerateTagsForNewColumns(ctx, tableName, newColNames, newColKinds, nil)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	idx := 0
   183  	return schema.MapColCollection(cc, func(col schema.Column) schema.Column {
   184  		col.Tag = newTags[idx]
   185  		idx++
   186  		return col
   187  	}), nil
   188  }
   189  
   190  // GenerateTagsForNewColumns deterministically generates a slice of new tags that are unique within the history of this root. The names and NomsKinds of
   191  // the new columns are used to see the tag generator.
   192  func (root *RootValue) GenerateTagsForNewColumns(ctx context.Context, tableName string, newColNames []string, newColKinds []types.NomsKind, headRoot *RootValue) ([]uint64, error) {
   193  	if len(newColNames) != len(newColKinds) {
   194  		return nil, fmt.Errorf("error generating tags, newColNames and newColKinds must be of equal length")
   195  	}
   196  
   197  	if headRoot != nil {
   198  		tbl, found, err := headRoot.GetTable(ctx, tableName)
   199  		if err != nil {
   200  			return nil, err
   201  		}
   202  
   203  		if found {
   204  			sch, err := tbl.GetSchema(ctx)
   205  			if err != nil {
   206  				return nil, err
   207  			}
   208  
   209  			colOverlap := schema.GetSharedCols(sch, newColNames, newColKinds)
   210  			if len(colOverlap) == len(newColNames) {
   211  				var reusedTags []uint64
   212  				for _, k := range newColNames {
   213  					reusedTags = append(reusedTags, colOverlap[k])
   214  				}
   215  				return reusedTags, nil
   216  			}
   217  		}
   218  	}
   219  
   220  	rootSuperSchema, err := GetRootValueSuperSchema(ctx, root)
   221  
   222  	if err != nil {
   223  		return nil, err
   224  	}
   225  
   226  	var existingColKinds []types.NomsKind
   227  	tbl, found, err := root.GetTable(ctx, tableName)
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  	if found {
   232  		sch, err := tbl.GetSchema(ctx)
   233  		if err != nil {
   234  			return nil, err
   235  		}
   236  		_ = sch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
   237  			existingColKinds = append(existingColKinds, col.Kind)
   238  			return false, nil
   239  		})
   240  	}
   241  
   242  	newTags := make([]uint64, len(newColNames))
   243  	existingTags := set.NewUint64Set(rootSuperSchema.AllTags())
   244  	for i := range newTags {
   245  		newTags[i] = schema.AutoGenerateTag(existingTags, tableName, existingColKinds, newColNames[i], newColKinds[i])
   246  		existingColKinds = append(existingColKinds, newColKinds[i])
   247  		existingTags.Add(newTags[i])
   248  	}
   249  
   250  	return newTags, nil
   251  }
   252  
   253  // GerSuperSchemaMap returns the Noms map that tracks SuperSchemas, used to create new RootValues on checkout branch.
   254  func (root *RootValue) GetSuperSchemaMap(ctx context.Context) (types.Map, error) {
   255  	return root.getOrCreateSuperSchemaMap(ctx)
   256  }
   257  
   258  // SuperSchemas are only persisted on commit.
   259  func (root *RootValue) getSuperSchemaAtLastCommit(ctx context.Context, tName string) (*schema.SuperSchema, bool, error) {
   260  	ssm, err := root.getOrCreateSuperSchemaMap(ctx)
   261  	if err != nil {
   262  		return nil, false, err
   263  	}
   264  
   265  	v, found, err := ssm.MaybeGet(ctx, types.String(tName))
   266  	if err != nil {
   267  		return nil, false, err
   268  	}
   269  	if !found {
   270  		// Super Schema doesn't exist for new or nonexistent table
   271  		return nil, false, nil
   272  	}
   273  
   274  	ssValRef := v.(types.Ref)
   275  	ssVal, err := ssValRef.TargetValue(ctx, root.vrw)
   276  	if err != nil {
   277  		return nil, false, err
   278  	}
   279  
   280  	ss, err := encoding.UnmarshalSuperSchemaNomsValue(ctx, root.vrw.Format(), ssVal)
   281  	if err != nil {
   282  		return nil, false, err
   283  	}
   284  
   285  	return ss, true, nil
   286  }
   287  
   288  func (root *RootValue) getOrCreateSuperSchemaMap(ctx context.Context) (types.Map, error) {
   289  	v, found, err := root.valueSt.MaybeGet(superSchemasKey)
   290  
   291  	if err != nil {
   292  		return types.EmptyMap, err
   293  	}
   294  
   295  	var ssm types.Map
   296  	if found {
   297  		ssm = v.(types.Map)
   298  	} else {
   299  		ssm, err = types.NewMap(ctx, root.vrw)
   300  	}
   301  	return ssm, err
   302  }
   303  
   304  func (root *RootValue) getTableSt(ctx context.Context, tName string) (*types.Struct, bool, error) {
   305  	tableMap, err := root.getTableMap()
   306  
   307  	if err != nil {
   308  		return nil, false, err
   309  	}
   310  
   311  	tVal, found, err := tableMap.MaybeGet(ctx, types.String(tName))
   312  	if err != nil {
   313  		return nil, false, err
   314  	}
   315  
   316  	if tVal == nil || !found {
   317  		return nil, false, nil
   318  	}
   319  
   320  	tValRef := tVal.(types.Ref)
   321  	val, err := tValRef.TargetValue(ctx, root.vrw)
   322  	if err != nil {
   323  		return nil, false, err
   324  	}
   325  
   326  	tableStruct := val.(types.Struct)
   327  	return &tableStruct, true, nil
   328  }
   329  
   330  func (root *RootValue) GetAllSchemas(ctx context.Context) (map[string]schema.Schema, error) {
   331  	m := make(map[string]schema.Schema)
   332  	err := root.IterTables(ctx, func(name string, table *Table, sch schema.Schema) (stop bool, err error) {
   333  		m[name] = sch
   334  		return false, nil
   335  	})
   336  
   337  	if err != nil {
   338  		return nil, err
   339  	}
   340  
   341  	return m, nil
   342  }
   343  
   344  func (root *RootValue) GetTableHash(ctx context.Context, tName string) (hash.Hash, bool, error) {
   345  	tableMap, err := root.getTableMap()
   346  	if err != nil {
   347  		return hash.Hash{}, false, err
   348  	}
   349  
   350  	tVal, found, err := tableMap.MaybeGet(ctx, types.String(tName))
   351  	if err != nil {
   352  		return hash.Hash{}, false, err
   353  	}
   354  
   355  	if tVal == nil || !found {
   356  		return hash.Hash{}, false, nil
   357  	}
   358  
   359  	tValRef := tVal.(types.Ref)
   360  	return tValRef.TargetHash(), true, nil
   361  }
   362  
   363  func (root *RootValue) SetTableHash(ctx context.Context, tName string, h hash.Hash) (*RootValue, error) {
   364  	val, err := root.vrw.ReadValue(ctx, h)
   365  
   366  	if err != nil {
   367  		return nil, err
   368  	}
   369  
   370  	ref, err := types.NewRef(val, root.vrw.Format())
   371  
   372  	if err != nil {
   373  		return nil, err
   374  	}
   375  
   376  	return putTable(ctx, root, tName, ref)
   377  }
   378  
   379  // GetTable will retrieve a table by name
   380  func (root *RootValue) GetTable(ctx context.Context, tName string) (*Table, bool, error) {
   381  	if st, ok, err := root.getTableSt(ctx, tName); err != nil {
   382  		return nil, false, err
   383  	} else if ok {
   384  		return &Table{root.vrw, *st}, true, nil
   385  	}
   386  
   387  	return nil, false, nil
   388  }
   389  
   390  func (root *RootValue) GetTableInsensitive(ctx context.Context, tName string) (*Table, string, bool, error) {
   391  	tableMap, err := root.getTableMap()
   392  
   393  	if err != nil {
   394  		return nil, "", false, err
   395  	}
   396  
   397  	var foundKey string
   398  	hasExact, err := tableMap.Has(ctx, types.String(tName))
   399  
   400  	if err != nil {
   401  		return nil, "", false, err
   402  	}
   403  
   404  	if hasExact {
   405  		foundKey = tName
   406  	} else {
   407  		lwrName := strings.ToLower(tName)
   408  		err = tableMap.Iter(ctx, func(key, value types.Value) (stop bool, err error) {
   409  			keyStr := string(key.(types.String))
   410  			if lwrName == strings.ToLower(keyStr) {
   411  				foundKey = keyStr
   412  				return true, nil
   413  			}
   414  
   415  			return false, nil
   416  		})
   417  
   418  		if err != nil {
   419  			return nil, "", false, nil
   420  		}
   421  	}
   422  
   423  	tbl, ok, err := root.GetTable(ctx, foundKey)
   424  
   425  	if err != nil {
   426  		return nil, "", false, err
   427  	}
   428  
   429  	return tbl, foundKey, ok, nil
   430  }
   431  
   432  // GetTableByColTag looks for the table containing the given column tag. It returns false if no table exists in the history.
   433  // If the table containing the given tag previously existed and was deleted, it will return its name and a nil pointer.
   434  func (root *RootValue) GetTableByColTag(ctx context.Context, tag uint64) (tbl *Table, name string, found bool, err error) {
   435  	err = root.IterTables(ctx, func(tn string, t *Table, s schema.Schema) (bool, error) {
   436  		_, found = s.GetAllCols().GetByTag(tag)
   437  		if found {
   438  			name, tbl = tn, t
   439  		}
   440  
   441  		return found, nil
   442  	})
   443  
   444  	if err != nil {
   445  		return nil, "", false, err
   446  	}
   447  
   448  	err = root.iterSuperSchemas(ctx, func(tn string, ss *schema.SuperSchema) (bool, error) {
   449  		_, found = ss.GetByTag(tag)
   450  		if found {
   451  			name = tn
   452  		}
   453  
   454  		return found, nil
   455  	})
   456  	if err != nil {
   457  		return nil, "", false, err
   458  	}
   459  
   460  	return tbl, name, found, nil
   461  }
   462  
   463  // GetTableNames retrieves the lists of all tables for a RootValue
   464  func (root *RootValue) GetTableNames(ctx context.Context) ([]string, error) {
   465  	tableMap, err := root.getTableMap()
   466  
   467  	if err != nil {
   468  		return nil, err
   469  	}
   470  
   471  	numTables := int(tableMap.Len())
   472  	names := make([]string, 0, numTables)
   473  
   474  	err = tableMap.Iter(ctx, func(key, _ types.Value) (stop bool, err error) {
   475  		names = append(names, string(key.(types.String)))
   476  		return false, nil
   477  	})
   478  
   479  	if err != nil {
   480  		return nil, err
   481  	}
   482  
   483  	return names, nil
   484  }
   485  
   486  func (root *RootValue) getTableMap() (types.Map, error) {
   487  	val, found, err := root.valueSt.MaybeGet(tablesKey)
   488  
   489  	if err != nil {
   490  		return types.EmptyMap, err
   491  	}
   492  
   493  	if !found || val == nil {
   494  		return types.EmptyMap, err
   495  	}
   496  
   497  	tableMap := val.(types.Map)
   498  	return tableMap, err
   499  }
   500  
   501  func (root *RootValue) TablesInConflict(ctx context.Context) ([]string, error) {
   502  	tableMap, err := root.getTableMap()
   503  
   504  	if err != nil {
   505  		return nil, err
   506  	}
   507  
   508  	numTables := int(tableMap.Len())
   509  	names := make([]string, 0, numTables)
   510  
   511  	err = tableMap.Iter(ctx, func(key, tblRefVal types.Value) (stop bool, err error) {
   512  		tblVal, err := tblRefVal.(types.Ref).TargetValue(ctx, root.vrw)
   513  
   514  		if err != nil {
   515  			return false, err
   516  		}
   517  
   518  		tblSt := tblVal.(types.Struct)
   519  		tbl := &Table{root.vrw, tblSt}
   520  		if has, err := tbl.HasConflicts(); err != nil {
   521  			return false, err
   522  		} else if has {
   523  			names = append(names, string(key.(types.String)))
   524  		}
   525  
   526  		return false, nil
   527  	})
   528  
   529  	if err != nil {
   530  		return nil, err
   531  	}
   532  
   533  	return names, nil
   534  }
   535  
   536  func (root *RootValue) HasConflicts(ctx context.Context) (bool, error) {
   537  	cnfTbls, err := root.TablesInConflict(ctx)
   538  
   539  	if err != nil {
   540  		return false, err
   541  	}
   542  
   543  	return len(cnfTbls) > 0, nil
   544  }
   545  
   546  // IterTables calls the callback function cb on each table in this RootValue.
   547  func (root *RootValue) IterTables(ctx context.Context, cb func(name string, table *Table, sch schema.Schema) (stop bool, err error)) error {
   548  	tm, err := root.getTableMap()
   549  
   550  	if err != nil {
   551  		return err
   552  	}
   553  
   554  	itr, err := tm.Iterator(ctx)
   555  
   556  	if err != nil {
   557  		return err
   558  	}
   559  
   560  	for {
   561  		nm, tableRef, err := itr.Next(ctx)
   562  
   563  		if err != nil || nm == nil || tableRef == nil {
   564  			return err
   565  		}
   566  
   567  		tableStruct, err := tableRef.(types.Ref).TargetValue(ctx, root.vrw)
   568  
   569  		if err != nil {
   570  			return err
   571  		}
   572  
   573  		name := string(nm.(types.String))
   574  		table := &Table{root.vrw, tableStruct.(types.Struct)}
   575  
   576  		sch, err := table.GetSchema(ctx)
   577  		if err != nil {
   578  			return err
   579  		}
   580  
   581  		stop, err := cb(name, table, sch)
   582  
   583  		if err != nil || stop {
   584  			return err
   585  		}
   586  	}
   587  }
   588  
   589  func (root *RootValue) iterSuperSchemas(ctx context.Context, cb func(name string, ss *schema.SuperSchema) (stop bool, err error)) error {
   590  	m, err := root.getOrCreateSuperSchemaMap(ctx)
   591  	if err != nil {
   592  		return err
   593  	}
   594  
   595  	return m.Iter(ctx, func(key, value types.Value) (stop bool, err error) {
   596  		name := string(key.(types.String))
   597  
   598  		// use GetSuperSchema() to pickup uncommitted SuperSchemas
   599  		ss, _, err := root.GetSuperSchema(ctx, name)
   600  		if err != nil {
   601  			return false, err
   602  		}
   603  
   604  		return cb(name, ss)
   605  	})
   606  }
   607  
   608  // PutSuperSchema writes a new map entry for the table name and super schema supplied, it will overwrite an existing entry.
   609  func (root *RootValue) PutSuperSchema(ctx context.Context, tName string, ss *schema.SuperSchema) (*RootValue, error) {
   610  	newRoot := root
   611  	ssm, err := newRoot.getOrCreateSuperSchemaMap(ctx)
   612  
   613  	if err != nil {
   614  		return nil, err
   615  	}
   616  
   617  	ssVal, err := encoding.MarshalSuperSchemaAsNomsValue(ctx, newRoot.VRW(), ss)
   618  
   619  	if err != nil {
   620  		return nil, err
   621  	}
   622  
   623  	ssRef, err := WriteValAndGetRef(ctx, newRoot.VRW(), ssVal)
   624  
   625  	if err != nil {
   626  		return nil, err
   627  	}
   628  
   629  	m, err := ssm.Edit().Set(types.String(tName), ssRef).Map(ctx)
   630  
   631  	if err != nil {
   632  		return nil, err
   633  	}
   634  
   635  	newRootSt := newRoot.valueSt
   636  	newRootSt, err = newRootSt.Set(superSchemasKey, m)
   637  
   638  	if err != nil {
   639  		return nil, err
   640  	}
   641  
   642  	return newRootValue(root.vrw, newRootSt)
   643  }
   644  
   645  // PutTable inserts a table by name into the map of tables. If a table already exists with that name it will be replaced
   646  func (root *RootValue) PutTable(ctx context.Context, tName string, table *Table) (*RootValue, error) {
   647  	err := validateTagUniqueness(ctx, root, tName, table)
   648  
   649  	if err != nil {
   650  		return nil, err
   651  	}
   652  
   653  	tableRef, err := WriteValAndGetRef(ctx, root.VRW(), table.tableStruct)
   654  
   655  	if err != nil {
   656  		return nil, err
   657  	}
   658  
   659  	return putTable(ctx, root, tName, tableRef)
   660  }
   661  
   662  func putTable(ctx context.Context, root *RootValue, tName string, tableRef types.Ref) (*RootValue, error) {
   663  	if !IsValidTableName(tName) {
   664  		panic("Don't attempt to put a table with a name that fails the IsValidTableName check")
   665  	}
   666  
   667  	tableMap, err := root.getTableMap()
   668  
   669  	if err != nil {
   670  		return nil, err
   671  	}
   672  
   673  	tMapEditor := tableMap.Edit()
   674  	tMapEditor = tMapEditor.Set(types.String(tName), tableRef)
   675  
   676  	m, err := tMapEditor.Map(ctx)
   677  
   678  	if err != nil {
   679  		return nil, err
   680  	}
   681  
   682  	rootValSt := root.valueSt
   683  	rootValSt, err = rootValSt.Set(tablesKey, m)
   684  
   685  	if err != nil {
   686  		return nil, err
   687  	}
   688  
   689  	return newRootValue(root.vrw, rootValSt)
   690  }
   691  
   692  // CreateEmptyTable creates an empty table in this root with the name and schema given, returning the new root value.
   693  func (root *RootValue) CreateEmptyTable(ctx context.Context, tName string, sch schema.Schema) (*RootValue, error) {
   694  	schVal, err := encoding.MarshalSchemaAsNomsValue(ctx, root.VRW(), sch)
   695  	if err != nil {
   696  		return nil, err
   697  	}
   698  
   699  	empty, err := types.NewMap(ctx, root.VRW())
   700  	if err != nil {
   701  		return nil, err
   702  	}
   703  
   704  	emptyRef, err := WriteValAndGetRef(ctx, root.VRW(), empty)
   705  	if err != nil {
   706  		return nil, err
   707  	}
   708  
   709  	ed := empty.Edit()
   710  	err = sch.Indexes().Iter(func(index schema.Index) (stop bool, err error) {
   711  		// create an empty indexRowData map for every index
   712  		ed.Set(types.String(index.Name()), emptyRef)
   713  		return
   714  	})
   715  	if err != nil {
   716  		return nil, err
   717  	}
   718  
   719  	indexes, err := ed.Map(ctx)
   720  	if err != nil {
   721  		return nil, err
   722  	}
   723  
   724  	tbl, err := NewTable(ctx, root.VRW(), schVal, empty, indexes, nil)
   725  	if err != nil {
   726  		return nil, err
   727  	}
   728  
   729  	newRoot, err := root.PutTable(ctx, tName, tbl)
   730  	if err != nil {
   731  		return nil, err
   732  	}
   733  
   734  	return newRoot, nil
   735  }
   736  
   737  // HashOf gets the hash of the root value
   738  func (root *RootValue) HashOf() (hash.Hash, error) {
   739  	return root.valueSt.Hash(root.vrw.Format())
   740  }
   741  
   742  // UpdateSuperSchemasFromOther updates SuperSchemas of tblNames using SuperSchemas from other.
   743  func (root *RootValue) UpdateSuperSchemasFromOther(ctx context.Context, tblNames []string, other *RootValue) (*RootValue, error) {
   744  	newRoot := root
   745  	ssm, err := newRoot.getOrCreateSuperSchemaMap(ctx)
   746  
   747  	if err != nil {
   748  		return nil, err
   749  	}
   750  
   751  	sse := ssm.Edit()
   752  
   753  	for _, tn := range tblNames {
   754  
   755  		ss, found, err := root.GetSuperSchema(ctx, tn)
   756  
   757  		if err != nil {
   758  			return nil, err
   759  		}
   760  
   761  		oss, foundOther, err := other.GetSuperSchema(ctx, tn)
   762  
   763  		if err != nil {
   764  			return nil, err
   765  		}
   766  
   767  		var newSS *schema.SuperSchema
   768  		if found && foundOther {
   769  			newSS, err = schema.SuperSchemaUnion(ss, oss)
   770  		} else if found {
   771  			newSS = ss
   772  		} else if foundOther {
   773  			newSS = oss
   774  		} else {
   775  			h, _ := root.HashOf()
   776  			oh, _ := other.HashOf()
   777  			return nil, errors.New(fmt.Sprintf("table %s does not exist in root %s or root %s", tn, h.String(), oh.String()))
   778  		}
   779  
   780  		if err != nil {
   781  			return nil, err
   782  		}
   783  
   784  		ssVal, err := encoding.MarshalSuperSchemaAsNomsValue(ctx, newRoot.VRW(), newSS)
   785  
   786  		if err != nil {
   787  			return nil, err
   788  		}
   789  
   790  		ssRef, err := WriteValAndGetRef(ctx, newRoot.VRW(), ssVal)
   791  
   792  		if err != nil {
   793  			return nil, err
   794  		}
   795  
   796  		sse = sse.Set(types.String(tn), ssRef)
   797  	}
   798  
   799  	m, err := sse.Map(ctx)
   800  
   801  	if err != nil {
   802  		return nil, err
   803  	}
   804  
   805  	newRootSt := newRoot.valueSt
   806  	newRootSt, err = newRootSt.Set(superSchemasKey, m)
   807  
   808  	if err != nil {
   809  		return nil, err
   810  	}
   811  
   812  	return newRootValue(root.vrw, newRootSt)
   813  }
   814  
   815  // RenameTable renames a table by changing its string key in the RootValue's table map. In order to preserve
   816  // column tag information, use this method instead of a table drop + add.
   817  func (root *RootValue) RenameTable(ctx context.Context, oldName, newName string) (*RootValue, error) {
   818  	tableMap, err := root.getTableMap()
   819  	if err != nil {
   820  		return nil, err
   821  	}
   822  
   823  	tv, found, err := tableMap.MaybeGet(ctx, types.String(oldName))
   824  	if err != nil {
   825  		return nil, err
   826  	}
   827  	if !found {
   828  		return nil, ErrTableNotFound
   829  	}
   830  
   831  	_, found, err = tableMap.MaybeGet(ctx, types.String(newName))
   832  	if err != nil {
   833  		return nil, err
   834  	}
   835  	if found {
   836  		return nil, ErrTableExists
   837  	}
   838  
   839  	tme := tableMap.Edit().Remove(types.String(oldName))
   840  	tme = tme.Set(types.String(newName), tv)
   841  	tableMap, err = tme.Map(ctx)
   842  	if err != nil {
   843  		return nil, err
   844  	}
   845  	rootValSt := root.valueSt
   846  	rootValSt, err = rootValSt.Set(tablesKey, tableMap)
   847  	if err != nil {
   848  		return nil, err
   849  	}
   850  
   851  	foreignKeyCollection, err := root.GetForeignKeyCollection(ctx)
   852  	if err != nil {
   853  		return nil, err
   854  	}
   855  	foreignKeyCollection.RenameTable(oldName, newName)
   856  	fkMap, err := foreignKeyCollection.Map(ctx, root.vrw)
   857  	if err != nil {
   858  		return nil, err
   859  	}
   860  	rootValSt, err = rootValSt.Set(foreignKeyKey, fkMap)
   861  	if err != nil {
   862  		return nil, err
   863  	}
   864  
   865  	ssMap, err := root.getOrCreateSuperSchemaMap(ctx)
   866  	if err != nil {
   867  		return nil, err
   868  	}
   869  
   870  	ssv, found, err := ssMap.MaybeGet(ctx, types.String(oldName))
   871  	if err != nil {
   872  		return nil, err
   873  	}
   874  	if found {
   875  		ssme := ssMap.Edit().Remove(types.String(oldName))
   876  		ssme = ssme.Set(types.String(newName), ssv)
   877  		ssMap, err = ssme.Map(ctx)
   878  		if err != nil {
   879  			return nil, err
   880  		}
   881  
   882  		rootValSt, err = rootValSt.Set(superSchemasKey, ssMap)
   883  		if err != nil {
   884  			return nil, err
   885  		}
   886  		return newRootValue(root.vrw, rootValSt)
   887  	}
   888  
   889  	return newRootValue(root.vrw, rootValSt)
   890  }
   891  
   892  func (root *RootValue) RemoveTables(ctx context.Context, tables ...string) (*RootValue, error) {
   893  	tableMap, err := root.getTableMap()
   894  
   895  	if err != nil {
   896  		return nil, err
   897  	}
   898  
   899  	me := tableMap.Edit()
   900  	for _, tbl := range tables {
   901  		key := types.String(tbl)
   902  
   903  		if has, err := tableMap.Has(ctx, key); err != nil {
   904  			return nil, err
   905  		} else if has {
   906  			me = me.Remove(key)
   907  		} else {
   908  			return nil, ErrTableNotFound
   909  		}
   910  	}
   911  
   912  	m, err := me.Map(ctx)
   913  
   914  	if err != nil {
   915  		return nil, err
   916  	}
   917  
   918  	rootValSt, err := root.valueSt.Set(tablesKey, m)
   919  
   920  	if err != nil {
   921  		return nil, err
   922  	}
   923  
   924  	newRoot, err := newRootValue(root.vrw, rootValSt)
   925  	if err != nil {
   926  		return nil, err
   927  	}
   928  
   929  	fkc, err := newRoot.GetForeignKeyCollection(ctx)
   930  
   931  	if err != nil {
   932  		return nil, err
   933  	}
   934  
   935  	err = fkc.RemoveTables(ctx, tables...)
   936  
   937  	if err != nil {
   938  		return nil, err
   939  	}
   940  
   941  	return newRoot.PutForeignKeyCollection(ctx, fkc)
   942  }
   943  
   944  // GetForeignKeyCollection returns the ForeignKeyCollection for this root. As collections are meant to be modified
   945  // in-place, each returned collection may freely be altered without affecting future returned collections from this root.
   946  func (root *RootValue) GetForeignKeyCollection(ctx context.Context) (*ForeignKeyCollection, error) {
   947  	if root.fkc == nil {
   948  		fkMap, err := root.GetForeignKeyCollectionMap(ctx)
   949  		if err != nil {
   950  			return nil, err
   951  		}
   952  		root.fkc, err = LoadForeignKeyCollection(ctx, fkMap)
   953  		if err != nil {
   954  			return nil, err
   955  		}
   956  	}
   957  	return root.fkc.copy(), nil
   958  }
   959  
   960  // GetForeignKeyCollectionMap returns the persisted noms Map of the foreign key collection on this root. If the intent
   961  // is to retrieve a ForeignKeyCollection in particular, it is advised to call GetForeignKeyCollection as it caches the
   962  // result for performance.
   963  func (root *RootValue) GetForeignKeyCollectionMap(ctx context.Context) (types.Map, error) {
   964  	v, found, err := root.valueSt.MaybeGet(foreignKeyKey)
   965  	if err != nil {
   966  		return types.EmptyMap, err
   967  	}
   968  
   969  	var fkMap types.Map
   970  	if found {
   971  		fkMap = v.(types.Map)
   972  	} else {
   973  		fkMap, err = types.NewMap(ctx, root.vrw)
   974  		if err != nil {
   975  			return types.EmptyMap, err
   976  		}
   977  	}
   978  	return fkMap, nil
   979  }
   980  
   981  // PutForeignKeyCollection returns a new root with the given foreign key collection.
   982  func (root *RootValue) PutForeignKeyCollection(ctx context.Context, fkc *ForeignKeyCollection) (*RootValue, error) {
   983  	fkMap, err := fkc.Map(ctx, root.vrw)
   984  	if err != nil {
   985  		return nil, err
   986  	}
   987  	rootValSt, err := root.valueSt.Set(foreignKeyKey, fkMap)
   988  	if err != nil {
   989  		return nil, err
   990  	}
   991  	return &RootValue{root.vrw, rootValSt, fkc.copy()}, nil
   992  }
   993  
   994  // ValidateForeignKeysOnSchemas ensures that all foreign keys' tables are present, removing any foreign keys where the declared
   995  // table is missing, and returning an error if a key is in an invalid state or a referenced table is missing. Does not
   996  // check any tables' row data.
   997  func (root *RootValue) ValidateForeignKeysOnSchemas(ctx context.Context) (*RootValue, error) {
   998  	fkCollection, err := root.GetForeignKeyCollection(ctx)
   999  	if err != nil {
  1000  		return nil, err
  1001  	}
  1002  	allTablesSlice, err := root.GetTableNames(ctx)
  1003  	if err != nil {
  1004  		return nil, err
  1005  	}
  1006  	allTablesSet := make(map[string]schema.Schema)
  1007  	for _, tableName := range allTablesSlice {
  1008  		tbl, ok, err := root.GetTable(ctx, tableName)
  1009  		if err != nil {
  1010  			return nil, err
  1011  		}
  1012  		if !ok {
  1013  			return nil, fmt.Errorf("found table `%s` in staging but could not load for foreign key check", tableName)
  1014  		}
  1015  		tblSch, err := tbl.GetSchema(ctx)
  1016  		if err != nil {
  1017  			return nil, err
  1018  		}
  1019  		allTablesSet[tableName] = tblSch
  1020  	}
  1021  
  1022  	// some of these checks are sanity checks and should never happen
  1023  	allForeignKeys := fkCollection.AllKeys()
  1024  	for _, foreignKey := range allForeignKeys {
  1025  		tblSch, existsInRoot := allTablesSet[foreignKey.TableName]
  1026  		if existsInRoot {
  1027  			if err := foreignKey.ValidateTableSchema(tblSch); err != nil {
  1028  				return nil, err
  1029  			}
  1030  			parentSch, existsInRoot := allTablesSet[foreignKey.ReferencedTableName]
  1031  			if !existsInRoot {
  1032  				return nil, fmt.Errorf("foreign key `%s` requires the referenced table `%s`", foreignKey.Name, foreignKey.ReferencedTableName)
  1033  			}
  1034  			if err := foreignKey.ValidateReferencedTableSchema(parentSch); err != nil {
  1035  				return nil, err
  1036  			}
  1037  		} else {
  1038  			err := fkCollection.RemoveKeyByName(foreignKey.Name)
  1039  			if err != nil {
  1040  				return nil, err
  1041  			}
  1042  		}
  1043  	}
  1044  
  1045  	return root.PutForeignKeyCollection(ctx, fkCollection)
  1046  }
  1047  
  1048  // RootNeedsUniqueTagsMigration determines if this root needs to be migrated to uniquify its tags.
  1049  func RootNeedsUniqueTagsMigration(root *RootValue) (bool, error) {
  1050  	// SuperSchemas were added in the same update that required unique tags. If a root does not have a
  1051  	// SuperSchema map then it was created before the unique tags constraint was enforced.
  1052  	_, found, err := root.valueSt.MaybeGet(superSchemasKey)
  1053  	if err != nil {
  1054  		return false, err
  1055  	}
  1056  	needToMigrate := !found
  1057  	return needToMigrate, nil
  1058  }
  1059  
  1060  // GetRootValueSuperSchema creates a SuperSchema with every column in history of root.
  1061  func GetRootValueSuperSchema(ctx context.Context, root *RootValue) (*schema.SuperSchema, error) {
  1062  	ssMap, err := root.getOrCreateSuperSchemaMap(ctx)
  1063  
  1064  	if err != nil {
  1065  		return nil, err
  1066  	}
  1067  
  1068  	var sss []*schema.SuperSchema
  1069  	err = ssMap.Iter(ctx, func(key, value types.Value) (stop bool, err error) {
  1070  		ssValRef := value.(types.Ref)
  1071  		ssVal, err := ssValRef.TargetValue(ctx, root.vrw)
  1072  
  1073  		if err != nil {
  1074  			return true, err
  1075  		}
  1076  
  1077  		ss, err := encoding.UnmarshalSuperSchemaNomsValue(ctx, root.vrw.Format(), ssVal)
  1078  
  1079  		if err != nil {
  1080  			return true, err
  1081  		}
  1082  
  1083  		sss = append(sss, ss) // go get -f parseltongue
  1084  		return false, nil
  1085  	})
  1086  
  1087  	if err != nil {
  1088  		return nil, err
  1089  	}
  1090  
  1091  	rootSuperSchema, err := schema.SuperSchemaUnion(sss...)
  1092  	if err != nil {
  1093  		return nil, err
  1094  	}
  1095  
  1096  	// super schemas are only persisted on commit, so add in working schemas
  1097  	tblMap, err := root.getTableMap()
  1098  	if err != nil {
  1099  		return nil, err
  1100  	}
  1101  
  1102  	err = tblMap.Iter(ctx, func(key, _ types.Value) (stop bool, err error) {
  1103  		tbl, _, err := root.GetTable(ctx, string(key.(types.String)))
  1104  		if err != nil {
  1105  			return true, err
  1106  		}
  1107  		sch, err := tbl.GetSchema(ctx)
  1108  		if err != nil {
  1109  			return true, err
  1110  		}
  1111  		err = rootSuperSchema.AddSchemas(sch)
  1112  		if err != nil {
  1113  			return true, err
  1114  		}
  1115  		return false, nil
  1116  	})
  1117  	if err != nil {
  1118  		return nil, err
  1119  	}
  1120  
  1121  	return rootSuperSchema, nil
  1122  }
  1123  
  1124  // UnionTableNames returns an array of all table names in all roots passed as params.
  1125  func UnionTableNames(ctx context.Context, roots ...*RootValue) ([]string, error) {
  1126  	allTblNames := make([]string, 0, 16)
  1127  	for _, root := range roots {
  1128  		tblNames, err := root.GetTableNames(ctx)
  1129  
  1130  		if err != nil {
  1131  			return nil, err
  1132  		}
  1133  
  1134  		allTblNames = append(allTblNames, tblNames...)
  1135  	}
  1136  
  1137  	return set.Unique(allTblNames), nil
  1138  }
  1139  
  1140  // validateTagUniqueness checks for tag collisions between the given table and the set of tables in then given root.
  1141  func validateTagUniqueness(ctx context.Context, root *RootValue, tableName string, table *Table) error {
  1142  	prev, ok, err := root.GetTable(ctx, tableName)
  1143  	if err != nil {
  1144  		return err
  1145  	}
  1146  	if ok {
  1147  		prevRef, err := prev.GetSchemaRef()
  1148  		if err != nil {
  1149  			return err
  1150  		}
  1151  
  1152  		newRef, err := table.GetSchemaRef()
  1153  		if err != nil {
  1154  			return err
  1155  		}
  1156  
  1157  		// short-circuit if schema unchanged
  1158  		if prevRef.Equals(newRef) {
  1159  			return nil
  1160  		}
  1161  	}
  1162  
  1163  	sch, err := table.GetSchema(ctx)
  1164  	if err != nil {
  1165  		return err
  1166  	}
  1167  
  1168  	var ee []string
  1169  	err = root.iterSuperSchemas(ctx, func(tn string, ss *schema.SuperSchema) (stop bool, err error) {
  1170  		if tn == tableName {
  1171  			return false, nil
  1172  		}
  1173  
  1174  		err = sch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
  1175  			_, ok := ss.GetByTag(tag)
  1176  			if ok {
  1177  				ee = append(ee, schema.ErrTagPrevUsed(tag, col.Name, tn).Error())
  1178  			}
  1179  			return false, nil
  1180  		})
  1181  		return false, err
  1182  	})
  1183  	if err != nil {
  1184  		return err
  1185  	}
  1186  
  1187  	if len(ee) > 0 {
  1188  		return fmt.Errorf(strings.Join(ee, "\n"))
  1189  	}
  1190  
  1191  	return nil
  1192  }
  1193  
  1194  // DebugString returns a human readable string with the contents of this root. If |transitive| is true, row data from
  1195  // all tables is also included. This method is very expensive for large root values, so |transitive| should only be used
  1196  // when debugging tests.
  1197  func (root *RootValue) DebugString(ctx context.Context, transitive bool) string {
  1198  	var buf bytes.Buffer
  1199  	err := types.WriteEncodedValue(ctx, &buf, root.valueSt)
  1200  	if err != nil {
  1201  		panic(err)
  1202  	}
  1203  
  1204  	if transitive {
  1205  		buf.WriteString("\nTables:")
  1206  		root.IterTables(ctx, func(name string, table *Table, sch schema.Schema) (stop bool, err error) {
  1207  			buf.WriteString("\nName:")
  1208  			buf.WriteString(name)
  1209  			buf.WriteString("\n")
  1210  
  1211  			buf.WriteString("Data:\n")
  1212  			data, err := table.GetRowData(ctx)
  1213  			if err != nil {
  1214  				panic(err)
  1215  			}
  1216  
  1217  			err = types.WriteEncodedValue(ctx, &buf, data)
  1218  			if err != nil {
  1219  				panic(err)
  1220  			}
  1221  			return false, nil
  1222  		})
  1223  	}
  1224  
  1225  	return buf.String()
  1226  }