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 }