github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/pg_catalog.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  	"bytes"
    15  	"context"
    16  	"encoding/binary"
    17  	"fmt"
    18  	"hash"
    19  	"hash/fnv"
    20  	"strings"
    21  	"time"
    22  	"unicode"
    23  
    24  	"github.com/cockroachdb/cockroach/pkg/keys"
    25  	"github.com/cockroachdb/cockroach/pkg/security"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/parser"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    30  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    31  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    32  	"github.com/cockroachdb/cockroach/pkg/util/log"
    33  	"github.com/cockroachdb/errors"
    34  	"github.com/lib/pq/oid"
    35  	"golang.org/x/text/collate"
    36  )
    37  
    38  var (
    39  	oidZero   = tree.NewDOid(0)
    40  	zeroVal   = tree.DZero
    41  	negOneVal = tree.NewDInt(-1)
    42  
    43  	passwdStarString = tree.NewDString("********")
    44  )
    45  
    46  const (
    47  	indexTypeForwardIndex  = "prefix"
    48  	indexTypeInvertedIndex = "inverted"
    49  	defaultCollationTag    = "en-US"
    50  )
    51  
    52  // Bitmasks for pg_index.indoption. Each column in the index has a bitfield
    53  // indicating how the columns are indexed. The constants below are the same as
    54  // the ones in Postgres:
    55  // https://github.com/postgres/postgres/blob/b6423e92abfadaa1ed9642319872aa1654403cd6/src/include/catalog/pg_index.h#L70-L76
    56  const (
    57  	// indoptionDesc indicates that the values in the index are in reverse order.
    58  	indoptionDesc = 0x01
    59  	// indoptionNullsFirst indicates that NULLs appear first in the index.
    60  	indoptionNullsFirst = 0x02
    61  )
    62  
    63  var forwardIndexOid = stringOid(indexTypeForwardIndex)
    64  var invertedIndexOid = stringOid(indexTypeInvertedIndex)
    65  
    66  // pgCatalog contains a set of system tables mirroring PostgreSQL's pg_catalog schema.
    67  // This code attempts to comply as closely as possible to the system catalogs documented
    68  // in https://www.postgresql.org/docs/9.6/static/catalogs.html.
    69  var pgCatalog = virtualSchema{
    70  	name: pgCatalogName,
    71  	allTableNames: buildStringSet(
    72  		// Generated with:
    73  		// select distinct '"'||table_name||'",' from information_schema.tables
    74  		//    where table_schema='pg_catalog' order by table_name;
    75  		"pg_aggregate",
    76  		"pg_am",
    77  		"pg_amop",
    78  		"pg_amproc",
    79  		"pg_attrdef",
    80  		"pg_attribute",
    81  		"pg_auth_members",
    82  		"pg_authid",
    83  		"pg_available_extension_versions",
    84  		"pg_available_extensions",
    85  		"pg_cast",
    86  		"pg_class",
    87  		"pg_collation",
    88  		"pg_config",
    89  		"pg_constraint",
    90  		"pg_conversion",
    91  		"pg_cursors",
    92  		"pg_database",
    93  		"pg_db_role_setting",
    94  		"pg_default_acl",
    95  		"pg_depend",
    96  		"pg_description",
    97  		"pg_enum",
    98  		"pg_event_trigger",
    99  		"pg_extension",
   100  		"pg_file_settings",
   101  		"pg_foreign_data_wrapper",
   102  		"pg_foreign_server",
   103  		"pg_foreign_table",
   104  		"pg_group",
   105  		"pg_hba_file_rules",
   106  		"pg_index",
   107  		"pg_indexes",
   108  		"pg_inherits",
   109  		"pg_init_privs",
   110  		"pg_language",
   111  		"pg_largeobject",
   112  		"pg_largeobject_metadata",
   113  		"pg_locks",
   114  		"pg_matviews",
   115  		"pg_namespace",
   116  		"pg_opclass",
   117  		"pg_operator",
   118  		"pg_opfamily",
   119  		"pg_partitioned_table",
   120  		"pg_pltemplate",
   121  		"pg_policies",
   122  		"pg_policy",
   123  		"pg_prepared_statements",
   124  		"pg_prepared_xacts",
   125  		"pg_proc",
   126  		"pg_publication",
   127  		"pg_publication_rel",
   128  		"pg_publication_tables",
   129  		"pg_range",
   130  		"pg_replication_origin",
   131  		"pg_replication_origin_status",
   132  		"pg_replication_slots",
   133  		"pg_rewrite",
   134  		"pg_roles",
   135  		"pg_rules",
   136  		"pg_seclabel",
   137  		"pg_seclabels",
   138  		"pg_sequence",
   139  		"pg_sequences",
   140  		"pg_settings",
   141  		"pg_shadow",
   142  		"pg_shdepend",
   143  		"pg_shdescription",
   144  		"pg_shseclabel",
   145  		"pg_stat_activity",
   146  		"pg_stat_all_indexes",
   147  		"pg_stat_all_tables",
   148  		"pg_stat_archiver",
   149  		"pg_stat_bgwriter",
   150  		"pg_stat_database",
   151  		"pg_stat_database_conflicts",
   152  		"pg_stat_progress_vacuum",
   153  		"pg_stat_replication",
   154  		"pg_stat_ssl",
   155  		"pg_stat_subscription",
   156  		"pg_stat_sys_indexes",
   157  		"pg_stat_sys_tables",
   158  		"pg_stat_user_functions",
   159  		"pg_stat_user_indexes",
   160  		"pg_stat_user_tables",
   161  		"pg_stat_wal_receiver",
   162  		"pg_stat_xact_all_tables",
   163  		"pg_stat_xact_sys_tables",
   164  		"pg_stat_xact_user_functions",
   165  		"pg_stat_xact_user_tables",
   166  		"pg_statio_all_indexes",
   167  		"pg_statio_all_sequences",
   168  		"pg_statio_all_tables",
   169  		"pg_statio_sys_indexes",
   170  		"pg_statio_sys_sequences",
   171  		"pg_statio_sys_tables",
   172  		"pg_statio_user_indexes",
   173  		"pg_statio_user_sequences",
   174  		"pg_statio_user_tables",
   175  		"pg_statistic",
   176  		"pg_statistic_ext",
   177  		"pg_stats",
   178  		"pg_subscription",
   179  		"pg_subscription_rel",
   180  		"pg_tables",
   181  		"pg_tablespace",
   182  		"pg_timezone_abbrevs",
   183  		"pg_timezone_names",
   184  		"pg_transform",
   185  		"pg_trigger",
   186  		"pg_ts_config",
   187  		"pg_ts_config_map",
   188  		"pg_ts_dict",
   189  		"pg_ts_parser",
   190  		"pg_ts_template",
   191  		"pg_type",
   192  		"pg_user",
   193  		"pg_user_mapping",
   194  		"pg_user_mappings",
   195  		"pg_views",
   196  	),
   197  	tableDefs: map[sqlbase.ID]virtualSchemaDef{
   198  		sqlbase.PgCatalogAmTableID:                  pgCatalogAmTable,
   199  		sqlbase.PgCatalogAttrDefTableID:             pgCatalogAttrDefTable,
   200  		sqlbase.PgCatalogAttributeTableID:           pgCatalogAttributeTable,
   201  		sqlbase.PgCatalogAuthIDTableID:              pgCatalogAuthIDTable,
   202  		sqlbase.PgCatalogAuthMembersTableID:         pgCatalogAuthMembersTable,
   203  		sqlbase.PgCatalogAvailableExtensionsTableID: pgCatalogAvailableExtensionsTable,
   204  		sqlbase.PgCatalogCastTableID:                pgCatalogCastTable,
   205  		sqlbase.PgCatalogClassTableID:               pgCatalogClassTable,
   206  		sqlbase.PgCatalogCollationTableID:           pgCatalogCollationTable,
   207  		sqlbase.PgCatalogConstraintTableID:          pgCatalogConstraintTable,
   208  		sqlbase.PgCatalogConversionTableID:          pgCatalogConversionTable,
   209  		sqlbase.PgCatalogDatabaseTableID:            pgCatalogDatabaseTable,
   210  		sqlbase.PgCatalogDefaultACLTableID:          pgCatalogDefaultACLTable,
   211  		sqlbase.PgCatalogDependTableID:              pgCatalogDependTable,
   212  		sqlbase.PgCatalogDescriptionTableID:         pgCatalogDescriptionTable,
   213  		sqlbase.PgCatalogSharedDescriptionTableID:   pgCatalogSharedDescriptionTable,
   214  		sqlbase.PgCatalogEnumTableID:                pgCatalogEnumTable,
   215  		sqlbase.PgCatalogEventTriggerTableID:        pgCatalogEventTriggerTable,
   216  		sqlbase.PgCatalogExtensionTableID:           pgCatalogExtensionTable,
   217  		sqlbase.PgCatalogForeignDataWrapperTableID:  pgCatalogForeignDataWrapperTable,
   218  		sqlbase.PgCatalogForeignServerTableID:       pgCatalogForeignServerTable,
   219  		sqlbase.PgCatalogForeignTableTableID:        pgCatalogForeignTableTable,
   220  		sqlbase.PgCatalogIndexTableID:               pgCatalogIndexTable,
   221  		sqlbase.PgCatalogIndexesTableID:             pgCatalogIndexesTable,
   222  		sqlbase.PgCatalogInheritsTableID:            pgCatalogInheritsTable,
   223  		sqlbase.PgCatalogLanguageTableID:            pgCatalogLanguageTable,
   224  		sqlbase.PgCatalogLocksTableID:               pgCatalogLocksTable,
   225  		sqlbase.PgCatalogMatViewsTableID:            pgCatalogMatViewsTable,
   226  		sqlbase.PgCatalogNamespaceTableID:           pgCatalogNamespaceTable,
   227  		sqlbase.PgCatalogOperatorTableID:            pgCatalogOperatorTable,
   228  		sqlbase.PgCatalogPreparedStatementsTableID:  pgCatalogPreparedStatementsTable,
   229  		sqlbase.PgCatalogPreparedXactsTableID:       pgCatalogPreparedXactsTable,
   230  		sqlbase.PgCatalogProcTableID:                pgCatalogProcTable,
   231  		sqlbase.PgCatalogAggregateTableID:           pgCatalogAggregateTable,
   232  		sqlbase.PgCatalogRangeTableID:               pgCatalogRangeTable,
   233  		sqlbase.PgCatalogRewriteTableID:             pgCatalogRewriteTable,
   234  		sqlbase.PgCatalogRolesTableID:               pgCatalogRolesTable,
   235  		sqlbase.PgCatalogSecLabelsTableID:           pgCatalogSecLabelsTable,
   236  		sqlbase.PgCatalogSequencesTableID:           pgCatalogSequencesTable,
   237  		sqlbase.PgCatalogSettingsTableID:            pgCatalogSettingsTable,
   238  		sqlbase.PgCatalogShdependTableID:            pgCatalogShdependTable,
   239  		sqlbase.PgCatalogUserTableID:                pgCatalogUserTable,
   240  		sqlbase.PgCatalogUserMappingTableID:         pgCatalogUserMappingTable,
   241  		sqlbase.PgCatalogTablesTableID:              pgCatalogTablesTable,
   242  		sqlbase.PgCatalogTablespaceTableID:          pgCatalogTablespaceTable,
   243  		sqlbase.PgCatalogTriggerTableID:             pgCatalogTriggerTable,
   244  		sqlbase.PgCatalogTypeTableID:                pgCatalogTypeTable,
   245  		sqlbase.PgCatalogViewsTableID:               pgCatalogViewsTable,
   246  		sqlbase.PgCatalogStatActivityTableID:        pgCatalogStatActivityTable,
   247  		sqlbase.PgCatalogSecurityLabelTableID:       pgCatalogSecurityLabelTable,
   248  		sqlbase.PgCatalogSharedSecurityLabelTableID: pgCatalogSharedSecurityLabelTable,
   249  	},
   250  	// Postgres's catalogs are ill-defined when there is no current
   251  	// database set. Simply reject any attempts to use them in that
   252  	// case.
   253  	validWithNoDatabaseContext: false,
   254  	containsTypes:              true,
   255  }
   256  
   257  // The catalog pg_am stores information about relation access methods.
   258  // It's important to note that this table changed drastically between Postgres
   259  // versions 9.5 and 9.6. We currently support both versions of this table.
   260  // See: https://www.postgresql.org/docs/9.5/static/catalog-pg-am.html and
   261  // https://www.postgresql.org/docs/9.6/static/catalog-pg-am.html.
   262  var pgCatalogAmTable = virtualSchemaTable{
   263  	comment: `index access methods (incomplete)
   264  https://www.postgresql.org/docs/9.5/catalog-pg-am.html`,
   265  	schema: `
   266  CREATE TABLE pg_catalog.pg_am (
   267  	oid OID,
   268  	amname NAME,
   269  	amstrategies INT2,
   270  	amsupport INT2,
   271  	amcanorder BOOL,
   272  	amcanorderbyop BOOL,
   273  	amcanbackward BOOL,
   274  	amcanunique BOOL,
   275  	amcanmulticol BOOL,
   276  	amoptionalkey BOOL,
   277  	amsearcharray BOOL,
   278  	amsearchnulls BOOL,
   279  	amstorage BOOL,
   280  	amclusterable BOOL,
   281  	ampredlocks BOOL,
   282  	amkeytype OID,
   283  	aminsert OID,
   284  	ambeginscan OID,
   285  	amgettuple OID,
   286  	amgetbitmap OID,
   287  	amrescan OID,
   288  	amendscan OID,
   289  	ammarkpos OID,
   290  	amrestrpos OID,
   291  	ambuild OID,
   292  	ambuildempty OID,
   293  	ambulkdelete OID,
   294  	amvacuumcleanup OID,
   295  	amcanreturn OID,
   296  	amcostestimate OID,
   297  	amoptions OID,
   298  	amhandler OID,
   299  	amtype CHAR
   300  )`,
   301  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   302  		// add row for forward indexes
   303  		if err := addRow(
   304  			forwardIndexOid,                      // oid - all versions
   305  			tree.NewDName(indexTypeForwardIndex), // amname - all versions
   306  			zeroVal,                              // amstrategies - < v9.6
   307  			zeroVal,                              // amsupport - < v9.6
   308  			tree.DBoolTrue,                       // amcanorder - < v9.6
   309  			tree.DBoolFalse,                      // amcanorderbyop - < v9.6
   310  			tree.DBoolTrue,                       // amcanbackward - < v9.6
   311  			tree.DBoolTrue,                       // amcanunique - < v9.6
   312  			tree.DBoolTrue,                       // amcanmulticol - < v9.6
   313  			tree.DBoolTrue,                       // amoptionalkey - < v9.6
   314  			tree.DBoolTrue,                       // amsearcharray - < v9.6
   315  			tree.DBoolTrue,                       // amsearchnulls - < v9.6
   316  			tree.DBoolFalse,                      // amstorage - < v9.6
   317  			tree.DBoolFalse,                      // amclusterable - < v9.6
   318  			tree.DBoolFalse,                      // ampredlocks - < v9.6
   319  			oidZero,                              // amkeytype - < v9.6
   320  			tree.DNull,                           // aminsert - < v9.6
   321  			tree.DNull,                           // ambeginscan - < v9.6
   322  			oidZero,                              // amgettuple - < v9.6
   323  			oidZero,                              // amgetbitmap - < v9.6
   324  			tree.DNull,                           // amrescan - < v9.6
   325  			tree.DNull,                           // amendscan - < v9.6
   326  			tree.DNull,                           // ammarkpos - < v9.6
   327  			tree.DNull,                           // amrestrpos - < v9.6
   328  			tree.DNull,                           // ambuild - < v9.6
   329  			tree.DNull,                           // ambuildempty - < v9.6
   330  			tree.DNull,                           // ambulkdelete - < v9.6
   331  			tree.DNull,                           // amvacuumcleanup - < v9.6
   332  			tree.DNull,                           // amcanreturn - < v9.6
   333  			tree.DNull,                           // amcostestimate - < v9.6
   334  			tree.DNull,                           // amoptions - < v9.6
   335  			tree.DNull,                           // amhandler - > v9.6
   336  			tree.NewDString("i"),                 // amtype - > v9.6
   337  		); err != nil {
   338  			return err
   339  		}
   340  
   341  		// add row for inverted indexes
   342  		if err := addRow(
   343  			invertedIndexOid,                      // oid - all versions
   344  			tree.NewDName(indexTypeInvertedIndex), // amname - all versions
   345  			zeroVal,                               // amstrategies - < v9.6
   346  			zeroVal,                               // amsupport - < v9.6
   347  			tree.DBoolFalse,                       // amcanorder - < v9.6
   348  			tree.DBoolFalse,                       // amcanorderbyop - < v9.6
   349  			tree.DBoolFalse,                       // amcanbackward - < v9.6
   350  			tree.DBoolFalse,                       // amcanunique - < v9.6
   351  			tree.DBoolFalse,                       // amcanmulticol - < v9.6
   352  			tree.DBoolFalse,                       // amoptionalkey - < v9.6
   353  			tree.DBoolFalse,                       // amsearcharray - < v9.6
   354  			tree.DBoolTrue,                        // amsearchnulls - < v9.6
   355  			tree.DBoolFalse,                       // amstorage - < v9.6
   356  			tree.DBoolFalse,                       // amclusterable - < v9.6
   357  			tree.DBoolFalse,                       // ampredlocks - < v9.6
   358  			oidZero,                               // amkeytype - < v9.6
   359  			tree.DNull,                            // aminsert - < v9.6
   360  			tree.DNull,                            // ambeginscan - < v9.6
   361  			oidZero,                               // amgettuple - < v9.6
   362  			oidZero,                               // amgetbitmap - < v9.6
   363  			tree.DNull,                            // amrescan - < v9.6
   364  			tree.DNull,                            // amendscan - < v9.6
   365  			tree.DNull,                            // ammarkpos - < v9.6
   366  			tree.DNull,                            // amrestrpos - < v9.6
   367  			tree.DNull,                            // ambuild - < v9.6
   368  			tree.DNull,                            // ambuildempty - < v9.6
   369  			tree.DNull,                            // ambulkdelete - < v9.6
   370  			tree.DNull,                            // amvacuumcleanup - < v9.6
   371  			tree.DNull,                            // amcanreturn - < v9.6
   372  			tree.DNull,                            // amcostestimate - < v9.6
   373  			tree.DNull,                            // amoptions - < v9.6
   374  			tree.DNull,                            // amhandler - > v9.6
   375  			tree.NewDString("i"),                  // amtype - > v9.6
   376  		); err != nil {
   377  			return err
   378  		}
   379  		return nil
   380  	},
   381  }
   382  
   383  var pgCatalogAttrDefTable = makeAllRelationsVirtualTableWithDescriptorIDIndex(
   384  	`column default values
   385  https://www.postgresql.org/docs/9.5/catalog-pg-attrdef.html`,
   386  	`
   387  CREATE TABLE pg_catalog.pg_attrdef (
   388  	oid OID,
   389  	adrelid OID NOT NULL,
   390  	adnum INT2,
   391  	adbin STRING,
   392  	adsrc STRING,
   393    INDEX(adrelid)
   394  )`,
   395  	virtualMany, false, /* includesIndexEntries */
   396  	func(ctx context.Context, p *planner, h oidHasher, db *DatabaseDescriptor, scName string,
   397  		table *sqlbase.TableDescriptor,
   398  		lookup simpleSchemaResolver,
   399  		addRow func(...tree.Datum) error) error {
   400  		colNum := 0
   401  		return forEachColumnInTable(table, func(column *sqlbase.ColumnDescriptor) error {
   402  			colNum++
   403  			if column.DefaultExpr == nil {
   404  				// pg_attrdef only expects rows for columns with default values.
   405  				return nil
   406  			}
   407  			var defSrc *tree.DString
   408  			expr, err := parser.ParseExpr(*column.DefaultExpr)
   409  			if err != nil {
   410  				defSrc = tree.NewDString(*column.DefaultExpr)
   411  			} else {
   412  				// Use type check to resolve types in expr. We don't use
   413  				// DeserializeTableDescExpr here because that returns a typed
   414  				// expression under the hood. Since typed expressions don't contain
   415  				// type annotations, we wouldn't format some defaults as intended.
   416  				if _, err := expr.TypeCheck(ctx, &p.semaCtx, types.Any); err != nil {
   417  					return err
   418  				}
   419  				ctx := tree.NewFmtCtx(tree.FmtPGAttrdefAdbin)
   420  				ctx.FormatNode(expr)
   421  				defSrc = tree.NewDString(ctx.String())
   422  			}
   423  			return addRow(
   424  				h.ColumnOid(table.ID, column.ID),                     // oid
   425  				tableOid(table.ID),                                   // adrelid
   426  				tree.NewDInt(tree.DInt(column.GetLogicalColumnID())), // adnum
   427  				defSrc, // adbin
   428  				defSrc, // adsrc
   429  			)
   430  		})
   431  	})
   432  
   433  var pgCatalogAttributeTable = makeAllRelationsVirtualTableWithDescriptorIDIndex(
   434  	`table columns (incomplete - see also information_schema.columns)
   435  https://www.postgresql.org/docs/9.5/catalog-pg-attribute.html`,
   436  	`
   437  CREATE TABLE pg_catalog.pg_attribute (
   438  	attrelid OID NOT NULL,
   439  	attname NAME,
   440  	atttypid OID,
   441  	attstattarget INT4,
   442  	attlen INT2,
   443  	attnum INT2,
   444  	attndims INT4,
   445  	attcacheoff INT4,
   446  	atttypmod INT4,
   447  	attbyval BOOL,
   448  	attstorage CHAR,
   449  	attalign CHAR,
   450  	attnotnull BOOL,
   451  	atthasdef BOOL,
   452  	attisdropped BOOL,
   453  	attislocal BOOL,
   454  	attinhcount INT4,
   455  	attcollation OID,
   456  	attacl STRING[],
   457  	attoptions STRING[],
   458  	attfdwoptions STRING[],
   459    INDEX(attrelid)
   460  )`,
   461  	virtualMany, true, /* includesIndexEntries */
   462  	func(ctx context.Context, p *planner, h oidHasher, db *DatabaseDescriptor, scName string,
   463  		table *sqlbase.TableDescriptor,
   464  		lookup simpleSchemaResolver,
   465  		addRow func(...tree.Datum) error) error {
   466  		// addColumn adds adds either a table or a index column to the pg_attribute table.
   467  		addColumn := func(column *sqlbase.ColumnDescriptor, attRelID tree.Datum, colID sqlbase.ColumnID) error {
   468  			colTyp := column.Type
   469  			return addRow(
   470  				attRelID,                       // attrelid
   471  				tree.NewDName(column.Name),     // attname
   472  				typOid(colTyp),                 // atttypid
   473  				zeroVal,                        // attstattarget
   474  				typLen(colTyp),                 // attlen
   475  				tree.NewDInt(tree.DInt(colID)), // attnum
   476  				zeroVal,                        // attndims
   477  				negOneVal,                      // attcacheoff
   478  				tree.NewDInt(tree.DInt(colTyp.TypeModifier())), // atttypmod
   479  				tree.DNull, // attbyval (see pg_type.typbyval)
   480  				tree.DNull, // attstorage
   481  				tree.DNull, // attalign
   482  				tree.MakeDBool(tree.DBool(!column.Nullable)),          // attnotnull
   483  				tree.MakeDBool(tree.DBool(column.DefaultExpr != nil)), // atthasdef
   484  				tree.DBoolFalse,    // attisdropped
   485  				tree.DBoolTrue,     // attislocal
   486  				zeroVal,            // attinhcount
   487  				typColl(colTyp, h), // attcollation
   488  				tree.DNull,         // attacl
   489  				tree.DNull,         // attoptions
   490  				tree.DNull,         // attfdwoptions
   491  			)
   492  		}
   493  
   494  		// Columns for table.
   495  		if err := forEachColumnInTable(table, func(column *sqlbase.ColumnDescriptor) error {
   496  			tableID := tableOid(table.ID)
   497  			return addColumn(column, tableID, column.GetLogicalColumnID())
   498  		}); err != nil {
   499  			return err
   500  		}
   501  
   502  		// Columns for each index.
   503  		return forEachIndexInTable(table, func(index *sqlbase.IndexDescriptor) error {
   504  			return forEachColumnInIndex(table, index,
   505  				func(column *sqlbase.ColumnDescriptor) error {
   506  					idxID := h.IndexOid(table.ID, index.ID)
   507  					return addColumn(column, idxID, column.GetLogicalColumnID())
   508  				},
   509  			)
   510  		})
   511  	})
   512  
   513  var pgCatalogCastTable = virtualSchemaTable{
   514  	comment: `casts (empty - needs filling out)
   515  https://www.postgresql.org/docs/9.6/catalog-pg-cast.html`,
   516  	schema: `
   517  CREATE TABLE pg_catalog.pg_cast (
   518  	oid OID,
   519  	castsource OID,
   520  	casttarget OID,
   521  	castfunc OID,
   522  	castcontext CHAR,
   523  	castmethod CHAR
   524  )`,
   525  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   526  		// TODO(someone): to populate this, we should split up the big PerformCast
   527  		// method in tree/eval.go into entries in a list. Then, this virtual table
   528  		// can simply range over the list. This would probably be better for
   529  		// maintainability anyway.
   530  		return nil
   531  	},
   532  }
   533  
   534  var pgCatalogAuthIDTable = virtualSchemaTable{
   535  	comment: `authorization identifiers - differs from postgres as we do not display passwords, 
   536  and thus do not require admin privileges for access. 
   537  https://www.postgresql.org/docs/9.5/catalog-pg-authid.html`,
   538  	schema: `
   539  CREATE TABLE pg_catalog.pg_authid (
   540    oid OID,
   541    rolname NAME,
   542    rolsuper BOOL,
   543    rolinherit BOOL,
   544    rolcreaterole BOOL,
   545    rolcreatedb BOOL,
   546    rolcanlogin BOOL,
   547    rolreplication BOOL,
   548    rolbypassrls BOOL,
   549    rolconnlimit INT4,
   550    rolpassword TEXT, 
   551    rolvaliduntil TIMESTAMPTZ
   552  )`,
   553  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   554  		h := makeOidHasher()
   555  		return forEachRole(ctx, p, func(username string, isRole bool, noLogin bool) error {
   556  			isRoot := tree.DBool(username == security.RootUser || username == sqlbase.AdminRole)
   557  			isRoleDBool := tree.DBool(isRole)
   558  			roleCanLogin := tree.DBool(!noLogin)
   559  			return addRow(
   560  				h.UserOid(username),          // oid
   561  				tree.NewDName(username),      // rolname
   562  				tree.MakeDBool(isRoot),       // rolsuper
   563  				tree.MakeDBool(isRoleDBool),  // rolinherit. Roles inherit by default.
   564  				tree.MakeDBool(isRoot),       // rolcreaterole
   565  				tree.MakeDBool(isRoot),       // rolcreatedb
   566  				tree.MakeDBool(roleCanLogin), // rolcanlogin.
   567  				tree.DBoolFalse,              // rolreplication
   568  				tree.DBoolFalse,              // rolbypassrls
   569  				negOneVal,                    // rolconnlimit
   570  				passwdStarString,             // rolpassword
   571  				tree.DNull,                   // rolvaliduntil
   572  			)
   573  		})
   574  	},
   575  }
   576  
   577  var pgCatalogAuthMembersTable = virtualSchemaTable{
   578  	comment: `role membership
   579  https://www.postgresql.org/docs/9.5/catalog-pg-auth-members.html`,
   580  	schema: `
   581  CREATE TABLE pg_catalog.pg_auth_members (
   582  	roleid OID,
   583  	member OID,
   584  	grantor OID,
   585  	admin_option BOOL
   586  )`,
   587  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   588  		h := makeOidHasher()
   589  		return forEachRoleMembership(ctx, p,
   590  			func(roleName, memberName string, isAdmin bool) error {
   591  				return addRow(
   592  					h.UserOid(roleName),                 // roleid
   593  					h.UserOid(memberName),               // member
   594  					tree.DNull,                          // grantor
   595  					tree.MakeDBool(tree.DBool(isAdmin)), // admin_option
   596  				)
   597  			})
   598  	},
   599  }
   600  
   601  var pgCatalogAvailableExtensionsTable = virtualSchemaTable{
   602  	comment: `available extensions
   603  https://www.postgresql.org/docs/9.6/view-pg-available-extensions.html`,
   604  	schema: `
   605  CREATE TABLE pg_catalog.pg_available_extensions (
   606  	name NAME,
   607  	default_version TEXT,
   608  	installed_version TEXT,
   609  	comment TEXT
   610  )`,
   611  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   612  		// We support no extensions.
   613  		return nil
   614  	},
   615  }
   616  
   617  var (
   618  	relKindTable    = tree.NewDString("r")
   619  	relKindIndex    = tree.NewDString("i")
   620  	relKindView     = tree.NewDString("v")
   621  	relKindSequence = tree.NewDString("S")
   622  
   623  	relPersistencePermanent = tree.NewDString("p")
   624  )
   625  
   626  var pgCatalogClassTable = makeAllRelationsVirtualTableWithDescriptorIDIndex(
   627  	`tables and relation-like objects (incomplete - see also information_schema.tables/sequences/views)
   628  https://www.postgresql.org/docs/9.5/catalog-pg-class.html`,
   629  	`
   630  CREATE TABLE pg_catalog.pg_class (
   631  	oid OID NOT NULL,
   632  	relname NAME NOT NULL,
   633  	relnamespace OID,
   634  	reltype OID,
   635  	reloftype OID,
   636  	relowner OID,
   637  	relam OID,
   638  	relfilenode OID,
   639  	reltablespace OID,
   640  	relpages INT4,
   641  	reltuples FLOAT4,
   642  	relallvisible INT4,
   643  	reltoastrelid OID,
   644  	relhasindex BOOL,
   645  	relisshared BOOL,
   646  	relpersistence CHAR,
   647  	relistemp BOOL,
   648  	relkind CHAR,
   649  	relnatts INT2,
   650  	relchecks INT2,
   651  	relhasoids BOOL,
   652  	relhaspkey BOOL,
   653  	relhasrules BOOL,
   654  	relhastriggers BOOL,
   655  	relhassubclass BOOL,
   656  	relfrozenxid INT,
   657  	relacl STRING[],
   658  	reloptions STRING[],
   659    INDEX (oid)
   660  )`,
   661  	virtualMany, true, /* includesIndexEntries */
   662  	func(ctx context.Context, p *planner, h oidHasher, db *DatabaseDescriptor, scName string,
   663  		table *sqlbase.TableDescriptor, _ simpleSchemaResolver, addRow func(...tree.Datum) error) error {
   664  		// The only difference between tables, views and sequences are the relkind and relam columns.
   665  		relKind := relKindTable
   666  		relAm := forwardIndexOid
   667  		if table.IsView() {
   668  			relKind = relKindView
   669  			relAm = oidZero
   670  		} else if table.IsSequence() {
   671  			relKind = relKindSequence
   672  			relAm = oidZero
   673  		}
   674  		namespaceOid := h.NamespaceOid(db, scName)
   675  		if err := addRow(
   676  			tableOid(table.ID),        // oid
   677  			tree.NewDName(table.Name), // relname
   678  			namespaceOid,              // relnamespace
   679  			oidZero,                   // reltype (PG creates a composite type in pg_type for each table)
   680  			oidZero,                   // reloftype (PG creates a composite type in pg_type for each table)
   681  			tree.DNull,                // relowner
   682  			relAm,                     // relam
   683  			oidZero,                   // relfilenode
   684  			oidZero,                   // reltablespace
   685  			tree.DNull,                // relpages
   686  			tree.DNull,                // reltuples
   687  			zeroVal,                   // relallvisible
   688  			oidZero,                   // reltoastrelid
   689  			tree.MakeDBool(tree.DBool(table.IsPhysicalTable())), // relhasindex
   690  			tree.DBoolFalse,         // relisshared
   691  			relPersistencePermanent, // relPersistence
   692  			tree.DBoolFalse,         // relistemp
   693  			relKind,                 // relkind
   694  			tree.NewDInt(tree.DInt(len(table.Columns))), // relnatts
   695  			tree.NewDInt(tree.DInt(len(table.Checks))),  // relchecks
   696  			tree.DBoolFalse, // relhasoids
   697  			tree.MakeDBool(tree.DBool(table.IsPhysicalTable())), // relhaspkey
   698  			tree.DBoolFalse, // relhasrules
   699  			tree.DBoolFalse, // relhastriggers
   700  			tree.DBoolFalse, // relhassubclass
   701  			zeroVal,         // relfrozenxid
   702  			tree.DNull,      // relacl
   703  			tree.DNull,      // reloptions
   704  		); err != nil {
   705  			return err
   706  		}
   707  
   708  		// Skip adding indexes for sequences (their table descriptors hav a primary
   709  		// index to make them comprehensible to backup/restore, but PG doesn't include
   710  		// an index in pg_class).
   711  		if table.IsSequence() {
   712  			return nil
   713  		}
   714  
   715  		// Indexes.
   716  		return forEachIndexInTable(table, func(index *sqlbase.IndexDescriptor) error {
   717  			indexType := forwardIndexOid
   718  			if index.Type == sqlbase.IndexDescriptor_INVERTED {
   719  				indexType = invertedIndexOid
   720  			}
   721  			return addRow(
   722  				h.IndexOid(table.ID, index.ID), // oid
   723  				tree.NewDName(index.Name),      // relname
   724  				namespaceOid,                   // relnamespace
   725  				oidZero,                        // reltype
   726  				oidZero,                        // reloftype
   727  				tree.DNull,                     // relowner
   728  				indexType,                      // relam
   729  				oidZero,                        // relfilenode
   730  				oidZero,                        // reltablespace
   731  				tree.DNull,                     // relpages
   732  				tree.DNull,                     // reltuples
   733  				zeroVal,                        // relallvisible
   734  				oidZero,                        // reltoastrelid
   735  				tree.DBoolFalse,                // relhasindex
   736  				tree.DBoolFalse,                // relisshared
   737  				relPersistencePermanent,        // relPersistence
   738  				tree.DBoolFalse,                // relistemp
   739  				relKindIndex,                   // relkind
   740  				tree.NewDInt(tree.DInt(len(index.ColumnNames))), // relnatts
   741  				zeroVal,         // relchecks
   742  				tree.DBoolFalse, // relhasoids
   743  				tree.DBoolFalse, // relhaspkey
   744  				tree.DBoolFalse, // relhasrules
   745  				tree.DBoolFalse, // relhastriggers
   746  				tree.DBoolFalse, // relhassubclass
   747  				zeroVal,         // relfrozenxid
   748  				tree.DNull,      // relacl
   749  				tree.DNull,      // reloptions
   750  			)
   751  		})
   752  	})
   753  
   754  var pgCatalogCollationTable = virtualSchemaTable{
   755  	comment: `available collations (incomplete)
   756  https://www.postgresql.org/docs/9.5/catalog-pg-collation.html`,
   757  	schema: `
   758  CREATE TABLE pg_catalog.pg_collation (
   759    oid OID,
   760    collname STRING,
   761    collnamespace OID,
   762    collowner OID,
   763    collencoding INT4,
   764    collcollate STRING,
   765    collctype STRING
   766  )`,
   767  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
   768  		h := makeOidHasher()
   769  		return forEachDatabaseDesc(ctx, p, dbContext, false /* requiresPrivileges */, func(db *DatabaseDescriptor) error {
   770  			namespaceOid := h.NamespaceOid(db, pgCatalogName)
   771  			for _, tag := range collate.Supported() {
   772  				collName := tag.String()
   773  				if err := addRow(
   774  					h.CollationOid(collName),  // oid
   775  					tree.NewDString(collName), // collname
   776  					namespaceOid,              // collnamespace
   777  					tree.DNull,                // collowner
   778  					builtins.DatEncodingUTFId, // collencoding
   779  					// It's not clear how to translate a Go collation tag into the format
   780  					// required by LC_COLLATE and LC_CTYPE.
   781  					tree.DNull, // collcollate
   782  					tree.DNull, // collctype
   783  				); err != nil {
   784  					return err
   785  				}
   786  			}
   787  			return nil
   788  		})
   789  	},
   790  }
   791  
   792  var (
   793  	conTypeCheck     = tree.NewDString("c")
   794  	conTypeFK        = tree.NewDString("f")
   795  	conTypePKey      = tree.NewDString("p")
   796  	conTypeUnique    = tree.NewDString("u")
   797  	conTypeTrigger   = tree.NewDString("t")
   798  	conTypeExclusion = tree.NewDString("x")
   799  
   800  	// Avoid unused warning for constants.
   801  	_ = conTypeTrigger
   802  	_ = conTypeExclusion
   803  
   804  	fkActionNone       = tree.NewDString("a")
   805  	fkActionRestrict   = tree.NewDString("r")
   806  	fkActionCascade    = tree.NewDString("c")
   807  	fkActionSetNull    = tree.NewDString("n")
   808  	fkActionSetDefault = tree.NewDString("d")
   809  
   810  	fkActionMap = map[sqlbase.ForeignKeyReference_Action]tree.Datum{
   811  		sqlbase.ForeignKeyReference_NO_ACTION:   fkActionNone,
   812  		sqlbase.ForeignKeyReference_RESTRICT:    fkActionRestrict,
   813  		sqlbase.ForeignKeyReference_CASCADE:     fkActionCascade,
   814  		sqlbase.ForeignKeyReference_SET_NULL:    fkActionSetNull,
   815  		sqlbase.ForeignKeyReference_SET_DEFAULT: fkActionSetDefault,
   816  	}
   817  
   818  	fkMatchTypeFull    = tree.NewDString("f")
   819  	fkMatchTypePartial = tree.NewDString("p")
   820  	fkMatchTypeSimple  = tree.NewDString("s")
   821  
   822  	fkMatchMap = map[sqlbase.ForeignKeyReference_Match]tree.Datum{
   823  		sqlbase.ForeignKeyReference_SIMPLE:  fkMatchTypeSimple,
   824  		sqlbase.ForeignKeyReference_FULL:    fkMatchTypeFull,
   825  		sqlbase.ForeignKeyReference_PARTIAL: fkMatchTypePartial,
   826  	}
   827  )
   828  
   829  func populateTableConstraints(
   830  	ctx context.Context,
   831  	p *planner,
   832  	h oidHasher,
   833  	db *sqlbase.DatabaseDescriptor,
   834  	scName string,
   835  	table *sqlbase.TableDescriptor,
   836  	tableLookup simpleSchemaResolver,
   837  	addRow func(...tree.Datum) error,
   838  ) error {
   839  	conInfo, err := table.GetConstraintInfoWithLookup(tableLookup.getTableByID)
   840  	if err != nil {
   841  		return err
   842  	}
   843  	namespaceOid := h.NamespaceOid(db, scName)
   844  	tblOid := tableOid(table.ID)
   845  	for conName, con := range conInfo {
   846  		oid := tree.DNull
   847  		contype := tree.DNull
   848  		conindid := oidZero
   849  		confrelid := oidZero
   850  		confupdtype := tree.DNull
   851  		confdeltype := tree.DNull
   852  		confmatchtype := tree.DNull
   853  		conkey := tree.DNull
   854  		confkey := tree.DNull
   855  		consrc := tree.DNull
   856  		conbin := tree.DNull
   857  		condef := tree.DNull
   858  
   859  		// Determine constraint kind-specific fields.
   860  		var err error
   861  		switch con.Kind {
   862  		case sqlbase.ConstraintTypePK:
   863  			oid = h.PrimaryKeyConstraintOid(db, scName, table, con.Index)
   864  			contype = conTypePKey
   865  			conindid = h.IndexOid(table.ID, con.Index.ID)
   866  
   867  			var err error
   868  			if conkey, err = colIDArrayToDatum(con.Index.ColumnIDs); err != nil {
   869  				return err
   870  			}
   871  			condef = tree.NewDString(table.PrimaryKeyString())
   872  
   873  		case sqlbase.ConstraintTypeFK:
   874  			oid = h.ForeignKeyConstraintOid(db, scName, table, con.FK)
   875  			contype = conTypeFK
   876  			// Foreign keys don't have a single linked index. Pick the first one
   877  			// that matches on the referenced table.
   878  			referencedTable, err := tableLookup.getTableByID(con.FK.ReferencedTableID)
   879  			if err != nil {
   880  				return err
   881  			}
   882  			if idx, err := sqlbase.FindFKReferencedIndex(referencedTable, con.FK.ReferencedColumnIDs); err != nil {
   883  				// We couldn't find an index that matched. This shouldn't happen.
   884  				log.Warningf(ctx, "broken fk reference: %v", err)
   885  			} else {
   886  				conindid = h.IndexOid(con.ReferencedTable.ID, idx.ID)
   887  			}
   888  			confrelid = tableOid(con.ReferencedTable.ID)
   889  			if r, ok := fkActionMap[con.FK.OnUpdate]; ok {
   890  				confupdtype = r
   891  			}
   892  			if r, ok := fkActionMap[con.FK.OnDelete]; ok {
   893  				confdeltype = r
   894  			}
   895  			if r, ok := fkMatchMap[con.FK.Match]; ok {
   896  				confmatchtype = r
   897  			}
   898  			if conkey, err = colIDArrayToDatum(con.FK.OriginColumnIDs); err != nil {
   899  				return err
   900  			}
   901  			if confkey, err = colIDArrayToDatum(con.FK.ReferencedColumnIDs); err != nil {
   902  				return err
   903  			}
   904  			var buf bytes.Buffer
   905  			if err := showForeignKeyConstraint(&buf, db.Name, table, con.FK, tableLookup); err != nil {
   906  				return err
   907  			}
   908  			condef = tree.NewDString(buf.String())
   909  
   910  		case sqlbase.ConstraintTypeUnique:
   911  			oid = h.UniqueConstraintOid(db, scName, table, con.Index)
   912  			contype = conTypeUnique
   913  			conindid = h.IndexOid(table.ID, con.Index.ID)
   914  			var err error
   915  			if conkey, err = colIDArrayToDatum(con.Index.ColumnIDs); err != nil {
   916  				return err
   917  			}
   918  			f := tree.NewFmtCtx(tree.FmtSimple)
   919  			f.WriteString("UNIQUE (")
   920  			con.Index.ColNamesFormat(f)
   921  			f.WriteByte(')')
   922  			condef = tree.NewDString(f.CloseAndGetString())
   923  
   924  		case sqlbase.ConstraintTypeCheck:
   925  			oid = h.CheckConstraintOid(db, scName, table, con.CheckConstraint)
   926  			contype = conTypeCheck
   927  			if conkey, err = colIDArrayToDatum(con.CheckConstraint.ColumnIDs); err != nil {
   928  				return err
   929  			}
   930  			consrc = tree.NewDString(fmt.Sprintf("(%s)", con.Details))
   931  			conbin = consrc
   932  			condef = tree.NewDString(fmt.Sprintf("CHECK ((%s))", con.Details))
   933  		}
   934  
   935  		if err := addRow(
   936  			oid,                  // oid
   937  			dNameOrNull(conName), // conname
   938  			namespaceOid,         // connamespace
   939  			contype,              // contype
   940  			tree.DBoolFalse,      // condeferrable
   941  			tree.DBoolFalse,      // condeferred
   942  			tree.MakeDBool(tree.DBool(!con.Unvalidated)), // convalidated
   943  			tblOid,         // conrelid
   944  			oidZero,        // contypid
   945  			conindid,       // conindid
   946  			confrelid,      // confrelid
   947  			confupdtype,    // confupdtype
   948  			confdeltype,    // confdeltype
   949  			confmatchtype,  // confmatchtype
   950  			tree.DBoolTrue, // conislocal
   951  			zeroVal,        // coninhcount
   952  			tree.DBoolTrue, // connoinherit
   953  			conkey,         // conkey
   954  			confkey,        // confkey
   955  			tree.DNull,     // conpfeqop
   956  			tree.DNull,     // conppeqop
   957  			tree.DNull,     // conffeqop
   958  			tree.DNull,     // conexclop
   959  			conbin,         // conbin
   960  			consrc,         // consrc
   961  			condef,         // condef
   962  		); err != nil {
   963  			return err
   964  		}
   965  	}
   966  	return nil
   967  }
   968  
   969  type oneAtATimeSchemaResolver struct {
   970  	ctx context.Context
   971  	p   *planner
   972  }
   973  
   974  func (r oneAtATimeSchemaResolver) getDatabaseByID(id sqlbase.ID) (*DatabaseDescriptor, error) {
   975  	return r.p.Tables().DatabaseCache().GetDatabaseDescByID(r.ctx, r.p.txn, id)
   976  }
   977  
   978  func (r oneAtATimeSchemaResolver) getTableByID(id sqlbase.ID) (*TableDescriptor, error) {
   979  	table, err := r.p.LookupTableByID(r.ctx, id)
   980  	if err != nil {
   981  		return nil, err
   982  	}
   983  	return table.Desc.TableDesc(), nil
   984  }
   985  
   986  // makeAllRelationsVirtualTableWithDescriptorIDIndex creates a virtual table that searches through
   987  // all table descriptors in the system. It automatically adds a virtual index implementation to the
   988  // table id column as well. The input schema must have a single INDEX definition
   989  // with a single column, which must be the column that contains the table id.
   990  // includesIndexEntries should be set to true if the indexed column produces
   991  // index ids as well as just ordinary table descriptor ids. In this case, the
   992  // caller must pass true for this variable to prevent failed lookups.
   993  func makeAllRelationsVirtualTableWithDescriptorIDIndex(
   994  	comment string,
   995  	schemaDef string,
   996  	virtualOpts virtualOpts,
   997  	includesIndexEntries bool,
   998  	populateFromTable func(ctx context.Context, p *planner, h oidHasher, db *sqlbase.DatabaseDescriptor,
   999  		scName string, table *sqlbase.TableDescriptor, lookup simpleSchemaResolver,
  1000  		addRow func(...tree.Datum) error,
  1001  	) error,
  1002  ) virtualSchemaTable {
  1003  	populateAll := func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1004  		h := makeOidHasher()
  1005  		return forEachTableDescWithTableLookup(ctx, p, dbContext, virtualOpts,
  1006  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor, lookup tableLookupFn) error {
  1007  				return populateFromTable(ctx, p, h, db, scName, table, lookup, addRow)
  1008  			})
  1009  	}
  1010  	return virtualSchemaTable{
  1011  		comment: comment,
  1012  		schema:  schemaDef,
  1013  		indexes: []virtualIndex{
  1014  			{
  1015  				partial: includesIndexEntries,
  1016  				populate: func(ctx context.Context, constraint tree.Datum, p *planner, db *DatabaseDescriptor,
  1017  					addRow func(...tree.Datum) error) (bool, error) {
  1018  					var id sqlbase.ID
  1019  					d := tree.UnwrapDatum(p.EvalContext(), constraint)
  1020  					if d == tree.DNull {
  1021  						return false, nil
  1022  					}
  1023  					switch t := d.(type) {
  1024  					case *tree.DOid:
  1025  						id = sqlbase.ID(t.DInt)
  1026  					case *tree.DInt:
  1027  						id = sqlbase.ID(*t)
  1028  					default:
  1029  						return false, errors.AssertionFailedf("unexpected type %T for table id column in virtual table %s",
  1030  							d, schemaDef)
  1031  					}
  1032  					table, err := p.LookupTableByID(ctx, id)
  1033  					if err != nil {
  1034  						if sqlbase.IsUndefinedRelationError(err) {
  1035  							// No table found, so no rows. In this case, we'll fall back to the
  1036  							// full table scan if the index isn't complete - see the
  1037  							// indexContainsNonTableDescriptorIDs parameter.
  1038  							//nolint:returnerrcheck
  1039  							return false, nil
  1040  						}
  1041  						return false, err
  1042  					}
  1043  					// Don't include tables that aren't in the current database unless
  1044  					// they're virtual, dropped tables, or ones that the user can't see.
  1045  					if (!table.Desc.IsVirtualTable() && table.Desc.ParentID != db.ID) ||
  1046  						table.Desc.Dropped() ||
  1047  						!userCanSeeTable(ctx, p, table.Desc.TableDesc(), true /*allowAdding*/) {
  1048  						return false, nil
  1049  					}
  1050  					h := makeOidHasher()
  1051  					scResolver := oneAtATimeSchemaResolver{p: p, ctx: ctx}
  1052  					scName, err := resolver.ResolveSchemaNameByID(ctx, p.txn, p.ExecCfg().Codec, db.ID, table.Desc.GetParentSchemaID())
  1053  					if err != nil {
  1054  						return false, err
  1055  					}
  1056  					if err := populateFromTable(ctx, p, h, db, scName, table.Desc.TableDesc(), scResolver,
  1057  						addRow); err != nil {
  1058  						return false, err
  1059  					}
  1060  					return true, nil
  1061  				},
  1062  			},
  1063  		},
  1064  		populate: populateAll,
  1065  	}
  1066  }
  1067  
  1068  var pgCatalogConstraintTable = makeAllRelationsVirtualTableWithDescriptorIDIndex(
  1069  	`table constraints (incomplete - see also information_schema.table_constraints)
  1070  https://www.postgresql.org/docs/9.5/catalog-pg-constraint.html`,
  1071  	`
  1072  CREATE TABLE pg_catalog.pg_constraint (
  1073  	oid OID,
  1074  	conname NAME,
  1075  	connamespace OID,
  1076  	contype STRING,
  1077  	condeferrable BOOL,
  1078  	condeferred BOOL,
  1079  	convalidated BOOL,
  1080  	conrelid OID NOT NULL,
  1081  	contypid OID,
  1082  	conindid OID,
  1083  	confrelid OID,
  1084  	confupdtype STRING,
  1085  	confdeltype STRING,
  1086  	confmatchtype STRING,
  1087  	conislocal BOOL,
  1088  	coninhcount INT4,
  1089  	connoinherit BOOL,
  1090  	conkey INT2[],
  1091  	confkey INT2[],
  1092  	conpfeqop OID[],
  1093  	conppeqop OID[],
  1094  	conffeqop OID[],
  1095  	conexclop OID[],
  1096  	conbin STRING,
  1097  	consrc STRING,
  1098  	-- condef is a CockroachDB extension that provides a SHOW CREATE CONSTRAINT
  1099  	-- style string, for use by pg_get_constraintdef().
  1100  	condef STRING,
  1101    INDEX (conrelid)
  1102  )`,
  1103  	hideVirtual, /* Virtual tables have no constraints */
  1104  	false,       /* includesIndexEntries */
  1105  	populateTableConstraints)
  1106  
  1107  // colIDArrayToDatum returns an int[] containing the ColumnIDs, or NULL if there
  1108  // are no ColumnIDs.
  1109  func colIDArrayToDatum(arr []sqlbase.ColumnID) (tree.Datum, error) {
  1110  	if len(arr) == 0 {
  1111  		return tree.DNull, nil
  1112  	}
  1113  	d := tree.NewDArray(types.Int)
  1114  	for _, val := range arr {
  1115  		if err := d.Append(tree.NewDInt(tree.DInt(val))); err != nil {
  1116  			return nil, err
  1117  		}
  1118  	}
  1119  	return d, nil
  1120  }
  1121  
  1122  // colIDArrayToVector returns an INT2VECTOR containing the ColumnIDs, or NULL if
  1123  // there are no ColumnIDs.
  1124  func colIDArrayToVector(arr []sqlbase.ColumnID) (tree.Datum, error) {
  1125  	dArr, err := colIDArrayToDatum(arr)
  1126  	if err != nil {
  1127  		return nil, err
  1128  	}
  1129  	if dArr == tree.DNull {
  1130  		return dArr, nil
  1131  	}
  1132  	return tree.NewDIntVectorFromDArray(tree.MustBeDArray(dArr)), nil
  1133  }
  1134  
  1135  var pgCatalogConversionTable = virtualSchemaTable{
  1136  	comment: `encoding conversions (empty - unimplemented)
  1137  https://www.postgresql.org/docs/9.6/catalog-pg-conversion.html`,
  1138  	schema: `
  1139  CREATE TABLE pg_catalog.pg_conversion (
  1140  	oid OID,
  1141  	conname NAME,
  1142  	connamespace OID,
  1143  	conowner OID,
  1144  	conforencoding INT4,
  1145  	contoencoding INT4,
  1146  	conproc OID,
  1147    condefault BOOL
  1148  )`,
  1149  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1150  		return nil
  1151  	},
  1152  }
  1153  
  1154  var pgCatalogDatabaseTable = virtualSchemaTable{
  1155  	comment: `available databases (incomplete)
  1156  https://www.postgresql.org/docs/9.5/catalog-pg-database.html`,
  1157  	schema: `
  1158  CREATE TABLE pg_catalog.pg_database (
  1159  	oid OID,
  1160  	datname Name,
  1161  	datdba OID,
  1162  	encoding INT4,
  1163  	datcollate STRING,
  1164  	datctype STRING,
  1165  	datistemplate BOOL,
  1166  	datallowconn BOOL,
  1167  	datconnlimit INT4,
  1168  	datlastsysoid OID,
  1169  	datfrozenxid INT,
  1170  	datminmxid INT,
  1171  	dattablespace OID,
  1172  	datacl STRING[]
  1173  )`,
  1174  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1175  		return forEachDatabaseDesc(ctx, p, nil /*all databases*/, false, /* requiresPrivileges */
  1176  			func(db *sqlbase.DatabaseDescriptor) error {
  1177  				return addRow(
  1178  					dbOid(db.ID),           // oid
  1179  					tree.NewDName(db.Name), // datname
  1180  					tree.DNull,             // datdba
  1181  					// If there is a change in encoding value for the database we must update
  1182  					// the definitions of getdatabaseencoding within pg_builtin.
  1183  					builtins.DatEncodingUTFId,  // encoding
  1184  					builtins.DatEncodingEnUTF8, // datcollate
  1185  					builtins.DatEncodingEnUTF8, // datctype
  1186  					tree.DBoolFalse,            // datistemplate
  1187  					tree.DBoolTrue,             // datallowconn
  1188  					negOneVal,                  // datconnlimit
  1189  					oidZero,                    // datlastsysoid
  1190  					tree.DNull,                 // datfrozenxid
  1191  					tree.DNull,                 // datminmxid
  1192  					oidZero,                    // dattablespace
  1193  					tree.DNull,                 // datacl
  1194  				)
  1195  			})
  1196  	},
  1197  }
  1198  
  1199  var pgCatalogDefaultACLTable = virtualSchemaTable{
  1200  	comment: `default ACLs (empty - unimplemented)
  1201  https://www.postgresql.org/docs/9.6/catalog-pg-default-acl.html`,
  1202  	schema: `
  1203  CREATE TABLE pg_catalog.pg_default_acl (
  1204  	oid OID,
  1205  	defaclrole OID,
  1206  	defaclnamespace OID,
  1207  	defaclobjtype CHAR,
  1208  	defaclacl STRING[]
  1209  )`,
  1210  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1211  		return nil
  1212  	},
  1213  }
  1214  
  1215  var (
  1216  	depTypeNormal        = tree.NewDString("n")
  1217  	depTypeAuto          = tree.NewDString("a")
  1218  	depTypeInternal      = tree.NewDString("i")
  1219  	depTypeExtension     = tree.NewDString("e")
  1220  	depTypeAutoExtension = tree.NewDString("x")
  1221  	depTypePin           = tree.NewDString("p")
  1222  
  1223  	// Avoid unused warning for constants.
  1224  	_ = depTypeAuto
  1225  	_ = depTypeInternal
  1226  	_ = depTypeExtension
  1227  	_ = depTypeAutoExtension
  1228  	_ = depTypePin
  1229  
  1230  	pgConstraintsTableName = tree.MakeTableNameWithSchema("", tree.Name(pgCatalogName), tree.Name("pg_constraint"))
  1231  	pgClassTableName       = tree.MakeTableNameWithSchema("", tree.Name(pgCatalogName), tree.Name("pg_class"))
  1232  )
  1233  
  1234  // pg_depend is a fairly complex table that details many different kinds of
  1235  // relationships between database objects. We do not implement the vast
  1236  // majority of this table, as it is mainly used by pgjdbc to address a
  1237  // deficiency in pg_constraint that was removed in postgres v9.0 with the
  1238  // addition of the conindid column. To provide backward compatibility with
  1239  // pgjdbc drivers before https://github.com/pgjdbc/pgjdbc/pull/689, we
  1240  // provide those rows in pg_depend that track the dependency of foreign key
  1241  // constraints on their supporting index entries in pg_class.
  1242  var pgCatalogDependTable = virtualSchemaTable{
  1243  	comment: `dependency relationships (incomplete)
  1244  https://www.postgresql.org/docs/9.5/catalog-pg-depend.html`,
  1245  	schema: `
  1246  CREATE TABLE pg_catalog.pg_depend (
  1247    classid OID,
  1248    objid OID,
  1249    objsubid INT4,
  1250    refclassid OID,
  1251    refobjid OID,
  1252    refobjsubid INT4,
  1253    deptype CHAR
  1254  )`,
  1255  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1256  		vt := p.getVirtualTabler()
  1257  		pgConstraintsDesc, err := vt.getVirtualTableDesc(&pgConstraintsTableName)
  1258  		if err != nil {
  1259  			return errors.New("could not find pg_catalog.pg_constraint")
  1260  		}
  1261  		pgClassDesc, err := vt.getVirtualTableDesc(&pgClassTableName)
  1262  		if err != nil {
  1263  			return errors.New("could not find pg_catalog.pg_class")
  1264  		}
  1265  		h := makeOidHasher()
  1266  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual /*virtual tables have no constraints*/, func(
  1267  			db *sqlbase.DatabaseDescriptor,
  1268  			scName string,
  1269  			table *sqlbase.TableDescriptor,
  1270  			tableLookup tableLookupFn,
  1271  		) error {
  1272  			pgConstraintTableOid := tableOid(pgConstraintsDesc.ID)
  1273  			pgClassTableOid := tableOid(pgClassDesc.ID)
  1274  			if table.IsSequence() &&
  1275  				!table.SequenceOpts.SequenceOwner.Equal(sqlbase.TableDescriptor_SequenceOpts_SequenceOwner{}) {
  1276  				refObjID := tableOid(table.SequenceOpts.SequenceOwner.OwnerTableID)
  1277  				refObjSubID := tree.NewDInt(tree.DInt(table.SequenceOpts.SequenceOwner.OwnerColumnID))
  1278  				objID := tableOid(table.GetID())
  1279  				return addRow(
  1280  					pgConstraintTableOid, // classid
  1281  					objID,                // objid
  1282  					zeroVal,              // objsubid
  1283  					pgClassTableOid,      // refclassid
  1284  					refObjID,             // refobjid
  1285  					refObjSubID,          // refobjsubid
  1286  					depTypeAuto,          // deptype
  1287  				)
  1288  			}
  1289  			conInfo, err := table.GetConstraintInfoWithLookup(tableLookup.getTableByID)
  1290  			if err != nil {
  1291  				return err
  1292  			}
  1293  			for _, con := range conInfo {
  1294  				if con.Kind != sqlbase.ConstraintTypeFK {
  1295  					continue
  1296  				}
  1297  
  1298  				// Foreign keys don't have a single linked index. Pick the first one
  1299  				// that matches on the referenced table.
  1300  				referencedTable, err := tableLookup.getTableByID(con.FK.ReferencedTableID)
  1301  				if err != nil {
  1302  					return err
  1303  				}
  1304  				refObjID := oidZero
  1305  				if idx, err := sqlbase.FindFKReferencedIndex(referencedTable, con.FK.ReferencedColumnIDs); err != nil {
  1306  					// We couldn't find an index that matched. This shouldn't happen.
  1307  					log.Warningf(ctx, "broken fk reference: %v", err)
  1308  				} else {
  1309  					refObjID = h.IndexOid(con.ReferencedTable.ID, idx.ID)
  1310  				}
  1311  				constraintOid := h.ForeignKeyConstraintOid(db, scName, table, con.FK)
  1312  
  1313  				if err := addRow(
  1314  					pgConstraintTableOid, // classid
  1315  					constraintOid,        // objid
  1316  					zeroVal,              // objsubid
  1317  					pgClassTableOid,      // refclassid
  1318  					refObjID,             // refobjid
  1319  					zeroVal,              // refobjsubid
  1320  					depTypeNormal,        // deptype
  1321  				); err != nil {
  1322  					return err
  1323  				}
  1324  			}
  1325  			return nil
  1326  		})
  1327  	},
  1328  }
  1329  
  1330  // getComments returns all comments in the database. A comment is represented
  1331  // as a datum row, containing object id, sub id (column id in the case of
  1332  // columns), comment text, and comment type (keys.FooCommentType).
  1333  func getComments(ctx context.Context, p *planner) ([]tree.Datums, error) {
  1334  	return p.extendedEvalCtx.ExecCfg.InternalExecutor.Query(
  1335  		ctx,
  1336  		"select-comments",
  1337  		p.EvalContext().Txn,
  1338  		`SELECT COALESCE(pc.object_id, sc.object_id) AS object_id,
  1339                COALESCE(pc.sub_id, sc.sub_id) AS sub_id,
  1340                COALESCE(pc.comment, sc.comment) AS comment,
  1341                COALESCE(pc.type, sc.type) AS type
  1342           FROM (SELECT * FROM system.comments) AS sc
  1343      FULL JOIN (SELECT * FROM crdb_internal.predefined_comments) AS pc
  1344             ON (pc.object_id = sc.object_id AND pc.sub_id = sc.sub_id AND pc.type = sc.type)`)
  1345  }
  1346  
  1347  var pgCatalogDescriptionTable = virtualSchemaTable{
  1348  	comment: `object comments
  1349  https://www.postgresql.org/docs/9.5/catalog-pg-description.html`,
  1350  	schema: `
  1351  CREATE TABLE pg_catalog.pg_description (
  1352  	objoid OID,
  1353  	classoid OID,
  1354  	objsubid INT4,
  1355  	description STRING
  1356  )`,
  1357  	populate: func(
  1358  		ctx context.Context,
  1359  		p *planner,
  1360  		dbContext *DatabaseDescriptor,
  1361  		addRow func(...tree.Datum) error) error {
  1362  
  1363  		// This is less efficient than it has to be - if we see performance problems
  1364  		// here, we can push the filter into the query that getComments runs,
  1365  		// instead of filtering client-side below.
  1366  		comments, err := getComments(ctx, p)
  1367  		if err != nil {
  1368  			return err
  1369  		}
  1370  		for _, comment := range comments {
  1371  			objID := comment[0]
  1372  			objSubID := comment[1]
  1373  			description := comment[2]
  1374  			commentType := tree.MustBeDInt(comment[3])
  1375  
  1376  			classOid := oidZero
  1377  
  1378  			switch commentType {
  1379  			case keys.DatabaseCommentType:
  1380  				// Database comments are exported in pg_shdescription.
  1381  				continue
  1382  			case keys.ColumnCommentType, keys.TableCommentType:
  1383  				objID = tree.NewDOid(tree.MustBeDInt(objID))
  1384  				classOid = tree.NewDOid(sqlbase.PgCatalogClassTableID)
  1385  			case keys.IndexCommentType:
  1386  				objID = makeOidHasher().IndexOid(
  1387  					sqlbase.ID(tree.MustBeDInt(objID)),
  1388  					sqlbase.IndexID(tree.MustBeDInt(objSubID)))
  1389  				objSubID = tree.DZero
  1390  				classOid = tree.NewDOid(sqlbase.PgCatalogClassTableID)
  1391  			}
  1392  			if err := addRow(
  1393  				objID,
  1394  				classOid,
  1395  				objSubID,
  1396  				description); err != nil {
  1397  				return err
  1398  			}
  1399  		}
  1400  		return nil
  1401  	},
  1402  }
  1403  
  1404  var pgCatalogSharedDescriptionTable = virtualSchemaTable{
  1405  	comment: `shared object comments
  1406  https://www.postgresql.org/docs/9.5/catalog-pg-shdescription.html`,
  1407  	schema: `
  1408  CREATE TABLE pg_catalog.pg_shdescription (
  1409  	objoid OID,
  1410  	classoid OID,
  1411  	description STRING
  1412  )`,
  1413  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1414  		// See comment above - could make this more efficient if necessary.
  1415  		comments, err := getComments(ctx, p)
  1416  		if err != nil {
  1417  			return err
  1418  		}
  1419  		for _, comment := range comments {
  1420  			commentType := tree.MustBeDInt(comment[3])
  1421  			if commentType != keys.DatabaseCommentType {
  1422  				// Only database comments are exported in this table.
  1423  				continue
  1424  			}
  1425  			classOid := tree.NewDOid(sqlbase.PgCatalogDatabaseTableID)
  1426  			objID := sqlbase.ID(tree.MustBeDInt(comment[0]))
  1427  			if err := addRow(
  1428  				tableOid(objID),
  1429  				classOid,
  1430  				comment[2]); err != nil {
  1431  				return err
  1432  			}
  1433  		}
  1434  		return nil
  1435  	},
  1436  }
  1437  
  1438  var pgCatalogEnumTable = virtualSchemaTable{
  1439  	comment: `enum types and labels (empty - feature does not exist)
  1440  https://www.postgresql.org/docs/9.5/catalog-pg-enum.html`,
  1441  	schema: `
  1442  CREATE TABLE pg_catalog.pg_enum (
  1443    oid OID,
  1444    enumtypid OID,
  1445    enumsortorder FLOAT4,
  1446    enumlabel STRING
  1447  )`,
  1448  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1449  		h := makeOidHasher()
  1450  		return forEachTypeDesc(ctx, p, dbContext, func(_ *DatabaseDescriptor, _ string, typDesc *TypeDescriptor) error {
  1451  			// We only want to iterate over ENUM types.
  1452  			if typDesc.Kind != sqlbase.TypeDescriptor_ENUM {
  1453  				return nil
  1454  			}
  1455  			// Generate a row for each member of the enum. We don't represent enums
  1456  			// internally using floats for ordering like Postgres, so just pick a
  1457  			// float entry for the rows.
  1458  			typOID := tree.NewDOid(tree.DInt(types.StableTypeIDToOID(uint32(typDesc.ID))))
  1459  			for i, member := range typDesc.EnumMembers {
  1460  				if err := addRow(
  1461  					h.EnumEntryOid(typOID, member.PhysicalRepresentation),
  1462  					typOID,
  1463  					tree.NewDFloat(tree.DFloat(float64(i))),
  1464  					tree.NewDString(member.LogicalRepresentation),
  1465  				); err != nil {
  1466  					return err
  1467  				}
  1468  			}
  1469  			return nil
  1470  		})
  1471  	},
  1472  }
  1473  
  1474  var pgCatalogEventTriggerTable = virtualSchemaTable{
  1475  	comment: `event triggers (empty - feature does not exist)
  1476  https://www.postgresql.org/docs/9.6/catalog-pg-event-trigger.html`,
  1477  	schema: `
  1478  CREATE TABLE pg_catalog.pg_event_trigger (
  1479  	evtname NAME,
  1480  	evtevent NAME,
  1481  	evtowner OID,
  1482  	evtfoid OID,
  1483  	evtenabled CHAR,
  1484  	evttags TEXT[]
  1485  )`,
  1486  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1487  		// Event triggers are not currently supported.
  1488  		return nil
  1489  	},
  1490  }
  1491  
  1492  var pgCatalogExtensionTable = virtualSchemaTable{
  1493  	comment: `installed extensions (empty - feature does not exist)
  1494  https://www.postgresql.org/docs/9.5/catalog-pg-extension.html`,
  1495  	schema: `
  1496  CREATE TABLE pg_catalog.pg_extension (
  1497    oid OID,
  1498    extname NAME,
  1499    extowner OID,
  1500    extnamespace OID,
  1501    extrelocatable BOOL,
  1502    extversion STRING,
  1503    extconfig STRING,
  1504    extcondition STRING
  1505  )`,
  1506  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1507  		// Extensions are not supported.
  1508  		return nil
  1509  	},
  1510  }
  1511  
  1512  var pgCatalogForeignDataWrapperTable = virtualSchemaTable{
  1513  	comment: `foreign data wrappers (empty - feature does not exist)
  1514  https://www.postgresql.org/docs/9.5/catalog-pg-foreign-data-wrapper.html`,
  1515  	schema: `
  1516  CREATE TABLE pg_catalog.pg_foreign_data_wrapper (
  1517    oid OID,
  1518    fdwname NAME,
  1519    fdwowner OID,
  1520    fdwhandler OID,
  1521    fdwvalidator OID,
  1522    fdwacl STRING[],
  1523    fdwoptions STRING[]
  1524  )`,
  1525  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1526  		// Foreign data wrappers are not supported.
  1527  		return nil
  1528  	},
  1529  }
  1530  
  1531  var pgCatalogForeignServerTable = virtualSchemaTable{
  1532  	comment: `foreign servers (empty - feature does not exist)
  1533  https://www.postgresql.org/docs/9.5/catalog-pg-foreign-server.html`,
  1534  	schema: `
  1535  CREATE TABLE pg_catalog.pg_foreign_server (
  1536    oid OID,
  1537    srvname NAME,
  1538    srvowner OID,
  1539    srvfdw OID,
  1540    srvtype STRING,
  1541    srvversion STRING,
  1542    srvacl STRING[],
  1543    srvoptions STRING[]
  1544  )`,
  1545  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1546  		// Foreign servers are not supported.
  1547  		return nil
  1548  	},
  1549  }
  1550  
  1551  var pgCatalogForeignTableTable = virtualSchemaTable{
  1552  	comment: `foreign tables (empty  - feature does not exist)
  1553  https://www.postgresql.org/docs/9.5/catalog-pg-foreign-table.html`,
  1554  	schema: `
  1555  CREATE TABLE pg_catalog.pg_foreign_table (
  1556    ftrelid OID,
  1557    ftserver OID,
  1558    ftoptions STRING[]
  1559  )`,
  1560  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1561  		// Foreign tables are not supported.
  1562  		return nil
  1563  	},
  1564  }
  1565  
  1566  func makeZeroedOidVector(size int) (tree.Datum, error) {
  1567  	oidArray := tree.NewDArray(types.Oid)
  1568  	for i := 0; i < size; i++ {
  1569  		if err := oidArray.Append(oidZero); err != nil {
  1570  			return nil, err
  1571  		}
  1572  	}
  1573  	return tree.NewDOidVectorFromDArray(oidArray), nil
  1574  }
  1575  
  1576  var pgCatalogIndexTable = virtualSchemaTable{
  1577  	comment: `indexes (incomplete)
  1578  https://www.postgresql.org/docs/9.5/catalog-pg-index.html`,
  1579  	schema: `
  1580  CREATE TABLE pg_catalog.pg_index (
  1581      indexrelid OID,
  1582      indrelid OID,
  1583      indnatts INT2,
  1584      indisunique BOOL,
  1585      indisprimary BOOL,
  1586      indisexclusion BOOL,
  1587      indimmediate BOOL,
  1588      indisclustered BOOL,
  1589      indisvalid BOOL,
  1590      indcheckxmin BOOL,
  1591      indisready BOOL,
  1592      indislive BOOL,
  1593      indisreplident BOOL,
  1594      indkey INT2VECTOR,
  1595      indcollation OIDVECTOR,
  1596      indclass OIDVECTOR,
  1597      indoption INT2VECTOR,
  1598      indexprs STRING,
  1599      indpred STRING
  1600  )`,
  1601  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1602  		h := makeOidHasher()
  1603  		return forEachTableDesc(ctx, p, dbContext, hideVirtual, /* virtual tables do not have indexes */
  1604  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  1605  				tableOid := tableOid(table.ID)
  1606  				return forEachIndexInTable(table, func(index *sqlbase.IndexDescriptor) error {
  1607  					isMutation, isWriteOnly :=
  1608  						table.GetIndexMutationCapabilities(index.ID)
  1609  					isReady := isMutation && isWriteOnly
  1610  					indkey, err := colIDArrayToVector(index.ColumnIDs)
  1611  					if err != nil {
  1612  						return err
  1613  					}
  1614  					// Get the collations for all of the columns. To do this we require
  1615  					// the type of the column.
  1616  					// Also fill in indoption for each column to indicate if the index
  1617  					// is ASC/DESC and if nulls appear first/last.
  1618  					collationOids := tree.NewDArray(types.Oid)
  1619  					indoption := tree.NewDArray(types.Int)
  1620  					for i, columnID := range index.ColumnIDs {
  1621  						col, err := table.FindColumnByID(columnID)
  1622  						if err != nil {
  1623  							return err
  1624  						}
  1625  						if err := collationOids.Append(typColl(col.Type, h)); err != nil {
  1626  							return err
  1627  						}
  1628  						// Currently, nulls always appear first if the order is ascending,
  1629  						// and always appear last if the order is descending.
  1630  						var thisIndOption tree.DInt
  1631  						if index.ColumnDirections[i] == sqlbase.IndexDescriptor_ASC {
  1632  							thisIndOption = indoptionNullsFirst
  1633  						} else {
  1634  							thisIndOption = indoptionDesc
  1635  						}
  1636  						if err := indoption.Append(tree.NewDInt(thisIndOption)); err != nil {
  1637  							return err
  1638  						}
  1639  					}
  1640  					collationOidVector := tree.NewDOidVectorFromDArray(collationOids)
  1641  					indoptionIntVector := tree.NewDIntVectorFromDArray(indoption)
  1642  					// TODO(bram): #27763 indclass still needs to be populated but it
  1643  					// requires pg_catalog.pg_opclass first.
  1644  					indclass, err := makeZeroedOidVector(len(index.ColumnIDs))
  1645  					isPrimary := table.PrimaryIndex.ID == index.ID && table.IsPhysicalTable()
  1646  					if err != nil {
  1647  						return err
  1648  					}
  1649  					return addRow(
  1650  						h.IndexOid(table.ID, index.ID), // indexrelid
  1651  						tableOid,                       // indrelid
  1652  						tree.NewDInt(tree.DInt(len(index.ColumnNames))), // indnatts
  1653  						tree.MakeDBool(tree.DBool(index.Unique)),        // indisunique
  1654  						tree.MakeDBool(tree.DBool(isPrimary)),           // indisprimary
  1655  						tree.DBoolFalse,                                 // indisexclusion
  1656  						tree.MakeDBool(tree.DBool(index.Unique)),        // indimmediate
  1657  						tree.DBoolFalse,                                 // indisclustered
  1658  						tree.MakeDBool(tree.DBool(!isMutation)),         // indisvalid
  1659  						tree.DBoolFalse,                                 // indcheckxmin
  1660  						tree.MakeDBool(tree.DBool(isReady)),             // indisready
  1661  						tree.DBoolTrue,                                  // indislive
  1662  						tree.DBoolFalse,                                 // indisreplident
  1663  						indkey,                                          // indkey
  1664  						collationOidVector,                              // indcollation
  1665  						indclass,                                        // indclass
  1666  						indoptionIntVector,                              // indoption
  1667  						tree.DNull,                                      // indexprs
  1668  						tree.DNull,                                      // indpred
  1669  					)
  1670  				})
  1671  			})
  1672  	},
  1673  }
  1674  
  1675  var pgCatalogIndexesTable = virtualSchemaTable{
  1676  	comment: `index creation statements
  1677  https://www.postgresql.org/docs/9.5/view-pg-indexes.html`,
  1678  	// Note: crdb_oid is an extension of the schema to much more easily map
  1679  	// index OIDs to the corresponding index definition.
  1680  	schema: `
  1681  CREATE TABLE pg_catalog.pg_indexes (
  1682  	crdb_oid OID,
  1683  	schemaname NAME,
  1684  	tablename NAME,
  1685  	indexname NAME,
  1686  	tablespace NAME,
  1687  	indexdef STRING
  1688  )`,
  1689  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1690  		h := makeOidHasher()
  1691  		return forEachTableDescWithTableLookup(ctx, p, dbContext, hideVirtual, /* virtual tables do not have indexes */
  1692  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor, tableLookup tableLookupFn) error {
  1693  				scNameName := tree.NewDName(scName)
  1694  				tblName := tree.NewDName(table.Name)
  1695  				return forEachIndexInTable(table, func(index *sqlbase.IndexDescriptor) error {
  1696  					def, err := indexDefFromDescriptor(ctx, p, db, table, index, tableLookup)
  1697  					if err != nil {
  1698  						return err
  1699  					}
  1700  					return addRow(
  1701  						h.IndexOid(table.ID, index.ID), // oid
  1702  						scNameName,                     // schemaname
  1703  						tblName,                        // tablename
  1704  						tree.NewDName(index.Name),      // indexname
  1705  						tree.DNull,                     // tablespace
  1706  						tree.NewDString(def),           // indexdef
  1707  					)
  1708  				})
  1709  			})
  1710  	},
  1711  }
  1712  
  1713  // indexDefFromDescriptor creates an index definition (`CREATE INDEX ... ON (...)`) from
  1714  // and index descriptor by reconstructing a CreateIndex parser node and calling its
  1715  // String method.
  1716  func indexDefFromDescriptor(
  1717  	ctx context.Context,
  1718  	p *planner,
  1719  	db *sqlbase.DatabaseDescriptor,
  1720  	table *sqlbase.TableDescriptor,
  1721  	index *sqlbase.IndexDescriptor,
  1722  	tableLookup tableLookupFn,
  1723  ) (string, error) {
  1724  	indexDef := tree.CreateIndex{
  1725  		Name:     tree.Name(index.Name),
  1726  		Table:    tree.MakeTableName(tree.Name(db.Name), tree.Name(table.Name)),
  1727  		Unique:   index.Unique,
  1728  		Columns:  make(tree.IndexElemList, len(index.ColumnNames)),
  1729  		Storing:  make(tree.NameList, len(index.StoreColumnNames)),
  1730  		Inverted: index.Type == sqlbase.IndexDescriptor_INVERTED,
  1731  	}
  1732  	for i, name := range index.ColumnNames {
  1733  		elem := tree.IndexElem{
  1734  			Column:    tree.Name(name),
  1735  			Direction: tree.Ascending,
  1736  		}
  1737  		if index.ColumnDirections[i] == sqlbase.IndexDescriptor_DESC {
  1738  			elem.Direction = tree.Descending
  1739  		}
  1740  		indexDef.Columns[i] = elem
  1741  	}
  1742  	for i, name := range index.StoreColumnNames {
  1743  		indexDef.Storing[i] = tree.Name(name)
  1744  	}
  1745  	if len(index.Interleave.Ancestors) > 0 {
  1746  		intl := index.Interleave
  1747  		parentTable, err := tableLookup.getTableByID(intl.Ancestors[len(intl.Ancestors)-1].TableID)
  1748  		if err != nil {
  1749  			return "", err
  1750  		}
  1751  		parentDb, err := tableLookup.getDatabaseByID(parentTable.ParentID)
  1752  		if err != nil {
  1753  			return "", err
  1754  		}
  1755  		var sharedPrefixLen int
  1756  		for _, ancestor := range intl.Ancestors {
  1757  			sharedPrefixLen += int(ancestor.SharedPrefixLen)
  1758  		}
  1759  		fields := index.ColumnNames[:sharedPrefixLen]
  1760  		intlDef := &tree.InterleaveDef{
  1761  			Parent: tree.MakeTableName(tree.Name(parentDb.Name), tree.Name(parentTable.Name)),
  1762  			Fields: make(tree.NameList, len(fields)),
  1763  		}
  1764  		for i, field := range fields {
  1765  			intlDef.Fields[i] = tree.Name(field)
  1766  		}
  1767  		indexDef.Interleave = intlDef
  1768  	}
  1769  	fmtCtx := tree.NewFmtCtx(tree.FmtPGIndexDef)
  1770  	fmtCtx.FormatNode(&indexDef)
  1771  	return fmtCtx.String(), nil
  1772  }
  1773  
  1774  var pgCatalogInheritsTable = virtualSchemaTable{
  1775  	comment: `table inheritance hierarchy (empty - feature does not exist)
  1776  https://www.postgresql.org/docs/9.5/catalog-pg-inherits.html`,
  1777  	schema: `
  1778  CREATE TABLE pg_catalog.pg_inherits (
  1779  	inhrelid OID,
  1780  	inhparent OID,
  1781  	inhseqno INT4
  1782  )`,
  1783  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1784  		// Table inheritance is not supported.
  1785  		return nil
  1786  	},
  1787  }
  1788  
  1789  var pgCatalogLanguageTable = virtualSchemaTable{
  1790  	comment: `available languages (empty - feature does not exist)
  1791  https://www.postgresql.org/docs/9.5/catalog-pg-language.html`,
  1792  	schema: `
  1793  CREATE TABLE pg_catalog.pg_language (
  1794  	oid OID,
  1795  	lanname NAME,
  1796  	lanowner OID,
  1797  	lanispl BOOL,
  1798  	lanpltrusted BOOL,
  1799  	lanplcallfoid OID,
  1800  	laninline OID,
  1801  	lanvalidator OID,
  1802  	lanacl STRING[]
  1803  )`,
  1804  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1805  		// Languages to write functions and stored procedures are not supported.
  1806  		return nil
  1807  	},
  1808  }
  1809  
  1810  var pgCatalogLocksTable = virtualSchemaTable{
  1811  	comment: `locks held by active processes (empty - feature does not exist)
  1812  https://www.postgresql.org/docs/9.6/view-pg-locks.html`,
  1813  	schema: `
  1814  CREATE TABLE pg_catalog.pg_locks (
  1815    locktype TEXT,
  1816    database OID,
  1817    relation OID,
  1818    page INT4,
  1819    tuple SMALLINT,
  1820    virtualxid TEXT,
  1821    transactionid INT,
  1822    classid OID,
  1823    objid OID,
  1824    objsubid SMALLINT,
  1825    virtualtransaction TEXT,
  1826    pid INT4,
  1827    mode TEXT,
  1828    granted BOOLEAN,
  1829    fastpath BOOLEAN
  1830  )`,
  1831  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1832  		return nil
  1833  	},
  1834  }
  1835  
  1836  var pgCatalogMatViewsTable = virtualSchemaTable{
  1837  	comment: `available materialized views (empty - feature does not exist)
  1838  https://www.postgresql.org/docs/9.6/view-pg-matviews.html`,
  1839  	schema: `
  1840  CREATE TABLE pg_catalog.pg_matviews (
  1841    schemaname NAME,
  1842    matviewname NAME,
  1843    matviewowner NAME,
  1844    tablespace NAME,
  1845    hasindexes BOOL,
  1846    ispopulated BOOL,
  1847    definition TEXT
  1848  )`,
  1849  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1850  		return nil
  1851  	},
  1852  }
  1853  
  1854  var pgCatalogNamespaceTable = virtualSchemaTable{
  1855  	comment: `available namespaces (incomplete; namespaces and databases are congruent in CockroachDB)
  1856  https://www.postgresql.org/docs/9.5/catalog-pg-namespace.html`,
  1857  	schema: `
  1858  CREATE TABLE pg_catalog.pg_namespace (
  1859  	oid OID,
  1860  	nspname NAME NOT NULL,
  1861  	nspowner OID,
  1862  	nspacl STRING[]
  1863  )`,
  1864  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1865  		h := makeOidHasher()
  1866  		return forEachDatabaseDesc(ctx, p, dbContext, true, /* requiresPrivileges */
  1867  			func(db *sqlbase.DatabaseDescriptor) error {
  1868  				return forEachSchemaName(ctx, p, db, func(s string) error {
  1869  					return addRow(
  1870  						h.NamespaceOid(db, s), // oid
  1871  						tree.NewDString(s),    // nspname
  1872  						tree.DNull,            // nspowner
  1873  						tree.DNull,            // nspacl
  1874  					)
  1875  				})
  1876  			})
  1877  	},
  1878  }
  1879  
  1880  var (
  1881  	infixKind   = tree.NewDString("b")
  1882  	prefixKind  = tree.NewDString("l")
  1883  	postfixKind = tree.NewDString("r")
  1884  
  1885  	// Avoid unused warning for constants.
  1886  	_ = postfixKind
  1887  )
  1888  
  1889  var pgCatalogOperatorTable = virtualSchemaTable{
  1890  	comment: `operators (incomplete)
  1891  https://www.postgresql.org/docs/9.5/catalog-pg-operator.html`,
  1892  	schema: `
  1893  CREATE TABLE pg_catalog.pg_operator (
  1894  	oid OID,
  1895  	oprname NAME,
  1896  	oprnamespace OID,
  1897  	oprowner OID,
  1898  	oprkind TEXT,
  1899  	oprcanmerge BOOL,
  1900  	oprcanhash BOOL,
  1901  	oprleft OID,
  1902  	oprright OID,
  1903  	oprresult OID,
  1904  	oprcom OID,
  1905  	oprnegate OID,
  1906  	oprcode OID,
  1907  	oprrest OID,
  1908  	oprjoin OID
  1909  )`,
  1910  	populate: func(ctx context.Context, p *planner, db *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  1911  		h := makeOidHasher()
  1912  		nspOid := h.NamespaceOid(db, pgCatalogName)
  1913  		addOp := func(opName string, kind tree.Datum, params tree.TypeList, returnTyper tree.ReturnTyper) error {
  1914  			var leftType, rightType *tree.DOid
  1915  			switch params.Length() {
  1916  			case 1:
  1917  				leftType = oidZero
  1918  				rightType = tree.NewDOid(tree.DInt(params.Types()[0].Oid()))
  1919  			case 2:
  1920  				leftType = tree.NewDOid(tree.DInt(params.Types()[0].Oid()))
  1921  				rightType = tree.NewDOid(tree.DInt(params.Types()[1].Oid()))
  1922  			default:
  1923  				panic(fmt.Sprintf("Unexpected operator %s with %d params",
  1924  					opName, params.Length()))
  1925  			}
  1926  			returnType := tree.NewDOid(tree.DInt(returnTyper(nil).Oid()))
  1927  			err := addRow(
  1928  				h.OperatorOid(opName, leftType, rightType, returnType), // oid
  1929  
  1930  				tree.NewDString(opName), // oprname
  1931  				nspOid,                  // oprnamespace
  1932  				tree.DNull,              // oprowner
  1933  				kind,                    // oprkind
  1934  				tree.DBoolFalse,         // oprcanmerge
  1935  				tree.DBoolFalse,         // oprcanhash
  1936  				leftType,                // oprleft
  1937  				rightType,               // oprright
  1938  				returnType,              // oprresult
  1939  				tree.DNull,              // oprcom
  1940  				tree.DNull,              // oprnegate
  1941  				tree.DNull,              // oprcode
  1942  				tree.DNull,              // oprrest
  1943  				tree.DNull,              // oprjoin
  1944  			)
  1945  			return err
  1946  		}
  1947  		for cmpOp, overloads := range tree.CmpOps {
  1948  			// n.b. the In operator cannot be included in this list because it isn't
  1949  			// a generalized operator. It is a special syntax form, because it only
  1950  			// permits parenthesized subqueries or row expressions on the RHS.
  1951  			if cmpOp == tree.In {
  1952  				continue
  1953  			}
  1954  			for _, overload := range overloads {
  1955  				params, returnType := tree.GetParamsAndReturnType(overload)
  1956  				if err := addOp(cmpOp.String(), infixKind, params, returnType); err != nil {
  1957  					return err
  1958  				}
  1959  				if inverse, ok := cmpOp.Inverse(); ok {
  1960  					if err := addOp(inverse.String(), infixKind, params, returnType); err != nil {
  1961  						return err
  1962  					}
  1963  				}
  1964  			}
  1965  		}
  1966  		for binOp, overloads := range tree.BinOps {
  1967  			for _, overload := range overloads {
  1968  				params, returnType := tree.GetParamsAndReturnType(overload)
  1969  				if err := addOp(binOp.String(), infixKind, params, returnType); err != nil {
  1970  					return err
  1971  				}
  1972  			}
  1973  		}
  1974  		for unaryOp, overloads := range tree.UnaryOps {
  1975  			for _, overload := range overloads {
  1976  				params, returnType := tree.GetParamsAndReturnType(overload)
  1977  				if err := addOp(unaryOp.String(), prefixKind, params, returnType); err != nil {
  1978  					return err
  1979  				}
  1980  			}
  1981  		}
  1982  		return nil
  1983  	},
  1984  }
  1985  
  1986  func newSingletonStringArray(s string) tree.Datum {
  1987  	return &tree.DArray{ParamTyp: types.String, Array: tree.Datums{tree.NewDString(s)}}
  1988  }
  1989  
  1990  var (
  1991  	proArgModeInOut    = newSingletonStringArray("b")
  1992  	proArgModeIn       = newSingletonStringArray("i")
  1993  	proArgModeOut      = newSingletonStringArray("o")
  1994  	proArgModeTable    = newSingletonStringArray("t")
  1995  	proArgModeVariadic = newSingletonStringArray("v")
  1996  
  1997  	// Avoid unused warning for constants.
  1998  	_ = proArgModeInOut
  1999  	_ = proArgModeIn
  2000  	_ = proArgModeOut
  2001  	_ = proArgModeTable
  2002  )
  2003  
  2004  var pgCatalogPreparedXactsTable = virtualSchemaTable{
  2005  	comment: `prepared transactions (empty - feature does not exist)
  2006  https://www.postgresql.org/docs/9.6/view-pg-prepared-xacts.html`,
  2007  	schema: `
  2008  CREATE TABLE pg_catalog.pg_prepared_xacts (
  2009    transaction INTEGER,
  2010    gid TEXT,
  2011    prepared TIMESTAMP WITH TIME ZONE,
  2012    owner NAME,
  2013    database NAME
  2014  )`,
  2015  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2016  		return nil
  2017  	},
  2018  }
  2019  
  2020  // pgCatalogPreparedStatementsTable implements the pg_prepared_statements table.
  2021  // The statement field differs in that it uses the parsed version
  2022  // of the PREPARE statement.
  2023  // The parameter_types field differs from postgres as the type names in
  2024  // cockroach are slightly different.
  2025  var pgCatalogPreparedStatementsTable = virtualSchemaTable{
  2026  	comment: `prepared statements
  2027  https://www.postgresql.org/docs/9.6/view-pg-prepared-statements.html`,
  2028  	schema: `
  2029  CREATE TABLE pg_catalog.pg_prepared_statements (
  2030  	name TEXT,
  2031  	statement TEXT,
  2032  	prepare_time TIMESTAMPTZ,
  2033  	parameter_types REGTYPE[],
  2034  	from_sql boolean
  2035  )`,
  2036  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2037  		for name, stmt := range p.preparedStatements.List() {
  2038  			placeholderTypes := stmt.PrepareMetadata.PlaceholderTypesInfo.Types
  2039  			paramTypes := tree.NewDArray(types.RegType)
  2040  			paramTypes.Array = make(tree.Datums, len(placeholderTypes))
  2041  			paramNames := make([]string, len(placeholderTypes))
  2042  
  2043  			for i, placeholderType := range placeholderTypes {
  2044  				paramTypes.Array[i] = tree.NewDOidWithName(
  2045  					tree.DInt(placeholderType.Oid()),
  2046  					placeholderType,
  2047  					placeholderType.SQLStandardName(),
  2048  				)
  2049  				paramNames[i] = placeholderType.Name()
  2050  			}
  2051  
  2052  			// Only append arguments to string if required.
  2053  			argumentsStr := ""
  2054  			if len(paramNames) > 0 {
  2055  				argumentsStr = fmt.Sprintf(" (%s)", strings.Join(paramNames, ", "))
  2056  			}
  2057  
  2058  			fromSQL := tree.DBoolFalse
  2059  			if stmt.origin == PreparedStatementOriginSQL {
  2060  				fromSQL = tree.DBoolTrue
  2061  			}
  2062  
  2063  			ts, err := tree.MakeDTimestampTZ(stmt.createdAt, time.Microsecond)
  2064  			if err != nil {
  2065  				return err
  2066  			}
  2067  			if err := addRow(
  2068  				tree.NewDString(name),
  2069  				tree.NewDString(fmt.Sprintf("PREPARE %s%s AS %s", name, argumentsStr, stmt.SQL)),
  2070  				ts,
  2071  				paramTypes,
  2072  				fromSQL,
  2073  			); err != nil {
  2074  				return err
  2075  			}
  2076  		}
  2077  		return nil
  2078  	},
  2079  }
  2080  
  2081  var pgCatalogProcTable = virtualSchemaTable{
  2082  	comment: `built-in functions (incomplete)
  2083  https://www.postgresql.org/docs/9.5/catalog-pg-proc.html`,
  2084  	schema: `
  2085  CREATE TABLE pg_catalog.pg_proc (
  2086  	oid OID,
  2087  	proname NAME,
  2088  	pronamespace OID,
  2089  	proowner OID,
  2090  	prolang OID,
  2091  	procost FLOAT4,
  2092  	prorows FLOAT4,
  2093  	provariadic OID,
  2094  	protransform STRING,
  2095  	proisagg BOOL,
  2096  	proiswindow BOOL,
  2097  	prosecdef BOOL,
  2098  	proleakproof BOOL,
  2099  	proisstrict BOOL,
  2100  	proretset BOOL,
  2101  	provolatile CHAR,
  2102  	proparallel CHAR,
  2103  	pronargs INT2,
  2104  	pronargdefaults INT2,
  2105  	prorettype OID,
  2106  	proargtypes OIDVECTOR,
  2107  	proallargtypes OID[],
  2108  	proargmodes STRING[],
  2109  	proargnames STRING[],
  2110  	proargdefaults STRING,
  2111  	protrftypes OID[],
  2112  	prosrc STRING,
  2113  	probin STRING,
  2114  	proconfig STRING[],
  2115  	proacl STRING[]
  2116  )`,
  2117  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2118  		h := makeOidHasher()
  2119  		return forEachDatabaseDesc(ctx, p, dbContext, false, /* requiresPrivileges */
  2120  			func(db *DatabaseDescriptor) error {
  2121  				nspOid := h.NamespaceOid(db, pgCatalogName)
  2122  				for _, name := range builtins.AllBuiltinNames {
  2123  					// parser.Builtins contains duplicate uppercase and lowercase keys.
  2124  					// Only return the lowercase ones for compatibility with postgres.
  2125  					var first rune
  2126  					for _, c := range name {
  2127  						first = c
  2128  						break
  2129  					}
  2130  					if unicode.IsUpper(first) {
  2131  						continue
  2132  					}
  2133  					props, overloads := builtins.GetBuiltinProperties(name)
  2134  					isAggregate := props.Class == tree.AggregateClass
  2135  					isWindow := props.Class == tree.WindowClass
  2136  					for _, builtin := range overloads {
  2137  						dName := tree.NewDName(name)
  2138  						dSrc := tree.NewDString(name)
  2139  
  2140  						var retType tree.Datum
  2141  						isRetSet := false
  2142  						if fixedRetType := builtin.FixedReturnType(); fixedRetType != nil {
  2143  							var retOid oid.Oid
  2144  							if fixedRetType.Family() == types.TupleFamily && builtin.Generator != nil {
  2145  								isRetSet = true
  2146  								// Functions returning tables with zero, or more than one
  2147  								// columns are marked to return "anyelement"
  2148  								// (e.g. `unnest`)
  2149  								retOid = oid.T_anyelement
  2150  								if len(fixedRetType.TupleContents()) == 1 {
  2151  									// Functions returning tables with exactly one column
  2152  									// are marked to return the type of that column
  2153  									// (e.g. `generate_series`).
  2154  									retOid = fixedRetType.TupleContents()[0].Oid()
  2155  								}
  2156  							} else {
  2157  								retOid = fixedRetType.Oid()
  2158  							}
  2159  							retType = tree.NewDOid(tree.DInt(retOid))
  2160  						}
  2161  
  2162  						argTypes := builtin.Types
  2163  						dArgTypes := tree.NewDArray(types.Oid)
  2164  						for _, argType := range argTypes.Types() {
  2165  							if err := dArgTypes.Append(tree.NewDOid(tree.DInt(argType.Oid()))); err != nil {
  2166  								return err
  2167  							}
  2168  						}
  2169  
  2170  						var argmodes tree.Datum
  2171  						var variadicType tree.Datum
  2172  						switch v := argTypes.(type) {
  2173  						case tree.VariadicType:
  2174  							if len(v.FixedTypes) == 0 {
  2175  								argmodes = proArgModeVariadic
  2176  							} else {
  2177  								ary := tree.NewDArray(types.String)
  2178  								for range v.FixedTypes {
  2179  									if err := ary.Append(tree.NewDString("i")); err != nil {
  2180  										return err
  2181  									}
  2182  								}
  2183  								if err := ary.Append(tree.NewDString("v")); err != nil {
  2184  									return err
  2185  								}
  2186  								argmodes = ary
  2187  							}
  2188  							variadicType = tree.NewDOid(tree.DInt(v.VarType.Oid()))
  2189  						case tree.HomogeneousType:
  2190  							argmodes = proArgModeVariadic
  2191  							argType := types.Any
  2192  							oid := argType.Oid()
  2193  							variadicType = tree.NewDOid(tree.DInt(oid))
  2194  						default:
  2195  							argmodes = tree.DNull
  2196  							variadicType = oidZero
  2197  						}
  2198  						provolatile, proleakproof := builtin.Volatility.ToPostgres()
  2199  
  2200  						err := addRow(
  2201  							h.BuiltinOid(name, &builtin),             // oid
  2202  							dName,                                    // proname
  2203  							nspOid,                                   // pronamespace
  2204  							tree.DNull,                               // proowner
  2205  							oidZero,                                  // prolang
  2206  							tree.DNull,                               // procost
  2207  							tree.DNull,                               // prorows
  2208  							variadicType,                             // provariadic
  2209  							tree.DNull,                               // protransform
  2210  							tree.MakeDBool(tree.DBool(isAggregate)),  // proisagg
  2211  							tree.MakeDBool(tree.DBool(isWindow)),     // proiswindow
  2212  							tree.DBoolFalse,                          // prosecdef
  2213  							tree.MakeDBool(tree.DBool(proleakproof)), // proleakproof
  2214  							tree.DBoolFalse,                          // proisstrict
  2215  							tree.MakeDBool(tree.DBool(isRetSet)),     // proretset
  2216  							tree.NewDString(provolatile),             // provolatile
  2217  							tree.DNull,                               // proparallel
  2218  							tree.NewDInt(tree.DInt(builtin.Types.Length())), // pronargs
  2219  							tree.NewDInt(tree.DInt(0)),                      // pronargdefaults
  2220  							retType,                                         // prorettype
  2221  							tree.NewDOidVectorFromDArray(dArgTypes),         // proargtypes
  2222  							tree.DNull,                                      // proallargtypes
  2223  							argmodes,                                        // proargmodes
  2224  							tree.DNull,                                      // proargnames
  2225  							tree.DNull,                                      // proargdefaults
  2226  							tree.DNull,                                      // protrftypes
  2227  							dSrc,                                            // prosrc
  2228  							tree.DNull,                                      // probin
  2229  							tree.DNull,                                      // proconfig
  2230  							tree.DNull,                                      // proacl
  2231  						)
  2232  						if err != nil {
  2233  							return err
  2234  						}
  2235  					}
  2236  				}
  2237  				return nil
  2238  			})
  2239  	},
  2240  }
  2241  
  2242  var pgCatalogRangeTable = virtualSchemaTable{
  2243  	comment: `range types (empty - feature does not exist)
  2244  https://www.postgresql.org/docs/9.5/catalog-pg-range.html`,
  2245  	schema: `
  2246  CREATE TABLE pg_catalog.pg_range (
  2247  	rngtypid OID,
  2248  	rngsubtype OID,
  2249  	rngcollation OID,
  2250  	rngsubopc OID,
  2251  	rngcanonical OID,
  2252  	rngsubdiff OID
  2253  )`,
  2254  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2255  		// We currently do not support any range types, so this table is empty.
  2256  		// This table should be populated when any range types are added to
  2257  		// oidToDatum (and therefore pg_type).
  2258  		return nil
  2259  	},
  2260  }
  2261  
  2262  var pgCatalogRewriteTable = virtualSchemaTable{
  2263  	comment: `rewrite rules (empty - feature does not exist)
  2264  https://www.postgresql.org/docs/9.5/catalog-pg-rewrite.html`,
  2265  	schema: `
  2266  CREATE TABLE pg_catalog.pg_rewrite (
  2267  	oid OID,
  2268  	rulename NAME,
  2269  	ev_class OID,
  2270  	ev_type TEXT,
  2271  	ev_enabled TEXT,
  2272  	is_instead BOOL,
  2273  	ev_qual TEXT,
  2274  	ev_action TEXT
  2275  )`,
  2276  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2277  		// Rewrite rules are not supported.
  2278  		return nil
  2279  	},
  2280  }
  2281  
  2282  var pgCatalogRolesTable = virtualSchemaTable{
  2283  	comment: `database roles
  2284  https://www.postgresql.org/docs/9.5/view-pg-roles.html`,
  2285  	schema: `
  2286  CREATE TABLE pg_catalog.pg_roles (
  2287  	oid OID,
  2288  	rolname NAME,
  2289  	rolsuper BOOL,
  2290  	rolinherit BOOL,
  2291  	rolcreaterole BOOL,
  2292  	rolcreatedb BOOL,
  2293  	rolcatupdate BOOL,
  2294  	rolcanlogin BOOL,
  2295  	rolreplication BOOL,
  2296  	rolconnlimit INT4,
  2297  	rolpassword STRING,
  2298  	rolvaliduntil TIMESTAMPTZ,
  2299  	rolbypassrls BOOL,
  2300  	rolconfig STRING[]
  2301  )`,
  2302  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2303  		// We intentionally do not check if the user has access to system.user.
  2304  		// Because Postgres allows access to pg_roles by non-privileged users, we
  2305  		// need to do the same. This shouldn't be an issue, because pg_roles doesn't
  2306  		// include sensitive information such as password hashes.
  2307  		h := makeOidHasher()
  2308  		return forEachRole(ctx, p,
  2309  			func(username string, isRole bool, noLogin bool) error {
  2310  				isRoot := tree.DBool(username == security.RootUser || username == sqlbase.AdminRole)
  2311  				isRoleDBool := tree.DBool(isRole)
  2312  				roleCanLogin := tree.DBool(!noLogin)
  2313  				return addRow(
  2314  					h.UserOid(username),          // oid
  2315  					tree.NewDName(username),      // rolname
  2316  					tree.MakeDBool(isRoot),       // rolsuper
  2317  					tree.MakeDBool(isRoleDBool),  // rolinherit. Roles inherit by default.
  2318  					tree.MakeDBool(isRoot),       // rolcreaterole
  2319  					tree.MakeDBool(isRoot),       // rolcreatedb
  2320  					tree.DBoolFalse,              // rolcatupdate
  2321  					tree.MakeDBool(roleCanLogin), // rolcanlogin.
  2322  					tree.DBoolFalse,              // rolreplication
  2323  					negOneVal,                    // rolconnlimit
  2324  					passwdStarString,             // rolpassword
  2325  					tree.DNull,                   // rolvaliduntil
  2326  					tree.DBoolFalse,              // rolbypassrls
  2327  					tree.DNull,                   // rolconfig
  2328  				)
  2329  			})
  2330  	},
  2331  }
  2332  
  2333  var pgCatalogSecLabelsTable = virtualSchemaTable{
  2334  	comment: `security labels (empty)
  2335  https://www.postgresql.org/docs/9.6/view-pg-seclabels.html`,
  2336  	schema: `
  2337  CREATE TABLE pg_catalog.pg_seclabels (
  2338  	objoid OID,
  2339    classoid OID,
  2340    objsubid INT4,
  2341    objtype TEXT,
  2342  	objnamespace OID,
  2343  	objname TEXT,
  2344  	provider TEXT,
  2345  	label TEXT
  2346  )`,
  2347  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2348  		return nil
  2349  	},
  2350  }
  2351  
  2352  var pgCatalogSequencesTable = virtualSchemaTable{
  2353  	comment: `sequences (see also information_schema.sequences)
  2354  https://www.postgresql.org/docs/9.5/catalog-pg-sequence.html`,
  2355  	schema: `
  2356  CREATE TABLE pg_catalog.pg_sequence (
  2357  	seqrelid OID,
  2358  	seqtypid OID,
  2359  	seqstart INT8,
  2360  	seqincrement INT8,
  2361  	seqmax INT8,
  2362  	seqmin INT8,
  2363  	seqcache INT8,
  2364  	seqcycle BOOL
  2365  )`,
  2366  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2367  		return forEachTableDesc(ctx, p, dbContext, hideVirtual, /* virtual schemas do not have indexes */
  2368  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  2369  				if !table.IsSequence() {
  2370  					return nil
  2371  				}
  2372  				opts := table.SequenceOpts
  2373  				return addRow(
  2374  					tableOid(table.ID),                      // seqrelid
  2375  					tree.NewDOid(tree.DInt(oid.T_int8)),     // seqtypid
  2376  					tree.NewDInt(tree.DInt(opts.Start)),     // seqstart
  2377  					tree.NewDInt(tree.DInt(opts.Increment)), // seqincrement
  2378  					tree.NewDInt(tree.DInt(opts.MaxValue)),  // seqmax
  2379  					tree.NewDInt(tree.DInt(opts.MinValue)),  // seqmin
  2380  					tree.NewDInt(1),                         // seqcache
  2381  					tree.DBoolFalse,                         // seqcycle
  2382  				)
  2383  			})
  2384  	},
  2385  }
  2386  
  2387  var (
  2388  	varTypeString   = tree.NewDString("string")
  2389  	settingsCtxUser = tree.NewDString("user")
  2390  )
  2391  
  2392  var pgCatalogSettingsTable = virtualSchemaTable{
  2393  	comment: `session variables (incomplete)
  2394  https://www.postgresql.org/docs/9.5/catalog-pg-settings.html`,
  2395  	schema: `
  2396  CREATE TABLE pg_catalog.pg_settings (
  2397      name STRING,
  2398      setting STRING,
  2399      unit STRING,
  2400      category STRING,
  2401      short_desc STRING,
  2402      extra_desc STRING,
  2403      context STRING,
  2404      vartype STRING,
  2405      source STRING,
  2406      min_val STRING,
  2407      max_val STRING,
  2408      enumvals STRING,
  2409      boot_val STRING,
  2410      reset_val STRING,
  2411      sourcefile STRING,
  2412      sourceline INT4,
  2413      pending_restart BOOL
  2414  )`,
  2415  	populate: func(_ context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2416  		for _, vName := range varNames {
  2417  			gen := varGen[vName]
  2418  			if gen.Hidden {
  2419  				continue
  2420  			}
  2421  			value := gen.Get(&p.extendedEvalCtx)
  2422  			valueDatum := tree.NewDString(value)
  2423  			var bootDatum tree.Datum = tree.DNull
  2424  			var resetDatum tree.Datum = tree.DNull
  2425  			if gen.Set == nil && gen.RuntimeSet == nil {
  2426  				// RESET/SET will leave the variable unchanged. Announce the
  2427  				// current value as boot/reset value.
  2428  				bootDatum = valueDatum
  2429  				resetDatum = bootDatum
  2430  			} else {
  2431  				if gen.GlobalDefault != nil {
  2432  					globalDefVal := gen.GlobalDefault(&p.EvalContext().Settings.SV)
  2433  					bootDatum = tree.NewDString(globalDefVal)
  2434  				}
  2435  				if hasDefault, defVal := getSessionVarDefaultString(vName, gen, p.sessionDataMutator); hasDefault {
  2436  					resetDatum = tree.NewDString(defVal)
  2437  				}
  2438  			}
  2439  			if err := addRow(
  2440  				tree.NewDString(strings.ToLower(vName)), // name
  2441  				valueDatum,                              // setting
  2442  				tree.DNull,                              // unit
  2443  				tree.DNull,                              // category
  2444  				tree.DNull,                              // short_desc
  2445  				tree.DNull,                              // extra_desc
  2446  				settingsCtxUser,                         // context
  2447  				varTypeString,                           // vartype
  2448  				tree.DNull,                              // source
  2449  				tree.DNull,                              // min_val
  2450  				tree.DNull,                              // max_val
  2451  				tree.DNull,                              // enumvals
  2452  				bootDatum,                               // boot_val
  2453  				resetDatum,                              // reset_val
  2454  				tree.DNull,                              // sourcefile
  2455  				tree.DNull,                              // sourceline
  2456  				tree.DBoolFalse,                         // pending_restart
  2457  			); err != nil {
  2458  				return err
  2459  			}
  2460  		}
  2461  		return nil
  2462  	},
  2463  }
  2464  
  2465  var pgCatalogShdependTable = virtualSchemaTable{
  2466  	comment: `shared dependencies (empty - not implemented)
  2467  https://www.postgresql.org/docs/9.6/catalog-pg-shdepend.html`,
  2468  	schema: `
  2469  CREATE TABLE pg_catalog.pg_shdepend (
  2470  	dbid OID,
  2471  	classid OID,
  2472  	objid OID,
  2473    objsubid INT4,
  2474  	refclassid OID,
  2475  	refobjid OID,
  2476  	deptype CHAR
  2477  )`,
  2478  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2479  		return nil
  2480  	},
  2481  }
  2482  
  2483  var pgCatalogTablesTable = virtualSchemaTable{
  2484  	comment: `tables summary (see also information_schema.tables, pg_catalog.pg_class)
  2485  https://www.postgresql.org/docs/9.5/view-pg-tables.html`,
  2486  	schema: `
  2487  CREATE TABLE pg_catalog.pg_tables (
  2488  	schemaname NAME,
  2489  	tablename NAME,
  2490  	tableowner NAME,
  2491  	tablespace NAME,
  2492  	hasindexes BOOL,
  2493  	hasrules BOOL,
  2494  	hastriggers BOOL,
  2495  	rowsecurity BOOL
  2496  )`,
  2497  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2498  		// Note: pg_catalog.pg_tables is not well-defined if the dbContext is
  2499  		// empty -- listing tables across databases can yield duplicate
  2500  		// schema/table names.
  2501  		return forEachTableDesc(ctx, p, dbContext, virtualMany,
  2502  			func(db *sqlbase.DatabaseDescriptor, scName string, table *sqlbase.TableDescriptor) error {
  2503  				if !table.IsTable() {
  2504  					return nil
  2505  				}
  2506  				return addRow(
  2507  					tree.NewDName(scName),     // schemaname
  2508  					tree.NewDName(table.Name), // tablename
  2509  					tree.DNull,                // tableowner
  2510  					tree.DNull,                // tablespace
  2511  					tree.MakeDBool(tree.DBool(table.IsPhysicalTable())), // hasindexes
  2512  					tree.DBoolFalse, // hasrules
  2513  					tree.DBoolFalse, // hastriggers
  2514  					tree.DBoolFalse, // rowsecurity
  2515  				)
  2516  			})
  2517  	},
  2518  }
  2519  
  2520  var pgCatalogTablespaceTable = virtualSchemaTable{
  2521  	comment: `available tablespaces (incomplete; concept inapplicable to CockroachDB)
  2522  https://www.postgresql.org/docs/9.5/catalog-pg-tablespace.html`,
  2523  	schema: `
  2524  CREATE TABLE pg_catalog.pg_tablespace (
  2525  	oid OID,
  2526  	spcname NAME,
  2527  	spcowner OID,
  2528  	spclocation TEXT,
  2529  	spcacl TEXT[],
  2530  	spcoptions TEXT[]
  2531  )`,
  2532  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2533  		return addRow(
  2534  			oidZero,                       // oid
  2535  			tree.NewDString("pg_default"), // spcname
  2536  			tree.DNull,                    // spcowner
  2537  			tree.DNull,                    // spclocation
  2538  			tree.DNull,                    // spcacl
  2539  			tree.DNull,                    // spcoptions
  2540  		)
  2541  	},
  2542  }
  2543  
  2544  var pgCatalogTriggerTable = virtualSchemaTable{
  2545  	comment: `triggers (empty - feature does not exist)
  2546  https://www.postgresql.org/docs/9.5/catalog-pg-trigger.html`,
  2547  	schema: `
  2548  CREATE TABLE pg_catalog.pg_trigger (
  2549  	oid OID,
  2550  	tgrelid OID,
  2551  	tgname NAME,
  2552  	tgfoid OID,
  2553  	tgtype INT2,
  2554  	tgenabled TEXT,
  2555  	tgisinternal BOOL,
  2556  	tgconstrrelid OID,
  2557  	tgconstrindid OID,
  2558  	tgconstraint OID,
  2559  	tgdeferrable BOOL,
  2560  	tginitdeferred BOOL,
  2561  	tgnargs INT2,
  2562  	tgattr INT2VECTOR,
  2563  	tgargs BYTEA,
  2564  	tgqual TEXT,
  2565  	tgoldtable NAME,
  2566  	tgnewtable NAME
  2567  )`,
  2568  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2569  		// Triggers are unsupported.
  2570  		return nil
  2571  	},
  2572  }
  2573  
  2574  var (
  2575  	typTypeBase      = tree.NewDString("b")
  2576  	typTypeComposite = tree.NewDString("c")
  2577  	typTypeDomain    = tree.NewDString("d")
  2578  	typTypeEnum      = tree.NewDString("e")
  2579  	typTypePseudo    = tree.NewDString("p")
  2580  	typTypeRange     = tree.NewDString("r")
  2581  
  2582  	// Avoid unused warning for constants.
  2583  	_ = typTypeComposite
  2584  	_ = typTypeDomain
  2585  	_ = typTypePseudo
  2586  	_ = typTypeRange
  2587  
  2588  	// See https://www.postgresql.org/docs/9.6/static/catalog-pg-type.html#CATALOG-TYPCATEGORY-TABLE.
  2589  	typCategoryArray       = tree.NewDString("A")
  2590  	typCategoryBoolean     = tree.NewDString("B")
  2591  	typCategoryComposite   = tree.NewDString("C")
  2592  	typCategoryDateTime    = tree.NewDString("D")
  2593  	typCategoryEnum        = tree.NewDString("E")
  2594  	typCategoryGeometric   = tree.NewDString("G")
  2595  	typCategoryNetworkAddr = tree.NewDString("I")
  2596  	typCategoryNumeric     = tree.NewDString("N")
  2597  	typCategoryPseudo      = tree.NewDString("P")
  2598  	typCategoryRange       = tree.NewDString("R")
  2599  	typCategoryString      = tree.NewDString("S")
  2600  	typCategoryTimespan    = tree.NewDString("T")
  2601  	typCategoryUserDefined = tree.NewDString("U")
  2602  	typCategoryBitString   = tree.NewDString("V")
  2603  	typCategoryUnknown     = tree.NewDString("X")
  2604  
  2605  	// Avoid unused warning for constants.
  2606  	_ = typCategoryComposite
  2607  	_ = typCategoryEnum
  2608  	_ = typCategoryGeometric
  2609  	_ = typCategoryRange
  2610  	_ = typCategoryBitString
  2611  
  2612  	typDelim = tree.NewDString(",")
  2613  )
  2614  
  2615  func addPGTypeRow(
  2616  	h oidHasher, nspOid tree.Datum, typ *types.T, addRow func(...tree.Datum) error,
  2617  ) error {
  2618  	cat := typCategory(typ)
  2619  	typType := typTypeBase
  2620  	typElem := oidZero
  2621  	typArray := oidZero
  2622  	builtinPrefix := builtins.PGIOBuiltinPrefix(typ)
  2623  	switch typ.Family() {
  2624  	case types.ArrayFamily:
  2625  		switch typ.Oid() {
  2626  		case oid.T_int2vector:
  2627  			// IntVector needs a special case because it's a special snowflake
  2628  			// type that behaves in some ways like a scalar type and in others
  2629  			// like an array type.
  2630  			typElem = tree.NewDOid(tree.DInt(oid.T_int2))
  2631  			typArray = tree.NewDOid(tree.DInt(oid.T__int2vector))
  2632  		case oid.T_oidvector:
  2633  			// Same story as above for OidVector.
  2634  			typElem = tree.NewDOid(tree.DInt(oid.T_oid))
  2635  			typArray = tree.NewDOid(tree.DInt(oid.T__oidvector))
  2636  		case oid.T_anyarray:
  2637  			// AnyArray does not use a prefix or element type.
  2638  		default:
  2639  			builtinPrefix = "array_"
  2640  			typElem = tree.NewDOid(tree.DInt(typ.ArrayContents().Oid()))
  2641  		}
  2642  	default:
  2643  		typArray = tree.NewDOid(tree.DInt(types.MakeArray(typ).Oid()))
  2644  	}
  2645  	if typ.Family() == types.EnumFamily {
  2646  		builtinPrefix = "enum_"
  2647  		typType = typTypeEnum
  2648  	}
  2649  	if cat == typCategoryPseudo {
  2650  		typType = typTypePseudo
  2651  	}
  2652  	typname := typ.PGName()
  2653  
  2654  	return addRow(
  2655  		tree.NewDOid(tree.DInt(typ.Oid())), // oid
  2656  		tree.NewDName(typname),             // typname
  2657  		nspOid,                             // typnamespace
  2658  		tree.DNull,                         // typowner
  2659  		typLen(typ),                        // typlen
  2660  		typByVal(typ),                      // typbyval (is it fixedlen or not)
  2661  		typType,                            // typtype
  2662  		cat,                                // typcategory
  2663  		tree.DBoolFalse,                    // typispreferred
  2664  		tree.DBoolTrue,                     // typisdefined
  2665  		typDelim,                           // typdelim
  2666  		oidZero,                            // typrelid
  2667  		typElem,                            // typelem
  2668  		typArray,                           // typarray
  2669  
  2670  		// regproc references
  2671  		h.RegProc(builtinPrefix+"in"),   // typinput
  2672  		h.RegProc(builtinPrefix+"out"),  // typoutput
  2673  		h.RegProc(builtinPrefix+"recv"), // typreceive
  2674  		h.RegProc(builtinPrefix+"send"), // typsend
  2675  		oidZero,                         // typmodin
  2676  		oidZero,                         // typmodout
  2677  		oidZero,                         // typanalyze
  2678  
  2679  		tree.DNull,      // typalign
  2680  		tree.DNull,      // typstorage
  2681  		tree.DBoolFalse, // typnotnull
  2682  		oidZero,         // typbasetype
  2683  		negOneVal,       // typtypmod
  2684  		zeroVal,         // typndims
  2685  		typColl(typ, h), // typcollation
  2686  		tree.DNull,      // typdefaultbin
  2687  		tree.DNull,      // typdefault
  2688  		tree.DNull,      // typacl
  2689  	)
  2690  }
  2691  
  2692  // TODO (rohany): We should add a virtual index on OID here. See #49208.
  2693  var pgCatalogTypeTable = virtualSchemaTable{
  2694  	comment: `scalar types (incomplete)
  2695  https://www.postgresql.org/docs/9.5/catalog-pg-type.html`,
  2696  	schema: `
  2697  CREATE TABLE pg_catalog.pg_type (
  2698  	oid OID,
  2699  	typname NAME NOT NULL,
  2700  	typnamespace OID,
  2701  	typowner OID,
  2702  	typlen INT2,
  2703  	typbyval BOOL,
  2704  	typtype CHAR,
  2705  	typcategory CHAR,
  2706  	typispreferred BOOL,
  2707  	typisdefined BOOL,
  2708  	typdelim CHAR,
  2709  	typrelid OID,
  2710  	typelem OID,
  2711  	typarray OID,
  2712  	typinput REGPROC,
  2713  	typoutput REGPROC,
  2714  	typreceive REGPROC,
  2715  	typsend REGPROC,
  2716  	typmodin REGPROC,
  2717  	typmodout REGPROC,
  2718  	typanalyze REGPROC,
  2719  	typalign CHAR,
  2720  	typstorage CHAR,
  2721  	typnotnull BOOL,
  2722  	typbasetype OID,
  2723  	typtypmod INT4,
  2724  	typndims INT4,
  2725  	typcollation OID,
  2726  	typdefaultbin STRING,
  2727  	typdefault STRING,
  2728  	typacl STRING[]
  2729  )`,
  2730  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2731  		h := makeOidHasher()
  2732  		return forEachDatabaseDesc(ctx, p, dbContext, false, /* requiresPrivileges */
  2733  			func(db *DatabaseDescriptor) error {
  2734  				nspOid := h.NamespaceOid(db, pgCatalogName)
  2735  
  2736  				// Generate rows for all predefined types.
  2737  				for _, typ := range types.OidToType {
  2738  					if err := addPGTypeRow(h, nspOid, typ, addRow); err != nil {
  2739  						return err
  2740  					}
  2741  				}
  2742  
  2743  				// Now generate rows for user defined types in this database.
  2744  				return forEachTypeDesc(ctx, p, dbContext, func(_ *DatabaseDescriptor, _ string, typDesc *TypeDescriptor) error {
  2745  					typ, err := typDesc.MakeTypesT(
  2746  						tree.NewUnqualifiedTypeName(tree.Name(typDesc.Name)),
  2747  						p.makeTypeLookupFn(ctx),
  2748  					)
  2749  					if err != nil {
  2750  						return err
  2751  					}
  2752  					return addPGTypeRow(h, nspOid, typ, addRow)
  2753  				})
  2754  			})
  2755  	},
  2756  }
  2757  
  2758  var pgCatalogUserTable = virtualSchemaTable{
  2759  	comment: `database users
  2760  https://www.postgresql.org/docs/9.5/view-pg-user.html`,
  2761  	schema: `
  2762  CREATE TABLE pg_catalog.pg_user (
  2763  	usename NAME,
  2764  	usesysid OID,
  2765  	usecreatedb BOOL,
  2766  	usesuper BOOL,
  2767  	userepl  BOOL,
  2768  	usebypassrls BOOL,
  2769  	passwd TEXT,
  2770  	valuntil TIMESTAMP,
  2771  	useconfig TEXT[]
  2772  )`,
  2773  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2774  		h := makeOidHasher()
  2775  		return forEachRole(ctx, p,
  2776  			func(username string, isRole bool, noLogin bool) error {
  2777  				if isRole {
  2778  					return nil
  2779  				}
  2780  				isRoot := tree.DBool(username == security.RootUser)
  2781  				return addRow(
  2782  					tree.NewDName(username), // usename
  2783  					h.UserOid(username),     // usesysid
  2784  					tree.MakeDBool(isRoot),  // usecreatedb
  2785  					tree.MakeDBool(isRoot),  // usesuper
  2786  					tree.DBoolFalse,         // userepl
  2787  					tree.DBoolFalse,         // usebypassrls
  2788  					passwdStarString,        // passwd
  2789  					tree.DNull,              // valuntil
  2790  					tree.DNull,              // useconfig
  2791  				)
  2792  			})
  2793  	},
  2794  }
  2795  
  2796  var pgCatalogUserMappingTable = virtualSchemaTable{
  2797  	comment: `local to remote user mapping (empty - feature does not exist)
  2798  https://www.postgresql.org/docs/9.5/catalog-pg-user-mapping.html`,
  2799  	schema: `
  2800  CREATE TABLE pg_catalog.pg_user_mapping (
  2801  	oid OID,
  2802  	umuser OID,
  2803  	umserver OID,
  2804  	umoptions TEXT[]
  2805  )`,
  2806  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2807  		// This table stores the mapping to foreign server users.
  2808  		// Foreign servers are not supported.
  2809  		return nil
  2810  	},
  2811  }
  2812  
  2813  var pgCatalogStatActivityTable = virtualSchemaTable{
  2814  	comment: `backend access statistics (empty - monitoring works differently in CockroachDB)
  2815  https://www.postgresql.org/docs/9.6/monitoring-stats.html#PG-STAT-ACTIVITY-VIEW`,
  2816  	schema: `
  2817  CREATE TABLE pg_catalog.pg_stat_activity (
  2818  	datid OID,
  2819  	datname NAME,
  2820  	pid INTEGER,
  2821  	usesysid OID,
  2822  	usename NAME,
  2823  	application_name TEXT,
  2824  	client_addr INET,
  2825  	client_hostname TEXT,
  2826  	client_port INTEGER,
  2827  	backend_start TIMESTAMPTZ,
  2828  	xact_start TIMESTAMPTZ,
  2829  	query_start TIMESTAMPTZ,
  2830  	state_change TIMESTAMPTZ,
  2831  	wait_event_type TEXT,
  2832  	wait_event TEXT,
  2833  	state TEXT,
  2834  	backend_xid INTEGER,
  2835  	backend_xmin INTEGER,
  2836  	query TEXT
  2837  )
  2838  `,
  2839  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2840  		return nil
  2841  	},
  2842  }
  2843  
  2844  var pgCatalogSecurityLabelTable = virtualSchemaTable{
  2845  	comment: `security labels (empty - feature does not exist)
  2846  https://www.postgresql.org/docs/9.5/catalog-pg-seclabel.html`,
  2847  	schema: `
  2848  CREATE TABLE pg_catalog.pg_seclabel (
  2849  	objoid OID,
  2850  	classoid OID,
  2851  	objsubid INTEGER,
  2852  	provider TEXT,
  2853  	label TEXT
  2854  )
  2855  `,
  2856  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2857  		return nil
  2858  	},
  2859  }
  2860  
  2861  var pgCatalogSharedSecurityLabelTable = virtualSchemaTable{
  2862  	comment: `shared security labels (empty - feature not supported)
  2863  https://www.postgresql.org/docs/9.5/catalog-pg-shseclabel.html`,
  2864  	schema: `
  2865  CREATE TABLE pg_catalog.pg_shseclabel (
  2866  	objoid OID,
  2867  	classoid OID,
  2868  	provider TEXT,
  2869  	label TEXT
  2870  )
  2871  `,
  2872  	populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2873  		return nil
  2874  	},
  2875  }
  2876  
  2877  // typOid is the only OID generation approach that does not use oidHasher, because
  2878  // object identifiers for types are not arbitrary, but instead need to be kept in
  2879  // sync with Postgres.
  2880  func typOid(typ *types.T) tree.Datum {
  2881  	return tree.NewDOid(tree.DInt(typ.Oid()))
  2882  }
  2883  
  2884  func typLen(typ *types.T) *tree.DInt {
  2885  	if sz, variable := tree.DatumTypeSize(typ); !variable {
  2886  		return tree.NewDInt(tree.DInt(sz))
  2887  	}
  2888  	return negOneVal
  2889  }
  2890  
  2891  func typByVal(typ *types.T) tree.Datum {
  2892  	_, variable := tree.DatumTypeSize(typ)
  2893  	return tree.MakeDBool(tree.DBool(!variable))
  2894  }
  2895  
  2896  // typColl returns the collation OID for a given type.
  2897  // The default collation is en-US, which is equivalent to but spelled
  2898  // differently than the default database collation, en_US.utf8.
  2899  func typColl(typ *types.T, h oidHasher) tree.Datum {
  2900  	switch typ.Family() {
  2901  	case types.AnyFamily:
  2902  		return oidZero
  2903  	case types.StringFamily:
  2904  		return h.CollationOid(defaultCollationTag)
  2905  	case types.CollatedStringFamily:
  2906  		return h.CollationOid(typ.Locale())
  2907  	}
  2908  
  2909  	if typ.Equivalent(types.StringArray) {
  2910  		return h.CollationOid(defaultCollationTag)
  2911  	}
  2912  	return oidZero
  2913  }
  2914  
  2915  // This mapping should be kept sync with PG's categorization.
  2916  var datumToTypeCategory = map[types.Family]*tree.DString{
  2917  	types.AnyFamily:         typCategoryPseudo,
  2918  	types.BitFamily:         typCategoryBitString,
  2919  	types.BoolFamily:        typCategoryBoolean,
  2920  	types.BytesFamily:       typCategoryUserDefined,
  2921  	types.DateFamily:        typCategoryDateTime,
  2922  	types.EnumFamily:        typCategoryEnum,
  2923  	types.TimeFamily:        typCategoryDateTime,
  2924  	types.TimeTZFamily:      typCategoryDateTime,
  2925  	types.FloatFamily:       typCategoryNumeric,
  2926  	types.IntFamily:         typCategoryNumeric,
  2927  	types.IntervalFamily:    typCategoryTimespan,
  2928  	types.GeographyFamily:   typCategoryUserDefined,
  2929  	types.GeometryFamily:    typCategoryUserDefined,
  2930  	types.JsonFamily:        typCategoryUserDefined,
  2931  	types.DecimalFamily:     typCategoryNumeric,
  2932  	types.StringFamily:      typCategoryString,
  2933  	types.TimestampFamily:   typCategoryDateTime,
  2934  	types.TimestampTZFamily: typCategoryDateTime,
  2935  	types.ArrayFamily:       typCategoryArray,
  2936  	types.TupleFamily:       typCategoryPseudo,
  2937  	types.OidFamily:         typCategoryNumeric,
  2938  	types.UuidFamily:        typCategoryUserDefined,
  2939  	types.INetFamily:        typCategoryNetworkAddr,
  2940  	types.UnknownFamily:     typCategoryUnknown,
  2941  }
  2942  
  2943  func typCategory(typ *types.T) tree.Datum {
  2944  	// Special case ARRAY of ANY.
  2945  	if typ.Family() == types.ArrayFamily && typ.ArrayContents().Family() == types.AnyFamily {
  2946  		return typCategoryPseudo
  2947  	}
  2948  	return datumToTypeCategory[typ.Family()]
  2949  }
  2950  
  2951  var pgCatalogViewsTable = virtualSchemaTable{
  2952  	comment: `view definitions (incomplete - see also information_schema.views)
  2953  https://www.postgresql.org/docs/9.5/view-pg-views.html`,
  2954  	schema: `
  2955  CREATE TABLE pg_catalog.pg_views (
  2956  	schemaname NAME,
  2957  	viewname NAME,
  2958  	viewowner STRING,
  2959  	definition STRING
  2960  )`,
  2961  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  2962  		// Note: pg_views is not well defined if the dbContext is empty,
  2963  		// because it does not distinguish views in separate databases.
  2964  		return forEachTableDesc(ctx, p, dbContext, hideVirtual, /*virtual schemas do not have views*/
  2965  			func(db *sqlbase.DatabaseDescriptor, scName string, desc *sqlbase.TableDescriptor) error {
  2966  				if !desc.IsView() {
  2967  					return nil
  2968  				}
  2969  				// Note that the view query printed will not include any column aliases
  2970  				// specified outside the initial view query into the definition
  2971  				// returned, unlike postgres. For example, for the view created via
  2972  				//  `CREATE VIEW (a) AS SELECT b FROM foo`
  2973  				// we'll only print `SELECT b FROM foo` as the view definition here,
  2974  				// while postgres would more accurately print `SELECT b AS a FROM foo`.
  2975  				// TODO(a-robinson): Insert column aliases into view query once we
  2976  				// have a semantic query representation to work with (#10083).
  2977  				return addRow(
  2978  					tree.NewDName(scName),           // schemaname
  2979  					tree.NewDName(desc.Name),        // viewname
  2980  					tree.DNull,                      // viewowner
  2981  					tree.NewDString(desc.ViewQuery), // definition
  2982  				)
  2983  			})
  2984  	},
  2985  }
  2986  
  2987  var pgCatalogAggregateTable = virtualSchemaTable{
  2988  	comment: `aggregated built-in functions (incomplete)
  2989  https://www.postgresql.org/docs/9.6/catalog-pg-aggregate.html`,
  2990  	schema: `
  2991  CREATE TABLE pg_catalog.pg_aggregate (
  2992  	aggfnoid REGPROC,
  2993  	aggkind  CHAR,
  2994  	aggnumdirectargs INT2,
  2995  	aggtransfn REGPROC,
  2996  	aggfinalfn REGPROC,
  2997  	aggcombinefn REGPROC,
  2998  	aggserialfn REGPROC,
  2999  	aggdeserialfn REGPROC,
  3000  	aggmtransfn REGPROC,
  3001  	aggminvtransfn REGPROC,
  3002  	aggmfinalfn REGPROC,
  3003  	aggfinalextra BOOL,
  3004  	aggmfinalextra BOOL,
  3005  	aggsortop OID,
  3006  	aggtranstype OID,
  3007  	aggtransspace INT4,
  3008  	aggmtranstype OID,
  3009  	aggmtransspace INT4,
  3010  	agginitval TEXT,
  3011  	aggminitval TEXT
  3012  )
  3013  `,
  3014  	populate: func(ctx context.Context, p *planner, dbContext *DatabaseDescriptor, addRow func(...tree.Datum) error) error {
  3015  		h := makeOidHasher()
  3016  		return forEachDatabaseDesc(ctx, p, dbContext, false, /* requiresPrivileges */
  3017  			func(db *DatabaseDescriptor) error {
  3018  				for _, name := range builtins.AllAggregateBuiltinNames {
  3019  					if name == builtins.AnyNotNull {
  3020  						// any_not_null is treated as a special case.
  3021  						continue
  3022  					}
  3023  					_, overloads := builtins.GetBuiltinProperties(name)
  3024  					for _, overload := range overloads {
  3025  						params, _ := tree.GetParamsAndReturnType(overload)
  3026  						sortOperatorOid := oidZero
  3027  						aggregateKind := tree.NewDString("n")
  3028  						aggNumDirectArgs := zeroVal
  3029  						if params.Length() != 0 {
  3030  							argType := tree.NewDOid(tree.DInt(params.Types()[0].Oid()))
  3031  							returnType := tree.NewDOid(tree.DInt(oid.T_bool))
  3032  							switch name {
  3033  							// Cases to determine sort operator.
  3034  							case "max", "bool_or":
  3035  								sortOperatorOid = h.OperatorOid(">", argType, argType, returnType)
  3036  							case "min", "bool_and", "every":
  3037  								sortOperatorOid = h.OperatorOid("<", argType, argType, returnType)
  3038  
  3039  							// Cases to determine aggregate kind.
  3040  							case "rank", "percent_rank", "cume_dist", "dense_rank":
  3041  								aggregateKind = tree.NewDString("h")
  3042  								aggNumDirectArgs = tree.NewDInt(1)
  3043  							case "mode":
  3044  								aggregateKind = tree.NewDString("o")
  3045  							default:
  3046  								if strings.HasPrefix(name, "percentile_") {
  3047  									aggregateKind = tree.NewDString("o")
  3048  									aggNumDirectArgs = tree.NewDInt(1)
  3049  								}
  3050  							}
  3051  						}
  3052  						regprocForZeroOid := tree.NewDOidWithName(tree.DInt(0), types.RegProc, "-")
  3053  						err := addRow(
  3054  							h.BuiltinOid(name, &overload).AsRegProc(name), // aggfnoid
  3055  							aggregateKind,     // aggkind
  3056  							aggNumDirectArgs,  // aggnumdirectargs
  3057  							regprocForZeroOid, // aggtransfn
  3058  							regprocForZeroOid, // aggfinalfn
  3059  							regprocForZeroOid, // aggcombinefn
  3060  							regprocForZeroOid, // aggserialfn
  3061  							regprocForZeroOid, // aggdeserialfn
  3062  							regprocForZeroOid, // aggmtransfn
  3063  							regprocForZeroOid, // aggminvtransfn
  3064  							regprocForZeroOid, // aggmfinalfn
  3065  							tree.DBoolFalse,   // aggfinalextra
  3066  							tree.DBoolFalse,   // aggmfinalextra
  3067  							sortOperatorOid,   // aggsortop
  3068  							tree.DNull,        // aggtranstype
  3069  							tree.DNull,        // aggtransspace
  3070  							tree.DNull,        // aggmtranstype
  3071  							tree.DNull,        // aggmtransspace
  3072  							tree.DNull,        // agginitval
  3073  							tree.DNull,        // aggminitval
  3074  						)
  3075  						if err != nil {
  3076  							return err
  3077  						}
  3078  					}
  3079  				}
  3080  				return nil
  3081  			})
  3082  	},
  3083  }
  3084  
  3085  // oidHasher provides a consistent hashing mechanism for object identifiers in
  3086  // pg_catalog tables, allowing for reliable joins across tables.
  3087  //
  3088  // In Postgres, oids are physical properties of database objects which are
  3089  // sequentially generated and naturally unique across all objects. See:
  3090  // https://www.postgresql.org/docs/9.6/static/datatype-oid.html.
  3091  // Because Cockroach does not have an equivalent concept, we generate arbitrary
  3092  // fingerprints for database objects with the only requirements being that they
  3093  // are unique across all objects and that they are stable across accesses.
  3094  //
  3095  // The type has a few layers of methods:
  3096  // - write<go_type> methods write concrete types to the underlying running hash.
  3097  // - write<db_object> methods account for single database objects like TableDescriptors
  3098  //   or IndexDescriptors in the running hash. These methods aim to write information
  3099  //   that would uniquely fingerprint the object to the hash using the first layer of
  3100  //   methods.
  3101  // - <DB_Object>Oid methods use the second layer of methods to construct a unique
  3102  //   object identifier for the provided database object. This object identifier will
  3103  //   be returned as a *tree.DInt, and the running hash will be reset. These are the
  3104  //   only methods that are part of the oidHasher's external facing interface.
  3105  //
  3106  type oidHasher struct {
  3107  	h hash.Hash32
  3108  }
  3109  
  3110  func makeOidHasher() oidHasher {
  3111  	return oidHasher{h: fnv.New32()}
  3112  }
  3113  
  3114  func (h oidHasher) writeStr(s string) {
  3115  	if _, err := h.h.Write([]byte(s)); err != nil {
  3116  		panic(err)
  3117  	}
  3118  }
  3119  
  3120  func (h oidHasher) writeBytes(b []byte) {
  3121  	if _, err := h.h.Write(b); err != nil {
  3122  		panic(err)
  3123  	}
  3124  }
  3125  
  3126  func (h oidHasher) writeUInt8(i uint8) {
  3127  	if err := binary.Write(h.h, binary.BigEndian, i); err != nil {
  3128  		panic(err)
  3129  	}
  3130  }
  3131  
  3132  func (h oidHasher) writeUInt32(i uint32) {
  3133  	if err := binary.Write(h.h, binary.BigEndian, i); err != nil {
  3134  		panic(err)
  3135  	}
  3136  }
  3137  
  3138  func (h oidHasher) writeUInt64(i uint64) {
  3139  	if err := binary.Write(h.h, binary.BigEndian, i); err != nil {
  3140  		panic(err)
  3141  	}
  3142  }
  3143  
  3144  func (h oidHasher) writeOID(oid *tree.DOid) {
  3145  	h.writeUInt64(uint64(oid.DInt))
  3146  }
  3147  
  3148  type oidTypeTag uint8
  3149  
  3150  const (
  3151  	_ oidTypeTag = iota
  3152  	namespaceTypeTag
  3153  	indexTypeTag
  3154  	columnTypeTag
  3155  	checkConstraintTypeTag
  3156  	fkConstraintTypeTag
  3157  	pKeyConstraintTypeTag
  3158  	uniqueConstraintTypeTag
  3159  	functionTypeTag
  3160  	userTypeTag
  3161  	collationTypeTag
  3162  	operatorTypeTag
  3163  	enumEntryTypeTag
  3164  )
  3165  
  3166  func (h oidHasher) writeTypeTag(tag oidTypeTag) {
  3167  	h.writeUInt8(uint8(tag))
  3168  }
  3169  
  3170  func (h oidHasher) getOid() *tree.DOid {
  3171  	i := h.h.Sum32()
  3172  	h.h.Reset()
  3173  	return tree.NewDOid(tree.DInt(i))
  3174  }
  3175  
  3176  func (h oidHasher) writeDB(db *sqlbase.DatabaseDescriptor) {
  3177  	h.writeUInt32(uint32(db.ID))
  3178  }
  3179  
  3180  func (h oidHasher) writeSchema(scName string) {
  3181  	h.writeStr(scName)
  3182  }
  3183  
  3184  func (h oidHasher) writeTable(tableID sqlbase.ID) {
  3185  	h.writeUInt32(uint32(tableID))
  3186  }
  3187  
  3188  func (h oidHasher) writeIndex(indexID sqlbase.IndexID) {
  3189  	h.writeUInt32(uint32(indexID))
  3190  }
  3191  
  3192  func (h oidHasher) writeCheckConstraint(check *sqlbase.TableDescriptor_CheckConstraint) {
  3193  	h.writeStr(check.Name)
  3194  	h.writeStr(check.Expr)
  3195  }
  3196  
  3197  func (h oidHasher) writeForeignKeyConstraint(fk *sqlbase.ForeignKeyConstraint) {
  3198  	h.writeUInt32(uint32(fk.ReferencedTableID))
  3199  	h.writeStr(fk.Name)
  3200  }
  3201  
  3202  func (h oidHasher) NamespaceOid(db *sqlbase.DatabaseDescriptor, scName string) *tree.DOid {
  3203  	h.writeTypeTag(namespaceTypeTag)
  3204  	h.writeDB(db)
  3205  	h.writeSchema(scName)
  3206  	return h.getOid()
  3207  }
  3208  
  3209  func (h oidHasher) IndexOid(tableID sqlbase.ID, indexID sqlbase.IndexID) *tree.DOid {
  3210  	h.writeTypeTag(indexTypeTag)
  3211  	h.writeTable(tableID)
  3212  	h.writeIndex(indexID)
  3213  	return h.getOid()
  3214  }
  3215  
  3216  func (h oidHasher) ColumnOid(tableID sqlbase.ID, columnID sqlbase.ColumnID) *tree.DOid {
  3217  	h.writeTypeTag(columnTypeTag)
  3218  	h.writeUInt32(uint32(tableID))
  3219  	h.writeUInt32(uint32(columnID))
  3220  	return h.getOid()
  3221  }
  3222  
  3223  func (h oidHasher) CheckConstraintOid(
  3224  	db *sqlbase.DatabaseDescriptor,
  3225  	scName string,
  3226  	table *sqlbase.TableDescriptor,
  3227  	check *sqlbase.TableDescriptor_CheckConstraint,
  3228  ) *tree.DOid {
  3229  	h.writeTypeTag(checkConstraintTypeTag)
  3230  	h.writeDB(db)
  3231  	h.writeSchema(scName)
  3232  	h.writeTable(table.ID)
  3233  	h.writeCheckConstraint(check)
  3234  	return h.getOid()
  3235  }
  3236  
  3237  func (h oidHasher) PrimaryKeyConstraintOid(
  3238  	db *sqlbase.DatabaseDescriptor,
  3239  	scName string,
  3240  	table *sqlbase.TableDescriptor,
  3241  	pkey *sqlbase.IndexDescriptor,
  3242  ) *tree.DOid {
  3243  	h.writeTypeTag(pKeyConstraintTypeTag)
  3244  	h.writeDB(db)
  3245  	h.writeSchema(scName)
  3246  	h.writeTable(table.ID)
  3247  	h.writeIndex(pkey.ID)
  3248  	return h.getOid()
  3249  }
  3250  
  3251  func (h oidHasher) ForeignKeyConstraintOid(
  3252  	db *sqlbase.DatabaseDescriptor,
  3253  	scName string,
  3254  	table *sqlbase.TableDescriptor,
  3255  	fk *sqlbase.ForeignKeyConstraint,
  3256  ) *tree.DOid {
  3257  	h.writeTypeTag(fkConstraintTypeTag)
  3258  	h.writeDB(db)
  3259  	h.writeSchema(scName)
  3260  	h.writeTable(table.ID)
  3261  	h.writeForeignKeyConstraint(fk)
  3262  	return h.getOid()
  3263  }
  3264  
  3265  func (h oidHasher) UniqueConstraintOid(
  3266  	db *sqlbase.DatabaseDescriptor,
  3267  	scName string,
  3268  	table *sqlbase.TableDescriptor,
  3269  	index *sqlbase.IndexDescriptor,
  3270  ) *tree.DOid {
  3271  	h.writeTypeTag(uniqueConstraintTypeTag)
  3272  	h.writeDB(db)
  3273  	h.writeSchema(scName)
  3274  	h.writeTable(table.ID)
  3275  	h.writeIndex(index.ID)
  3276  	return h.getOid()
  3277  }
  3278  
  3279  func (h oidHasher) BuiltinOid(name string, builtin *tree.Overload) *tree.DOid {
  3280  	h.writeTypeTag(functionTypeTag)
  3281  	h.writeStr(name)
  3282  	h.writeStr(builtin.Types.String())
  3283  	h.writeStr(builtin.FixedReturnType().String())
  3284  	return h.getOid()
  3285  }
  3286  
  3287  func (h oidHasher) RegProc(name string) tree.Datum {
  3288  	_, overloads := builtins.GetBuiltinProperties(name)
  3289  	if len(overloads) == 0 {
  3290  		return tree.DNull
  3291  	}
  3292  	return h.BuiltinOid(name, &overloads[0]).AsRegProc(name)
  3293  }
  3294  
  3295  func (h oidHasher) UserOid(username string) *tree.DOid {
  3296  	h.writeTypeTag(userTypeTag)
  3297  	h.writeStr(username)
  3298  	return h.getOid()
  3299  }
  3300  
  3301  func (h oidHasher) CollationOid(collation string) *tree.DOid {
  3302  	h.writeTypeTag(collationTypeTag)
  3303  	h.writeStr(collation)
  3304  	return h.getOid()
  3305  }
  3306  
  3307  func (h oidHasher) OperatorOid(name string, leftType, rightType, returnType *tree.DOid) *tree.DOid {
  3308  	h.writeTypeTag(operatorTypeTag)
  3309  	h.writeStr(name)
  3310  	h.writeOID(leftType)
  3311  	h.writeOID(rightType)
  3312  	h.writeOID(returnType)
  3313  	return h.getOid()
  3314  }
  3315  
  3316  func (h oidHasher) EnumEntryOid(typOID *tree.DOid, physicalRep []byte) *tree.DOid {
  3317  	h.writeTypeTag(enumEntryTypeTag)
  3318  	h.writeOID(typOID)
  3319  	h.writeBytes(physicalRep)
  3320  	return h.getOid()
  3321  }
  3322  
  3323  func tableOid(id sqlbase.ID) *tree.DOid {
  3324  	return tree.NewDOid(tree.DInt(id))
  3325  }
  3326  
  3327  func dbOid(id sqlbase.ID) *tree.DOid {
  3328  	return tree.NewDOid(tree.DInt(id))
  3329  }
  3330  
  3331  func stringOid(s string) *tree.DOid {
  3332  	h := makeOidHasher()
  3333  	h.writeStr(s)
  3334  	return h.getOid()
  3335  }