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

     1  // Copyright 2016 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 sql
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"sort"
    17  	"strconv"
    18  	"unicode/utf8"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/base"
    21  	"github.com/cockroachdb/cockroach/pkg/security"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkv"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/privilege"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/schemaexpr"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    30  	"github.com/cockroachdb/cockroach/pkg/sql/vtable"
    31  	"github.com/cockroachdb/errors"
    32  )
    33  
    34  const (
    35  	pgCatalogName = sessiondata.PgCatalogName
    36  )
    37  
    38  var pgCatalogNameDString = tree.NewDString(pgCatalogName)
    39  
    40  // informationSchema lists all the table definitions for
    41  // information_schema.
    42  var informationSchema = virtualSchema{
    43  	name: sessiondata.InformationSchemaName,
    44  	allTableNames: buildStringSet(
    45  		// Generated with:
    46  		// select distinct '"'||table_name||'",' from information_schema.tables
    47  		//    where table_schema='information_schema' order by table_name;
    48  		"_pg_foreign_data_wrappers",
    49  		"_pg_foreign_servers",
    50  		"_pg_foreign_table_columns",
    51  		"_pg_foreign_tables",
    52  		"_pg_user_mappings",
    53  		"administrable_role_authorizations",
    54  		"applicable_roles",
    55  		"attributes",
    56  		"character_sets",
    57  		"check_constraint_routine_usage",
    58  		"check_constraints",
    59  		"collation_character_set_applicability",
    60  		"collations",
    61  		"column_domain_usage",
    62  		"column_options",
    63  		"column_privileges",
    64  		"column_udt_usage",
    65  		"columns",
    66  		"constraint_column_usage",
    67  		"constraint_table_usage",
    68  		"data_type_privileges",
    69  		"domain_constraints",
    70  		"domain_udt_usage",
    71  		"domains",
    72  		"element_types",
    73  		"enabled_roles",
    74  		"foreign_data_wrapper_options",
    75  		"foreign_data_wrappers",
    76  		"foreign_server_options",
    77  		"foreign_servers",
    78  		"foreign_table_options",
    79  		"foreign_tables",
    80  		"information_schema_catalog_name",
    81  		"key_column_usage",
    82  		"parameters",
    83  		"referential_constraints",
    84  		"role_column_grants",
    85  		"role_routine_grants",
    86  		"role_table_grants",
    87  		"role_udt_grants",
    88  		"role_usage_grants",
    89  		"routine_privileges",
    90  		"routines",
    91  		"schemata",
    92  		"sequences",
    93  		"sql_features",
    94  		"sql_implementation_info",
    95  		"sql_languages",
    96  		"sql_packages",
    97  		"sql_parts",
    98  		"sql_sizing",
    99  		"sql_sizing_profiles",
   100  		"table_constraints",
   101  		"table_privileges",
   102  		"tables",
   103  		"transforms",
   104  		"triggered_update_columns",
   105  		"triggers",
   106  		"udt_privileges",
   107  		"usage_privileges",
   108  		"user_defined_types",
   109  		"user_mapping_options",
   110  		"user_mappings",
   111  		"view_column_usage",
   112  		"view_routine_usage",
   113  		"view_table_usage",
   114  		"views",
   115  	),
   116  	tableDefs: map[sqlbase.ID]virtualSchemaDef{
   117  		sqlbase.InformationSchemaAdministrableRoleAuthorizationsID: informationSchemaAdministrableRoleAuthorizations,
   118  		sqlbase.InformationSchemaApplicableRolesID:                 informationSchemaApplicableRoles,
   119  		sqlbase.InformationSchemaCheckConstraints:                  informationSchemaCheckConstraints,
   120  		sqlbase.InformationSchemaColumnPrivilegesID:                informationSchemaColumnPrivileges,
   121  		sqlbase.InformationSchemaColumnsTableID:                    informationSchemaColumnsTable,
   122  		sqlbase.InformationSchemaConstraintColumnUsageTableID:      informationSchemaConstraintColumnUsageTable,
   123  		sqlbase.InformationSchemaEnabledRolesID:                    informationSchemaEnabledRoles,
   124  		sqlbase.InformationSchemaKeyColumnUsageTableID:             informationSchemaKeyColumnUsageTable,
   125  		sqlbase.InformationSchemaParametersTableID:                 informationSchemaParametersTable,
   126  		sqlbase.InformationSchemaReferentialConstraintsTableID:     informationSchemaReferentialConstraintsTable,
   127  		sqlbase.InformationSchemaRoleTableGrantsID:                 informationSchemaRoleTableGrants,
   128  		sqlbase.InformationSchemaRoutineTableID:                    informationSchemaRoutineTable,
   129  		sqlbase.InformationSchemaSchemataTableID:                   informationSchemaSchemataTable,
   130  		sqlbase.InformationSchemaSchemataTablePrivilegesID:         informationSchemaSchemataTablePrivileges,
   131  		sqlbase.InformationSchemaSequencesID:                       informationSchemaSequences,
   132  		sqlbase.InformationSchemaStatisticsTableID:                 informationSchemaStatisticsTable,
   133  		sqlbase.InformationSchemaTableConstraintTableID:            informationSchemaTableConstraintTable,
   134  		sqlbase.InformationSchemaTablePrivilegesID:                 informationSchemaTablePrivileges,
   135  		sqlbase.InformationSchemaTablesTableID:                     informationSchemaTablesTable,
   136  		sqlbase.InformationSchemaViewsTableID:                      informationSchemaViewsTable,
   137  		sqlbase.InformationSchemaUserPrivilegesID:                  informationSchemaUserPrivileges,
   138  	},
   139  	tableValidator:             validateInformationSchemaTable,
   140  	validWithNoDatabaseContext: true,
   141  }
   142  
   143  func buildStringSet(ss ...string) map[string]struct{} {
   144  	m := map[string]struct{}{}
   145  	for _, s := range ss {
   146  		m[s] = struct{}{}
   147  	}
   148  	return m
   149  }
   150  
   151  var (
   152  	emptyString = tree.NewDString("")
   153  	// information_schema was defined before the BOOLEAN data type was added to
   154  	// the SQL specification. Because of this, boolean values are represented as
   155  	// STRINGs. The BOOLEAN data type should NEVER be used in information_schema
   156  	// tables. Instead, define columns as STRINGs and map bools to STRINGs using
   157  	// yesOrNoDatum.
   158  	yesString = tree.NewDString("YES")
   159  	noString  = tree.NewDString("NO")
   160  )
   161  
   162  func yesOrNoDatum(b bool) tree.Datum {
   163  	if b {
   164  		return yesString
   165  	}
   166  	return noString
   167  }
   168  
   169  func dNameOrNull(s string) tree.Datum {
   170  	if s == "" {
   171  		return tree.DNull
   172  	}
   173  	return tree.NewDName(s)
   174  }
   175  
   176  func dIntFnOrNull(fn func() (int32, bool)) tree.Datum {
   177  	if n, ok := fn(); ok {
   178  		return tree.NewDInt(tree.DInt(n))
   179  	}
   180  	return tree.DNull
   181  }
   182  
   183  func validateInformationSchemaTable(table *sqlbase.TableDescriptor) error {
   184  	// Make sure no tables have boolean columns.
   185  	for i := range table.Columns {
   186  		if table.Columns[i].Type.Family() == types.BoolFamily {
   187  			return errors.Errorf("information_schema tables should never use BOOL columns. "+
   188  				"See the comment about yesOrNoDatum. Found BOOL column in %s.", table.Name)
   189  		}
   190  	}
   191  	return nil
   192  }
   193  
   194  var informationSchemaAdministrableRoleAuthorizations = virtualSchemaTable{
   195  	comment: `roles for which the current user has admin option
   196  ` + base.DocsURL("information-schema.html#administrable_role_authorizations") + `
   197  https://www.postgresql.org/docs/9.5/infoschema-administrable-role-authorizations.html`,
   198  	schema: vtable.InformationSchemaAdministrableRoleAuthorizations,
   199  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   200  		currentUser := p.SessionData().User
   201  		memberMap, err := p.MemberOfWithAdminOption(ctx, currentUser)
   202  		if err != nil {
   203  			return err
   204  		}
   205  
   206  		grantee := tree.NewDString(currentUser)
   207  		for roleName, isAdmin := range memberMap {
   208  			if !isAdmin {
   209  				// We only show memberships with the admin option.
   210  				continue
   211  			}
   212  
   213  			if err := addRow(
   214  				grantee,                   // grantee: always the current user
   215  				tree.NewDString(roleName), // role_name
   216  				yesString,                 // is_grantable: always YES
   217  			); err != nil {
   218  				return err
   219  			}
   220  		}
   221  
   222  		return nil
   223  	},
   224  }
   225  
   226  var informationSchemaApplicableRoles = virtualSchemaTable{
   227  	comment: `roles available to the current user
   228  ` + base.DocsURL("information-schema.html#applicable_roles") + `
   229  https://www.postgresql.org/docs/9.5/infoschema-applicable-roles.html`,
   230  	schema: vtable.InformationSchemaApplicableRoles,
   231  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   232  		currentUser := p.SessionData().User
   233  		memberMap, err := p.MemberOfWithAdminOption(ctx, currentUser)
   234  		if err != nil {
   235  			return err
   236  		}
   237  
   238  		grantee := tree.NewDString(currentUser)
   239  
   240  		for roleName, isAdmin := range memberMap {
   241  			if err := addRow(
   242  				grantee,                   // grantee: always the current user
   243  				tree.NewDString(roleName), // role_name
   244  				yesOrNoDatum(isAdmin),     // is_grantable
   245  			); err != nil {
   246  				return err
   247  			}
   248  		}
   249  
   250  		return nil
   251  	},
   252  }
   253  
   254  var informationSchemaCheckConstraints = virtualSchemaTable{
   255  	comment: `check constraints
   256  ` + base.DocsURL("information-schema.html#check_constraints") + `
   257  https://www.postgresql.org/docs/9.5/infoschema-check-constraints.html`,
   258  	schema: vtable.InformationSchemaCheckConstraints,
   259  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   260  		h := makeOidHasher()
   261  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual /* no constraints in virtual tables */, func(
   262  			db *sqlbase.DatabaseDescriptor,
   263  			scName string,
   264  			table *sqlbase.TableDescriptor,
   265  			tableLookup tableLookupFn,
   266  		) error {
   267  			conInfo, err := table.GetConstraintInfoWithLookup(tableLookup.getTableByID)
   268  			if err != nil {
   269  				return err
   270  			}
   271  			dbNameStr := tree.NewDString(db.Name)
   272  			scNameStr := tree.NewDString(scName)
   273  			for conName, con := range conInfo {
   274  				// Only Check constraints are included.
   275  				if con.Kind != sqlbase.ConstraintTypeCheck {
   276  					continue
   277  				}
   278  				conNameStr := tree.NewDString(conName)
   279  				// Like with pg_catalog.pg_constraint, Postgres wraps the check
   280  				// constraint expression in two pairs of parentheses.
   281  				chkExprStr := tree.NewDString(fmt.Sprintf("((%s))", con.Details))
   282  				if err := addRow(
   283  					dbNameStr,  // constraint_catalog
   284  					scNameStr,  // constraint_schema
   285  					conNameStr, // constraint_name
   286  					chkExprStr, // check_clause
   287  				); err != nil {
   288  					return err
   289  				}
   290  			}
   291  
   292  			// Unlike with pg_catalog.pg_constraint, Postgres also includes NOT
   293  			// NULL column constraints in information_schema.check_constraints.
   294  			// Cockroach doesn't track these constraints as check constraints,
   295  			// but we can pull them off of the table's column descriptors.
   296  			colNum := 0
   297  			return forEachColumnInTable(table, func(column *sqlbase.ColumnDescriptor) error {
   298  				colNum++
   299  				// Only visible, non-nullable columns are included.
   300  				if column.Hidden || column.Nullable {
   301  					return nil
   302  				}
   303  				// Generate a unique name for each NOT NULL constraint. Postgres
   304  				// uses the format <namespace_oid>_<table_oid>_<col_idx>_not_null.
   305  				// We might as well do the same.
   306  				conNameStr := tree.NewDString(fmt.Sprintf(
   307  					"%s_%s_%d_not_null", h.NamespaceOid(db, scName), tableOid(table.ID), colNum,
   308  				))
   309  				chkExprStr := tree.NewDString(fmt.Sprintf(
   310  					"%s IS NOT NULL", column.Name,
   311  				))
   312  				return addRow(
   313  					dbNameStr,  // constraint_catalog
   314  					scNameStr,  // constraint_schema
   315  					conNameStr, // constraint_name
   316  					chkExprStr, // check_clause
   317  				)
   318  			})
   319  		})
   320  	},
   321  }
   322  
   323  var informationSchemaColumnPrivileges = virtualSchemaTable{
   324  	comment: `column privilege grants (incomplete)
   325  ` + base.DocsURL("information-schema.html#column_privileges") + `
   326  https://www.postgresql.org/docs/9.5/infoschema-column-privileges.html`,
   327  	schema: vtable.InformationSchemaColumnPrivileges,
   328  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   329  		return forEachTableDesc(ctx, p, dbContext, virtualMany, func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
   330  			dbNameStr := tree.NewDString(db.Name)
   331  			scNameStr := tree.NewDString(scName)
   332  			columndata := privilege.List{privilege.SELECT, privilege.INSERT, privilege.UPDATE} // privileges for column level granularity
   333  			for _, u := range table.Privileges.Users {
   334  				for _, priv := range columndata {
   335  					if priv.Mask()&u.Privileges != 0 {
   336  						for i := range table.Columns {
   337  							cd := &table.Columns[i]
   338  							if err := addRow(
   339  								tree.DNull,                     // grantor
   340  								tree.NewDString(u.User),        // grantee
   341  								dbNameStr,                      // table_catalog
   342  								scNameStr,                      // table_schema
   343  								tree.NewDString(table.Name),    // table_name
   344  								tree.NewDString(cd.Name),       // column_name
   345  								tree.NewDString(priv.String()), // privilege_type
   346  								tree.DNull,                     // is_grantable
   347  							); err != nil {
   348  								return err
   349  							}
   350  						}
   351  					}
   352  				}
   353  			}
   354  			return nil
   355  		})
   356  	},
   357  }
   358  
   359  var informationSchemaColumnsTable = virtualSchemaTable{
   360  	comment: `table and view columns (incomplete)
   361  ` + base.DocsURL("information-schema.html#columns") + `
   362  https://www.postgresql.org/docs/9.5/infoschema-columns.html`,
   363  	schema: vtable.InformationSchemaColumns,
   364  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   365  		return forEachTableDesc(ctx, p, dbContext, virtualMany, func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
   366  			dbNameStr := tree.NewDString(db.Name)
   367  			scNameStr := tree.NewDString(scName)
   368  			return forEachColumnInTable(table, func(column *sqlbase.ColumnDescriptor) error {
   369  				collationCatalog := tree.DNull
   370  				collationSchema := tree.DNull
   371  				collationName := tree.DNull
   372  				if locale := column.Type.Locale(); locale != "" {
   373  					collationCatalog = dbNameStr
   374  					collationSchema = pgCatalogNameDString
   375  					collationName = tree.NewDString(locale)
   376  				}
   377  				colDefault := tree.DNull
   378  				if column.DefaultExpr != nil {
   379  					colExpr, err := schemaexpr.DeserializeTableDescExpr(ctx, &p.semaCtx, table, *column.DefaultExpr)
   380  					if err != nil {
   381  						return err
   382  					}
   383  					colDefault = tree.NewDString(tree.SerializeForDisplay(colExpr))
   384  				}
   385  				colComputed := emptyString
   386  				if column.ComputeExpr != nil {
   387  					colExpr, err := schemaexpr.DeserializeTableDescExpr(ctx, &p.semaCtx, table, *column.ComputeExpr)
   388  					if err != nil {
   389  						return err
   390  					}
   391  					colComputed = tree.NewDString(tree.SerializeForDisplay(colExpr))
   392  				}
   393  				return addRow(
   394  					dbNameStr,                    // table_catalog
   395  					scNameStr,                    // table_schema
   396  					tree.NewDString(table.Name),  // table_name
   397  					tree.NewDString(column.Name), // column_name
   398  					tree.NewDInt(tree.DInt(column.GetLogicalColumnID())), // ordinal_position
   399  					colDefault,                    // column_default
   400  					yesOrNoDatum(column.Nullable), // is_nullable
   401  					tree.NewDString(column.Type.InformationSchemaName()), // data_type
   402  					characterMaximumLength(column.Type),                  // character_maximum_length
   403  					characterOctetLength(column.Type),                    // character_octet_length
   404  					numericPrecision(column.Type),                        // numeric_precision
   405  					numericPrecisionRadix(column.Type),                   // numeric_precision_radix
   406  					numericScale(column.Type),                            // numeric_scale
   407  					datetimePrecision(column.Type),                       // datetime_precision
   408  					tree.DNull,                                           // interval_type
   409  					tree.DNull,                                           // interval_precision
   410  					tree.DNull,                                           // character_set_catalog
   411  					tree.DNull,                                           // character_set_schema
   412  					tree.DNull,                                           // character_set_name
   413  					collationCatalog,                                     // collation_catalog
   414  					collationSchema,                                      // collation_schema
   415  					collationName,                                        // collation_name
   416  					tree.DNull,                                           // domain_catalog
   417  					tree.DNull,                                           // domain_schema
   418  					tree.DNull,                                           // domain_name
   419  					dbNameStr,                                            // udt_catalog
   420  					pgCatalogNameDString,                                 // udt_schema
   421  					tree.NewDString(column.Type.PGName()),                // udt_name
   422  					tree.DNull,                                           // scope_catalog
   423  					tree.DNull,                                           // scope_schema
   424  					tree.DNull,                                           // scope_name
   425  					tree.DNull,                                           // maximum_cardinality
   426  					tree.DNull,                                           // dtd_identifier
   427  					tree.DNull,                                           // is_self_referencing
   428  					tree.DNull,                                           // is_identity
   429  					tree.DNull,                                           // identity_generation
   430  					tree.DNull,                                           // identity_start
   431  					tree.DNull,                                           // identity_increment
   432  					tree.DNull,                                           // identity_maximum
   433  					tree.DNull,                                           // identity_minimum
   434  					tree.DNull,                                           // identity_cycle
   435  					yesOrNoDatum(column.IsComputed()),                    // is_generated
   436  					colComputed,                                          // generation_expression
   437  					yesOrNoDatum(table.IsTable() &&
   438  						!table.IsVirtualTable() &&
   439  						!column.IsComputed(),
   440  					), // is_updatable
   441  					yesOrNoDatum(column.Hidden),              // is_hidden
   442  					tree.NewDString(column.Type.SQLString()), // crdb_sql_type
   443  				)
   444  			})
   445  		})
   446  	},
   447  }
   448  
   449  var informationSchemaEnabledRoles = virtualSchemaTable{
   450  	comment: `roles for the current user
   451  ` + base.DocsURL("information-schema.html#enabled_roles") + `
   452  https://www.postgresql.org/docs/9.5/infoschema-enabled-roles.html`,
   453  	schema: `
   454  CREATE TABLE information_schema.enabled_roles (
   455  	ROLE_NAME STRING NOT NULL
   456  )`,
   457  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   458  		currentUser := p.SessionData().User
   459  		memberMap, err := p.MemberOfWithAdminOption(ctx, currentUser)
   460  		if err != nil {
   461  			return err
   462  		}
   463  
   464  		// The current user is always listed.
   465  		if err := addRow(
   466  			tree.NewDString(currentUser), // role_name: the current user
   467  		); err != nil {
   468  			return err
   469  		}
   470  
   471  		for roleName := range memberMap {
   472  			if err := addRow(
   473  				tree.NewDString(roleName), // role_name
   474  			); err != nil {
   475  				return err
   476  			}
   477  		}
   478  
   479  		return nil
   480  	},
   481  }
   482  
   483  // characterMaximumLength returns the declared maximum length of
   484  // characters if the type is a character or bit string data
   485  // type. Returns false if the data type is not a character or bit
   486  // string, or if the string's length is not bounded.
   487  func characterMaximumLength(colType *types.T) tree.Datum {
   488  	return dIntFnOrNull(func() (int32, bool) {
   489  		switch colType.Family() {
   490  		case types.StringFamily, types.CollatedStringFamily, types.BitFamily:
   491  			if colType.Width() > 0 {
   492  				return colType.Width(), true
   493  			}
   494  		}
   495  		return 0, false
   496  	})
   497  }
   498  
   499  // characterOctetLength returns the maximum possible length in
   500  // octets of a datum if the T is a character string. Returns
   501  // false if the data type is not a character string, or if the
   502  // string's length is not bounded.
   503  func characterOctetLength(colType *types.T) tree.Datum {
   504  	return dIntFnOrNull(func() (int32, bool) {
   505  		switch colType.Family() {
   506  		case types.StringFamily, types.CollatedStringFamily:
   507  			if colType.Width() > 0 {
   508  				return colType.Width() * utf8.UTFMax, true
   509  			}
   510  		}
   511  		return 0, false
   512  	})
   513  }
   514  
   515  // numericPrecision returns the declared or implicit precision of numeric
   516  // data types. Returns false if the data type is not numeric, or if the precision
   517  // of the numeric type is not bounded.
   518  func numericPrecision(colType *types.T) tree.Datum {
   519  	return dIntFnOrNull(func() (int32, bool) {
   520  		switch colType.Family() {
   521  		case types.IntFamily:
   522  			return colType.Width(), true
   523  		case types.FloatFamily:
   524  			if colType.Width() == 32 {
   525  				return 24, true
   526  			}
   527  			return 53, true
   528  		case types.DecimalFamily:
   529  			if colType.Precision() > 0 {
   530  				return colType.Precision(), true
   531  			}
   532  		}
   533  		return 0, false
   534  	})
   535  }
   536  
   537  // numericPrecisionRadix returns the implicit precision radix of
   538  // numeric data types. Returns false if the data type is not numeric.
   539  func numericPrecisionRadix(colType *types.T) tree.Datum {
   540  	return dIntFnOrNull(func() (int32, bool) {
   541  		switch colType.Family() {
   542  		case types.IntFamily:
   543  			return 2, true
   544  		case types.FloatFamily:
   545  			return 2, true
   546  		case types.DecimalFamily:
   547  			return 10, true
   548  		}
   549  		return 0, false
   550  	})
   551  }
   552  
   553  // NumericScale returns the declared or implicit precision of exact numeric
   554  // data types. Returns false if the data type is not an exact numeric, or if the
   555  // scale of the exact numeric type is not bounded.
   556  func numericScale(colType *types.T) tree.Datum {
   557  	return dIntFnOrNull(func() (int32, bool) {
   558  		switch colType.Family() {
   559  		case types.IntFamily:
   560  			return 0, true
   561  		case types.DecimalFamily:
   562  			if colType.Precision() > 0 {
   563  				return colType.Width(), true
   564  			}
   565  		}
   566  		return 0, false
   567  	})
   568  }
   569  
   570  func datetimePrecision(colType *types.T) tree.Datum {
   571  	// We currently do not support a datetime precision.
   572  	return tree.DNull
   573  }
   574  
   575  var informationSchemaConstraintColumnUsageTable = virtualSchemaTable{
   576  	comment: `columns usage by constraints
   577  https://www.postgresql.org/docs/9.5/infoschema-constraint-column-usage.html`,
   578  	schema: `
   579  CREATE TABLE information_schema.constraint_column_usage (
   580  	TABLE_CATALOG      STRING NOT NULL,
   581  	TABLE_SCHEMA       STRING NOT NULL,
   582  	TABLE_NAME         STRING NOT NULL,
   583  	COLUMN_NAME        STRING NOT NULL,
   584  	CONSTRAINT_CATALOG STRING NOT NULL,
   585  	CONSTRAINT_SCHEMA  STRING NOT NULL,
   586  	CONSTRAINT_NAME    STRING NOT NULL
   587  )`,
   588  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   589  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual /* no constraints in virtual tables */, func(
   590  			db *sqlbase.DatabaseDescriptor,
   591  			scName string,
   592  			table *sqlbase.TableDescriptor,
   593  			tableLookup tableLookupFn,
   594  		) error {
   595  			conInfo, err := table.GetConstraintInfoWithLookup(tableLookup.getTableByID)
   596  			if err != nil {
   597  				return err
   598  			}
   599  			scNameStr := tree.NewDString(scName)
   600  			dbNameStr := tree.NewDString(db.Name)
   601  
   602  			for conName, con := range conInfo {
   603  				conTable := table
   604  				conCols := con.Columns
   605  				conNameStr := tree.NewDString(conName)
   606  				if con.Kind == sqlbase.ConstraintTypeFK {
   607  					// For foreign key constraint, constraint_column_usage
   608  					// identifies the table/columns that the foreign key
   609  					// references.
   610  					conTable = con.ReferencedTable
   611  					conCols, err = conTable.NamesForColumnIDs(con.FK.ReferencedColumnIDs)
   612  					if err != nil {
   613  						return err
   614  					}
   615  				}
   616  				tableNameStr := tree.NewDString(conTable.Name)
   617  				for _, col := range conCols {
   618  					if err := addRow(
   619  						dbNameStr,            // table_catalog
   620  						scNameStr,            // table_schema
   621  						tableNameStr,         // table_name
   622  						tree.NewDString(col), // column_name
   623  						dbNameStr,            // constraint_catalog
   624  						scNameStr,            // constraint_schema
   625  						conNameStr,           // constraint_name
   626  					); err != nil {
   627  						return err
   628  					}
   629  				}
   630  			}
   631  			return nil
   632  		})
   633  	},
   634  }
   635  
   636  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/key-column-usage-table.html
   637  var informationSchemaKeyColumnUsageTable = virtualSchemaTable{
   638  	comment: `column usage by indexes and key constraints
   639  ` + base.DocsURL("information-schema.html#key_column_usage") + `
   640  https://www.postgresql.org/docs/9.5/infoschema-key-column-usage.html`,
   641  	schema: `
   642  CREATE TABLE information_schema.key_column_usage (
   643  	CONSTRAINT_CATALOG STRING NOT NULL,
   644  	CONSTRAINT_SCHEMA  STRING NOT NULL,
   645  	CONSTRAINT_NAME    STRING NOT NULL,
   646  	TABLE_CATALOG      STRING NOT NULL,
   647  	TABLE_SCHEMA       STRING NOT NULL,
   648  	TABLE_NAME         STRING NOT NULL,
   649  	COLUMN_NAME        STRING NOT NULL,
   650  	ORDINAL_POSITION   INT NOT NULL,
   651  	POSITION_IN_UNIQUE_CONSTRAINT INT
   652  )`,
   653  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   654  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual /* no constraints in virtual tables */, func(
   655  			db *sqlbase.DatabaseDescriptor,
   656  			scName string,
   657  			table *sqlbase.TableDescriptor,
   658  			tableLookup tableLookupFn,
   659  		) error {
   660  			conInfo, err := table.GetConstraintInfoWithLookup(tableLookup.getTableByID)
   661  			if err != nil {
   662  				return err
   663  			}
   664  			dbNameStr := tree.NewDString(db.Name)
   665  			scNameStr := tree.NewDString(scName)
   666  			tbNameStr := tree.NewDString(table.Name)
   667  			for conName, con := range conInfo {
   668  				// Only Primary Key, Foreign Key, and Unique constraints are included.
   669  				switch con.Kind {
   670  				case sqlbase.ConstraintTypePK:
   671  				case sqlbase.ConstraintTypeFK:
   672  				case sqlbase.ConstraintTypeUnique:
   673  				default:
   674  					continue
   675  				}
   676  
   677  				cstNameStr := tree.NewDString(conName)
   678  
   679  				for pos, col := range con.Columns {
   680  					ordinalPos := tree.NewDInt(tree.DInt(pos + 1))
   681  					uniquePos := tree.DNull
   682  					if con.Kind == sqlbase.ConstraintTypeFK {
   683  						uniquePos = ordinalPos
   684  					}
   685  					if err := addRow(
   686  						dbNameStr,            // constraint_catalog
   687  						scNameStr,            // constraint_schema
   688  						cstNameStr,           // constraint_name
   689  						dbNameStr,            // table_catalog
   690  						scNameStr,            // table_schema
   691  						tbNameStr,            // table_name
   692  						tree.NewDString(col), // column_name
   693  						ordinalPos,           // ordinal_position, 1-indexed
   694  						uniquePos,            // position_in_unique_constraint
   695  					); err != nil {
   696  						return err
   697  					}
   698  				}
   699  			}
   700  			return nil
   701  		})
   702  	},
   703  }
   704  
   705  // Postgres: https://www.postgresql.org/docs/9.6/static/infoschema-parameters.html
   706  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/parameters-table.html
   707  var informationSchemaParametersTable = virtualSchemaTable{
   708  	comment: `built-in function parameters (empty - introspection not yet supported)
   709  https://www.postgresql.org/docs/9.5/infoschema-parameters.html`,
   710  	schema: `
   711  CREATE TABLE information_schema.parameters (
   712  	SPECIFIC_CATALOG STRING,
   713  	SPECIFIC_SCHEMA STRING,
   714  	SPECIFIC_NAME STRING,
   715  	ORDINAL_POSITION INT,
   716  	PARAMETER_MODE STRING,
   717  	IS_RESULT STRING,
   718  	AS_LOCATOR STRING,
   719  	PARAMETER_NAME STRING,
   720  	DATA_TYPE STRING,
   721  	CHARACTER_MAXIMUM_LENGTH INT,
   722  	CHARACTER_OCTET_LENGTH INT,
   723  	CHARACTER_SET_CATALOG STRING,
   724  	CHARACTER_SET_SCHEMA STRING,
   725  	CHARACTER_SET_NAME STRING,
   726  	COLLATION_CATALOG STRING,
   727  	COLLATION_SCHEMA STRING,
   728  	COLLATION_NAME STRING,
   729  	NUMERIC_PRECISION INT,
   730  	NUMERIC_PRECISION_RADIX INT,
   731  	NUMERIC_SCALE INT,
   732  	DATETIME_PRECISION INT,
   733  	INTERVAL_TYPE STRING,
   734  	INTERVAL_PRECISION INT,
   735  	UDT_CATALOG STRING,
   736  	UDT_SCHEMA STRING,
   737  	UDT_NAME STRING,
   738  	SCOPE_CATALOG STRING,
   739  	SCOPE_SCHEMA STRING,
   740  	SCOPE_NAME STRING,
   741  	MAXIMUM_CARDINALITY INT,
   742  	DTD_IDENTIFIER STRING,
   743  	PARAMETER_DEFAULT STRING
   744  )`,
   745  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   746  		return nil
   747  	},
   748  }
   749  
   750  var (
   751  	matchOptionFull    = tree.NewDString("FULL")
   752  	matchOptionPartial = tree.NewDString("PARTIAL")
   753  	matchOptionNone    = tree.NewDString("NONE")
   754  
   755  	matchOptionMap = map[sqlbase.ForeignKeyReference_Match]tree.Datum{
   756  		sqlbase.ForeignKeyReference_SIMPLE:  matchOptionNone,
   757  		sqlbase.ForeignKeyReference_FULL:    matchOptionFull,
   758  		sqlbase.ForeignKeyReference_PARTIAL: matchOptionPartial,
   759  	}
   760  
   761  	refConstraintRuleNoAction   = tree.NewDString("NO ACTION")
   762  	refConstraintRuleRestrict   = tree.NewDString("RESTRICT")
   763  	refConstraintRuleSetNull    = tree.NewDString("SET NULL")
   764  	refConstraintRuleSetDefault = tree.NewDString("SET DEFAULT")
   765  	refConstraintRuleCascade    = tree.NewDString("CASCADE")
   766  )
   767  
   768  func dStringForFKAction(action sqlbase.ForeignKeyReference_Action) tree.Datum {
   769  	switch action {
   770  	case sqlbase.ForeignKeyReference_NO_ACTION:
   771  		return refConstraintRuleNoAction
   772  	case sqlbase.ForeignKeyReference_RESTRICT:
   773  		return refConstraintRuleRestrict
   774  	case sqlbase.ForeignKeyReference_SET_NULL:
   775  		return refConstraintRuleSetNull
   776  	case sqlbase.ForeignKeyReference_SET_DEFAULT:
   777  		return refConstraintRuleSetDefault
   778  	case sqlbase.ForeignKeyReference_CASCADE:
   779  		return refConstraintRuleCascade
   780  	}
   781  	panic(errors.Errorf("unexpected ForeignKeyReference_Action: %v", action))
   782  }
   783  
   784  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/referential-constraints-table.html
   785  var informationSchemaReferentialConstraintsTable = virtualSchemaTable{
   786  	comment: `foreign key constraints
   787  ` + base.DocsURL("information-schema.html#referential_constraints") + `
   788  https://www.postgresql.org/docs/9.5/infoschema-referential-constraints.html`,
   789  	schema: `
   790  CREATE TABLE information_schema.referential_constraints (
   791  	CONSTRAINT_CATALOG        STRING NOT NULL,
   792  	CONSTRAINT_SCHEMA         STRING NOT NULL,
   793  	CONSTRAINT_NAME           STRING NOT NULL,
   794  	UNIQUE_CONSTRAINT_CATALOG STRING NOT NULL,
   795  	UNIQUE_CONSTRAINT_SCHEMA  STRING NOT NULL,
   796  	UNIQUE_CONSTRAINT_NAME    STRING,
   797  	MATCH_OPTION              STRING NOT NULL,
   798  	UPDATE_RULE               STRING NOT NULL,
   799  	DELETE_RULE               STRING NOT NULL,
   800  	TABLE_NAME                STRING NOT NULL,
   801  	REFERENCED_TABLE_NAME     STRING NOT NULL
   802  )`,
   803  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   804  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual /* no constraints in virtual tables */, func(
   805  			db *sqlbase.DatabaseDescriptor,
   806  			scName string,
   807  			table *sqlbase.TableDescriptor,
   808  			tableLookup tableLookupFn,
   809  		) error {
   810  			dbNameStr := tree.NewDString(db.Name)
   811  			scNameStr := tree.NewDString(scName)
   812  			tbNameStr := tree.NewDString(table.Name)
   813  			for i := range table.OutboundFKs {
   814  				fk := &table.OutboundFKs[i]
   815  				refTable, err := tableLookup.getTableByID(fk.ReferencedTableID)
   816  				if err != nil {
   817  					return err
   818  				}
   819  				var matchType = tree.DNull
   820  				if r, ok := matchOptionMap[fk.Match]; ok {
   821  					matchType = r
   822  				}
   823  				referencedIdx, err := sqlbase.FindFKReferencedIndex(refTable, fk.ReferencedColumnIDs)
   824  				if err != nil {
   825  					return err
   826  				}
   827  				if err := addRow(
   828  					dbNameStr,                           // constraint_catalog
   829  					scNameStr,                           // constraint_schema
   830  					tree.NewDString(fk.Name),            // constraint_name
   831  					dbNameStr,                           // unique_constraint_catalog
   832  					scNameStr,                           // unique_constraint_schema
   833  					tree.NewDString(referencedIdx.Name), // unique_constraint_name
   834  					matchType,                           // match_option
   835  					dStringForFKAction(fk.OnUpdate),     // update_rule
   836  					dStringForFKAction(fk.OnDelete),     // delete_rule
   837  					tbNameStr,                           // table_name
   838  					tree.NewDString(refTable.Name),      // referenced_table_name
   839  				); err != nil {
   840  					return err
   841  				}
   842  			}
   843  			return nil
   844  		})
   845  	},
   846  }
   847  
   848  // Postgres: https://www.postgresql.org/docs/9.6/static/infoschema-role-table-grants.html
   849  // MySQL:    missing
   850  var informationSchemaRoleTableGrants = virtualSchemaTable{
   851  	comment: `privileges granted on table or views (incomplete; see also information_schema.table_privileges; may contain excess users or roles)
   852  ` + base.DocsURL("information-schema.html#role_table_grants") + `
   853  https://www.postgresql.org/docs/9.5/infoschema-role-table-grants.html`,
   854  	schema: `
   855  CREATE TABLE information_schema.role_table_grants (
   856  	GRANTOR        STRING,
   857  	GRANTEE        STRING NOT NULL,
   858  	TABLE_CATALOG  STRING NOT NULL,
   859  	TABLE_SCHEMA   STRING NOT NULL,
   860  	TABLE_NAME     STRING NOT NULL,
   861  	PRIVILEGE_TYPE STRING NOT NULL,
   862  	IS_GRANTABLE   STRING,
   863  	WITH_HIERARCHY STRING
   864  )`,
   865  	// This is the same as information_schema.table_privileges. In postgres, this virtual table does
   866  	// not show tables with grants provided through PUBLIC, but table_privileges does.
   867  	// Since we don't have the PUBLIC concept, the two virtual tables are identical.
   868  	populate: populateTablePrivileges,
   869  }
   870  
   871  // MySQL:    https://dev.mysql.com/doc/mysql-infoschema-excerpt/5.7/en/routines-table.html
   872  var informationSchemaRoutineTable = virtualSchemaTable{
   873  	comment: `built-in functions (empty - introspection not yet supported)
   874  https://www.postgresql.org/docs/9.5/infoschema-routines.html`,
   875  	schema: `
   876  CREATE TABLE information_schema.routines (
   877  	SPECIFIC_CATALOG STRING,
   878  	SPECIFIC_SCHEMA STRING,
   879  	SPECIFIC_NAME STRING,
   880  	ROUTINE_CATALOG STRING,
   881  	ROUTINE_SCHEMA STRING,
   882  	ROUTINE_NAME STRING,
   883  	ROUTINE_TYPE STRING,
   884  	MODULE_CATALOG STRING,
   885  	MODULE_SCHEMA STRING,
   886  	MODULE_NAME STRING,
   887  	UDT_CATALOG STRING,
   888  	UDT_SCHEMA STRING,
   889  	UDT_NAME STRING,
   890  	DATA_TYPE STRING,
   891  	CHARACTER_MAXIMUM_LENGTH INT,
   892  	CHARACTER_OCTET_LENGTH INT,
   893  	CHARACTER_SET_CATALOG STRING,
   894  	CHARACTER_SET_SCHEMA STRING,
   895  	CHARACTER_SET_NAME STRING,
   896  	COLLATION_CATALOG STRING,
   897  	COLLATION_SCHEMA STRING,
   898  	COLLATION_NAME STRING,
   899  	NUMERIC_PRECISION INT,
   900  	NUMERIC_PRECISION_RADIX INT,
   901  	NUMERIC_SCALE INT,
   902  	DATETIME_PRECISION INT,
   903  	INTERVAL_TYPE STRING,
   904  	INTERVAL_PRECISION STRING,
   905  	TYPE_UDT_CATALOG STRING,
   906  	TYPE_UDT_SCHEMA STRING,
   907  	TYPE_UDT_NAME STRING,
   908  	SCOPE_CATALOG STRING,
   909  	SCOPE_NAME STRING,
   910  	MAXIMUM_CARDINALITY INT,
   911  	DTD_IDENTIFIER STRING,
   912  	ROUTINE_BODY STRING,
   913  	ROUTINE_DEFINITION STRING,
   914  	EXTERNAL_NAME STRING,
   915  	EXTERNAL_LANGUAGE STRING,
   916  	PARAMETER_STYLE STRING,
   917  	IS_DETERMINISTIC STRING,
   918  	SQL_DATA_ACCESS STRING,
   919  	IS_NULL_CALL STRING,
   920  	SQL_PATH STRING,
   921  	SCHEMA_LEVEL_ROUTINE STRING,
   922  	MAX_DYNAMIC_RESULT_SETS INT,
   923  	IS_USER_DEFINED_CAST STRING,
   924  	IS_IMPLICITLY_INVOCABLE STRING,
   925  	SECURITY_TYPE STRING,
   926  	TO_SQL_SPECIFIC_CATALOG STRING,
   927  	TO_SQL_SPECIFIC_SCHEMA STRING,
   928  	TO_SQL_SPECIFIC_NAME STRING,
   929  	AS_LOCATOR STRING,
   930  	CREATED  TIMESTAMPTZ,
   931  	LAST_ALTERED TIMESTAMPTZ,
   932  	NEW_SAVEPOINT_LEVEL  STRING,
   933  	IS_UDT_DEPENDENT STRING,
   934  	RESULT_CAST_FROM_DATA_TYPE STRING,
   935  	RESULT_CAST_AS_LOCATOR STRING,
   936  	RESULT_CAST_CHAR_MAX_LENGTH  INT,
   937  	RESULT_CAST_CHAR_OCTET_LENGTH STRING,
   938  	RESULT_CAST_CHAR_SET_CATALOG STRING,
   939  	RESULT_CAST_CHAR_SET_SCHEMA  STRING,
   940  	RESULT_CAST_CHAR_SET_NAME STRING,
   941  	RESULT_CAST_COLLATION_CATALOG STRING,
   942  	RESULT_CAST_COLLATION_SCHEMA STRING,
   943  	RESULT_CAST_COLLATION_NAME STRING,
   944  	RESULT_CAST_NUMERIC_PRECISION INT,
   945  	RESULT_CAST_NUMERIC_PRECISION_RADIX INT,
   946  	RESULT_CAST_NUMERIC_SCALE INT,
   947  	RESULT_CAST_DATETIME_PRECISION STRING,
   948  	RESULT_CAST_INTERVAL_TYPE STRING,
   949  	RESULT_CAST_INTERVAL_PRECISION INT,
   950  	RESULT_CAST_TYPE_UDT_CATALOG STRING,
   951  	RESULT_CAST_TYPE_UDT_SCHEMA  STRING,
   952  	RESULT_CAST_TYPE_UDT_NAME STRING,
   953  	RESULT_CAST_SCOPE_CATALOG STRING,
   954  	RESULT_CAST_SCOPE_SCHEMA STRING,
   955  	RESULT_CAST_SCOPE_NAME STRING,
   956  	RESULT_CAST_MAXIMUM_CARDINALITY INT,
   957  	RESULT_CAST_DTD_IDENTIFIER STRING
   958  )`,
   959  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   960  		return nil
   961  	},
   962  }
   963  
   964  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/schemata-table.html
   965  var informationSchemaSchemataTable = virtualSchemaTable{
   966  	comment: `database schemas (may contain schemata without permission)
   967  ` + base.DocsURL("information-schema.html#schemata") + `
   968  https://www.postgresql.org/docs/9.5/infoschema-schemata.html`,
   969  	schema: vtable.InformationSchemaSchemata,
   970  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   971  		return forEachDatabaseDesc(ctx, p, dbContext, true, /* requiresPrivileges */
   972  			func(db *sqlbase.DatabaseDescriptor) error {
   973  				return forEachSchemaName(ctx, p, db, func(sc string) error {
   974  					return addRow(
   975  						tree.NewDString(db.Name), // catalog_name
   976  						tree.NewDString(sc),      // schema_name
   977  						tree.DNull,               // default_character_set_name
   978  						tree.DNull,               // sql_path
   979  					)
   980  				})
   981  			})
   982  	},
   983  }
   984  
   985  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/schema-privileges-table.html
   986  var informationSchemaSchemataTablePrivileges = virtualSchemaTable{
   987  	comment: `schema privileges (incomplete; may contain excess users or roles)
   988  ` + base.DocsURL("information-schema.html#schema_privileges"),
   989  	schema: `
   990  CREATE TABLE information_schema.schema_privileges (
   991  	GRANTEE         STRING NOT NULL,
   992  	TABLE_CATALOG   STRING NOT NULL,
   993  	TABLE_SCHEMA    STRING NOT NULL,
   994  	PRIVILEGE_TYPE  STRING NOT NULL,
   995  	IS_GRANTABLE    STRING
   996  )`,
   997  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   998  		return forEachDatabaseDesc(ctx, p, dbContext, true, /* requiresPrivileges */
   999  			func(db *sqlbase.DatabaseDescriptor) error {
  1000  				return forEachSchemaName(ctx, p, db, func(scName string) error {
  1001  					privs := db.Privileges.Show()
  1002  					dbNameStr := tree.NewDString(db.Name)
  1003  					scNameStr := tree.NewDString(scName)
  1004  					// TODO(knz): This should filter for the current user, see
  1005  					// https://github.com/cockroachdb/cockroach/issues/35572
  1006  					for _, u := range privs {
  1007  						userNameStr := tree.NewDString(u.User)
  1008  						for _, priv := range u.Privileges {
  1009  							if err := addRow(
  1010  								userNameStr,           // grantee
  1011  								dbNameStr,             // table_catalog
  1012  								scNameStr,             // table_schema
  1013  								tree.NewDString(priv), // privilege_type
  1014  								tree.DNull,            // is_grantable
  1015  							); err != nil {
  1016  								return err
  1017  							}
  1018  						}
  1019  					}
  1020  					return nil
  1021  				})
  1022  			})
  1023  	},
  1024  }
  1025  
  1026  var (
  1027  	indexDirectionNA   = tree.NewDString("N/A")
  1028  	indexDirectionAsc  = tree.NewDString(sqlbase.IndexDescriptor_ASC.String())
  1029  	indexDirectionDesc = tree.NewDString(sqlbase.IndexDescriptor_DESC.String())
  1030  )
  1031  
  1032  func dStringForIndexDirection(dir sqlbase.IndexDescriptor_Direction) tree.Datum {
  1033  	switch dir {
  1034  	case sqlbase.IndexDescriptor_ASC:
  1035  		return indexDirectionAsc
  1036  	case sqlbase.IndexDescriptor_DESC:
  1037  		return indexDirectionDesc
  1038  	}
  1039  	panic("unreachable")
  1040  }
  1041  
  1042  var informationSchemaSequences = virtualSchemaTable{
  1043  	comment: `sequences
  1044  ` + base.DocsURL("information-schema.html#sequences") + `
  1045  https://www.postgresql.org/docs/9.5/infoschema-sequences.html`,
  1046  	schema: `
  1047  CREATE TABLE information_schema.sequences (
  1048      SEQUENCE_CATALOG         STRING NOT NULL,
  1049      SEQUENCE_SCHEMA          STRING NOT NULL,
  1050      SEQUENCE_NAME            STRING NOT NULL,
  1051      DATA_TYPE                STRING NOT NULL,
  1052      NUMERIC_PRECISION        INT NOT NULL,
  1053      NUMERIC_PRECISION_RADIX  INT NOT NULL,
  1054      NUMERIC_SCALE            INT NOT NULL,
  1055      START_VALUE              STRING NOT NULL,
  1056      MINIMUM_VALUE            STRING NOT NULL,
  1057      MAXIMUM_VALUE            STRING NOT NULL,
  1058      INCREMENT                STRING NOT NULL,
  1059      CYCLE_OPTION             STRING NOT NULL
  1060  )`,
  1061  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1062  		return forEachTableDesc(ctx, p, dbContext, hideVirtual, /* no sequences in virtual schemas */
  1063  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  1064  				if !table.IsSequence() {
  1065  					return nil
  1066  				}
  1067  				return addRow(
  1068  					tree.NewDString(db.GetName()),    // catalog
  1069  					tree.NewDString(scName),          // schema
  1070  					tree.NewDString(table.GetName()), // name
  1071  					tree.NewDString("bigint"),        // type
  1072  					tree.NewDInt(64),                 // numeric precision
  1073  					tree.NewDInt(2),                  // numeric precision radix
  1074  					tree.NewDInt(0),                  // numeric scale
  1075  					tree.NewDString(strconv.FormatInt(table.SequenceOpts.Start, 10)),     // start value
  1076  					tree.NewDString(strconv.FormatInt(table.SequenceOpts.MinValue, 10)),  // min value
  1077  					tree.NewDString(strconv.FormatInt(table.SequenceOpts.MaxValue, 10)),  // max value
  1078  					tree.NewDString(strconv.FormatInt(table.SequenceOpts.Increment, 10)), // increment
  1079  					noString, // cycle
  1080  				)
  1081  			})
  1082  	},
  1083  }
  1084  
  1085  // Postgres: missing
  1086  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/statistics-table.html
  1087  var informationSchemaStatisticsTable = virtualSchemaTable{
  1088  	comment: `index metadata and statistics (incomplete)
  1089  ` + base.DocsURL("information-schema.html#statistics"),
  1090  	schema: `
  1091  CREATE TABLE information_schema.statistics (
  1092  	TABLE_CATALOG STRING NOT NULL,
  1093  	TABLE_SCHEMA  STRING NOT NULL,
  1094  	TABLE_NAME    STRING NOT NULL,
  1095  	NON_UNIQUE    STRING NOT NULL,
  1096  	INDEX_SCHEMA  STRING NOT NULL,
  1097  	INDEX_NAME    STRING NOT NULL,
  1098  	SEQ_IN_INDEX  INT NOT NULL,
  1099  	COLUMN_NAME   STRING NOT NULL,
  1100  	"COLLATION"   STRING,
  1101  	CARDINALITY   INT,
  1102  	DIRECTION     STRING NOT NULL,
  1103  	STORING       STRING NOT NULL,
  1104  	IMPLICIT      STRING NOT NULL
  1105  )`,
  1106  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1107  		return forEachTableDesc(ctx, p, dbContext, hideVirtual, /* virtual tables have no indexes */
  1108  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  1109  				dbNameStr := tree.NewDString(db.GetName())
  1110  				scNameStr := tree.NewDString(scName)
  1111  				tbNameStr := tree.NewDString(table.GetName())
  1112  
  1113  				appendRow := func(index *sqlbase.IndexDescriptor, colName string, sequence int,
  1114  					direction tree.Datum, isStored, isImplicit bool,
  1115  				) error {
  1116  					return addRow(
  1117  						dbNameStr,                         // table_catalog
  1118  						scNameStr,                         // table_schema
  1119  						tbNameStr,                         // table_name
  1120  						yesOrNoDatum(!index.Unique),       // non_unique
  1121  						scNameStr,                         // index_schema
  1122  						tree.NewDString(index.Name),       // index_name
  1123  						tree.NewDInt(tree.DInt(sequence)), // seq_in_index
  1124  						tree.NewDString(colName),          // column_name
  1125  						tree.DNull,                        // collation
  1126  						tree.DNull,                        // cardinality
  1127  						direction,                         // direction
  1128  						yesOrNoDatum(isStored),            // storing
  1129  						yesOrNoDatum(isImplicit),          // implicit
  1130  					)
  1131  				}
  1132  
  1133  				return forEachIndexInTable(table, func(index *sqlbase.IndexDescriptor) error {
  1134  					// Columns in the primary key that aren't in index.ColumnNames or
  1135  					// index.StoreColumnNames are implicit columns in the index.
  1136  					var implicitCols map[string]struct{}
  1137  					var hasImplicitCols bool
  1138  					if index.HasOldStoredColumns() {
  1139  						// Old STORING format: implicit columns are extra columns minus stored
  1140  						// columns.
  1141  						hasImplicitCols = len(index.ExtraColumnIDs) > len(index.StoreColumnNames)
  1142  					} else {
  1143  						// New STORING format: implicit columns are extra columns.
  1144  						hasImplicitCols = len(index.ExtraColumnIDs) > 0
  1145  					}
  1146  					if hasImplicitCols {
  1147  						implicitCols = make(map[string]struct{})
  1148  						for _, col := range table.PrimaryIndex.ColumnNames {
  1149  							implicitCols[col] = struct{}{}
  1150  						}
  1151  					}
  1152  
  1153  					sequence := 1
  1154  					for i, col := range index.ColumnNames {
  1155  						// We add a row for each column of index.
  1156  						dir := dStringForIndexDirection(index.ColumnDirections[i])
  1157  						if err := appendRow(index, col, sequence, dir, false, false); err != nil {
  1158  							return err
  1159  						}
  1160  						sequence++
  1161  						delete(implicitCols, col)
  1162  					}
  1163  					for _, col := range index.StoreColumnNames {
  1164  						// We add a row for each stored column of index.
  1165  						if err := appendRow(index, col, sequence,
  1166  							indexDirectionNA, true, false); err != nil {
  1167  							return err
  1168  						}
  1169  						sequence++
  1170  						delete(implicitCols, col)
  1171  					}
  1172  					for col := range implicitCols {
  1173  						// We add a row for each implicit column of index.
  1174  						if err := appendRow(index, col, sequence,
  1175  							indexDirectionAsc, false, true); err != nil {
  1176  							return err
  1177  						}
  1178  						sequence++
  1179  					}
  1180  					return nil
  1181  				})
  1182  			})
  1183  	},
  1184  }
  1185  
  1186  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/table-constraints-table.html
  1187  var informationSchemaTableConstraintTable = virtualSchemaTable{
  1188  	comment: `table constraints
  1189  ` + base.DocsURL("information-schema.html#table_constraints") + `
  1190  https://www.postgresql.org/docs/9.5/infoschema-table-constraints.html`,
  1191  	schema: `
  1192  CREATE TABLE information_schema.table_constraints (
  1193  	CONSTRAINT_CATALOG STRING NOT NULL,
  1194  	CONSTRAINT_SCHEMA  STRING NOT NULL,
  1195  	CONSTRAINT_NAME    STRING NOT NULL,
  1196  	TABLE_CATALOG      STRING NOT NULL,
  1197  	TABLE_SCHEMA       STRING NOT NULL,
  1198  	TABLE_NAME         STRING NOT NULL,
  1199  	CONSTRAINT_TYPE    STRING NOT NULL,
  1200  	IS_DEFERRABLE      STRING NOT NULL,
  1201  	INITIALLY_DEFERRED STRING NOT NULL
  1202  )`,
  1203  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1204  		h := makeOidHasher()
  1205  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual, /* virtual tables have no constraints */
  1206  			func(
  1207  				db *sqlbase.DatabaseDescriptor,
  1208  				scName string,
  1209  				table *sqlbase.TableDescriptor,
  1210  				tableLookup tableLookupFn,
  1211  			) error {
  1212  				conInfo, err := table.GetConstraintInfoWithLookup(tableLookup.getTableByID)
  1213  				if err != nil {
  1214  					return err
  1215  				}
  1216  
  1217  				dbNameStr := tree.NewDString(db.Name)
  1218  				scNameStr := tree.NewDString(scName)
  1219  				tbNameStr := tree.NewDString(table.Name)
  1220  
  1221  				for conName, c := range conInfo {
  1222  					if err := addRow(
  1223  						dbNameStr,                       // constraint_catalog
  1224  						scNameStr,                       // constraint_schema
  1225  						tree.NewDString(conName),        // constraint_name
  1226  						dbNameStr,                       // table_catalog
  1227  						scNameStr,                       // table_schema
  1228  						tbNameStr,                       // table_name
  1229  						tree.NewDString(string(c.Kind)), // constraint_type
  1230  						yesOrNoDatum(false),             // is_deferrable
  1231  						yesOrNoDatum(false),             // initially_deferred
  1232  					); err != nil {
  1233  						return err
  1234  					}
  1235  				}
  1236  
  1237  				// Unlike with pg_catalog.pg_constraint, Postgres also includes NOT
  1238  				// NULL column constraints in information_schema.check_constraints.
  1239  				// Cockroach doesn't track these constraints as check constraints,
  1240  				// but we can pull them off of the table's column descriptors.
  1241  				colNum := 0
  1242  				return forEachColumnInTable(table, func(col *sqlbase.ColumnDescriptor) error {
  1243  					colNum++
  1244  					// NOT NULL column constraints are implemented as a CHECK in postgres.
  1245  					conNameStr := tree.NewDString(fmt.Sprintf(
  1246  						"%s_%s_%d_not_null", h.NamespaceOid(db, scName), tableOid(table.ID), colNum,
  1247  					))
  1248  					if !col.Nullable {
  1249  						if err := addRow(
  1250  							dbNameStr,                // constraint_catalog
  1251  							scNameStr,                // constraint_schema
  1252  							conNameStr,               // constraint_name
  1253  							dbNameStr,                // table_catalog
  1254  							scNameStr,                // table_schema
  1255  							tbNameStr,                // table_name
  1256  							tree.NewDString("CHECK"), // constraint_type
  1257  							yesOrNoDatum(false),      // is_deferrable
  1258  							yesOrNoDatum(false),      // initially_deferred
  1259  						); err != nil {
  1260  							return err
  1261  						}
  1262  					}
  1263  					return nil
  1264  				})
  1265  			})
  1266  	},
  1267  }
  1268  
  1269  // Postgres: not provided
  1270  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/user-privileges-table.html
  1271  // TODO(knz): this introspection facility is of dubious utility.
  1272  var informationSchemaUserPrivileges = virtualSchemaTable{
  1273  	comment: `grantable privileges (incomplete)`,
  1274  	schema: `
  1275  CREATE TABLE information_schema.user_privileges (
  1276  	GRANTEE        STRING NOT NULL,
  1277  	TABLE_CATALOG  STRING NOT NULL,
  1278  	PRIVILEGE_TYPE STRING NOT NULL,
  1279  	IS_GRANTABLE   STRING
  1280  )`,
  1281  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1282  		return forEachDatabaseDesc(ctx, p, dbContext, true, /* requiresPrivileges */
  1283  			func(dbDesc *DatabaseDescriptor) error {
  1284  				dbNameStr := tree.NewDString(dbDesc.Name)
  1285  				for _, u := range []string{security.RootUser, sqlbase.AdminRole} {
  1286  					grantee := tree.NewDString(u)
  1287  					for _, p := range privilege.List(privilege.ByValue[:]).SortedNames() {
  1288  						if err := addRow(
  1289  							grantee,            // grantee
  1290  							dbNameStr,          // table_catalog
  1291  							tree.NewDString(p), // privilege_type
  1292  							tree.DNull,         // is_grantable
  1293  						); err != nil {
  1294  							return err
  1295  						}
  1296  					}
  1297  				}
  1298  				return nil
  1299  			})
  1300  	},
  1301  }
  1302  
  1303  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/table-privileges-table.html
  1304  var informationSchemaTablePrivileges = virtualSchemaTable{
  1305  	comment: `privileges granted on table or views (incomplete; may contain excess users or roles)
  1306  ` + base.DocsURL("information-schema.html#table_privileges") + `
  1307  https://www.postgresql.org/docs/9.5/infoschema-table-privileges.html`,
  1308  	schema: `
  1309  CREATE TABLE information_schema.table_privileges (
  1310  	GRANTOR        STRING,
  1311  	GRANTEE        STRING NOT NULL,
  1312  	TABLE_CATALOG  STRING NOT NULL,
  1313  	TABLE_SCHEMA   STRING NOT NULL,
  1314  	TABLE_NAME     STRING NOT NULL,
  1315  	PRIVILEGE_TYPE STRING NOT NULL,
  1316  	IS_GRANTABLE   STRING,
  1317  	WITH_HIERARCHY STRING NOT NULL
  1318  )`,
  1319  	populate: populateTablePrivileges,
  1320  }
  1321  
  1322  // populateTablePrivileges is used to populate both table_privileges and role_table_grants.
  1323  func populateTablePrivileges(
  1324  	ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error,
  1325  ) error {
  1326  	return forEachTableDesc(ctx, p, dbContext, virtualMany,
  1327  		func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  1328  			dbNameStr := tree.NewDString(db.Name)
  1329  			scNameStr := tree.NewDString(scName)
  1330  			tbNameStr := tree.NewDString(table.Name)
  1331  			// TODO(knz): This should filter for the current user, see
  1332  			// https://github.com/cockroachdb/cockroach/issues/35572
  1333  			for _, u := range table.Privileges.Show() {
  1334  				for _, priv := range u.Privileges {
  1335  					if err := addRow(
  1336  						tree.DNull,                     // grantor
  1337  						tree.NewDString(u.User),        // grantee
  1338  						dbNameStr,                      // table_catalog
  1339  						scNameStr,                      // table_schema
  1340  						tbNameStr,                      // table_name
  1341  						tree.NewDString(priv),          // privilege_type
  1342  						tree.DNull,                     // is_grantable
  1343  						yesOrNoDatum(priv == "SELECT"), // with_hierarchy
  1344  					); err != nil {
  1345  						return err
  1346  					}
  1347  				}
  1348  			}
  1349  			return nil
  1350  		})
  1351  }
  1352  
  1353  var (
  1354  	tableTypeSystemView = tree.NewDString("SYSTEM VIEW")
  1355  	tableTypeBaseTable  = tree.NewDString("BASE TABLE")
  1356  	tableTypeView       = tree.NewDString("VIEW")
  1357  	tableTypeTemporary  = tree.NewDString("LOCAL TEMPORARY")
  1358  )
  1359  
  1360  var informationSchemaTablesTable = virtualSchemaTable{
  1361  	comment: `tables and views
  1362  ` + base.DocsURL("information-schema.html#tables") + `
  1363  https://www.postgresql.org/docs/9.5/infoschema-tables.html`,
  1364  	schema: vtable.InformationSchemaTables,
  1365  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1366  		return forEachTableDesc(ctx, p, dbContext, virtualMany, addTablesTableRow(addRow))
  1367  	},
  1368  	indexes: []virtualIndex{
  1369  		{
  1370  			populate: func(ctx context.Context, constraint tree.Datum, p *planner, db *DatabaseDescriptor,
  1371  				addRow func(...tree.Datum) error) (bool, error) {
  1372  				// This index is on the TABLE_NAME column.
  1373  				name := tree.MustBeDString(constraint)
  1374  				desc, err := resolver.ResolveExistingTableObject(ctx, p, tree.NewUnqualifiedTableName(tree.Name(name)),
  1375  					tree.ObjectLookupFlags{}, resolver.ResolveAnyDescType)
  1376  				if err != nil || desc == nil {
  1377  					return false, err
  1378  				}
  1379  				schemaName, err := resolver.ResolveSchemaNameByID(ctx, p.txn, p.ExecCfg().Codec, db.ID, desc.GetParentSchemaID())
  1380  				if err != nil {
  1381  					return false, err
  1382  				}
  1383  				return true, addTablesTableRow(addRow)(db, schemaName, desc.TableDesc())
  1384  			},
  1385  		},
  1386  	},
  1387  }
  1388  
  1389  func addTablesTableRow(
  1390  	addRow func(...tree.Datum) error,
  1391  ) func(db *sqlbase.DatabaseDescriptor, scName string,
  1392  	table *sqlbase.TableDescriptor) error {
  1393  	return func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  1394  		if table.IsSequence() {
  1395  			return nil
  1396  		}
  1397  		tableType := tableTypeBaseTable
  1398  		insertable := yesString
  1399  		if table.IsVirtualTable() {
  1400  			tableType = tableTypeSystemView
  1401  			insertable = noString
  1402  		} else if table.IsView() {
  1403  			tableType = tableTypeView
  1404  			insertable = noString
  1405  		} else if table.Temporary {
  1406  			tableType = tableTypeTemporary
  1407  		}
  1408  		dbNameStr := tree.NewDString(db.Name)
  1409  		scNameStr := tree.NewDString(scName)
  1410  		tbNameStr := tree.NewDString(table.Name)
  1411  		return addRow(
  1412  			dbNameStr,                              // table_catalog
  1413  			scNameStr,                              // table_schema
  1414  			tbNameStr,                              // table_name
  1415  			tableType,                              // table_type
  1416  			insertable,                             // is_insertable_into
  1417  			tree.NewDInt(tree.DInt(table.Version)), // version
  1418  		)
  1419  	}
  1420  }
  1421  
  1422  // Postgres: https://www.postgresql.org/docs/9.6/static/infoschema-views.html
  1423  // MySQL:    https://dev.mysql.com/doc/refman/5.7/en/views-table.html
  1424  var informationSchemaViewsTable = virtualSchemaTable{
  1425  	comment: `views (incomplete)
  1426  ` + base.DocsURL("information-schema.html#views") + `
  1427  https://www.postgresql.org/docs/9.5/infoschema-views.html`,
  1428  	schema: `
  1429  CREATE TABLE information_schema.views (
  1430      TABLE_CATALOG              STRING NOT NULL,
  1431      TABLE_SCHEMA               STRING NOT NULL,
  1432      TABLE_NAME                 STRING NOT NULL,
  1433      VIEW_DEFINITION            STRING NOT NULL,
  1434      CHECK_OPTION               STRING,
  1435      IS_UPDATABLE               STRING NOT NULL,
  1436      IS_INSERTABLE_INTO         STRING NOT NULL,
  1437      IS_TRIGGER_UPDATABLE       STRING NOT NULL,
  1438      IS_TRIGGER_DELETABLE       STRING NOT NULL,
  1439      IS_TRIGGER_INSERTABLE_INTO STRING NOT NULL
  1440  )`,
  1441  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1442  		return forEachTableDesc(ctx, p, dbContext, hideVirtual, /* virtual schemas have no views */
  1443  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  1444  				if !table.IsView() {
  1445  					return nil
  1446  				}
  1447  				// Note that the view query printed will not include any column aliases
  1448  				// specified outside the initial view query into the definition returned,
  1449  				// unlike Postgres. For example, for the view created via
  1450  				//  `CREATE VIEW (a) AS SELECT b FROM foo`
  1451  				// we'll only print `SELECT b FROM foo` as the view definition here,
  1452  				// while Postgres would more accurately print `SELECT b AS a FROM foo`.
  1453  				// TODO(a-robinson): Insert column aliases into view query once we
  1454  				// have a semantic query representation to work with (#10083).
  1455  				return addRow(
  1456  					tree.NewDString(db.Name),         // table_catalog
  1457  					tree.NewDString(scName),          // table_schema
  1458  					tree.NewDString(table.Name),      // table_name
  1459  					tree.NewDString(table.ViewQuery), // view_definition
  1460  					tree.DNull,                       // check_option
  1461  					noString,                         // is_updatable
  1462  					noString,                         // is_insertable_into
  1463  					noString,                         // is_trigger_updatable
  1464  					noString,                         // is_trigger_deletable
  1465  					noString,                         // is_trigger_insertable_into
  1466  				)
  1467  			})
  1468  	},
  1469  }
  1470  
  1471  // forEachSchemaName iterates over the physical and virtual schemas.
  1472  func forEachSchemaName(
  1473  	ctx context.Context, p *planner, db *sqlbase.DatabaseDescriptor, fn func(string) error,
  1474  ) error {
  1475  	schemaNames, err := getSchemaNames(ctx, p, db)
  1476  	if err != nil {
  1477  		return err
  1478  	}
  1479  	vtableEntries := p.getVirtualTabler().getEntries()
  1480  	scNames := make([]string, 0, len(schemaNames)+len(vtableEntries))
  1481  	for _, name := range schemaNames {
  1482  		scNames = append(scNames, name)
  1483  	}
  1484  	for _, schema := range vtableEntries {
  1485  		scNames = append(scNames, schema.desc.Name)
  1486  	}
  1487  	sort.Strings(scNames)
  1488  	for _, sc := range scNames {
  1489  		if err := fn(sc); err != nil {
  1490  			return err
  1491  		}
  1492  	}
  1493  	return nil
  1494  }
  1495  
  1496  // forEachDatabaseDesc calls a function for the given DatabaseDescriptor, or if
  1497  // it is nil, retrieves all database descriptors and iterates through them in
  1498  // lexicographical order with respect to their name. If privileges are required,
  1499  // the function is only called if the user has privileges on the database.
  1500  func forEachDatabaseDesc(
  1501  	ctx context.Context,
  1502  	p *planner,
  1503  	dbContext *DatabaseDescriptor,
  1504  	requiresPrivileges bool,
  1505  	fn func(*sqlbase.DatabaseDescriptor) error,
  1506  ) error {
  1507  	var dbDescs []*sqlbase.DatabaseDescriptor
  1508  	if dbContext == nil {
  1509  		allDbDescs, err := p.Tables().GetAllDatabaseDescriptors(ctx, p.txn)
  1510  		if err != nil {
  1511  			return err
  1512  		}
  1513  		dbDescs = allDbDescs
  1514  	} else {
  1515  		// We can't just use dbContext here because we need to fetch the descriptor
  1516  		// with privileges from kv.
  1517  		fetchedDbDesc, err := catalogkv.GetDatabaseDescriptorsFromIDs(ctx, p.txn, p.ExecCfg().Codec, []sqlbase.ID{dbContext.ID})
  1518  		if err != nil {
  1519  			return err
  1520  		}
  1521  		dbDescs = fetchedDbDesc
  1522  	}
  1523  
  1524  	// Ignore databases that the user cannot see.
  1525  	for _, dbDesc := range dbDescs {
  1526  		if !requiresPrivileges || userCanSeeDatabase(ctx, p, dbDesc) {
  1527  			if err := fn(dbDesc); err != nil {
  1528  				return err
  1529  			}
  1530  		}
  1531  	}
  1532  
  1533  	return nil
  1534  }
  1535  
  1536  // forEachTypeDesc calls a function for each TypeDescriptor. If dbContext is
  1537  // not nil, then the function is called for only TypeDescriptors within the
  1538  // given database.
  1539  func forEachTypeDesc(
  1540  	ctx context.Context,
  1541  	p *planner,
  1542  	dbContext *DatabaseDescriptor,
  1543  	fn func(db *DatabaseDescriptor, sc string, typ *TypeDescriptor) error,
  1544  ) error {
  1545  	descs, err := p.Tables().GetAllDescriptors(ctx, p.txn)
  1546  	if err != nil {
  1547  		return err
  1548  	}
  1549  	schemaNames, err := getSchemaNames(ctx, p, dbContext)
  1550  	if err != nil {
  1551  		return err
  1552  	}
  1553  	lCtx := newInternalLookupCtx(descs, dbContext)
  1554  	for _, id := range lCtx.typIDs {
  1555  		typ := lCtx.typDescs[id]
  1556  		dbDesc, parentExists := lCtx.dbDescs[typ.ParentID]
  1557  		if !parentExists {
  1558  			continue
  1559  		}
  1560  		scName, ok := schemaNames[typ.GetParentSchemaID()]
  1561  		if !ok {
  1562  			return errors.AssertionFailedf("schema id %d not found", typ.GetParentSchemaID())
  1563  		}
  1564  		if err := fn(dbDesc, scName, typ); err != nil {
  1565  			return err
  1566  		}
  1567  	}
  1568  	return nil
  1569  }
  1570  
  1571  // forEachTableDesc retrieves all table descriptors from the current
  1572  // database and all system databases and iterates through them. For
  1573  // each table, the function will call fn with its respective database
  1574  // and table descriptor.
  1575  //
  1576  // The dbContext argument specifies in which database context we are
  1577  // requesting the descriptors. In context nil all descriptors are
  1578  // visible, in non-empty contexts only the descriptors of that
  1579  // database are visible.
  1580  //
  1581  // The virtualOpts argument specifies how virtual tables are made
  1582  // visible.
  1583  func forEachTableDesc(
  1584  	ctx context.Context,
  1585  	p *planner,
  1586  	dbContext *DatabaseDescriptor,
  1587  	virtualOpts virtualOpts,
  1588  	fn func(*sqlbase.DatabaseDescriptor, string, *sqlbase.TableDescriptor) error,
  1589  ) error {
  1590  	return forEachTableDescWithTableLookup(ctx, p, dbContext, virtualOpts, func(
  1591  		db *sqlbase.DatabaseDescriptor,
  1592  		scName string,
  1593  		table *sqlbase.TableDescriptor,
  1594  		_ tableLookupFn,
  1595  	) error {
  1596  		return fn(db, scName, table)
  1597  	})
  1598  }
  1599  
  1600  type virtualOpts int
  1601  
  1602  const (
  1603  	// virtualMany iterates over virtual schemas in every catalog/database.
  1604  	virtualMany virtualOpts = iota
  1605  	// virtualOnce iterates over virtual schemas once, in the nil database.
  1606  	virtualOnce
  1607  	// hideVirtual completely hides virtual schemas during iteration.
  1608  	hideVirtual
  1609  )
  1610  
  1611  // forEachTableDescAll does the same as forEachTableDesc but also
  1612  // includes newly added non-public descriptors.
  1613  func forEachTableDescAll(
  1614  	ctx context.Context,
  1615  	p *planner,
  1616  	dbContext *DatabaseDescriptor,
  1617  	virtualOpts virtualOpts,
  1618  	fn func(*sqlbase.DatabaseDescriptor, string, *sqlbase.TableDescriptor) error,
  1619  ) error {
  1620  	return forEachTableDescAllWithTableLookup(ctx,
  1621  		p, dbContext, virtualOpts,
  1622  		func(
  1623  			db *sqlbase.DatabaseDescriptor,
  1624  			scName string,
  1625  			table *sqlbase.TableDescriptor,
  1626  			_ tableLookupFn,
  1627  		) error {
  1628  			return fn(db, scName, table)
  1629  		})
  1630  }
  1631  
  1632  // forEachTableDescAllWithTableLookup is like forEachTableDescAll, but it also
  1633  // provides a tableLookupFn like forEachTableDescWithTableLookup.
  1634  func forEachTableDescAllWithTableLookup(
  1635  	ctx context.Context,
  1636  	p *planner,
  1637  	dbContext *DatabaseDescriptor,
  1638  	virtualOpts virtualOpts,
  1639  	fn func(*sqlbase.DatabaseDescriptor, string, *sqlbase.TableDescriptor, tableLookupFn) error,
  1640  ) error {
  1641  	return forEachTableDescWithTableLookupInternal(ctx,
  1642  		p, dbContext, virtualOpts, true /* allowAdding */, fn)
  1643  }
  1644  
  1645  // forEachTableDescWithTableLookup acts like forEachTableDesc, except it also provides a
  1646  // tableLookupFn when calling fn to allow callers to lookup fetched table descriptors
  1647  // on demand. This is important for callers dealing with objects like foreign keys, where
  1648  // the metadata for each object must be augmented by looking at the referenced table.
  1649  //
  1650  // The dbContext argument specifies in which database context we are
  1651  // requesting the descriptors.  In context "" all descriptors are
  1652  // visible, in non-empty contexts only the descriptors of that
  1653  // database are visible.
  1654  func forEachTableDescWithTableLookup(
  1655  	ctx context.Context,
  1656  	p *planner,
  1657  	dbContext *DatabaseDescriptor,
  1658  	virtualOpts virtualOpts,
  1659  	fn func(*sqlbase.DatabaseDescriptor, string, *sqlbase.TableDescriptor, tableLookupFn) error,
  1660  ) error {
  1661  	return forEachTableDescWithTableLookupInternal(ctx, p, dbContext, virtualOpts, false /* allowAdding */, fn)
  1662  }
  1663  
  1664  func getSchemaNames(
  1665  	ctx context.Context, p *planner, dbContext *DatabaseDescriptor,
  1666  ) (map[sqlbase.ID]string, error) {
  1667  	if dbContext != nil {
  1668  		return p.Tables().GetSchemasForDatabase(ctx, p.txn, dbContext.ID)
  1669  	}
  1670  	ret := make(map[sqlbase.ID]string)
  1671  	dbs, err := p.Tables().GetAllDatabaseDescriptors(ctx, p.txn)
  1672  	if err != nil {
  1673  		return nil, err
  1674  	}
  1675  	for _, db := range dbs {
  1676  		schemas, err := p.Tables().GetSchemasForDatabase(ctx, p.txn, db.ID)
  1677  		if err != nil {
  1678  			return nil, err
  1679  		}
  1680  		for id, name := range schemas {
  1681  			ret[id] = name
  1682  		}
  1683  	}
  1684  	return ret, nil
  1685  }
  1686  
  1687  // forEachTableDescWithTableLookupInternal is the logic that supports
  1688  // forEachTableDescWithTableLookup.
  1689  //
  1690  // The allowAdding argument if true includes newly added tables that
  1691  // are not yet public.
  1692  func forEachTableDescWithTableLookupInternal(
  1693  	ctx context.Context,
  1694  	p *planner,
  1695  	dbContext *DatabaseDescriptor,
  1696  	virtualOpts virtualOpts,
  1697  	allowAdding bool,
  1698  	fn func(*DatabaseDescriptor, string, *TableDescriptor, tableLookupFn) error,
  1699  ) error {
  1700  	descs, err := p.Tables().GetAllDescriptors(ctx, p.txn)
  1701  	if err != nil {
  1702  		return err
  1703  	}
  1704  	lCtx := newInternalLookupCtx(descs, dbContext)
  1705  
  1706  	if virtualOpts == virtualMany || virtualOpts == virtualOnce {
  1707  		// Virtual descriptors first.
  1708  		vt := p.getVirtualTabler()
  1709  		vEntries := vt.getEntries()
  1710  		vSchemaNames := vt.getSchemaNames()
  1711  		iterate := func(dbDesc *DatabaseDescriptor) error {
  1712  			for _, virtSchemaName := range vSchemaNames {
  1713  				e := vEntries[virtSchemaName]
  1714  				for _, tName := range e.orderedDefNames {
  1715  					te := e.defs[tName]
  1716  					if err := fn(dbDesc, virtSchemaName, te.desc, lCtx); err != nil {
  1717  						return err
  1718  					}
  1719  				}
  1720  			}
  1721  			return nil
  1722  		}
  1723  
  1724  		switch virtualOpts {
  1725  		case virtualOnce:
  1726  			if err := iterate(nil); err != nil {
  1727  				return err
  1728  			}
  1729  		case virtualMany:
  1730  			for _, dbID := range lCtx.dbIDs {
  1731  				dbDesc := lCtx.dbDescs[dbID]
  1732  				if err := iterate(dbDesc); err != nil {
  1733  					return err
  1734  				}
  1735  			}
  1736  		}
  1737  	}
  1738  
  1739  	// Generate all schema names, and keep a mapping.
  1740  	schemaNames, err := getSchemaNames(ctx, p, dbContext)
  1741  	if err != nil {
  1742  		return err
  1743  	}
  1744  
  1745  	// Physical descriptors next.
  1746  	for _, tbID := range lCtx.tbIDs {
  1747  		table := lCtx.tbDescs[tbID]
  1748  		dbDesc, parentExists := lCtx.dbDescs[table.GetParentID()]
  1749  		if table.Dropped() || !userCanSeeTable(ctx, p, table, allowAdding) || !parentExists {
  1750  			continue
  1751  		}
  1752  		scName, ok := schemaNames[table.GetParentSchemaID()]
  1753  		if !ok {
  1754  			return errors.AssertionFailedf("schema id %d not found", table.GetParentSchemaID())
  1755  		}
  1756  		if err := fn(dbDesc, scName, table, lCtx); err != nil {
  1757  			return err
  1758  		}
  1759  	}
  1760  	return nil
  1761  }
  1762  
  1763  func forEachIndexInTable(
  1764  	table *sqlbase.TableDescriptor, fn func(*sqlbase.IndexDescriptor) error,
  1765  ) error {
  1766  	if table.IsPhysicalTable() {
  1767  		if err := fn(&table.PrimaryIndex); err != nil {
  1768  			return err
  1769  		}
  1770  	}
  1771  	for i := range table.Indexes {
  1772  		if err := fn(&table.Indexes[i]); err != nil {
  1773  			return err
  1774  		}
  1775  	}
  1776  	return nil
  1777  }
  1778  
  1779  func forEachColumnInTable(
  1780  	table *sqlbase.TableDescriptor, fn func(*sqlbase.ColumnDescriptor) error,
  1781  ) error {
  1782  	// Table descriptors already hold columns in-order.
  1783  	for i := range table.Columns {
  1784  		if err := fn(&table.Columns[i]); err != nil {
  1785  			return err
  1786  		}
  1787  	}
  1788  	return nil
  1789  }
  1790  
  1791  func forEachColumnInIndex(
  1792  	table *sqlbase.TableDescriptor,
  1793  	index *sqlbase.IndexDescriptor,
  1794  	fn func(*sqlbase.ColumnDescriptor) error,
  1795  ) error {
  1796  	colMap := make(map[sqlbase.ColumnID]*sqlbase.ColumnDescriptor, len(table.Columns))
  1797  	for i := range table.Columns {
  1798  		id := table.Columns[i].ID
  1799  		colMap[id] = &table.Columns[i]
  1800  	}
  1801  	for _, columnID := range index.ColumnIDs {
  1802  		column := colMap[columnID]
  1803  		if err := fn(column); err != nil {
  1804  			return err
  1805  		}
  1806  	}
  1807  	return nil
  1808  }
  1809  
  1810  func forEachRole(
  1811  	ctx context.Context, p *planner, fn func(username string, isRole bool, noLogin bool) error,
  1812  ) error {
  1813  	query := `
  1814  SELECT
  1815  	username,
  1816  	"isRole",
  1817  	EXISTS(
  1818  		SELECT
  1819  			option
  1820  		FROM
  1821  			system.role_options AS r
  1822  		WHERE
  1823  			r.username = u.username AND option = 'NOLOGIN'
  1824  	)
  1825  		AS nologin
  1826  FROM
  1827  	system.users AS u;
  1828  `
  1829  	rows, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.Query(
  1830  		ctx, "read-roles", p.txn, query,
  1831  	)
  1832  
  1833  	if err != nil {
  1834  		return err
  1835  	}
  1836  
  1837  	for _, row := range rows {
  1838  		username := tree.MustBeDString(row[0])
  1839  		isRole, ok := row[1].(*tree.DBool)
  1840  		if !ok {
  1841  			return errors.Errorf("isRole should be a boolean value, found %s instead", row[1].ResolvedType())
  1842  		}
  1843  		noLogin, ok := row[2].(*tree.DBool)
  1844  		if !ok {
  1845  			return errors.Errorf("noLogin should be a boolean value, found %s instead", row[1].ResolvedType())
  1846  		}
  1847  		if err := fn(string(username), bool(*isRole), bool(*noLogin)); err != nil {
  1848  			return err
  1849  		}
  1850  	}
  1851  
  1852  	return nil
  1853  }
  1854  
  1855  func forEachRoleMembership(
  1856  	ctx context.Context, p *planner, fn func(role, member string, isAdmin bool) error,
  1857  ) error {
  1858  	query := `SELECT "role", "member", "isAdmin" FROM system.role_members`
  1859  	rows, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.Query(
  1860  		ctx, "read-members", p.txn, query,
  1861  	)
  1862  	if err != nil {
  1863  		return err
  1864  	}
  1865  
  1866  	for _, row := range rows {
  1867  		roleName := tree.MustBeDString(row[0])
  1868  		memberName := tree.MustBeDString(row[1])
  1869  		isAdmin := row[2].(*tree.DBool)
  1870  
  1871  		if err := fn(string(roleName), string(memberName), bool(*isAdmin)); err != nil {
  1872  			return err
  1873  		}
  1874  	}
  1875  	return nil
  1876  }
  1877  
  1878  func userCanSeeDatabase(ctx context.Context, p *planner, db *sqlbase.DatabaseDescriptor) bool {
  1879  	return p.CheckAnyPrivilege(ctx, db) == nil
  1880  }
  1881  
  1882  func userCanSeeTable(
  1883  	ctx context.Context, p *planner, table *sqlbase.TableDescriptor, allowAdding bool,
  1884  ) bool {
  1885  	return tableIsVisible(table, allowAdding) && p.CheckAnyPrivilege(ctx, table) == nil
  1886  }
  1887  
  1888  func tableIsVisible(table *TableDescriptor, allowAdding bool) bool {
  1889  	return table.State == sqlbase.TableDescriptor_PUBLIC ||
  1890  		(allowAdding && table.State == sqlbase.TableDescriptor_ADD)
  1891  }