From d2b4f6373a093209c9d1832e5fedde5ae3293ef8 Mon Sep 17 00:00:00 2001 From: Nathan VanBenschoten Date: Mon, 19 Aug 2024 13:47:14 -0400 Subject: [PATCH] sql: implement pg_catalog.pg_prepared_xacts Informs #22329. `pg_catalog.pg_prepared_xacts` reads from `system.prepared_transactions`. Release note: None --- pkg/cli/clisqlshell/testdata/describe | 2 +- .../testdata/logic_test/crdb_internal | 2 +- .../testdata/logic_test/two_phase_commit | 5 ++- pkg/sql/pg_catalog.go | 39 ++++++++++++++++++- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/pkg/cli/clisqlshell/testdata/describe b/pkg/cli/clisqlshell/testdata/describe index afb2dbef5c3f..ad4d4186a119 100644 --- a/pkg/cli/clisqlshell/testdata/describe +++ b/pkg/cli/clisqlshell/testdata/describe @@ -563,7 +563,7 @@ pg_catalog,pg_policies,table,node,permanent,prefix,pg_policies was created for c pg_catalog,pg_policy,table,node,permanent,prefix,pg_policy was created for compatibility and is currently unimplemented pg_catalog,pg_prepared_statements,table,node,permanent,prefix,"prepared statements https://www.postgresql.org/docs/9.6/view-pg-prepared-statements.html" -pg_catalog,pg_prepared_xacts,table,node,permanent,prefix,"prepared transactions (empty - feature does not exist) +pg_catalog,pg_prepared_xacts,table,node,permanent,prefix,"prepared transactions https://www.postgresql.org/docs/9.6/view-pg-prepared-xacts.html" pg_catalog,pg_proc,table,node,permanent,prefix,"built-in functions (incomplete) https://www.postgresql.org/docs/16/catalog-pg-proc.html" diff --git a/pkg/sql/logictest/testdata/logic_test/crdb_internal b/pkg/sql/logictest/testdata/logic_test/crdb_internal index 3badea94370c..8acaddb5415e 100644 --- a/pkg/sql/logictest/testdata/logic_test/crdb_internal +++ b/pkg/sql/logictest/testdata/logic_test/crdb_internal @@ -126,7 +126,7 @@ pg_partitioned_table true pg_policies true pg_policy true pg_prepared_statements false -pg_prepared_xacts true +pg_prepared_xacts false pg_proc false pg_publication true pg_publication_rel true diff --git a/pkg/sql/logictest/testdata/logic_test/two_phase_commit b/pkg/sql/logictest/testdata/logic_test/two_phase_commit index 751c5a270d7f..507b819b3cde 100644 --- a/pkg/sql/logictest/testdata/logic_test/two_phase_commit +++ b/pkg/sql/logictest/testdata/logic_test/two_phase_commit @@ -39,10 +39,10 @@ read-only root test # Verify the prepared transaction is visible in the pg_catalog.pg_prepared_xacts # table. -# TODO(nvanbenschoten): implement. query ITTT SELECT transaction, gid, owner, database FROM pg_catalog.pg_prepared_xacts ---- +0 read-only root test # Commit the read-only prepared transaction. statement ok @@ -279,10 +279,11 @@ SELECT global_id, owner, database FROM system.prepared_transactions read-write-root root test read-write-testuser testuser test -# TODO(nvanbenschoten): implement. query ITTT rowsort SELECT transaction, gid, owner, database FROM pg_catalog.pg_prepared_xacts ---- +0 read-write-root root test +0 read-write-testuser testuser test statement ok ROLLBACK PREPARED 'read-write-root' diff --git a/pkg/sql/pg_catalog.go b/pkg/sql/pg_catalog.go index 31a515fbe350..5a24bfa6a9a2 100644 --- a/pkg/sql/pg_catalog.go +++ b/pkg/sql/pg_catalog.go @@ -2419,13 +2419,48 @@ https://www.postgresql.org/docs/9.5/catalog-pg-operator.html`, } var pgCatalogPreparedXactsTable = virtualSchemaTable{ - comment: `prepared transactions (empty - feature does not exist) + comment: `prepared transactions https://www.postgresql.org/docs/9.6/view-pg-prepared-xacts.html`, schema: vtable.PGCatalogPreparedXacts, populate: func(ctx context.Context, p *planner, dbContext catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) error { + rows, err := p.InternalSQLTxn().QueryBufferedEx( + ctx, + "select-prepared-transactions", + p.Txn(), + sessiondata.NodeUserSessionDataOverride, + `SELECT global_id, prepared, owner, database FROM system.prepared_transactions`, + ) + if err != nil { + if pgerror.GetPGCode(err) == pgcode.UndefinedTable { + // If the table does not exist, we're in a mixed-version cluster and the + // feature is not supported yet. Just return an empty result. + // TODO(nvanbenschoten): Remove this logic when mixed-version support + // with v24.2 is no longer necessary. + return nil + } + return err + } + for _, row := range rows { + // NOTE: we can't map a 128-bit CockroachDB transaction ID to a 32-bit + // Postgres xid, so we just return zero for each transaction's xid. This + // is acceptable, as the gid is the important part of pg_prepared_xacts. + transaction := zeroVal + globalID := row[0] + prepared := row[1] + owner := tree.NewDName(string(tree.MustBeDString(row[2]))) + database := tree.NewDName(string(tree.MustBeDString(row[3]))) + if err := addRow( + transaction, // transaction + globalID, // gid + prepared, // prepared + owner, // owner + database, // database + ); err != nil { + return err + } + } return nil }, - unimplemented: true, } // pgCatalogPreparedStatementsTable implements the pg_prepared_statements table.