github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/testutils/testcat/test_catalog.go (about)

     1  // Copyright 2018 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 testcat
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"sort"
    17  	"time"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/config/zonepb"
    20  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/parser"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/privilege"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/stats"
    30  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    31  	"github.com/cockroachdb/cockroach/pkg/util/treeprinter"
    32  	"github.com/cockroachdb/errors"
    33  )
    34  
    35  const (
    36  	// testDB is the default current database for testing purposes.
    37  	testDB = "t"
    38  )
    39  
    40  // Catalog implements the cat.Catalog interface for testing purposes.
    41  type Catalog struct {
    42  	tree.TypeReferenceResolver
    43  	testSchema Schema
    44  	counter    int
    45  }
    46  
    47  type dataSource interface {
    48  	cat.DataSource
    49  	fqName() cat.DataSourceName
    50  }
    51  
    52  var _ cat.Catalog = &Catalog{}
    53  
    54  // New creates a new empty instance of the test catalog.
    55  func New() *Catalog {
    56  	return &Catalog{
    57  		testSchema: Schema{
    58  			SchemaID: 1,
    59  			SchemaName: cat.SchemaName{
    60  				CatalogName:     testDB,
    61  				SchemaName:      tree.PublicSchemaName,
    62  				ExplicitSchema:  true,
    63  				ExplicitCatalog: true,
    64  			},
    65  			dataSources: make(map[string]dataSource),
    66  		},
    67  	}
    68  }
    69  
    70  // ResolveSchema is part of the cat.Catalog interface.
    71  func (tc *Catalog) ResolveSchema(
    72  	_ context.Context, _ cat.Flags, name *cat.SchemaName,
    73  ) (cat.Schema, cat.SchemaName, error) {
    74  	// This is a simplified version of tree.TableName.ResolveTarget() from
    75  	// sql/tree/name_resolution.go.
    76  	toResolve := *name
    77  	if name.ExplicitSchema {
    78  		if name.ExplicitCatalog {
    79  			// Already 2 parts: nothing to do.
    80  			return tc.resolveSchema(&toResolve)
    81  		}
    82  
    83  		// Only one part specified; assume it's a schema name and determine
    84  		// whether the current database has that schema.
    85  		toResolve.CatalogName = testDB
    86  		if sch, resName, err := tc.resolveSchema(&toResolve); err == nil {
    87  			return sch, resName, nil
    88  		}
    89  
    90  		// No luck so far. Compatibility with CockroachDB v1.1: use D.public
    91  		// instead.
    92  		toResolve.CatalogName = name.SchemaName
    93  		toResolve.SchemaName = tree.PublicSchemaName
    94  		toResolve.ExplicitCatalog = true
    95  		return tc.resolveSchema(&toResolve)
    96  	}
    97  
    98  	// Neither schema or catalog was specified, so use t.public.
    99  	toResolve.CatalogName = tree.Name(testDB)
   100  	toResolve.SchemaName = tree.PublicSchemaName
   101  	return tc.resolveSchema(&toResolve)
   102  }
   103  
   104  // ResolveDataSource is part of the cat.Catalog interface.
   105  func (tc *Catalog) ResolveDataSource(
   106  	_ context.Context, _ cat.Flags, name *cat.DataSourceName,
   107  ) (cat.DataSource, cat.DataSourceName, error) {
   108  	// This is a simplified version of tree.TableName.ResolveExisting() from
   109  	// sql/tree/name_resolution.go.
   110  	var ds cat.DataSource
   111  	var err error
   112  	toResolve := *name
   113  	if name.ExplicitSchema && name.ExplicitCatalog {
   114  		// Already 3 parts.
   115  		ds, err = tc.resolveDataSource(&toResolve)
   116  		if err == nil {
   117  			return ds, toResolve, nil
   118  		}
   119  	} else if name.ExplicitSchema {
   120  		// Two parts: Try to use the current database, and be satisfied if it's
   121  		// sufficient to find the object.
   122  		toResolve.CatalogName = testDB
   123  		if tab, err := tc.resolveDataSource(&toResolve); err == nil {
   124  			return tab, toResolve, nil
   125  		}
   126  
   127  		// No luck so far. Compatibility with CockroachDB v1.1: try D.public.T
   128  		// instead.
   129  		toResolve.CatalogName = name.SchemaName
   130  		toResolve.SchemaName = tree.PublicSchemaName
   131  		toResolve.ExplicitCatalog = true
   132  		ds, err = tc.resolveDataSource(&toResolve)
   133  		if err == nil {
   134  			return ds, toResolve, nil
   135  		}
   136  	} else {
   137  		// This is a naked data source name. Use the current database.
   138  		toResolve.CatalogName = tree.Name(testDB)
   139  		toResolve.SchemaName = tree.PublicSchemaName
   140  		ds, err = tc.resolveDataSource(&toResolve)
   141  		if err == nil {
   142  			return ds, toResolve, nil
   143  		}
   144  	}
   145  
   146  	// If we didn't find the table in the catalog, try to lazily resolve it as
   147  	// a virtual table.
   148  	if table, ok := resolveVTable(name); ok {
   149  		// We rely on the check in CreateTable against this table's schema to infer
   150  		// that this is a virtual table.
   151  		return tc.CreateTable(table), *name, nil
   152  	}
   153  
   154  	// If this didn't end up being a virtual table, then return the original
   155  	// error returned by resolveDataSource.
   156  	return nil, cat.DataSourceName{}, err
   157  }
   158  
   159  // ResolveDataSourceByID is part of the cat.Catalog interface.
   160  func (tc *Catalog) ResolveDataSourceByID(
   161  	ctx context.Context, flags cat.Flags, id cat.StableID,
   162  ) (_ cat.DataSource, isAdding bool, _ error) {
   163  	for _, ds := range tc.testSchema.dataSources {
   164  		if ds.ID() == id {
   165  			return ds, false, nil
   166  		}
   167  	}
   168  	return nil, false, pgerror.Newf(pgcode.UndefinedTable,
   169  		"relation [%d] does not exist", id)
   170  }
   171  
   172  // CheckPrivilege is part of the cat.Catalog interface.
   173  func (tc *Catalog) CheckPrivilege(ctx context.Context, o cat.Object, priv privilege.Kind) error {
   174  	return tc.CheckAnyPrivilege(ctx, o)
   175  }
   176  
   177  // CheckAnyPrivilege is part of the cat.Catalog interface.
   178  func (tc *Catalog) CheckAnyPrivilege(ctx context.Context, o cat.Object) error {
   179  	switch t := o.(type) {
   180  	case *Schema:
   181  		if t.Revoked {
   182  			return pgerror.Newf(pgcode.InsufficientPrivilege, "user does not have privilege to access %v", t.SchemaName)
   183  		}
   184  	case *Table:
   185  		if t.Revoked {
   186  			return pgerror.Newf(pgcode.InsufficientPrivilege, "user does not have privilege to access %v", t.TabName)
   187  		}
   188  	case *View:
   189  		if t.Revoked {
   190  			return pgerror.Newf(pgcode.InsufficientPrivilege, "user does not have privilege to access %v", t.ViewName)
   191  		}
   192  	case *Sequence:
   193  		if t.Revoked {
   194  			return pgerror.Newf(pgcode.InsufficientPrivilege, "user does not have privilege to access %v", t.SeqName)
   195  		}
   196  	default:
   197  		panic("invalid Object")
   198  	}
   199  	return nil
   200  }
   201  
   202  // HasAdminRole is part of the cat.Catalog interface.
   203  func (tc *Catalog) HasAdminRole(ctx context.Context) (bool, error) {
   204  	return true, nil
   205  }
   206  
   207  // RequireAdminRole is part of the cat.Catalog interface.
   208  func (tc *Catalog) RequireAdminRole(ctx context.Context, action string) error {
   209  	return nil
   210  }
   211  
   212  // FullyQualifiedName is part of the cat.Catalog interface.
   213  func (tc *Catalog) FullyQualifiedName(
   214  	ctx context.Context, ds cat.DataSource,
   215  ) (cat.DataSourceName, error) {
   216  	return ds.(dataSource).fqName(), nil
   217  }
   218  
   219  func (tc *Catalog) resolveSchema(toResolve *cat.SchemaName) (cat.Schema, cat.SchemaName, error) {
   220  	if string(toResolve.CatalogName) != testDB {
   221  		return nil, cat.SchemaName{}, pgerror.Newf(pgcode.InvalidSchemaName,
   222  			"target database or schema does not exist")
   223  	}
   224  
   225  	if string(toResolve.SchemaName) != tree.PublicSchema {
   226  		return nil, cat.SchemaName{}, pgerror.Newf(pgcode.InvalidName,
   227  			"schema cannot be modified: %q", tree.ErrString(toResolve))
   228  	}
   229  
   230  	return &tc.testSchema, *toResolve, nil
   231  }
   232  
   233  // resolveDataSource checks if `toResolve` exists among the data sources in this
   234  // Catalog. If it does, returns the corresponding data source. Otherwise, it
   235  // returns an error.
   236  func (tc *Catalog) resolveDataSource(toResolve *cat.DataSourceName) (cat.DataSource, error) {
   237  	if table, ok := tc.testSchema.dataSources[toResolve.FQString()]; ok {
   238  		return table, nil
   239  	}
   240  	return nil, pgerror.Newf(pgcode.UndefinedTable,
   241  		"no data source matches prefix: %q", tree.ErrString(toResolve))
   242  }
   243  
   244  // Schema returns the singleton test schema.
   245  func (tc *Catalog) Schema() *Schema {
   246  	return &tc.testSchema
   247  }
   248  
   249  // Table returns the test table that was previously added with the given name.
   250  func (tc *Catalog) Table(name *tree.TableName) *Table {
   251  	ds, _, err := tc.ResolveDataSource(context.TODO(), cat.Flags{}, name)
   252  	if err != nil {
   253  		panic(err)
   254  	}
   255  	if tab, ok := ds.(*Table); ok {
   256  		return tab
   257  	}
   258  	panic(pgerror.Newf(pgcode.WrongObjectType,
   259  		"\"%q\" is not a table", tree.ErrString(name)))
   260  }
   261  
   262  // AddTable adds the given test table to the catalog.
   263  func (tc *Catalog) AddTable(tab *Table) {
   264  	fq := tab.TabName.FQString()
   265  	if _, ok := tc.testSchema.dataSources[fq]; ok {
   266  		panic(pgerror.Newf(pgcode.DuplicateObject,
   267  			"table %q already exists", tree.ErrString(&tab.TabName)))
   268  	}
   269  	tc.testSchema.dataSources[fq] = tab
   270  }
   271  
   272  // View returns the test view that was previously added with the given name.
   273  func (tc *Catalog) View(name *cat.DataSourceName) *View {
   274  	ds, _, err := tc.ResolveDataSource(context.TODO(), cat.Flags{}, name)
   275  	if err != nil {
   276  		panic(err)
   277  	}
   278  	if vw, ok := ds.(*View); ok {
   279  		return vw
   280  	}
   281  	panic(pgerror.Newf(pgcode.WrongObjectType,
   282  		"\"%q\" is not a view", tree.ErrString(name)))
   283  }
   284  
   285  // AddView adds the given test view to the catalog.
   286  func (tc *Catalog) AddView(view *View) {
   287  	fq := view.ViewName.FQString()
   288  	if _, ok := tc.testSchema.dataSources[fq]; ok {
   289  		panic(pgerror.Newf(pgcode.DuplicateObject,
   290  			"view %q already exists", tree.ErrString(&view.ViewName)))
   291  	}
   292  	tc.testSchema.dataSources[fq] = view
   293  }
   294  
   295  // AddSequence adds the given test sequence to the catalog.
   296  func (tc *Catalog) AddSequence(seq *Sequence) {
   297  	fq := seq.SeqName.FQString()
   298  	if _, ok := tc.testSchema.dataSources[fq]; ok {
   299  		panic(pgerror.Newf(pgcode.DuplicateObject,
   300  			"sequence %q already exists", tree.ErrString(&seq.SeqName)))
   301  	}
   302  	tc.testSchema.dataSources[fq] = seq
   303  }
   304  
   305  // ExecuteMultipleDDL parses the given semicolon-separated DDL SQL statements
   306  // and applies each of them to the test catalog.
   307  func (tc *Catalog) ExecuteMultipleDDL(sql string) error {
   308  	stmts, err := parser.Parse(sql)
   309  	if err != nil {
   310  		return err
   311  	}
   312  
   313  	for _, stmt := range stmts {
   314  		_, err := tc.ExecuteDDL(stmt.SQL)
   315  		if err != nil {
   316  			return err
   317  		}
   318  	}
   319  
   320  	return nil
   321  }
   322  
   323  // ExecuteDDL parses the given DDL SQL statement and creates objects in the test
   324  // catalog. This is used to test without spinning up a cluster.
   325  func (tc *Catalog) ExecuteDDL(sql string) (string, error) {
   326  	stmt, err := parser.ParseOne(sql)
   327  	if err != nil {
   328  		return "", err
   329  	}
   330  
   331  	switch stmt := stmt.AST.(type) {
   332  	case *tree.CreateTable:
   333  		tc.CreateTable(stmt)
   334  		return "", nil
   335  
   336  	case *tree.CreateView:
   337  		tc.CreateView(stmt)
   338  		return "", nil
   339  
   340  	case *tree.AlterTable:
   341  		tc.AlterTable(stmt)
   342  		return "", nil
   343  
   344  	case *tree.DropTable:
   345  		tc.DropTable(stmt)
   346  		return "", nil
   347  
   348  	case *tree.CreateSequence:
   349  		tc.CreateSequence(stmt)
   350  		return "", nil
   351  
   352  	case *tree.SetZoneConfig:
   353  		tc.SetZoneConfig(stmt)
   354  		return "", nil
   355  
   356  	case *tree.ShowCreate:
   357  		tn := stmt.Name.ToTableName()
   358  		ds, _, err := tc.ResolveDataSource(context.Background(), cat.Flags{}, &tn)
   359  		if err != nil {
   360  			return "", err
   361  		}
   362  		return ds.(fmt.Stringer).String(), nil
   363  
   364  	default:
   365  		return "", errors.AssertionFailedf("unsupported statement: %v", stmt)
   366  	}
   367  }
   368  
   369  // nextStableID returns a new unique StableID for a data source.
   370  func (tc *Catalog) nextStableID() cat.StableID {
   371  	tc.counter++
   372  
   373  	// 53 is a magic number derived from how CRDB internally stores tables. The
   374  	// first user table is 53. Use this to have the test catalog look more
   375  	// consistent with the real catalog.
   376  	return cat.StableID(53 + tc.counter - 1)
   377  }
   378  
   379  // qualifyTableName updates the given table name to include catalog and schema
   380  // if not already included.
   381  func (tc *Catalog) qualifyTableName(name *tree.TableName) {
   382  	hadExplicitSchema := name.ExplicitSchema
   383  	hadExplicitCatalog := name.ExplicitCatalog
   384  	name.ExplicitSchema = true
   385  	name.ExplicitCatalog = true
   386  
   387  	if hadExplicitSchema {
   388  		if hadExplicitCatalog {
   389  			// Already 3 parts: nothing to do.
   390  			return
   391  		}
   392  
   393  		if name.SchemaName == tree.PublicSchemaName {
   394  			// Use the current database.
   395  			name.CatalogName = testDB
   396  			return
   397  		}
   398  
   399  		// Compatibility with CockroachDB v1.1: use D.public.T.
   400  		name.CatalogName = name.SchemaName
   401  		name.SchemaName = tree.PublicSchemaName
   402  		return
   403  	}
   404  
   405  	// Use the current database.
   406  	name.CatalogName = testDB
   407  	name.SchemaName = tree.PublicSchemaName
   408  }
   409  
   410  // Schema implements the cat.Schema interface for testing purposes.
   411  type Schema struct {
   412  	SchemaID   cat.StableID
   413  	SchemaName cat.SchemaName
   414  
   415  	// If Revoked is true, then the user has had privileges on the schema revoked.
   416  	Revoked bool
   417  
   418  	dataSources map[string]dataSource
   419  }
   420  
   421  var _ cat.Schema = &Schema{}
   422  
   423  // ID is part of the cat.Object interface.
   424  func (s *Schema) ID() cat.StableID {
   425  	return s.SchemaID
   426  }
   427  
   428  // PostgresDescriptorID is part of the cat.Object interface.
   429  func (s *Schema) PostgresDescriptorID() cat.StableID {
   430  	return s.SchemaID
   431  }
   432  
   433  // Equals is part of the cat.Object interface.
   434  func (s *Schema) Equals(other cat.Object) bool {
   435  	otherSchema, ok := other.(*Schema)
   436  	return ok && s.SchemaID == otherSchema.SchemaID
   437  }
   438  
   439  // Name is part of the cat.Schema interface.
   440  func (s *Schema) Name() *cat.SchemaName {
   441  	return &s.SchemaName
   442  }
   443  
   444  // GetDataSourceNames is part of the cat.Schema interface.
   445  func (s *Schema) GetDataSourceNames(ctx context.Context) ([]cat.DataSourceName, error) {
   446  	var keys []string
   447  	for k := range s.dataSources {
   448  		keys = append(keys, k)
   449  	}
   450  	sort.Strings(keys)
   451  	var res []cat.DataSourceName
   452  	for _, k := range keys {
   453  		res = append(res, s.dataSources[k].fqName())
   454  	}
   455  	return res, nil
   456  }
   457  
   458  // View implements the cat.View interface for testing purposes.
   459  type View struct {
   460  	ViewID      cat.StableID
   461  	ViewVersion int
   462  	ViewName    cat.DataSourceName
   463  	QueryText   string
   464  	ColumnNames tree.NameList
   465  
   466  	// If Revoked is true, then the user has had privileges on the view revoked.
   467  	Revoked bool
   468  }
   469  
   470  var _ cat.View = &View{}
   471  
   472  func (tv *View) String() string {
   473  	tp := treeprinter.New()
   474  	cat.FormatView(tv, tp)
   475  	return tp.String()
   476  }
   477  
   478  // ID is part of the cat.DataSource interface.
   479  func (tv *View) ID() cat.StableID {
   480  	return tv.ViewID
   481  }
   482  
   483  // PostgresDescriptorID is part of the cat.Object interface.
   484  func (tv *View) PostgresDescriptorID() cat.StableID {
   485  	return tv.ViewID
   486  }
   487  
   488  // Equals is part of the cat.Object interface.
   489  func (tv *View) Equals(other cat.Object) bool {
   490  	otherView, ok := other.(*View)
   491  	if !ok {
   492  		return false
   493  	}
   494  	return tv.ViewID == otherView.ViewID && tv.ViewVersion == otherView.ViewVersion
   495  }
   496  
   497  // Name is part of the cat.DataSource interface.
   498  func (tv *View) Name() tree.Name {
   499  	return tv.ViewName.ObjectName
   500  }
   501  
   502  // fqName is part of the dataSource interface.
   503  func (tv *View) fqName() cat.DataSourceName {
   504  	return tv.ViewName
   505  }
   506  
   507  // IsSystemView is part of the cat.View interface.
   508  func (tv *View) IsSystemView() bool {
   509  	return false
   510  }
   511  
   512  // Query is part of the cat.View interface.
   513  func (tv *View) Query() string {
   514  	return tv.QueryText
   515  }
   516  
   517  // ColumnNameCount is part of the cat.View interface.
   518  func (tv *View) ColumnNameCount() int {
   519  	return len(tv.ColumnNames)
   520  }
   521  
   522  // ColumnName is part of the cat.View interface.
   523  func (tv *View) ColumnName(i int) tree.Name {
   524  	return tv.ColumnNames[i]
   525  }
   526  
   527  // Table implements the cat.Table interface for testing purposes.
   528  type Table struct {
   529  	TabID      cat.StableID
   530  	TabVersion int
   531  	TabName    tree.TableName
   532  	Columns    []*Column
   533  	Indexes    []*Index
   534  	Stats      TableStats
   535  	Checks     []cat.CheckConstraint
   536  	Families   []*Family
   537  	IsVirtual  bool
   538  	Catalog    cat.Catalog
   539  
   540  	// If Revoked is true, then the user has had privileges on the table revoked.
   541  	Revoked bool
   542  
   543  	writeOnlyColCount  int
   544  	deleteOnlyColCount int
   545  	writeOnlyIdxCount  int
   546  	deleteOnlyIdxCount int
   547  
   548  	// interleaved is true if the table's rows are interleaved with rows from
   549  	// other table(s).
   550  	interleaved bool
   551  
   552  	outboundFKs []ForeignKeyConstraint
   553  	inboundFKs  []ForeignKeyConstraint
   554  }
   555  
   556  var _ cat.Table = &Table{}
   557  
   558  func (tt *Table) String() string {
   559  	tp := treeprinter.New()
   560  	cat.FormatTable(tt.Catalog, tt, tp)
   561  	return tp.String()
   562  }
   563  
   564  // ID is part of the cat.DataSource interface.
   565  func (tt *Table) ID() cat.StableID {
   566  	return tt.TabID
   567  }
   568  
   569  // PostgresDescriptorID is part of the cat.Object interface.
   570  func (tt *Table) PostgresDescriptorID() cat.StableID {
   571  	return tt.TabID
   572  }
   573  
   574  // Equals is part of the cat.Object interface.
   575  func (tt *Table) Equals(other cat.Object) bool {
   576  	otherTable, ok := other.(*Table)
   577  	if !ok {
   578  		return false
   579  	}
   580  	return tt.TabID == otherTable.TabID && tt.TabVersion == otherTable.TabVersion
   581  }
   582  
   583  // Name is part of the cat.DataSource interface.
   584  func (tt *Table) Name() tree.Name {
   585  	return tt.TabName.ObjectName
   586  }
   587  
   588  // fqName is part of the dataSource interface.
   589  func (tt *Table) fqName() cat.DataSourceName {
   590  	return tt.TabName
   591  }
   592  
   593  // IsVirtualTable is part of the cat.Table interface.
   594  func (tt *Table) IsVirtualTable() bool {
   595  	return tt.IsVirtual
   596  }
   597  
   598  // ColumnCount is part of the cat.Table interface.
   599  func (tt *Table) ColumnCount() int {
   600  	return len(tt.Columns) - tt.writeOnlyColCount - tt.deleteOnlyColCount
   601  }
   602  
   603  // WritableColumnCount is part of the cat.Table interface.
   604  func (tt *Table) WritableColumnCount() int {
   605  	return len(tt.Columns) - tt.deleteOnlyColCount
   606  }
   607  
   608  // DeletableColumnCount is part of the cat.Table interface.
   609  func (tt *Table) DeletableColumnCount() int {
   610  	return len(tt.Columns)
   611  }
   612  
   613  // Column is part of the cat.Table interface.
   614  func (tt *Table) Column(i int) cat.Column {
   615  	return tt.Columns[i]
   616  }
   617  
   618  // IndexCount is part of the cat.Table interface.
   619  func (tt *Table) IndexCount() int {
   620  	return len(tt.Indexes) - tt.writeOnlyIdxCount - tt.deleteOnlyIdxCount
   621  }
   622  
   623  // WritableIndexCount is part of the cat.Table interface.
   624  func (tt *Table) WritableIndexCount() int {
   625  	return len(tt.Indexes) - tt.deleteOnlyIdxCount
   626  }
   627  
   628  // DeletableIndexCount is part of the cat.Table interface.
   629  func (tt *Table) DeletableIndexCount() int {
   630  	return len(tt.Indexes)
   631  }
   632  
   633  // Index is part of the cat.Table interface.
   634  func (tt *Table) Index(i cat.IndexOrdinal) cat.Index {
   635  	return tt.Indexes[i]
   636  }
   637  
   638  // StatisticCount is part of the cat.Table interface.
   639  func (tt *Table) StatisticCount() int {
   640  	return len(tt.Stats)
   641  }
   642  
   643  // Statistic is part of the cat.Table interface.
   644  func (tt *Table) Statistic(i int) cat.TableStatistic {
   645  	return tt.Stats[i]
   646  }
   647  
   648  // CheckCount is part of the cat.Table interface.
   649  func (tt *Table) CheckCount() int {
   650  	return len(tt.Checks)
   651  }
   652  
   653  // Check is part of the cat.Table interface.
   654  func (tt *Table) Check(i int) cat.CheckConstraint {
   655  	return tt.Checks[i]
   656  }
   657  
   658  // FamilyCount is part of the cat.Table interface.
   659  func (tt *Table) FamilyCount() int {
   660  	return len(tt.Families)
   661  }
   662  
   663  // Family is part of the cat.Table interface.
   664  func (tt *Table) Family(i int) cat.Family {
   665  	return tt.Families[i]
   666  }
   667  
   668  // OutboundForeignKeyCount is part of the cat.Table interface.
   669  func (tt *Table) OutboundForeignKeyCount() int {
   670  	return len(tt.outboundFKs)
   671  }
   672  
   673  // OutboundForeignKey is part of the cat.Table interface.
   674  func (tt *Table) OutboundForeignKey(i int) cat.ForeignKeyConstraint {
   675  	return &tt.outboundFKs[i]
   676  }
   677  
   678  // InboundForeignKeyCount is part of the cat.Table interface.
   679  func (tt *Table) InboundForeignKeyCount() int {
   680  	return len(tt.inboundFKs)
   681  }
   682  
   683  // InboundForeignKey is part of the cat.Table interface.
   684  func (tt *Table) InboundForeignKey(i int) cat.ForeignKeyConstraint {
   685  	return &tt.inboundFKs[i]
   686  }
   687  
   688  // FindOrdinal returns the ordinal of the column with the given name.
   689  func (tt *Table) FindOrdinal(name string) int {
   690  	for i, col := range tt.Columns {
   691  		if col.Name == name {
   692  			return i
   693  		}
   694  	}
   695  	panic(pgerror.Newf(pgcode.UndefinedColumn,
   696  		"cannot find column %q in table %q",
   697  		tree.ErrString((*tree.Name)(&name)),
   698  		tree.ErrString(&tt.TabName),
   699  	))
   700  }
   701  
   702  // Index implements the cat.Index interface for testing purposes.
   703  type Index struct {
   704  	IdxName string
   705  
   706  	// KeyCount is the number of columns that make up the unique key for the
   707  	// index. See the cat.Index.KeyColumnCount for more details.
   708  	KeyCount int
   709  
   710  	// LaxKeyCount is the number of columns that make up a lax key for the
   711  	// index, which allows duplicate rows when at least one of the values is
   712  	// NULL. See the cat.Index.LaxKeyColumnCount for more details.
   713  	LaxKeyCount int
   714  
   715  	// Unique is true if this index is declared as UNIQUE in the schema.
   716  	Unique bool
   717  
   718  	// Inverted is true when this index is an inverted index.
   719  	Inverted bool
   720  
   721  	Columns []cat.IndexColumn
   722  
   723  	// IdxZone is the zone associated with the index. This may be inherited from
   724  	// the parent table, database, or even the default zone.
   725  	IdxZone *zonepb.ZoneConfig
   726  
   727  	// Ordinal is the ordinal of this index in the table.
   728  	ordinal int
   729  
   730  	// table is a back reference to the table this index is on.
   731  	table *Table
   732  
   733  	// partitionBy is the partitioning clause that corresponds to this index. Used
   734  	// to implement PartitionByListPrefixes.
   735  	partitionBy *tree.PartitionBy
   736  
   737  	// predicate is the partial index predicate expression, if it exists.
   738  	predicate string
   739  }
   740  
   741  // ID is part of the cat.Index interface.
   742  func (ti *Index) ID() cat.StableID {
   743  	return 1 + cat.StableID(ti.ordinal)
   744  }
   745  
   746  // Name is part of the cat.Index interface.
   747  func (ti *Index) Name() tree.Name {
   748  	return tree.Name(ti.IdxName)
   749  }
   750  
   751  // Table is part of the cat.Index interface.
   752  func (ti *Index) Table() cat.Table {
   753  	return ti.table
   754  }
   755  
   756  // Ordinal is part of the cat.Index interface.
   757  func (ti *Index) Ordinal() int {
   758  	return ti.ordinal
   759  }
   760  
   761  // IsUnique is part of the cat.Index interface.
   762  func (ti *Index) IsUnique() bool {
   763  	return ti.Unique
   764  }
   765  
   766  // IsInverted is part of the cat.Index interface.
   767  func (ti *Index) IsInverted() bool {
   768  	return ti.Inverted
   769  }
   770  
   771  // ColumnCount is part of the cat.Index interface.
   772  func (ti *Index) ColumnCount() int {
   773  	return len(ti.Columns)
   774  }
   775  
   776  // KeyColumnCount is part of the cat.Index interface.
   777  func (ti *Index) KeyColumnCount() int {
   778  	return ti.KeyCount
   779  }
   780  
   781  // LaxKeyColumnCount is part of the cat.Index interface.
   782  func (ti *Index) LaxKeyColumnCount() int {
   783  	return ti.LaxKeyCount
   784  }
   785  
   786  // Column is part of the cat.Index interface.
   787  func (ti *Index) Column(i int) cat.IndexColumn {
   788  	return ti.Columns[i]
   789  }
   790  
   791  // Zone is part of the cat.Index interface.
   792  func (ti *Index) Zone() cat.Zone {
   793  	return ti.IdxZone
   794  }
   795  
   796  // Span is part of the cat.Index interface.
   797  func (ti *Index) Span() roachpb.Span {
   798  	panic("not implemented")
   799  }
   800  
   801  // Predicate is part of the cat.Index interface. It returns the predicate
   802  // expression and true if the index is a partial index. If the index is not
   803  // partial, the empty string and false is returned.
   804  func (ti *Index) Predicate() (string, bool) {
   805  	return ti.predicate, ti.predicate != ""
   806  }
   807  
   808  // PartitionByListPrefixes is part of the cat.Index interface.
   809  func (ti *Index) PartitionByListPrefixes() []tree.Datums {
   810  	ctx := context.Background()
   811  	p := ti.partitionBy
   812  	if p == nil {
   813  		return nil
   814  	}
   815  	if len(p.List) == 0 {
   816  		return nil
   817  	}
   818  	var res []tree.Datums
   819  	semaCtx := tree.MakeSemaContext()
   820  	evalCtx := tree.MakeTestingEvalContext(cluster.MakeTestingClusterSettings())
   821  	for i := range p.Fields {
   822  		if i >= len(ti.Columns) || p.Fields[i] != ti.Columns[i].ColName() {
   823  			panic("partition by columns must be a prefix of the index columns")
   824  		}
   825  	}
   826  	for i := range p.List {
   827  		// Exprs contains a list of values.
   828  		for _, e := range p.List[i].Exprs {
   829  			var vals []tree.Expr
   830  			switch t := e.(type) {
   831  			case *tree.Tuple:
   832  				vals = t.Exprs
   833  			default:
   834  				vals = []tree.Expr{e}
   835  			}
   836  
   837  			// Cut off at DEFAULT, if present.
   838  			for i := range vals {
   839  				if _, ok := vals[i].(tree.DefaultVal); ok {
   840  					vals = vals[:i]
   841  				}
   842  			}
   843  			if len(vals) == 0 {
   844  				continue
   845  			}
   846  			d := make(tree.Datums, len(vals))
   847  			for i := range vals {
   848  				c := tree.CastExpr{Expr: vals[i], Type: ti.Columns[i].DatumType()}
   849  				cTyped, err := c.TypeCheck(ctx, &semaCtx, nil)
   850  				if err != nil {
   851  					panic(err)
   852  				}
   853  				d[i], err = cTyped.Eval(&evalCtx)
   854  				if err != nil {
   855  					panic(err)
   856  				}
   857  			}
   858  
   859  			// TODO(radu): split into multiple prefixes if Subpartition is also by list.
   860  			// Note that this functionality should be kept in sync with the real catalog
   861  			// implementation (opt_catalog.go).
   862  
   863  			res = append(res, d)
   864  		}
   865  	}
   866  	return res
   867  }
   868  
   869  // InterleaveAncestorCount is part of the cat.Index interface.
   870  func (ti *Index) InterleaveAncestorCount() int {
   871  	return 0
   872  }
   873  
   874  // InterleaveAncestor is part of the cat.Index interface.
   875  func (ti *Index) InterleaveAncestor(i int) (table, index cat.StableID, numKeyCols int) {
   876  	panic("no interleavings")
   877  }
   878  
   879  // InterleavedByCount is part of the cat.Index interface.
   880  func (ti *Index) InterleavedByCount() int {
   881  	return 0
   882  }
   883  
   884  // InterleavedBy is part of the cat.Index interface.
   885  func (ti *Index) InterleavedBy(i int) (table, index cat.StableID) {
   886  	panic("no interleavings")
   887  }
   888  
   889  // Column implements the cat.Column interface for testing purposes.
   890  type Column struct {
   891  	Ordinal      int
   892  	Hidden       bool
   893  	Nullable     bool
   894  	Name         string
   895  	Type         *types.T
   896  	DefaultExpr  *string
   897  	ComputedExpr *string
   898  }
   899  
   900  var _ cat.Column = &Column{}
   901  
   902  // ColID is part of the cat.Index interface.
   903  func (tc *Column) ColID() cat.StableID {
   904  	return 1 + cat.StableID(tc.Ordinal)
   905  }
   906  
   907  // IsNullable is part of the cat.Column interface.
   908  func (tc *Column) IsNullable() bool {
   909  	return tc.Nullable
   910  }
   911  
   912  // ColName is part of the cat.Column interface.
   913  func (tc *Column) ColName() tree.Name {
   914  	return tree.Name(tc.Name)
   915  }
   916  
   917  // DatumType is part of the cat.Column interface.
   918  func (tc *Column) DatumType() *types.T {
   919  	return tc.Type
   920  }
   921  
   922  // ColTypePrecision is part of the cat.Column interface.
   923  func (tc *Column) ColTypePrecision() int {
   924  	if tc.Type.Family() == types.ArrayFamily {
   925  		if tc.Type.ArrayContents().Family() == types.ArrayFamily {
   926  			panic(errors.AssertionFailedf("column type should never be a nested array"))
   927  		}
   928  		return int(tc.Type.ArrayContents().Precision())
   929  	}
   930  	return int(tc.Type.Precision())
   931  }
   932  
   933  // ColTypeWidth is part of the cat.Column interface.
   934  func (tc *Column) ColTypeWidth() int {
   935  	if tc.Type.Family() == types.ArrayFamily {
   936  		if tc.Type.ArrayContents().Family() == types.ArrayFamily {
   937  			panic(errors.AssertionFailedf("column type should never be a nested array"))
   938  		}
   939  		return int(tc.Type.ArrayContents().Width())
   940  	}
   941  	return int(tc.Type.Width())
   942  }
   943  
   944  // ColTypeStr is part of the cat.Column interface.
   945  func (tc *Column) ColTypeStr() string {
   946  	return tc.Type.SQLString()
   947  }
   948  
   949  // IsHidden is part of the cat.Column interface.
   950  func (tc *Column) IsHidden() bool {
   951  	return tc.Hidden
   952  }
   953  
   954  // HasDefault is part of the cat.Column interface.
   955  func (tc *Column) HasDefault() bool {
   956  	return tc.DefaultExpr != nil
   957  }
   958  
   959  // IsComputed is part of the cat.Column interface.
   960  func (tc *Column) IsComputed() bool {
   961  	return tc.ComputedExpr != nil
   962  }
   963  
   964  // DefaultExprStr is part of the cat.Column interface.
   965  func (tc *Column) DefaultExprStr() string {
   966  	return *tc.DefaultExpr
   967  }
   968  
   969  // ComputedExprStr is part of the cat.Column interface.
   970  func (tc *Column) ComputedExprStr() string {
   971  	return *tc.ComputedExpr
   972  }
   973  
   974  // TableStat implements the cat.TableStatistic interface for testing purposes.
   975  type TableStat struct {
   976  	js stats.JSONStatistic
   977  	tt *Table
   978  }
   979  
   980  var _ cat.TableStatistic = &TableStat{}
   981  
   982  // CreatedAt is part of the cat.TableStatistic interface.
   983  func (ts *TableStat) CreatedAt() time.Time {
   984  	d, err := tree.ParseDTimestamp(nil, ts.js.CreatedAt, time.Microsecond)
   985  	if err != nil {
   986  		panic(err)
   987  	}
   988  	return d.Time
   989  }
   990  
   991  // ColumnCount is part of the cat.TableStatistic interface.
   992  func (ts *TableStat) ColumnCount() int {
   993  	return len(ts.js.Columns)
   994  }
   995  
   996  // ColumnOrdinal is part of the cat.TableStatistic interface.
   997  func (ts *TableStat) ColumnOrdinal(i int) int {
   998  	return ts.tt.FindOrdinal(ts.js.Columns[i])
   999  }
  1000  
  1001  // RowCount is part of the cat.TableStatistic interface.
  1002  func (ts *TableStat) RowCount() uint64 {
  1003  	return ts.js.RowCount
  1004  }
  1005  
  1006  // DistinctCount is part of the cat.TableStatistic interface.
  1007  func (ts *TableStat) DistinctCount() uint64 {
  1008  	return ts.js.DistinctCount
  1009  }
  1010  
  1011  // NullCount is part of the cat.TableStatistic interface.
  1012  func (ts *TableStat) NullCount() uint64 {
  1013  	return ts.js.NullCount
  1014  }
  1015  
  1016  // Histogram is part of the cat.TableStatistic interface.
  1017  func (ts *TableStat) Histogram() []cat.HistogramBucket {
  1018  	evalCtx := tree.MakeTestingEvalContext(cluster.MakeTestingClusterSettings())
  1019  	if ts.js.HistogramColumnType == "" || ts.js.HistogramBuckets == nil {
  1020  		return nil
  1021  	}
  1022  	colTypeRef, err := parser.ParseType(ts.js.HistogramColumnType)
  1023  	if err != nil {
  1024  		panic(err)
  1025  	}
  1026  	colType := tree.MustBeStaticallyKnownType(colTypeRef)
  1027  	histogram := make([]cat.HistogramBucket, len(ts.js.HistogramBuckets))
  1028  	for i := range histogram {
  1029  		bucket := &ts.js.HistogramBuckets[i]
  1030  		datum, err := sqlbase.ParseDatumStringAs(colType, bucket.UpperBound, &evalCtx)
  1031  		if err != nil {
  1032  			panic(err)
  1033  		}
  1034  		histogram[i] = cat.HistogramBucket{
  1035  			NumEq:         float64(bucket.NumEq),
  1036  			NumRange:      float64(bucket.NumRange),
  1037  			DistinctRange: bucket.DistinctRange,
  1038  			UpperBound:    datum,
  1039  		}
  1040  	}
  1041  	return histogram
  1042  }
  1043  
  1044  // TableStats is a slice of TableStat pointers.
  1045  type TableStats []*TableStat
  1046  
  1047  // Len is part of the Sorter interface.
  1048  func (ts TableStats) Len() int { return len(ts) }
  1049  
  1050  // Less is part of the Sorter interface.
  1051  func (ts TableStats) Less(i, j int) bool {
  1052  	// Sort with most recent first.
  1053  	return ts[i].CreatedAt().Unix() > ts[j].CreatedAt().Unix()
  1054  }
  1055  
  1056  // Swap is part of the Sorter interface.
  1057  func (ts TableStats) Swap(i, j int) {
  1058  	ts[i], ts[j] = ts[j], ts[i]
  1059  }
  1060  
  1061  // ForeignKeyConstraint implements cat.ForeignKeyConstraint. See that interface
  1062  // for more information on the fields.
  1063  type ForeignKeyConstraint struct {
  1064  	name              string
  1065  	originTableID     cat.StableID
  1066  	referencedTableID cat.StableID
  1067  
  1068  	originColumnOrdinals     []int
  1069  	referencedColumnOrdinals []int
  1070  
  1071  	validated    bool
  1072  	matchMethod  tree.CompositeKeyMatchMethod
  1073  	deleteAction tree.ReferenceAction
  1074  	updateAction tree.ReferenceAction
  1075  }
  1076  
  1077  var _ cat.ForeignKeyConstraint = &ForeignKeyConstraint{}
  1078  
  1079  // Name is part of the cat.ForeignKeyConstraint interface.
  1080  func (fk *ForeignKeyConstraint) Name() string {
  1081  	return fk.name
  1082  }
  1083  
  1084  // OriginTableID is part of the cat.ForeignKeyConstraint interface.
  1085  func (fk *ForeignKeyConstraint) OriginTableID() cat.StableID {
  1086  	return fk.originTableID
  1087  }
  1088  
  1089  // ReferencedTableID is part of the cat.ForeignKeyConstraint interface.
  1090  func (fk *ForeignKeyConstraint) ReferencedTableID() cat.StableID {
  1091  	return fk.referencedTableID
  1092  }
  1093  
  1094  // ColumnCount is part of the cat.ForeignKeyConstraint interface.
  1095  func (fk *ForeignKeyConstraint) ColumnCount() int {
  1096  	return len(fk.originColumnOrdinals)
  1097  }
  1098  
  1099  // OriginColumnOrdinal is part of the cat.ForeignKeyConstraint interface.
  1100  func (fk *ForeignKeyConstraint) OriginColumnOrdinal(originTable cat.Table, i int) int {
  1101  	if originTable.ID() != fk.originTableID {
  1102  		panic(errors.AssertionFailedf(
  1103  			"invalid table %d passed to OriginColumnOrdinal (expected %d)",
  1104  			originTable.ID(), fk.originTableID,
  1105  		))
  1106  	}
  1107  
  1108  	return fk.originColumnOrdinals[i]
  1109  }
  1110  
  1111  // ReferencedColumnOrdinal is part of the cat.ForeignKeyConstraint interface.
  1112  func (fk *ForeignKeyConstraint) ReferencedColumnOrdinal(referencedTable cat.Table, i int) int {
  1113  	if referencedTable.ID() != fk.referencedTableID {
  1114  		panic(errors.AssertionFailedf(
  1115  			"invalid table %d passed to ReferencedColumnOrdinal (expected %d)",
  1116  			referencedTable.ID(), fk.referencedTableID,
  1117  		))
  1118  	}
  1119  	return fk.referencedColumnOrdinals[i]
  1120  }
  1121  
  1122  // Validated is part of the cat.ForeignKeyConstraint interface.
  1123  func (fk *ForeignKeyConstraint) Validated() bool {
  1124  	return fk.validated
  1125  }
  1126  
  1127  // MatchMethod is part of the cat.ForeignKeyConstraint interface.
  1128  func (fk *ForeignKeyConstraint) MatchMethod() tree.CompositeKeyMatchMethod {
  1129  	return fk.matchMethod
  1130  }
  1131  
  1132  // DeleteReferenceAction is part of the cat.ForeignKeyConstraint interface.
  1133  func (fk *ForeignKeyConstraint) DeleteReferenceAction() tree.ReferenceAction {
  1134  	return fk.deleteAction
  1135  }
  1136  
  1137  // UpdateReferenceAction is part of the cat.ForeignKeyConstraint interface.
  1138  func (fk *ForeignKeyConstraint) UpdateReferenceAction() tree.ReferenceAction {
  1139  	return fk.updateAction
  1140  }
  1141  
  1142  // Sequence implements the cat.Sequence interface for testing purposes.
  1143  type Sequence struct {
  1144  	SeqID      cat.StableID
  1145  	SeqVersion int
  1146  	SeqName    tree.TableName
  1147  	Catalog    cat.Catalog
  1148  
  1149  	// If Revoked is true, then the user has had privileges on the sequence revoked.
  1150  	Revoked bool
  1151  }
  1152  
  1153  var _ cat.Sequence = &Sequence{}
  1154  
  1155  // ID is part of the cat.DataSource interface.
  1156  func (ts *Sequence) ID() cat.StableID {
  1157  	return ts.SeqID
  1158  }
  1159  
  1160  // PostgresDescriptorID is part of the cat.Object interface.
  1161  func (ts *Sequence) PostgresDescriptorID() cat.StableID {
  1162  	return ts.SeqID
  1163  }
  1164  
  1165  // Equals is part of the cat.Object interface.
  1166  func (ts *Sequence) Equals(other cat.Object) bool {
  1167  	otherSequence, ok := other.(*Sequence)
  1168  	if !ok {
  1169  		return false
  1170  	}
  1171  	return ts.SeqID == otherSequence.SeqID && ts.SeqVersion == otherSequence.SeqVersion
  1172  }
  1173  
  1174  // Name is part of the cat.DataSource interface.
  1175  func (ts *Sequence) Name() tree.Name {
  1176  	return ts.SeqName.ObjectName
  1177  }
  1178  
  1179  // fqName is part of the dataSource interface.
  1180  func (ts *Sequence) fqName() cat.DataSourceName {
  1181  	return ts.SeqName
  1182  }
  1183  
  1184  // SequenceMarker is part of the cat.Sequence interface.
  1185  func (ts *Sequence) SequenceMarker() {}
  1186  
  1187  func (ts *Sequence) String() string {
  1188  	tp := treeprinter.New()
  1189  	cat.FormatSequence(ts.Catalog, ts, tp)
  1190  	return tp.String()
  1191  }
  1192  
  1193  // Family implements the cat.Family interface for testing purposes.
  1194  type Family struct {
  1195  	FamName string
  1196  
  1197  	// Ordinal is the ordinal of this family in the table.
  1198  	Ordinal int
  1199  
  1200  	Columns []cat.FamilyColumn
  1201  
  1202  	// table is a back reference to the table this index is on.
  1203  	table *Table
  1204  }
  1205  
  1206  // ID is part of the cat.Family interface.
  1207  func (tf *Family) ID() cat.StableID {
  1208  	return 1 + cat.StableID(tf.Ordinal)
  1209  }
  1210  
  1211  // Name is part of the cat.Family interface.
  1212  func (tf *Family) Name() tree.Name {
  1213  	return tree.Name(tf.FamName)
  1214  }
  1215  
  1216  // Table is part of the cat.Family interface.
  1217  func (tf *Family) Table() cat.Table {
  1218  	return tf.table
  1219  }
  1220  
  1221  // ColumnCount is part of the cat.Family interface.
  1222  func (tf *Family) ColumnCount() int {
  1223  	return len(tf.Columns)
  1224  }
  1225  
  1226  // Column is part of the cat.Family interface.
  1227  func (tf *Family) Column(i int) cat.FamilyColumn {
  1228  	return tf.Columns[i]
  1229  }