github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/catalog/descs/collection.go (about)

     1  // Copyright 2020 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  // Package descs provides abstractions for dealing with sets of descriptors.
    12  // It is utilized during schema changes and by catalog.Accessor implementations.
    13  package descs
    14  
    15  import (
    16  	"context"
    17  	"fmt"
    18  	"sort"
    19  	"strings"
    20  	"sync"
    21  
    22  	"github.com/cockroachdb/cockroach/pkg/keys"
    23  	"github.com/cockroachdb/cockroach/pkg/kv"
    24  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkv"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/database"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/lease"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    30  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    31  	"github.com/cockroachdb/cockroach/pkg/util/log"
    32  	"github.com/cockroachdb/errors"
    33  )
    34  
    35  // UncommittedDatabase is a database that has been created/dropped
    36  // within the current transaction using the Collection. A rename
    37  // is a drop of the old name and creation of the new name.
    38  type UncommittedDatabase struct {
    39  	name    string
    40  	id      sqlbase.ID
    41  	dropped bool
    42  }
    43  
    44  // UncommittedTable is a table that has been created/dropped within the
    45  // current transaction.
    46  type UncommittedTable struct {
    47  	*sqlbase.MutableTableDescriptor
    48  	*sqlbase.ImmutableTableDescriptor
    49  }
    50  
    51  // MakeCollection constructs a Collection.
    52  func MakeCollection(
    53  	leaseMgr *lease.Manager,
    54  	settings *cluster.Settings,
    55  	dbCache *database.Cache,
    56  	dbCacheSubscriber DatabaseCacheSubscriber,
    57  ) Collection {
    58  	return Collection{
    59  		leaseMgr:          leaseMgr,
    60  		settings:          settings,
    61  		databaseCache:     dbCache,
    62  		dbCacheSubscriber: dbCacheSubscriber,
    63  	}
    64  }
    65  
    66  // NewCollection constructs a new *Collection.
    67  func NewCollection(leaseMgr *lease.Manager, settings *cluster.Settings) *Collection {
    68  	tc := MakeCollection(leaseMgr, settings, nil, nil)
    69  	return &tc
    70  }
    71  
    72  // Collection is a collection of tables held by a single session that
    73  // serves SQL requests, or a background job using a table descriptor. The
    74  // collection is cleared using ReleaseAll() which is called at the
    75  // end of each transaction on the session, or on hitting conditions such
    76  // as errors, or retries that result in transaction timestamp changes.
    77  type Collection struct {
    78  	// leaseMgr manages acquiring and releasing per-table leases.
    79  	leaseMgr *lease.Manager
    80  	// A collection of table descriptor valid for the timestamp.
    81  	// They are released once the transaction using them is complete.
    82  	// If the transaction gets pushed and the timestamp changes,
    83  	// the tables are released.
    84  	leasedTables []*sqlbase.ImmutableTableDescriptor
    85  	// Tables modified by the uncommitted transaction affiliated
    86  	// with this Collection. This allows a transaction to see
    87  	// its own modifications while bypassing the table lease mechanism.
    88  	// The table lease mechanism will have its own transaction to read
    89  	// the table and will hang waiting for the uncommitted changes to
    90  	// the table. These table descriptors are local to this
    91  	// Collection and invisible to other transactions. A dropped
    92  	// table is marked dropped.
    93  	uncommittedTables []UncommittedTable
    94  
    95  	// databaseCache is used as a cache for database names.
    96  	// This field is nil when the field is initialized for an internalPlanner.
    97  	// TODO(andrei): get rid of it and replace it with a leasing system for
    98  	// database descriptors.
    99  	databaseCache *database.Cache
   100  
   101  	// schemaCache maps {databaseID, schemaName} -> (schemaID, if exists, otherwise nil).
   102  	// TODO(sqlexec): replace with leasing system with custom schemas.
   103  	// This is currently never cleared, because there should only be unique schemas
   104  	// being added for each Collection as only temporary schemas can be
   105  	// made, and you cannot read from other schema caches.
   106  	schemaCache sync.Map
   107  
   108  	// DatabaseCacheSubscriber is used to block until the node's database cache has been
   109  	// updated when ReleaseAll is called.
   110  	dbCacheSubscriber DatabaseCacheSubscriber
   111  
   112  	// Same as uncommittedTables applying to databases modified within
   113  	// an uncommitted transaction.
   114  	uncommittedDatabases []UncommittedDatabase
   115  
   116  	// allDescriptors is a slice of all available descriptors. The descriptors
   117  	// are cached to avoid repeated lookups by users like virtual tables. The
   118  	// cache is purged whenever events would cause a scan of all descriptors to
   119  	// return different values, such as when the txn timestamp changes or when
   120  	// new descriptors are written in the txn.
   121  	allDescriptors []sqlbase.DescriptorProto
   122  
   123  	// allDatabaseDescriptors is a slice of all available database descriptors.
   124  	// These are purged at the same time as allDescriptors.
   125  	allDatabaseDescriptors []*sqlbase.DatabaseDescriptor
   126  
   127  	// allSchemasForDatabase maps databaseID -> schemaID -> schemaName.
   128  	// For each databaseID, all schemas visible under the database can be
   129  	// observed.
   130  	// These are purged at the same time as allDescriptors.
   131  	allSchemasForDatabase map[sqlbase.ID]map[sqlbase.ID]string
   132  
   133  	// settings are required to correctly resolve system.namespace accesses in
   134  	// mixed version (19.2/20.1) clusters.
   135  	// TODO(solon): This field could maybe be removed in 20.2.
   136  	settings *cluster.Settings
   137  }
   138  
   139  // isSupportedSchemaName returns whether this schema name is supported.
   140  // TODO(sqlexec): this should be deleted when we use custom schemas.
   141  // However, this introduces an extra lookup for cases where `<database>.<table>`
   142  // is looked up.
   143  // See #44733.
   144  func isSupportedSchemaName(n tree.Name) bool {
   145  	return n == tree.PublicSchemaName || strings.HasPrefix(string(n), "pg_temp")
   146  }
   147  
   148  // GetMutableTableDescriptor returns a mutable table descriptor.
   149  //
   150  // If flags.required is false, GetMutableTableDescriptor() will gracefully
   151  // return a nil descriptor and no error if the table does not exist.
   152  //
   153  func (tc *Collection) GetMutableTableDescriptor(
   154  	ctx context.Context, txn *kv.Txn, tn *tree.TableName, flags tree.ObjectLookupFlags,
   155  ) (*sqlbase.MutableTableDescriptor, error) {
   156  	if log.V(2) {
   157  		log.Infof(ctx, "reading mutable descriptor on table '%s'", tn)
   158  	}
   159  
   160  	if !isSupportedSchemaName(tn.SchemaName) {
   161  		return nil, nil
   162  	}
   163  
   164  	refuseFurtherLookup, dbID, err := tc.GetUncommittedDatabaseID(tn.Catalog(), flags.Required)
   165  	if refuseFurtherLookup || err != nil {
   166  		return nil, err
   167  	}
   168  
   169  	if dbID == sqlbase.InvalidID && tc.DatabaseCache() != nil {
   170  		// Resolve the database from the database cache when the transaction
   171  		// hasn't modified the database.
   172  		dbID, err = tc.DatabaseCache().GetDatabaseID(ctx, tc.leaseMgr.DB().Txn, tn.Catalog(), flags.Required)
   173  		if err != nil || dbID == sqlbase.InvalidID {
   174  			// dbID can still be invalid if required is false and the database is not found.
   175  			return nil, err
   176  		}
   177  	}
   178  
   179  	// The following checks only work if the dbID is not invalid.
   180  	if dbID != sqlbase.InvalidID {
   181  		// Resolve the schema to the ID of the schema.
   182  		foundSchema, schemaID, err := tc.ResolveSchemaID(ctx, txn, dbID, tn.Schema())
   183  		if err != nil || !foundSchema {
   184  			return nil, err
   185  		}
   186  
   187  		if refuseFurtherLookup, table, err := tc.getUncommittedTable(
   188  			dbID,
   189  			schemaID,
   190  			tn,
   191  			flags.Required,
   192  		); refuseFurtherLookup || err != nil {
   193  			return nil, err
   194  		} else if mut := table.MutableTableDescriptor; mut != nil {
   195  			log.VEventf(ctx, 2, "found uncommitted table %d", mut.ID)
   196  			return mut, nil
   197  		}
   198  	}
   199  
   200  	phyAccessor := catalogkv.UncachedPhysicalAccessor{}
   201  	obj, err := phyAccessor.GetObjectDesc(
   202  		ctx,
   203  		txn,
   204  		tc.settings,
   205  		tc.codec(),
   206  		tn.Catalog(),
   207  		tn.Schema(),
   208  		tn.Table(),
   209  		flags,
   210  	)
   211  	if obj == nil {
   212  		return nil, err
   213  	}
   214  	mutDesc, ok := obj.(*sqlbase.MutableTableDescriptor)
   215  	if !ok {
   216  		return nil, err
   217  	}
   218  	return mutDesc, nil
   219  }
   220  
   221  // ResolveSchemaID attempts to lookup the schema from the schemaCache if it exists,
   222  // otherwise falling back to a database lookup.
   223  func (tc *Collection) ResolveSchemaID(
   224  	ctx context.Context, txn *kv.Txn, dbID sqlbase.ID, schemaName string,
   225  ) (bool, sqlbase.ID, error) {
   226  	// Fast path public schema, as it is always found.
   227  	if schemaName == tree.PublicSchema {
   228  		return true, keys.PublicSchemaID, nil
   229  	}
   230  
   231  	type schemaCacheKey struct {
   232  		dbID       sqlbase.ID
   233  		schemaName string
   234  	}
   235  
   236  	key := schemaCacheKey{dbID: dbID, schemaName: schemaName}
   237  	// First lookup the cache.
   238  	if val, ok := tc.schemaCache.Load(key); ok {
   239  		return true, val.(sqlbase.ID), nil
   240  	}
   241  
   242  	// Next, try lookup the result from KV, storing and returning the value.
   243  	exists, schemaID, err := catalogkv.ResolveSchemaID(ctx, txn, tc.codec(), dbID, schemaName)
   244  	if err != nil || !exists {
   245  		return exists, schemaID, err
   246  	}
   247  	tc.schemaCache.Store(key, schemaID)
   248  	return exists, schemaID, err
   249  }
   250  
   251  // GetTableVersion returns a table descriptor with a version suitable for
   252  // the transaction: table.ModificationTime <= txn.Timestamp < expirationTime.
   253  // The table must be released by calling tc.ReleaseAll().
   254  //
   255  // If flags.required is false, GetTableVersion() will gracefully
   256  // return a nil descriptor and no error if the table does not exist.
   257  //
   258  // It might also add a transaction deadline to the transaction that is
   259  // enforced at the KV layer to ensure that the transaction doesn't violate
   260  // the validity window of the table descriptor version returned.
   261  //
   262  func (tc *Collection) GetTableVersion(
   263  	ctx context.Context, txn *kv.Txn, tn *tree.TableName, flags tree.ObjectLookupFlags,
   264  ) (*sqlbase.ImmutableTableDescriptor, error) {
   265  	if log.V(2) {
   266  		log.Infof(ctx, "planner acquiring lease on table '%s'", tn)
   267  	}
   268  
   269  	if !isSupportedSchemaName(tn.SchemaName) {
   270  		return nil, nil
   271  	}
   272  
   273  	readTableFromStore := func() (*sqlbase.ImmutableTableDescriptor, error) {
   274  		phyAccessor := catalogkv.UncachedPhysicalAccessor{}
   275  		obj, err := phyAccessor.GetObjectDesc(
   276  			ctx,
   277  			txn,
   278  			tc.settings,
   279  			tc.codec(),
   280  			tn.Catalog(),
   281  			tn.Schema(),
   282  			tn.Table(),
   283  			flags,
   284  		)
   285  		if obj == nil {
   286  			return nil, err
   287  		}
   288  		tbl, ok := obj.(*sqlbase.ImmutableTableDescriptor)
   289  		if !ok {
   290  			return nil, err
   291  		}
   292  		return tbl, err
   293  	}
   294  
   295  	refuseFurtherLookup, dbID, err := tc.GetUncommittedDatabaseID(tn.Catalog(), flags.Required)
   296  	if refuseFurtherLookup || err != nil {
   297  		return nil, err
   298  	}
   299  
   300  	if dbID == sqlbase.InvalidID && tc.DatabaseCache() != nil {
   301  		// Resolve the database from the database cache when the transaction
   302  		// hasn't modified the database.
   303  		dbID, err = tc.DatabaseCache().GetDatabaseID(ctx, tc.leaseMgr.DB().Txn, tn.Catalog(), flags.Required)
   304  		if err != nil || dbID == sqlbase.InvalidID {
   305  			// dbID can still be invalid if required is false and the database is not found.
   306  			return nil, err
   307  		}
   308  	}
   309  
   310  	// If at this point we have an InvalidID, we should immediately try read from store.
   311  	if dbID == sqlbase.InvalidID {
   312  		return readTableFromStore()
   313  	}
   314  
   315  	// Resolve the schema to the ID of the schema.
   316  	foundSchema, schemaID, err := tc.ResolveSchemaID(ctx, txn, dbID, tn.Schema())
   317  	if err != nil || !foundSchema {
   318  		return nil, err
   319  	}
   320  
   321  	// TODO(vivek): Ideally we'd avoid caching for only the
   322  	// system.descriptor and system.lease tables, because they are
   323  	// used for acquiring leases, creating a chicken&egg problem.
   324  	// But doing so turned problematic and the tests pass only by also
   325  	// disabling caching of system.eventlog, system.rangelog, and
   326  	// system.users. For now we're sticking to disabling caching of
   327  	// all system descriptors except the role-members-table.
   328  	avoidCache := flags.AvoidCached || lease.TestingTableLeasesAreDisabled() ||
   329  		(tn.Catalog() == sqlbase.SystemDB.Name && tn.ObjectName.String() != sqlbase.RoleMembersTable.Name)
   330  
   331  	if refuseFurtherLookup, table, err := tc.getUncommittedTable(
   332  		dbID,
   333  		schemaID,
   334  		tn,
   335  		flags.Required,
   336  	); refuseFurtherLookup || err != nil {
   337  		return nil, err
   338  	} else if immut := table.ImmutableTableDescriptor; immut != nil {
   339  		// If not forcing to resolve using KV, tables being added aren't visible.
   340  		if immut.Adding() && !avoidCache {
   341  			if !flags.Required {
   342  				return nil, nil
   343  			}
   344  			return nil, sqlbase.FilterTableState(immut.TableDesc())
   345  		}
   346  
   347  		log.VEventf(ctx, 2, "found uncommitted table %d", immut.ID)
   348  		return immut, nil
   349  	}
   350  
   351  	if avoidCache {
   352  		return readTableFromStore()
   353  	}
   354  
   355  	// First, look to see if we already have the table.
   356  	// This ensures that, once a SQL transaction resolved name N to id X, it will
   357  	// continue to use N to refer to X even if N is renamed during the
   358  	// transaction.
   359  	for _, table := range tc.leasedTables {
   360  		if lease.NameMatchesTable(&table.TableDescriptor, dbID, schemaID, tn.Table()) {
   361  			log.VEventf(ctx, 2, "found table in table collection for table '%s'", tn)
   362  			return table, nil
   363  		}
   364  	}
   365  
   366  	readTimestamp := txn.ReadTimestamp()
   367  	table, expiration, err := tc.leaseMgr.AcquireByName(ctx, readTimestamp, dbID, schemaID, tn.Table())
   368  	if err != nil {
   369  		// Read the descriptor from the store in the face of some specific errors
   370  		// because of a known limitation of AcquireByName. See the known
   371  		// limitations of AcquireByName for details.
   372  		if sqlbase.HasInactiveTableError(err) ||
   373  			errors.Is(err, sqlbase.ErrDescriptorNotFound) {
   374  			return readTableFromStore()
   375  		}
   376  		// Lease acquisition failed with some other error. This we don't
   377  		// know how to deal with, so propagate the error.
   378  		return nil, err
   379  	}
   380  
   381  	if expiration.LessEq(readTimestamp) {
   382  		log.Fatalf(ctx, "bad table for T=%s, expiration=%s", readTimestamp, expiration)
   383  	}
   384  
   385  	tc.leasedTables = append(tc.leasedTables, table)
   386  	log.VEventf(ctx, 2, "added table '%s' to table collection", tn)
   387  
   388  	// If the table we just acquired expires before the txn's deadline, reduce
   389  	// the deadline. We use ReadTimestamp() that doesn't return the commit timestamp,
   390  	// so we need to set a deadline on the transaction to prevent it from committing
   391  	// beyond the table version expiration time.
   392  	txn.UpdateDeadlineMaybe(ctx, expiration)
   393  	return table, nil
   394  }
   395  
   396  // GetTableVersionByID is a by-ID variant of GetTableVersion (i.e. uses same cache).
   397  func (tc *Collection) GetTableVersionByID(
   398  	ctx context.Context, txn *kv.Txn, tableID sqlbase.ID, flags tree.ObjectLookupFlags,
   399  ) (*sqlbase.ImmutableTableDescriptor, error) {
   400  	log.VEventf(ctx, 2, "planner getting table on table ID %d", tableID)
   401  
   402  	if flags.AvoidCached || lease.TestingTableLeasesAreDisabled() {
   403  		table, err := sqlbase.GetTableDescFromID(ctx, txn, tc.codec(), tableID)
   404  		if err != nil {
   405  			return nil, err
   406  		}
   407  		if err := sqlbase.FilterTableState(table); err != nil {
   408  			return nil, err
   409  		}
   410  		return sqlbase.NewImmutableTableDescriptor(*table), nil
   411  	}
   412  
   413  	for _, table := range tc.uncommittedTables {
   414  		if immut := table.ImmutableTableDescriptor; immut.ID == tableID {
   415  			log.VEventf(ctx, 2, "found uncommitted table %d", tableID)
   416  			if immut.Dropped() {
   417  				return nil, sqlbase.NewUndefinedRelationError(
   418  					tree.NewUnqualifiedTableName(tree.Name(fmt.Sprintf("<id=%d>", tableID))),
   419  				)
   420  			}
   421  			return immut, nil
   422  		}
   423  	}
   424  
   425  	// First, look to see if we already have the table -- including those
   426  	// via `GetTableVersion`.
   427  	for _, table := range tc.leasedTables {
   428  		if table.ID == tableID {
   429  			log.VEventf(ctx, 2, "found table %d in table cache", tableID)
   430  			return table, nil
   431  		}
   432  	}
   433  
   434  	readTimestamp := txn.ReadTimestamp()
   435  	table, expiration, err := tc.leaseMgr.Acquire(ctx, readTimestamp, tableID)
   436  	if err != nil {
   437  		if errors.Is(err, sqlbase.ErrDescriptorNotFound) {
   438  			// Transform the descriptor error into an error that references the
   439  			// table's ID.
   440  			return nil, sqlbase.NewUndefinedRelationError(
   441  				&tree.TableRef{TableID: int64(tableID)})
   442  		}
   443  		return nil, err
   444  	}
   445  
   446  	if expiration.LessEq(readTimestamp) {
   447  		log.Fatalf(ctx, "bad table for T=%s, expiration=%s", readTimestamp, expiration)
   448  	}
   449  
   450  	tc.leasedTables = append(tc.leasedTables, table)
   451  	log.VEventf(ctx, 2, "added table '%s' to table collection", table.Name)
   452  
   453  	// If the table we just acquired expires before the txn's deadline, reduce
   454  	// the deadline. We use ReadTimestamp() that doesn't return the commit timestamp,
   455  	// so we need to set a deadline on the transaction to prevent it from committing
   456  	// beyond the table version expiration time.
   457  	txn.UpdateDeadlineMaybe(ctx, expiration)
   458  	return table, nil
   459  }
   460  
   461  // GetMutableTableVersionByID is a variant of sqlbase.GetTableDescFromID which returns a mutable
   462  // table descriptor of the table modified in the same transaction.
   463  func (tc *Collection) GetMutableTableVersionByID(
   464  	ctx context.Context, tableID sqlbase.ID, txn *kv.Txn,
   465  ) (*sqlbase.MutableTableDescriptor, error) {
   466  	log.VEventf(ctx, 2, "planner getting mutable table on table ID %d", tableID)
   467  
   468  	if table := tc.GetUncommittedTableByID(tableID).MutableTableDescriptor; table != nil {
   469  		log.VEventf(ctx, 2, "found uncommitted table %d", tableID)
   470  		return table, nil
   471  	}
   472  	return sqlbase.GetMutableTableDescFromID(ctx, txn, tc.codec(), tableID)
   473  }
   474  
   475  // ReleaseTableLeases releases the leases for the tables with ids in
   476  // the passed slice. Errors are logged but ignored.
   477  func (tc *Collection) ReleaseTableLeases(ctx context.Context, tables []lease.IDVersion) {
   478  	// Sort the tables and leases to make it easy to find the leases to release.
   479  	leasedTables := tc.leasedTables
   480  	sort.Slice(tables, func(i, j int) bool {
   481  		return tables[i].ID < tables[j].ID
   482  	})
   483  	sort.Slice(leasedTables, func(i, j int) bool {
   484  		return leasedTables[i].ID < leasedTables[j].ID
   485  	})
   486  
   487  	filteredLeases := leasedTables[:0] // will store the remaining leases
   488  	tablesToConsider := tables
   489  	shouldRelease := func(id sqlbase.ID) (found bool) {
   490  		for len(tablesToConsider) > 0 && tablesToConsider[0].ID < id {
   491  			tablesToConsider = tablesToConsider[1:]
   492  		}
   493  		return len(tablesToConsider) > 0 && tablesToConsider[0].ID == id
   494  	}
   495  	for _, l := range leasedTables {
   496  		if !shouldRelease(l.ID) {
   497  			filteredLeases = append(filteredLeases, l)
   498  		} else if err := tc.leaseMgr.Release(l); err != nil {
   499  			log.Warningf(ctx, "%v", err)
   500  		}
   501  	}
   502  	tc.leasedTables = filteredLeases
   503  }
   504  
   505  // ReleaseLeases releases the leases for the tables with ids in
   506  // the passed slice. Errors are logged but ignored.
   507  func (tc *Collection) ReleaseLeases(ctx context.Context) {
   508  	if len(tc.leasedTables) > 0 {
   509  		log.VEventf(ctx, 2, "releasing %d tables", len(tc.leasedTables))
   510  		for _, table := range tc.leasedTables {
   511  			if err := tc.leaseMgr.Release(table); err != nil {
   512  				log.Warningf(ctx, "%v", err)
   513  			}
   514  		}
   515  		tc.leasedTables = tc.leasedTables[:0]
   516  	}
   517  }
   518  
   519  // ReleaseAll releases all state currently held by the Collection.
   520  // ReleaseAll calls ReleaseLeases.
   521  func (tc *Collection) ReleaseAll(ctx context.Context) {
   522  	tc.ReleaseLeases(ctx)
   523  	tc.uncommittedTables = nil
   524  	tc.uncommittedDatabases = nil
   525  	tc.releaseAllDescriptors()
   526  }
   527  
   528  // WaitForCacheToDropDatabases waits until the database cache has been updated
   529  // to properly reflect all dropped databases, so that future commands on the
   530  // same gateway node observe the dropped databases.
   531  func (tc *Collection) WaitForCacheToDropDatabases(ctx context.Context) {
   532  	for _, uc := range tc.uncommittedDatabases {
   533  		if !uc.dropped {
   534  			continue
   535  		}
   536  		// Wait until the database cache has been updated to properly
   537  		// reflect a dropped database, so that future commands on the
   538  		// same gateway node observe the dropped database.
   539  		tc.dbCacheSubscriber.WaitForCacheState(
   540  			func(dc *database.Cache) bool {
   541  				// Resolve the database name from the database cache.
   542  				dbID, err := dc.GetCachedDatabaseID(uc.name)
   543  				if err != nil || dbID == sqlbase.InvalidID {
   544  					// dbID can still be 0 if required is false and
   545  					// the database is not found. Swallowing error here
   546  					// because it was felt there was no value in returning
   547  					// it to a higher layer only to be swallow there. This
   548  					// entire codepath is only called from one place so
   549  					// it's better to swallow it here.
   550  					return true
   551  				}
   552  
   553  				// If the database name still exists but it now references another
   554  				// db with a more recent id, we're good - it means that the database
   555  				// name has been reused.
   556  				return dbID > uc.id
   557  			})
   558  	}
   559  }
   560  
   561  // HasUncommittedTables returns true if the Collection contains uncommitted
   562  // tables.
   563  func (tc *Collection) HasUncommittedTables() bool {
   564  	return len(tc.uncommittedTables) > 0
   565  }
   566  
   567  // AddUncommittedTable adds desc to the Collection.
   568  func (tc *Collection) AddUncommittedTable(desc sqlbase.MutableTableDescriptor) error {
   569  	if desc.Version != desc.ClusterVersion.Version+1 {
   570  		return errors.Errorf(
   571  			"descriptor version %d not incremented from cluster version %d",
   572  			desc.Version, desc.ClusterVersion.Version)
   573  	}
   574  	tbl := UncommittedTable{
   575  		MutableTableDescriptor:   &desc,
   576  		ImmutableTableDescriptor: sqlbase.NewImmutableTableDescriptor(desc.TableDescriptor),
   577  	}
   578  	for i, table := range tc.uncommittedTables {
   579  		if table.MutableTableDescriptor.ID == desc.ID {
   580  			tc.uncommittedTables[i] = tbl
   581  			return nil
   582  		}
   583  	}
   584  	tc.uncommittedTables = append(tc.uncommittedTables, tbl)
   585  	tc.releaseAllDescriptors()
   586  	return nil
   587  }
   588  
   589  // GetTablesWithNewVersion returns all the idVersion pairs that have undergone a
   590  // schema change. Returns nil for no schema changes. The version returned for
   591  // each schema change is ClusterVersion - 1, because that's the one that will be
   592  // used when checking for table descriptor two version invariance.
   593  // Also returns strings representing the new <name, version> pairs
   594  func (tc *Collection) GetTablesWithNewVersion() []lease.IDVersion {
   595  	var tables []lease.IDVersion
   596  	for _, table := range tc.uncommittedTables {
   597  		if mut := table.MutableTableDescriptor; !mut.IsNewTable() {
   598  			tables = append(tables, lease.NewIDVersionPrev(&mut.ClusterVersion))
   599  		}
   600  	}
   601  	return tables
   602  }
   603  
   604  // GetTableDescsWithNewVersion is like GetTablesWithNewVersion but returns descriptors.
   605  func (tc *Collection) GetTableDescsWithNewVersion() (
   606  	newTables []*sqlbase.ImmutableTableDescriptor,
   607  ) {
   608  	for _, table := range tc.uncommittedTables {
   609  		if mut := table.MutableTableDescriptor; mut.IsNewTable() {
   610  			newTables = append(newTables, table.ImmutableTableDescriptor)
   611  		}
   612  	}
   613  	return newTables
   614  }
   615  
   616  // DBAction is an operation to an uncommitted database.
   617  type DBAction bool
   618  
   619  const (
   620  	// DBCreated notes that the database has been created.
   621  	DBCreated DBAction = false
   622  	// DBDropped notes that the database has been dropped.
   623  	DBDropped DBAction = true
   624  )
   625  
   626  // AddUncommittedDatabase stages the database action for the relevant database.
   627  func (tc *Collection) AddUncommittedDatabase(name string, id sqlbase.ID, action DBAction) {
   628  	db := UncommittedDatabase{name: name, id: id, dropped: action == DBDropped}
   629  	tc.uncommittedDatabases = append(tc.uncommittedDatabases, db)
   630  	tc.releaseAllDescriptors()
   631  }
   632  
   633  // GetUncommittedDatabaseID returns a database ID for the requested tablename
   634  // if the requested tablename is for a database modified within the transaction
   635  // affiliated with the LeaseCollection.
   636  func (tc *Collection) GetUncommittedDatabaseID(
   637  	requestedDbName string, required bool,
   638  ) (c bool, res sqlbase.ID, err error) {
   639  	// Walk latest to earliest so that a DROP DATABASE followed by a
   640  	// CREATE DATABASE with the same name will result in the CREATE DATABASE
   641  	// being seen.
   642  	for i := len(tc.uncommittedDatabases) - 1; i >= 0; i-- {
   643  		db := tc.uncommittedDatabases[i]
   644  		if requestedDbName == db.name {
   645  			if db.dropped {
   646  				if required {
   647  					return true, sqlbase.InvalidID, sqlbase.NewUndefinedDatabaseError(requestedDbName)
   648  				}
   649  				return true, sqlbase.InvalidID, nil
   650  			}
   651  			return false, db.id, nil
   652  		}
   653  	}
   654  	return false, sqlbase.InvalidID, nil
   655  }
   656  
   657  // getUncommittedTable returns a table for the requested tablename
   658  // if the requested tablename is for a table modified within the transaction
   659  // affiliated with the LeaseCollection.
   660  //
   661  // The first return value "refuseFurtherLookup" is true when there is
   662  // a known deletion of that table, so it would be invalid to miss the
   663  // cache and go to KV (where the descriptor prior to the DROP may
   664  // still exist).
   665  func (tc *Collection) getUncommittedTable(
   666  	dbID sqlbase.ID, schemaID sqlbase.ID, tn *tree.TableName, required bool,
   667  ) (refuseFurtherLookup bool, table UncommittedTable, err error) {
   668  	// Walk latest to earliest so that a DROP TABLE followed by a CREATE TABLE
   669  	// with the same name will result in the CREATE TABLE being seen.
   670  	for i := len(tc.uncommittedTables) - 1; i >= 0; i-- {
   671  		table := tc.uncommittedTables[i]
   672  		mutTbl := table.MutableTableDescriptor
   673  		// If a table has gotten renamed we'd like to disallow using the old names.
   674  		// The renames could have happened in another transaction but it's still okay
   675  		// to disallow the use of the old name in this transaction because the other
   676  		// transaction has already committed and this transaction is seeing the
   677  		// effect of it.
   678  		for _, drain := range mutTbl.DrainingNames {
   679  			if drain.Name == string(tn.ObjectName) &&
   680  				drain.ParentID == dbID &&
   681  				drain.ParentSchemaID == schemaID {
   682  				// Table name has gone away.
   683  				if required {
   684  					// If it's required here, say it doesn't exist.
   685  					err = sqlbase.NewUndefinedRelationError(tn)
   686  				}
   687  				// The table collection knows better; the caller has to avoid
   688  				// going to KV in any case: refuseFurtherLookup = true
   689  				return true, UncommittedTable{}, err
   690  			}
   691  		}
   692  
   693  		// Do we know about a table with this name?
   694  		if lease.NameMatchesTable(
   695  			&mutTbl.TableDescriptor,
   696  			dbID,
   697  			schemaID,
   698  			tn.Table(),
   699  		) {
   700  			// Right state?
   701  			if err = sqlbase.FilterTableState(mutTbl.TableDesc()); err != nil && !sqlbase.HasAddingTableError(err) {
   702  				if !required {
   703  					// If it's not required here, we simply say we don't have it.
   704  					err = nil
   705  				}
   706  				// The table collection knows better; the caller has to avoid
   707  				// going to KV in any case: refuseFurtherLookup = true
   708  				return true, UncommittedTable{}, err
   709  			}
   710  
   711  			// Got a table.
   712  			return false, table, nil
   713  		}
   714  	}
   715  	return false, UncommittedTable{}, nil
   716  }
   717  
   718  // GetUncommittedTableByID returns an uncommitted table by its ID.
   719  func (tc *Collection) GetUncommittedTableByID(id sqlbase.ID) UncommittedTable {
   720  	// Walk latest to earliest so that a DROP TABLE followed by a CREATE TABLE
   721  	// with the same name will result in the CREATE TABLE being seen.
   722  	for i := len(tc.uncommittedTables) - 1; i >= 0; i-- {
   723  		table := tc.uncommittedTables[i]
   724  		if table.MutableTableDescriptor.ID == id {
   725  			return table
   726  		}
   727  	}
   728  	return UncommittedTable{}
   729  }
   730  
   731  // GetAllDescriptors returns all descriptors visible by the transaction,
   732  // first checking the Collection's cached descriptors for validity
   733  // before defaulting to a key-value scan, if necessary.
   734  func (tc *Collection) GetAllDescriptors(
   735  	ctx context.Context, txn *kv.Txn,
   736  ) ([]sqlbase.DescriptorProto, error) {
   737  	if tc.allDescriptors == nil {
   738  		descs, err := catalogkv.GetAllDescriptors(ctx, txn, tc.codec())
   739  		if err != nil {
   740  			return nil, err
   741  		}
   742  
   743  		// There could be tables with user defined types that need hydrating,
   744  		// so collect the needed information to set up metadata in those types.
   745  		dbDescs := make(map[sqlbase.ID]*sqlbase.DatabaseDescriptor)
   746  		typDescs := make(map[sqlbase.ID]*sqlbase.TypeDescriptor)
   747  		for i := range descs {
   748  			desc := descs[i]
   749  			switch t := desc.(type) {
   750  			case *sqlbase.DatabaseDescriptor:
   751  				dbDescs[t.ID] = t
   752  			case *sqlbase.TypeDescriptor:
   753  				typDescs[t.ID] = t
   754  			}
   755  		}
   756  		// If we found any type descriptors, that means that some of the tables we
   757  		// scanned might have types that need hydrating.
   758  		if len(typDescs) > 0 {
   759  			// Since we just scanned all the descriptors, we already have everything
   760  			// we need to hydrate our types. Set up an accessor for the type hydration
   761  			// method to look into the scanned set of descriptors.
   762  			typeLookup := func(id sqlbase.ID) (*tree.TypeName, *sqlbase.TypeDescriptor, error) {
   763  				typDesc := typDescs[id]
   764  				dbDesc := dbDescs[typDesc.ParentID]
   765  				schemaName, err := resolver.ResolveSchemaNameByID(ctx, txn, tc.codec(), dbDesc.ID, typDesc.ParentSchemaID)
   766  				if err != nil {
   767  					return nil, nil, err
   768  				}
   769  				name := tree.MakeNewQualifiedTypeName(dbDesc.Name, schemaName, typDesc.Name)
   770  				return &name, typDesc, nil
   771  			}
   772  			// Now hydrate all table descriptors.
   773  			for i := range descs {
   774  				desc := descs[i]
   775  				if tbl, ok := desc.(*sqlbase.TableDescriptor); ok {
   776  					if err := sqlbase.HydrateTypesInTableDescriptor(tbl, typeLookup); err != nil {
   777  						// If we ran into an error hydrating the types, that means that we
   778  						// have some sort of corrupted descriptor state. Rather than disable
   779  						// uses of GetAllDescriptors, just log the error.
   780  						log.Errorf(ctx, "%s", err.Error())
   781  					}
   782  				}
   783  			}
   784  		}
   785  
   786  		tc.allDescriptors = descs
   787  	}
   788  	return tc.allDescriptors, nil
   789  }
   790  
   791  // GetAllDatabaseDescriptors returns all database descriptors visible by the
   792  // transaction, first checking the Collection's cached descriptors for
   793  // validity before scanning system.namespace and looking up the descriptors
   794  // in the database cache, if necessary.
   795  func (tc *Collection) GetAllDatabaseDescriptors(
   796  	ctx context.Context, txn *kv.Txn,
   797  ) ([]*sqlbase.DatabaseDescriptor, error) {
   798  	if tc.allDatabaseDescriptors == nil {
   799  		dbDescIDs, err := catalogkv.GetAllDatabaseDescriptorIDs(ctx, txn, tc.codec())
   800  		if err != nil {
   801  			return nil, err
   802  		}
   803  		dbDescs, err := catalogkv.GetDatabaseDescriptorsFromIDs(ctx, txn, tc.codec(), dbDescIDs)
   804  		if err != nil {
   805  			return nil, err
   806  		}
   807  		tc.allDatabaseDescriptors = dbDescs
   808  	}
   809  	return tc.allDatabaseDescriptors, nil
   810  }
   811  
   812  // GetSchemasForDatabase returns the schemas for a given database
   813  // visible by the transaction. This uses the schema cache locally
   814  // if possible, or else performs a scan on kv.
   815  func (tc *Collection) GetSchemasForDatabase(
   816  	ctx context.Context, txn *kv.Txn, dbID sqlbase.ID,
   817  ) (map[sqlbase.ID]string, error) {
   818  	if tc.allSchemasForDatabase == nil {
   819  		tc.allSchemasForDatabase = make(map[sqlbase.ID]map[sqlbase.ID]string)
   820  	}
   821  	if _, ok := tc.allSchemasForDatabase[dbID]; !ok {
   822  		var err error
   823  		tc.allSchemasForDatabase[dbID], err = resolver.GetForDatabase(ctx, txn, tc.codec(), dbID)
   824  		if err != nil {
   825  			return nil, err
   826  		}
   827  	}
   828  	return tc.allSchemasForDatabase[dbID], nil
   829  }
   830  
   831  // releaseAllDescriptors releases the cached slice of all descriptors
   832  // held by Collection.
   833  func (tc *Collection) releaseAllDescriptors() {
   834  	tc.allDescriptors = nil
   835  	tc.allDatabaseDescriptors = nil
   836  	tc.allSchemasForDatabase = nil
   837  }
   838  
   839  // CopyModifiedObjects copies the modified schema to the table collection. Used
   840  // when initializing an InternalExecutor.
   841  func (tc *Collection) CopyModifiedObjects(to *Collection) {
   842  	if tc == nil {
   843  		return
   844  	}
   845  	to.uncommittedTables = tc.uncommittedTables
   846  	to.uncommittedDatabases = tc.uncommittedDatabases
   847  	// Do not copy the leased descriptors because we do not want
   848  	// the leased descriptors to be released by the "to" Collection.
   849  	// The "to" Collection can re-lease the same descriptors.
   850  }
   851  
   852  // ModifiedCollectionCopier is an interface used to copy modified schema elements
   853  // to a new Collection.
   854  type ModifiedCollectionCopier interface {
   855  	CopyModifiedObjects(to *Collection)
   856  }
   857  
   858  func (tc *Collection) codec() keys.SQLCodec {
   859  	return tc.leaseMgr.Codec()
   860  }
   861  
   862  // LeaseManager returns the lease.Manager.
   863  func (tc *Collection) LeaseManager() *lease.Manager {
   864  	return tc.leaseMgr
   865  }
   866  
   867  // DatabaseCache returns the database.Cache.
   868  func (tc *Collection) DatabaseCache() *database.Cache {
   869  	return tc.databaseCache
   870  }
   871  
   872  // ResetDatabaseCache resets the table collection's database.Cache.
   873  func (tc *Collection) ResetDatabaseCache(dbCache *database.Cache) {
   874  	tc.databaseCache = dbCache
   875  }
   876  
   877  // MigrationSchemaChangeRequiredContext flags a schema change as necessary to
   878  // run even in a mixed-version 19.2/20.1 state where schema changes are normally
   879  // banned, because the schema change is being run in a startup migration. It's
   880  // the caller's responsibility to ensure that the schema change job is safe to
   881  // run in a mixed-version state.
   882  //
   883  // TODO (lucy): Remove this in 20.2.
   884  func MigrationSchemaChangeRequiredContext(ctx context.Context) context.Context {
   885  	return context.WithValue(ctx, migrationSchemaChangeRequiredHint{}, migrationSchemaChangeRequiredHint{})
   886  }
   887  
   888  // MigrationSchemaChangeRequiredFromContext returns true if the context
   889  // indicates that a schema change should be run despite a mixed 19.2/20.1
   890  // cluster version.
   891  func MigrationSchemaChangeRequiredFromContext(ctx context.Context) bool {
   892  	return ctx.Value(migrationSchemaChangeRequiredHint{}) == nil
   893  }
   894  
   895  type migrationSchemaChangeRequiredHint struct{}
   896  
   897  // ErrSchemaChangeDisallowedInMixedState signifies that an attempted schema
   898  // change was disallowed from running in a mixed-version
   899  var ErrSchemaChangeDisallowedInMixedState = errors.New("schema change cannot be initiated in this version until the version upgrade is finalized")
   900  
   901  // DatabaseCacheSubscriber allows the connExecutor to wait for a callback.
   902  type DatabaseCacheSubscriber interface {
   903  	// WaitForCacheState takes a callback depending on the cache state and blocks
   904  	// until the callback declares success. The callback is repeatedly called as
   905  	// the cache is updated.
   906  	WaitForCacheState(cond func(*database.Cache) bool)
   907  }