From b4e72966b46b118b77a3ca98ffc0fdb5b77eade8 Mon Sep 17 00:00:00 2001 From: Andy Yang Date: Wed, 1 Mar 2023 15:05:01 -0500 Subject: [PATCH] sql,externalconn: add owner_id column to system.external_connections This patch adds a new `owner_id` column to the `system.external_connections` table, which corresponds to the existing `owner` column, in order to bring us closer to the eventual goal of allowing renaming of users. Migrations are also added to alter and backfill the table in older clusters. Release note: None --- .../settings/settings-for-tenants.txt | 2 +- docs/generated/settings/settings.html | 2 +- .../cloudccl/externalconn/datadriven_test.go | 6 +- .../testdata/create_drop_external_connection | 22 +-- .../create_drop_external_connection | 20 +-- .../privileges_external_connection | 8 +- .../testdata/privileges_external_connection | 8 +- pkg/cli/testdata/declarative-rules/deprules | 2 +- pkg/cli/testdata/declarative-rules/oprules | 2 +- pkg/cloud/externalconn/BUILD.bazel | 1 + pkg/cloud/externalconn/record.go | 35 +++- pkg/clusterversion/cockroach_versions.go | 17 ++ pkg/sql/catalog/bootstrap/testdata/testdata | 8 +- pkg/sql/catalog/systemschema/system.go | 8 +- .../systemschema_test/testdata/bootstrap | 3 +- pkg/sql/create_external_connection.go | 19 +- .../testdata/logic_test/crdb_internal_catalog | 2 +- .../testdata/logic_test/information_schema | 1 + ...ixed_version_external_connections_owner_id | 51 ++++++ .../BUILD.bazel | 2 +- .../generated_test.go | 7 + pkg/upgrade/upgrades/BUILD.bazel | 3 + ...nal_connections_table_user_id_migration.go | 88 +++++++++ ...onnections_table_user_id_migration_test.go | 167 ++++++++++++++++++ pkg/upgrade/upgrades/upgrades.go | 12 ++ 25 files changed, 444 insertions(+), 52 deletions(-) create mode 100644 pkg/sql/logictest/testdata/logic_test/mixed_version_external_connections_owner_id create mode 100644 pkg/upgrade/upgrades/external_connections_table_user_id_migration.go create mode 100644 pkg/upgrade/upgrades/external_connections_table_user_id_migration_test.go diff --git a/docs/generated/settings/settings-for-tenants.txt b/docs/generated/settings/settings-for-tenants.txt index 0f6328780e85..713d9ed3903f 100644 --- a/docs/generated/settings/settings-for-tenants.txt +++ b/docs/generated/settings/settings-for-tenants.txt @@ -299,4 +299,4 @@ trace.opentelemetry.collector string address of an OpenTelemetry trace collecto trace.snapshot.rate duration 0s if non-zero, interval at which background trace snapshots are captured trace.span_registry.enabled boolean true if set, ongoing traces can be seen at https:///#/debug/tracez trace.zipkin.collector string the address of a Zipkin instance to receive traces, as :. If no port is specified, 9411 will be used. -version version 1000022.2-72 set the active cluster version in the format '.' +version version 1000022.2-76 set the active cluster version in the format '.' diff --git a/docs/generated/settings/settings.html b/docs/generated/settings/settings.html index ebaf3e3f13d8..0e2acaf65bea 100644 --- a/docs/generated/settings/settings.html +++ b/docs/generated/settings/settings.html @@ -240,6 +240,6 @@
trace.snapshot.rate
duration0sif non-zero, interval at which background trace snapshots are captured
trace.span_registry.enabled
booleantrueif set, ongoing traces can be seen at https://<ui>/#/debug/tracez
trace.zipkin.collector
stringthe address of a Zipkin instance to receive traces, as <host>:<port>. If no port is specified, 9411 will be used. -
version
version1000022.2-72set the active cluster version in the format '<major>.<minor>' +
version
version1000022.2-76set the active cluster version in the format '<major>.<minor>' diff --git a/pkg/ccl/cloudccl/externalconn/datadriven_test.go b/pkg/ccl/cloudccl/externalconn/datadriven_test.go index e111522a646b..4477a540886e 100644 --- a/pkg/ccl/cloudccl/externalconn/datadriven_test.go +++ b/pkg/ccl/cloudccl/externalconn/datadriven_test.go @@ -123,7 +123,11 @@ func TestDataDriven(t *testing.T) { case "inspect-system-table": rows := tenant.Query(` -SELECT connection_name, connection_type, crdb_internal.pb_to_json('cockroach.cloud.externalconn.connectionpb.ConnectionDetails', connection_details), owner +SELECT connection_name, + connection_type, + crdb_internal.pb_to_json('cockroach.cloud.externalconn.connectionpb.ConnectionDetails', connection_details), + owner, + owner_id FROM system.external_connections; `) output, err := sqlutils.RowsToDataDrivenOutput(rows) diff --git a/pkg/ccl/cloudccl/externalconn/testdata/create_drop_external_connection b/pkg/ccl/cloudccl/externalconn/testdata/create_drop_external_connection index 2d254ee0c7a9..4d51f420e2d2 100644 --- a/pkg/ccl/cloudccl/externalconn/testdata/create_drop_external_connection +++ b/pkg/ccl/cloudccl/externalconn/testdata/create_drop_external_connection @@ -6,7 +6,7 @@ CREATE EXTERNAL CONNECTION foo AS 'nodelocal://1/foo/bar'; inspect-system-table ---- -foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root +foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1 # Reject invalid nodelocal URIs. exec-sql @@ -32,8 +32,8 @@ CREATE EXTERNAL CONNECTION bar123 AS 'nodelocal://1/baz'; inspect-system-table ---- -bar123 STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/baz"}} root -foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root +bar123 STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/baz"}} root 1 +foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1 # Drop an External Connection that does not exist. exec-sql @@ -46,7 +46,7 @@ DROP EXTERNAL CONNECTION bar123; inspect-system-table ---- -foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root +foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1 exec-sql DROP EXTERNAL CONNECTION foo; @@ -79,7 +79,7 @@ pq: failed to construct External Connection details: failed to create GCP KMS ex inspect-system-table ---- -foo-kms KMS {"provider": "gcp_kms", "simpleUri": {"uri": "gcp-kms:///cmk?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root +foo-kms KMS {"provider": "gcp_kms", "simpleUri": {"uri": "gcp-kms:///cmk?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-kms"; @@ -115,7 +115,7 @@ pq: failed to construct External Connection details: failed to create s3 externa inspect-system-table ---- -foo-s3 STORAGE {"provider": "s3", "simpleUri": {"uri": "s3://foo/bar?AUTH=implicit&AWS_ACCESS_KEY_ID=123&AWS_SECRET_ACCESS_KEY=456&ASSUME_ROLE=ronaldo,rashford,bruno"}} root +foo-s3 STORAGE {"provider": "s3", "simpleUri": {"uri": "s3://foo/bar?AUTH=implicit&AWS_ACCESS_KEY_ID=123&AWS_SECRET_ACCESS_KEY=456&ASSUME_ROLE=ronaldo,rashford,bruno"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-s3"; @@ -148,7 +148,7 @@ pq: failed to construct External Connection details: invalid changefeed sink URI inspect-system-table ---- -foo-kafka STORAGE {"provider": "kafka", "simpleUri": {"uri": "kafka://broker.address.com:9092?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg==&sasl_enabled=true&sasl_user={sasl user}&sasl_password={url-encoded password}&sasl_mechanism=SCRAM-SHA-256"}} root +foo-kafka STORAGE {"provider": "kafka", "simpleUri": {"uri": "kafka://broker.address.com:9092?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg==&sasl_enabled=true&sasl_user={sasl user}&sasl_password={url-encoded password}&sasl_mechanism=SCRAM-SHA-256"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-kafka" @@ -164,7 +164,7 @@ CREATE EXTERNAL CONNECTION "foo-userfile" AS 'userfile:///foo/bar'; inspect-system-table ---- -foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root +foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root 1 # Reject invalid userfile URIs. exec-sql @@ -179,7 +179,7 @@ pq: failed to construct External Connection details: failed to create userfile e inspect-system-table ---- -foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root +foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-userfile"; @@ -209,7 +209,7 @@ pq: failed to construct External Connection details: failed to create gs externa inspect-system-table ---- -foo-gs STORAGE {"provider": "gs", "simpleUri": {"uri": "gs://bucket/path?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root +foo-gs STORAGE {"provider": "gs", "simpleUri": {"uri": "gs://bucket/path?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-gs"; @@ -247,7 +247,7 @@ pq: failed to construct External Connection details: failed to create azure exte inspect-system-table ---- -foo-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure-storage://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root +foo-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure-storage://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-azure"; diff --git a/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/create_drop_external_connection b/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/create_drop_external_connection index 3de6affca688..ed3b8ebff40c 100644 --- a/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/create_drop_external_connection +++ b/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/create_drop_external_connection @@ -9,7 +9,7 @@ CREATE EXTERNAL CONNECTION foo AS 'nodelocal://1/foo/bar'; inspect-system-table ---- -foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root +foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1 # Reject invalid nodelocal URIs. exec-sql @@ -35,8 +35,8 @@ CREATE EXTERNAL CONNECTION bar123 AS 'nodelocal://1/baz'; inspect-system-table ---- -bar123 STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/baz"}} root -foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root +bar123 STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/baz"}} root 1 +foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1 # Drop an External Connection that does not exist. exec-sql @@ -49,7 +49,7 @@ DROP EXTERNAL CONNECTION bar123; inspect-system-table ---- -foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root +foo STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo/bar"}} root 1 exec-sql DROP EXTERNAL CONNECTION foo; @@ -71,7 +71,7 @@ CREATE EXTERNAL CONNECTION "foo-kms" AS 'gcp-kms:///cmk?AUTH=specified&BEARER_TO inspect-system-table ---- -foo-kms KMS {"provider": "gcp_kms", "simpleUri": {"uri": "gcp-kms:///cmk?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root +foo-kms KMS {"provider": "gcp_kms", "simpleUri": {"uri": "gcp-kms:///cmk?AUTH=specified&BEARER_TOKEN=c29tZXRoaW5nCg=="}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-kms"; @@ -107,7 +107,7 @@ pq: failed to construct External Connection details: failed to create s3 externa inspect-system-table ---- -foo-s3 STORAGE {"provider": "s3", "simpleUri": {"uri": "s3://foo/bar?AUTH=implicit&AWS_ACCESS_KEY_ID=123&AWS_SECRET_ACCESS_KEY=456&ASSUME_ROLE=ronaldo,rashford,bruno"}} root +foo-s3 STORAGE {"provider": "s3", "simpleUri": {"uri": "s3://foo/bar?AUTH=implicit&AWS_ACCESS_KEY_ID=123&AWS_SECRET_ACCESS_KEY=456&ASSUME_ROLE=ronaldo,rashford,bruno"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-s3"; @@ -140,7 +140,7 @@ pq: failed to construct External Connection details: invalid changefeed sink URI inspect-system-table ---- -foo-kafka STORAGE {"provider": "kafka", "simpleUri": {"uri": "kafka://broker.address.com:9092?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg==&sasl_enabled=true&sasl_user={sasl user}&sasl_password={url-encoded password}&sasl_mechanism=SCRAM-SHA-256"}} root +foo-kafka STORAGE {"provider": "kafka", "simpleUri": {"uri": "kafka://broker.address.com:9092?topic_prefix=bar_&tls_enabled=true&ca_cert=Zm9vCg==&sasl_enabled=true&sasl_user={sasl user}&sasl_password={url-encoded password}&sasl_mechanism=SCRAM-SHA-256"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-kafka" @@ -156,7 +156,7 @@ CREATE EXTERNAL CONNECTION "foo-userfile" AS 'userfile:///foo/bar'; inspect-system-table ---- -foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root +foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root 1 # Reject invalid userfile URIs. exec-sql @@ -171,7 +171,7 @@ pq: failed to construct External Connection details: failed to create userfile e inspect-system-table ---- -foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root +foo-userfile STORAGE {"provider": "userfile", "simpleUri": {"uri": "userfile:///foo/bar"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-userfile"; @@ -206,7 +206,7 @@ pq: failed to construct External Connection details: failed to create azure exte inspect-system-table ---- -foo-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure-storage://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root +foo-azure STORAGE {"provider": "azure_storage", "simpleUri": {"uri": "azure-storage://bucket/path?AZURE_ACCOUNT_NAME=foo&AZURE_ACCOUNT_KEY=Zm9vCg==&AZURE_ENVIRONMENT=AzureUSGovernmentCloud"}} root 1 exec-sql DROP EXTERNAL CONNECTION "foo-azure"; diff --git a/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/privileges_external_connection b/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/privileges_external_connection index e4f6a30ec448..d76b026b8c0a 100644 --- a/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/privileges_external_connection +++ b/pkg/ccl/cloudccl/externalconn/testdata/multi-tenant/privileges_external_connection @@ -22,7 +22,7 @@ CREATE EXTERNAL CONNECTION "global-privileged" AS 'nodelocal://1/foo' inspect-system-table ---- -global-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} testuser +global-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} testuser 100 exec-sql DROP EXTERNAL CONNECTION "global-privileged"; @@ -57,8 +57,8 @@ pq: user testuser does not have DROP privilege on external_connection drop-privi inspect-system-table ---- -drop-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root -drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root +drop-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root 1 +drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root 1 exec-sql GRANT DROP ON EXTERNAL CONNECTION "drop-privileged" TO testuser; @@ -76,7 +76,7 @@ pq: user testuser does not have DROP privilege on external_connection drop-privi inspect-system-table ---- -drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root +drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root 1 exec-sql DROP EXTERNAL CONNECTION 'drop-privileged-dup' diff --git a/pkg/ccl/cloudccl/externalconn/testdata/privileges_external_connection b/pkg/ccl/cloudccl/externalconn/testdata/privileges_external_connection index 4a7277662e20..e7cb398838a9 100644 --- a/pkg/ccl/cloudccl/externalconn/testdata/privileges_external_connection +++ b/pkg/ccl/cloudccl/externalconn/testdata/privileges_external_connection @@ -19,7 +19,7 @@ CREATE EXTERNAL CONNECTION "global-privileged" AS 'nodelocal://1/foo' inspect-system-table ---- -global-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} testuser +global-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} testuser 100 exec-sql DROP EXTERNAL CONNECTION "global-privileged"; @@ -54,8 +54,8 @@ pq: user testuser does not have DROP privilege on external_connection drop-privi inspect-system-table ---- -drop-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root -drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root +drop-privileged STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root 1 +drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root 1 exec-sql GRANT DROP ON EXTERNAL CONNECTION "drop-privileged" TO testuser; @@ -81,7 +81,7 @@ pq: user testuser does not have DROP privilege on external_connection drop-privi inspect-system-table ---- -drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root +drop-privileged-dup STORAGE {"provider": "nodelocal", "simpleUri": {"uri": "nodelocal://1/foo"}} root 1 exec-sql DROP EXTERNAL CONNECTION 'drop-privileged-dup' diff --git a/pkg/cli/testdata/declarative-rules/deprules b/pkg/cli/testdata/declarative-rules/deprules index 0f965d598bfb..27049d7bd84a 100644 --- a/pkg/cli/testdata/declarative-rules/deprules +++ b/pkg/cli/testdata/declarative-rules/deprules @@ -1,6 +1,6 @@ dep ---- -debug declarative-print-rules 1000022.2-72 dep +debug declarative-print-rules 1000022.2-76 dep deprules ---- - name: 'CheckConstraint transitions to ABSENT uphold 2-version invariant: PUBLIC->VALIDATED' diff --git a/pkg/cli/testdata/declarative-rules/oprules b/pkg/cli/testdata/declarative-rules/oprules index cc76a319262a..4f693c5a0512 100644 --- a/pkg/cli/testdata/declarative-rules/oprules +++ b/pkg/cli/testdata/declarative-rules/oprules @@ -1,6 +1,6 @@ op ---- -debug declarative-print-rules 1000022.2-72 op +debug declarative-print-rules 1000022.2-76 op rules ---- [] diff --git a/pkg/cloud/externalconn/BUILD.bazel b/pkg/cloud/externalconn/BUILD.bazel index f1adec1de0d7..0e614116925e 100644 --- a/pkg/cloud/externalconn/BUILD.bazel +++ b/pkg/cloud/externalconn/BUILD.bazel @@ -27,6 +27,7 @@ go_library( "//pkg/sql/sessiondata", "//pkg/util/protoutil", "@com_github_cockroachdb_errors//:errors", + "@com_github_lib_pq//oid", ], ) diff --git a/pkg/cloud/externalconn/record.go b/pkg/cloud/externalconn/record.go index 387095e56a30..1d5a9552e699 100644 --- a/pkg/cloud/externalconn/record.go +++ b/pkg/cloud/externalconn/record.go @@ -26,6 +26,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" "github.com/cockroachdb/cockroach/pkg/util/protoutil" "github.com/cockroachdb/errors" + "github.com/lib/pq/oid" ) // externalConnectionRecord is a reflective representation of a row in a @@ -39,6 +40,7 @@ type externalConnectionRecord struct { ConnectionType string `col:"connection_type"` ConnectionDetails connectionpb.ConnectionDetails `col:"connection_details"` Owner username.SQLUsername `col:"owner"` + OwnerID oid.Oid `col:"owner_id"` } // MutableExternalConnection is a mutable representation of an External @@ -112,6 +114,11 @@ func LoadExternalConnection( return ec, nil } +// ConnectionName returns the connection_name. +func (e *MutableExternalConnection) ConnectionName() string { + return e.rec.ConnectionName +} + // SetConnectionName updates the connection name. func (e *MutableExternalConnection) SetConnectionName(name string) { e.rec.ConnectionName = name @@ -151,9 +158,15 @@ func (e *MutableExternalConnection) SetOwner(owner username.SQLUsername) { e.markDirty("owner") } -// ConnectionName returns the connection_name. -func (e *MutableExternalConnection) ConnectionName() string { - return e.rec.ConnectionName +// OwnerID returns the user ID of the owner of the External Connection object. +func (e *MutableExternalConnection) OwnerID() oid.Oid { + return e.rec.OwnerID +} + +// SetOwnerID updates the External Connection object's owner user ID. +func (e *MutableExternalConnection) SetOwnerID(id oid.Oid) { + e.rec.OwnerID = id + e.markDirty("owner_id") } // UnredactedConnectionStatement implements the External Connection interface. @@ -181,6 +194,8 @@ func datumToNative(datum tree.Datum) (interface{}, error) { return []byte(*d), nil case *tree.DTimestamp: return d.Time, nil + case *tree.DOid: + return d.Oid, nil } return nil, errors.Newf("cannot handle type %T", datum) } @@ -279,9 +294,9 @@ func generatePlaceholders(n int) string { // table. If an error is returned, it is callers responsibility to handle it // (e.g. rollback transaction). func (e *MutableExternalConnection) Create( - ctx context.Context, txn isql.Txn, user username.SQLUsername, + ctx context.Context, txn isql.Txn, excludedCols map[string]bool, ) error { - cols, qargs, err := e.marshalChanges() + cols, qargs, err := e.marshalChanges(excludedCols) if err != nil { return err } @@ -320,11 +335,17 @@ func (e *MutableExternalConnection) Create( // marshalChanges marshals all changes in the in-memory representation and returns // the names of the columns and marshaled values. -func (e *MutableExternalConnection) marshalChanges() ([]string, []interface{}, error) { +func (e *MutableExternalConnection) marshalChanges( + excludedCols map[string]bool, +) ([]string, []interface{}, error) { var cols []string var qargs []interface{} for col := range e.dirty { + if excludedCols[col] { + continue + } + var arg tree.Datum var err error @@ -337,6 +358,8 @@ func (e *MutableExternalConnection) marshalChanges() ([]string, []interface{}, e arg, err = marshalProto(&e.rec.ConnectionDetails) case `owner`: arg = tree.NewDString(e.rec.Owner.Normalized()) + case `owner_id`: + arg = tree.NewDOid(e.rec.OwnerID) default: return nil, nil, errors.Newf("cannot marshal column %q", col) } diff --git a/pkg/clusterversion/cockroach_versions.go b/pkg/clusterversion/cockroach_versions.go index f2b1bd64dc09..0c174d74e4eb 100644 --- a/pkg/clusterversion/cockroach_versions.go +++ b/pkg/clusterversion/cockroach_versions.go @@ -473,6 +473,15 @@ const ( // keys that are not regional by row compatible. V23_1_SystemRbrCleanup + // V23_1ExternalConnectionsTableHasOwnerIDColumn is the version where the + // owner_id column has been added to the system.external_connections table. + V23_1ExternalConnectionsTableHasOwnerIDColumn + + // V23_1ExternalConnectionsTableOwnerIDColumnBackfilled is the version + // where the owner_id column in the system.external_connections table + // has been backfilled. + V23_1ExternalConnectionsTableOwnerIDColumnBackfilled + // ************************************************* // Step (1): Add new versions here. // Do not add new versions to a patch release. @@ -818,6 +827,14 @@ var rawVersionsSingleton = keyedVersions{ Key: V23_1_SystemRbrCleanup, Version: roachpb.Version{Major: 22, Minor: 2, Internal: 72}, }, + { + Key: V23_1ExternalConnectionsTableHasOwnerIDColumn, + Version: roachpb.Version{Major: 22, Minor: 2, Internal: 74}, + }, + { + Key: V23_1ExternalConnectionsTableOwnerIDColumnBackfilled, + Version: roachpb.Version{Major: 22, Minor: 2, Internal: 76}, + }, // ************************************************* // Step (2): Add new versions here. diff --git a/pkg/sql/catalog/bootstrap/testdata/testdata b/pkg/sql/catalog/bootstrap/testdata/testdata index 6880341b1fc1..1af08cb97881 100644 --- a/pkg/sql/catalog/bootstrap/testdata/testdata +++ b/pkg/sql/catalog/bootstrap/testdata/testdata @@ -1,4 +1,4 @@ -system hash=f97c02c734c17f44ad934c59245875f6c903ad104ba7e76caf207ff8e8781441 +system hash=e935d845b4027179deccb63f0590d74687a9f3ed1864c4f5c5e1e5a990f0357e ---- [{"key":"04646573632d696467656e","value":"01c801"} ,{"key":"8b"} @@ -43,7 +43,7 @@ system hash=f97c02c734c17f44ad934c59245875f6c903ad104ba7e76caf207ff8e8781441 ,{"key":"8b89b88a89","value":"030abe020a0b726f6c655f69645f7365711830200128013a00422a0a0576616c756510011a0c080110401800300050146000200030006800700078008001008801009801004800525c0a077072696d61727910011800220576616c7565300140004a10080010001a00200028003000380040005a007a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00100e0010060006a250a0d0a0561646d696e10a00618a0060a0c0a04726f6f7410a00618a00612046e6f64651802800100880103980100b201160a077072696d61727910001a0576616c756520012801b80100c20100e201180801106418ffffffff072064280032040800100038014200e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880300a80300b00300"} ,{"key":"8b89ba8a89","value":"030ad7050a0f74656e616e745f73657474696e67731832200128013a00422e0a0974656e616e745f696410011a0c0801104018003000501460002000300068007000780080010088010098010042290a046e616d6510021a0c08071000180030005019600020003000680070007800800100880100980100422a0a0576616c756510031a0c0807100018003000501960002000300068007000780080010088010098010042450a0c6c6173745f7570646174656410041a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d503000680070007800800100880100980100422f0a0a76616c75655f7479706510051a0c08071000180030005019600020003000680070007800800100880100980100422b0a06726561736f6e10061a0c080710001800300050196000200130006800700078008001008801009801004807529b010a077072696d61727910011801220974656e616e745f696422046e616d652a0576616c75652a0c6c6173745f757064617465642a0a76616c75655f747970652a06726561736f6e30013002400040004a10080010001a00200028003000380040005a0070037004700570067a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b20185010a3966616d5f305f74656e616e745f69645f6e616d655f76616c75655f6c6173745f757064617465645f76616c75655f747970655f726561736f6e10001a0974656e616e745f69641a046e616d651a0576616c75651a0c6c6173745f757064617465641a0a76616c75655f747970651a06726561736f6e2001200220032004200520062800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} ,{"key":"8b89bb8a89","value":"030ab2070a0a70726976696c656765731833200128013a00422d0a08757365726e616d6510011a0c0807100018003000501960002000300068007000780080010088010098010042290a047061746810021a0c0807100018003000501960002000300068007000780080010088010098010042400a0a70726976696c6567657310031a1d080f100018003000380750f1075a0c08071000180030005019600060002000300068007000780080010088010098010042430a0d6772616e745f6f7074696f6e7310041a1d080f100018003000380750f1075a0c080710001800300050196000600020003000680070007800800100880100980100422c0a07757365725f696410051a0c080c100018003000501a60002001300068007000780080010088010098010048065293010a077072696d617279100118012208757365726e616d652204706174682a0a70726976696c656765732a0d6772616e745f6f7074696f6e732a07757365725f696430013002400040004a10080010001a00200028003000380040005a007003700470057a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00103e001005a9d010a1b70726976696c656765735f706174685f757365725f69645f6b6579100218012204706174682207757365725f69642a0a70726976696c656765732a0d6772616e745f6f7074696f6e73300230053801400040004a10080010001a00200028003000380040005a00700370047a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00101e001005a9d010a1c70726976696c656765735f706174685f757365726e616d655f6b6579100318012204706174682208757365726e616d652a0a70726976696c656765732a0d6772616e745f6f7074696f6e7330023001400040004a10080010001a00200028003000380040005a00700370047a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00102e0010060046a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b2014b0a077072696d61727910001a08757365726e616d651a04706174681a0a70726976696c656765731a0d6772616e745f6f7074696f6e731a07757365725f6964200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880304a80300b00300"} -,{"key":"8b89bc8a89","value":"030afa050a1465787465726e616c5f636f6e6e656374696f6e731834200128013a0042340a0f636f6e6e656374696f6e5f6e616d6510011a0c0807100018003000501960002000300068007000780080010088010098010042400a076372656174656410021a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042400a077570646174656410031a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042340a0f636f6e6e656374696f6e5f7479706510041a0c0807100018003000501960002000300068007000780080010088010098010042370a12636f6e6e656374696f6e5f64657461696c7310051a0c08081000180030005011600020003000680070007800800100880100980100422a0a056f776e657210061a0c08071000180030005019600020003000680070007800800100880100980100480752ae010a077072696d61727910011801220f636f6e6e656374696f6e5f6e616d652a07637265617465642a07757064617465642a0f636f6e6e656374696f6e5f747970652a12636f6e6e656374696f6e5f64657461696c732a056f776e6572300140004a10080010001a00200028003000380040005a00700270037004700570067a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201680a077072696d61727910001a0f636f6e6e656374696f6e5f6e616d651a07637265617465641a07757064617465641a0f636f6e6e656374696f6e5f747970651a12636f6e6e656374696f6e5f64657461696c731a056f776e65722001200220032004200520062800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} +,{"key":"8b89bc8a89","value":"030ac1060a1465787465726e616c5f636f6e6e656374696f6e731834200128013a0042340a0f636f6e6e656374696f6e5f6e616d6510011a0c0807100018003000501960002000300068007000780080010088010098010042400a076372656174656410021a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042400a077570646174656410031a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042340a0f636f6e6e656374696f6e5f7479706510041a0c0807100018003000501960002000300068007000780080010088010098010042370a12636f6e6e656374696f6e5f64657461696c7310051a0c08081000180030005011600020003000680070007800800100880100980100422a0a056f776e657210061a0c08071000180030005019600020003000680070007800800100880100980100422d0a086f776e65725f696410071a0c080c100018003000501a600020013000680070007800800100880100980100480852ba010a077072696d61727910011801220f636f6e6e656374696f6e5f6e616d652a07637265617465642a07757064617465642a0f636f6e6e656374696f6e5f747970652a12636f6e6e656374696f6e5f64657461696c732a056f776e65722a086f776e65725f6964300140004a10080010001a00200028003000380040005a007002700370047005700670077a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201740a077072696d61727910001a0f636f6e6e656374696f6e5f6e616d651a07637265617465641a07757064617465641a0f636f6e6e656374696f6e5f747970651a12636f6e6e656374696f6e5f64657461696c731a056f776e65721a086f776e65725f696420012002200320042005200620072800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} ,{"key":"8b89bd8a89","value":"030a87040a086a6f625f696e666f1835200128013a00422b0a066a6f625f696410011a0c08011040180030005014600020003000680070007800800100880100980100422d0a08696e666f5f6b657910021a0c0808100018003000501160002000300068007000780080010088010098010042420a077772697474656e10031a0d080910001800300050a009600020002a136e6f7728293a3a3a54494d455354414d50545a3000680070007800800100880100980100422a0a0576616c756510041a0c0808100018003000501160002001300068007000780080010088010098010048055281010a077072696d6172791001180122066a6f625f69642208696e666f5f6b657922077772697474656e2a0576616c75653001300230034000400040014a10080010001a00200028003000380040005a0070047a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201370a077072696d61727910001a066a6f625f69641a08696e666f5f6b65791a077772697474656e1a0576616c756520012002200320042804b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} ,{"key":"8b89be8a89","value":"030af9030a167370616e5f73746174735f756e697175655f6b6579731836200128013a00423b0a02696410011a0d080e100018003000508617600020002a1167656e5f72616e646f6d5f7575696428293000680070007800800100880100980100422e0a096b65795f627974657310021a0c08081000180030005011600020013000680070007800800100880100980100480352660a077072696d61727910011801220269642a096b65795f6279746573300140004a10080010001a00200028003000380040005a0070027a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00102e001005a740a19756e697175655f6b6579735f6b65795f62797465735f6964781002180122096b65795f62797465733002380140004a10080010001a00200028003000380040005a007a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060036a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201200a077072696d61727910001a0269641a096b65795f6279746573200120022802b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880303a80300b00300"} ,{"key":"8b89bf8a89","value":"030adc050a127370616e5f73746174735f6275636b6574731837200128013a00423b0a02696410011a0d080e100018003000508617600020002a1167656e5f72616e646f6d5f7575696428293000680070007800800100880100980100422f0a0973616d706c655f696410021a0d080e10001800300050861760002000300068007000780080010088010098010042320a0c73746172745f6b65795f696410031a0d080e10001800300050861760002000300068007000780080010088010098010042300a0a656e645f6b65795f696410041a0d080e100018003000508617600020003000680070007800800100880100980100422d0a08726571756573747310051a0c0801104018003000501460002000300068007000780080010088010098010048065290010a077072696d61727910011801220269642a0973616d706c655f69642a0c73746172745f6b65795f69642a0a656e645f6b65795f69642a087265717565737473300140004a10080010001a00200028003000380040005a0070027003700470057a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e001005a700a156275636b6574735f73616d706c655f69645f69647810021800220973616d706c655f69643002380140004a10080010001a00200028003000380040005a007a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00100e0010060036a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b2014a0a077072696d61727910001a0269641a0973616d706c655f69641a0c73746172745f6b65795f69641a0a656e645f6b65795f69641a087265717565737473200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} @@ -163,7 +163,7 @@ system hash=f97c02c734c17f44ad934c59245875f6c903ad104ba7e76caf207ff8e8781441 ,{"key":"c1"} ] -tenant hash=76f051cc9eafd977b62ed5718d3412e532f961c3c229e3b3591946fa208d1952 +tenant hash=fa086a87fa2ecd8f485fc272ea7d85b08f30906235f83830dc446c098b895edc ---- [{"key":""} ,{"key":"8b89898a89","value":"0312390a0673797374656d10011a250a0d0a0561646d696e1080101880100a0c0a04726f6f7410801018801012046e6f646518022200280140004a00"} @@ -204,7 +204,7 @@ tenant hash=76f051cc9eafd977b62ed5718d3412e532f961c3c229e3b3591946fa208d1952 ,{"key":"8b89b88a89","value":"030abe020a0b726f6c655f69645f7365711830200128013a00422a0a0576616c756510011a0c080110401800300050146000200030006800700078008001008801009801004800525c0a077072696d61727910011800220576616c7565300140004a10080010001a00200028003000380040005a007a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00100e0010060006a250a0d0a0561646d696e10a00618a0060a0c0a04726f6f7410a00618a00612046e6f64651802800100880103980100b201160a077072696d61727910001a0576616c756520012801b80100c20100e201180801106418ffffffff072064280032040800100038014200e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880300a80300b00300"} ,{"key":"8b89ba8a89","value":"030aa5030a0a7370616e5f636f756e741832200128013a0042340a0973696e676c65746f6e10011a0c08001000180030005010600020002a04747275653000680070007800800100880100980100422f0a0a7370616e5f636f756e7410021a0c080110401800300050146000200030006800700078008001008801009801004803526e0a077072696d61727910011801220973696e676c65746f6e2a0a7370616e5f636f756e74300140004a10080010001a00200028003000380040005a0070027a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100a201210a0973696e676c65746f6e120a73696e676c655f726f7718002801300038004002b201280a077072696d61727910001a0973696e676c65746f6e1a0a7370616e5f636f756e74200120022802b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880303a80300b00300"} ,{"key":"8b89bb8a89","value":"030ab2070a0a70726976696c656765731833200128013a00422d0a08757365726e616d6510011a0c0807100018003000501960002000300068007000780080010088010098010042290a047061746810021a0c0807100018003000501960002000300068007000780080010088010098010042400a0a70726976696c6567657310031a1d080f100018003000380750f1075a0c08071000180030005019600060002000300068007000780080010088010098010042430a0d6772616e745f6f7074696f6e7310041a1d080f100018003000380750f1075a0c080710001800300050196000600020003000680070007800800100880100980100422c0a07757365725f696410051a0c080c100018003000501a60002001300068007000780080010088010098010048065293010a077072696d617279100118012208757365726e616d652204706174682a0a70726976696c656765732a0d6772616e745f6f7074696f6e732a07757365725f696430013002400040004a10080010001a00200028003000380040005a007003700470057a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00103e001005a9d010a1b70726976696c656765735f706174685f757365725f69645f6b6579100218012204706174682207757365725f69642a0a70726976696c656765732a0d6772616e745f6f7074696f6e73300230053801400040004a10080010001a00200028003000380040005a00700370047a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00101e001005a9d010a1c70726976696c656765735f706174685f757365726e616d655f6b6579100318012204706174682208757365726e616d652a0a70726976696c656765732a0d6772616e745f6f7074696f6e7330023001400040004a10080010001a00200028003000380040005a00700370047a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00102e0010060046a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b2014b0a077072696d61727910001a08757365726e616d651a04706174681a0a70726976696c656765731a0d6772616e745f6f7074696f6e731a07757365725f6964200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880304a80300b00300"} -,{"key":"8b89bc8a89","value":"030afa050a1465787465726e616c5f636f6e6e656374696f6e731834200128013a0042340a0f636f6e6e656374696f6e5f6e616d6510011a0c0807100018003000501960002000300068007000780080010088010098010042400a076372656174656410021a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042400a077570646174656410031a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042340a0f636f6e6e656374696f6e5f7479706510041a0c0807100018003000501960002000300068007000780080010088010098010042370a12636f6e6e656374696f6e5f64657461696c7310051a0c08081000180030005011600020003000680070007800800100880100980100422a0a056f776e657210061a0c08071000180030005019600020003000680070007800800100880100980100480752ae010a077072696d61727910011801220f636f6e6e656374696f6e5f6e616d652a07637265617465642a07757064617465642a0f636f6e6e656374696f6e5f747970652a12636f6e6e656374696f6e5f64657461696c732a056f776e6572300140004a10080010001a00200028003000380040005a00700270037004700570067a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201680a077072696d61727910001a0f636f6e6e656374696f6e5f6e616d651a07637265617465641a07757064617465641a0f636f6e6e656374696f6e5f747970651a12636f6e6e656374696f6e5f64657461696c731a056f776e65722001200220032004200520062800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} +,{"key":"8b89bc8a89","value":"030ac1060a1465787465726e616c5f636f6e6e656374696f6e731834200128013a0042340a0f636f6e6e656374696f6e5f6e616d6510011a0c0807100018003000501960002000300068007000780080010088010098010042400a076372656174656410021a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042400a077570646174656410031a0d080510001800300050da08600020002a116e6f7728293a3a3a54494d455354414d50300068007000780080010088010098010042340a0f636f6e6e656374696f6e5f7479706510041a0c0807100018003000501960002000300068007000780080010088010098010042370a12636f6e6e656374696f6e5f64657461696c7310051a0c08081000180030005011600020003000680070007800800100880100980100422a0a056f776e657210061a0c08071000180030005019600020003000680070007800800100880100980100422d0a086f776e65725f696410071a0c080c100018003000501a600020013000680070007800800100880100980100480852ba010a077072696d61727910011801220f636f6e6e656374696f6e5f6e616d652a07637265617465642a07757064617465642a0f636f6e6e656374696f6e5f747970652a12636f6e6e656374696f6e5f64657461696c732a056f776e65722a086f776e65725f6964300140004a10080010001a00200028003000380040005a007002700370047005700670077a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201740a077072696d61727910001a0f636f6e6e656374696f6e5f6e616d651a07637265617465641a07757064617465641a0f636f6e6e656374696f6e5f747970651a12636f6e6e656374696f6e5f64657461696c731a056f776e65721a086f776e65725f696420012002200320042005200620072800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} ,{"key":"8b89bd8a89","value":"030a87040a086a6f625f696e666f1835200128013a00422b0a066a6f625f696410011a0c08011040180030005014600020003000680070007800800100880100980100422d0a08696e666f5f6b657910021a0c0808100018003000501160002000300068007000780080010088010098010042420a077772697474656e10031a0d080910001800300050a009600020002a136e6f7728293a3a3a54494d455354414d50545a3000680070007800800100880100980100422a0a0576616c756510041a0c0808100018003000501160002001300068007000780080010088010098010048055281010a077072696d6172791001180122066a6f625f69642208696e666f5f6b657922077772697474656e2a0576616c75653001300230034000400040014a10080010001a00200028003000380040005a0070047a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060026a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201370a077072696d61727910001a066a6f625f69641a08696e666f5f6b65791a077772697474656e1a0576616c756520012002200320042804b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} ,{"key":"8b89be8a89","value":"030af9030a167370616e5f73746174735f756e697175655f6b6579731836200128013a00423b0a02696410011a0d080e100018003000508617600020002a1167656e5f72616e646f6d5f7575696428293000680070007800800100880100980100422e0a096b65795f627974657310021a0c08081000180030005011600020013000680070007800800100880100980100480352660a077072696d61727910011801220269642a096b65795f6279746573300140004a10080010001a00200028003000380040005a0070027a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00102e001005a740a19756e697175655f6b6579735f6b65795f62797465735f6964781002180122096b65795f62797465733002380140004a10080010001a00200028003000380040005a007a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00101e0010060036a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b201200a077072696d61727910001a0269641a096b65795f6279746573200120022802b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880303a80300b00300"} ,{"key":"8b89bf8a89","value":"030adc050a127370616e5f73746174735f6275636b6574731837200128013a00423b0a02696410011a0d080e100018003000508617600020002a1167656e5f72616e646f6d5f7575696428293000680070007800800100880100980100422f0a0973616d706c655f696410021a0d080e10001800300050861760002000300068007000780080010088010098010042320a0c73746172745f6b65795f696410031a0d080e10001800300050861760002000300068007000780080010088010098010042300a0a656e645f6b65795f696410041a0d080e100018003000508617600020003000680070007800800100880100980100422d0a08726571756573747310051a0c0801104018003000501460002000300068007000780080010088010098010048065290010a077072696d61727910011801220269642a0973616d706c655f69642a0c73746172745f6b65795f69642a0a656e645f6b65795f69642a087265717565737473300140004a10080010001a00200028003000380040005a0070027003700470057a0408002000800100880100900104980101a20106080012001800a80100b20100ba0100c00100c80100d00101e001005a700a156275636b6574735f73616d706c655f69645f69647810021800220973616d706c655f69643002380140004a10080010001a00200028003000380040005a007a0408002000800100880100900103980100a20106080012001800a80100b20100ba0100c00100c80100d00100e0010060036a250a0d0a0561646d696e10e00318e0030a0c0a04726f6f7410e00318e00312046e6f64651802800101880103980100b2014a0a077072696d61727910001a0269641a0973616d706c655f69641a0c73746172745f6b65795f69641a0a656e645f6b65795f69641a087265717565737473200120022003200420052800b80101c20100e80100f2010408001200f801008002009202009a0200b20200b80200c0021dc80200e00200800300880302a80300b00300"} diff --git a/pkg/sql/catalog/systemschema/system.go b/pkg/sql/catalog/systemschema/system.go index 4ec736cf9b9a..a822e35a0da5 100644 --- a/pkg/sql/catalog/systemschema/system.go +++ b/pkg/sql/catalog/systemschema/system.go @@ -759,8 +759,9 @@ CREATE TABLE system.external_connections ( connection_type STRING NOT NULL, connection_details BYTES NOT NULL, owner STRING NOT NULL, + owner_id OID, CONSTRAINT "primary" PRIMARY KEY (connection_name), - FAMILY "primary" (connection_name, created, updated, connection_type, connection_details, owner) + FAMILY "primary" (connection_name, created, updated, connection_type, connection_details, owner, owner_id) );` SystemJobInfoTableSchema = ` @@ -2988,13 +2989,14 @@ var ( {Name: "connection_type", ID: 4, Type: types.String}, {Name: "connection_details", ID: 5, Type: types.Bytes}, {Name: "owner", ID: 6, Type: types.String}, + {Name: "owner_id", ID: 7, Type: types.Oid, Nullable: true}, }, []descpb.ColumnFamilyDescriptor{ { Name: "primary", ID: 0, - ColumnNames: []string{"connection_name", "created", "updated", "connection_type", "connection_details", "owner"}, - ColumnIDs: []descpb.ColumnID{1, 2, 3, 4, 5, 6}, + ColumnNames: []string{"connection_name", "created", "updated", "connection_type", "connection_details", "owner", "owner_id"}, + ColumnIDs: []descpb.ColumnID{1, 2, 3, 4, 5, 6, 7}, }, }, descpb.IndexDescriptor{ diff --git a/pkg/sql/catalog/systemschema_test/testdata/bootstrap b/pkg/sql/catalog/systemschema_test/testdata/bootstrap index 84dc221df3bd..3711f0475263 100644 --- a/pkg/sql/catalog/systemschema_test/testdata/bootstrap +++ b/pkg/sql/catalog/systemschema_test/testdata/bootstrap @@ -412,6 +412,7 @@ CREATE TABLE public.external_connections ( connection_type STRING NOT NULL, connection_details BYTES NOT NULL, owner STRING NOT NULL, + owner_id OID NULL, CONSTRAINT "primary" PRIMARY KEY (connection_name ASC) ); CREATE TABLE public.job_info ( @@ -458,7 +459,7 @@ schema_telemetry {"table":{"name":"descriptor","id":3,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"id","id":1,"type":{"family":"IntFamily","width":64,"oid":20}},{"name":"descriptor","id":2,"type":{"family":"BytesFamily","oid":17},"nullable":true}],"nextColumnId":3,"families":[{"name":"primary","columnNames":["id"],"columnIds":[1]},{"name":"fam_2_descriptor","id":2,"columnNames":["descriptor"],"columnIds":[2],"defaultColumnId":2}],"nextFamilyId":3,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["id"],"keyColumnDirections":["ASC"],"storeColumnNames":["descriptor"],"keyColumnIds":[1],"storeColumnIds":[2],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"nextIndexId":2,"privileges":{"users":[{"userProto":"admin","privileges":"32","withGrantOption":"32"},{"userProto":"root","privileges":"32","withGrantOption":"32"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} {"table":{"name":"descriptor_id_seq","id":7,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"value","id":1,"type":{"family":"IntFamily","width":64,"oid":20}}],"families":[{"name":"primary","columnNames":["value"],"columnIds":[1],"defaultColumnId":1}],"primaryIndex":{"name":"primary","id":1,"version":4,"keyColumnNames":["value"],"keyColumnDirections":["ASC"],"keyColumnIds":[1],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{}},"privileges":{"users":[{"userProto":"admin","privileges":"32","withGrantOption":"32"},{"userProto":"root","privileges":"32","withGrantOption":"32"}],"ownerProto":"node","version":2},"formatVersion":3,"sequenceOpts":{"increment":"1","minValue":"1","maxValue":"9223372036854775807","start":"1","sequenceOwner":{},"cacheSize":"1"},"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"}}} {"table":{"name":"eventlog","id":12,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"timestamp","id":1,"type":{"family":"TimestampFamily","oid":1114}},{"name":"eventType","id":2,"type":{"family":"StringFamily","oid":25}},{"name":"targetID","id":3,"type":{"family":"IntFamily","width":64,"oid":20}},{"name":"reportingID","id":4,"type":{"family":"IntFamily","width":64,"oid":20}},{"name":"info","id":5,"type":{"family":"StringFamily","oid":25},"nullable":true},{"name":"uniqueID","id":6,"type":{"family":"BytesFamily","oid":17},"defaultExpr":"uuid_v4()"}],"nextColumnId":7,"families":[{"name":"primary","columnNames":["timestamp","uniqueID"],"columnIds":[1,6]},{"name":"fam_2_eventType","id":2,"columnNames":["eventType"],"columnIds":[2],"defaultColumnId":2},{"name":"fam_3_targetID","id":3,"columnNames":["targetID"],"columnIds":[3],"defaultColumnId":3},{"name":"fam_4_reportingID","id":4,"columnNames":["reportingID"],"columnIds":[4],"defaultColumnId":4},{"name":"fam_5_info","id":5,"columnNames":["info"],"columnIds":[5],"defaultColumnId":5}],"nextFamilyId":6,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["timestamp","uniqueID"],"keyColumnDirections":["ASC","ASC"],"storeColumnNames":["eventType","targetID","reportingID","info"],"keyColumnIds":[1,6],"storeColumnIds":[2,3,4,5],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"nextIndexId":2,"privileges":{"users":[{"userProto":"admin","privileges":"480","withGrantOption":"480"},{"userProto":"root","privileges":"480","withGrantOption":"480"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} -{"table":{"name":"external_connections","id":52,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"connection_name","id":1,"type":{"family":"StringFamily","oid":25}},{"name":"created","id":2,"type":{"family":"TimestampFamily","oid":1114},"defaultExpr":"now():::TIMESTAMP"},{"name":"updated","id":3,"type":{"family":"TimestampFamily","oid":1114},"defaultExpr":"now():::TIMESTAMP"},{"name":"connection_type","id":4,"type":{"family":"StringFamily","oid":25}},{"name":"connection_details","id":5,"type":{"family":"BytesFamily","oid":17}},{"name":"owner","id":6,"type":{"family":"StringFamily","oid":25}}],"nextColumnId":7,"families":[{"name":"primary","columnNames":["connection_name","created","updated","connection_type","connection_details","owner"],"columnIds":[1,2,3,4,5,6]}],"nextFamilyId":1,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["connection_name"],"keyColumnDirections":["ASC"],"storeColumnNames":["created","updated","connection_type","connection_details","owner"],"keyColumnIds":[1],"storeColumnIds":[2,3,4,5,6],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"nextIndexId":2,"privileges":{"users":[{"userProto":"admin","privileges":"480","withGrantOption":"480"},{"userProto":"root","privileges":"480","withGrantOption":"480"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} +{"table":{"name":"external_connections","id":52,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"connection_name","id":1,"type":{"family":"StringFamily","oid":25}},{"name":"created","id":2,"type":{"family":"TimestampFamily","oid":1114},"defaultExpr":"now():::TIMESTAMP"},{"name":"updated","id":3,"type":{"family":"TimestampFamily","oid":1114},"defaultExpr":"now():::TIMESTAMP"},{"name":"connection_type","id":4,"type":{"family":"StringFamily","oid":25}},{"name":"connection_details","id":5,"type":{"family":"BytesFamily","oid":17}},{"name":"owner","id":6,"type":{"family":"StringFamily","oid":25}},{"name":"owner_id","id":7,"type":{"family":"OidFamily","oid":26},"nullable":true}],"nextColumnId":8,"families":[{"name":"primary","columnNames":["connection_name","created","updated","connection_type","connection_details","owner","owner_id"],"columnIds":[1,2,3,4,5,6,7]}],"nextFamilyId":1,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["connection_name"],"keyColumnDirections":["ASC"],"storeColumnNames":["created","updated","connection_type","connection_details","owner","owner_id"],"keyColumnIds":[1],"storeColumnIds":[2,3,4,5,6,7],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"nextIndexId":2,"privileges":{"users":[{"userProto":"admin","privileges":"480","withGrantOption":"480"},{"userProto":"root","privileges":"480","withGrantOption":"480"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} {"table":{"name":"job_info","id":53,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"job_id","id":1,"type":{"family":"IntFamily","width":64,"oid":20}},{"name":"info_key","id":2,"type":{"family":"BytesFamily","oid":17}},{"name":"written","id":3,"type":{"family":"TimestampTZFamily","oid":1184},"defaultExpr":"now():::TIMESTAMPTZ"},{"name":"value","id":4,"type":{"family":"BytesFamily","oid":17},"nullable":true}],"nextColumnId":5,"families":[{"name":"primary","columnNames":["job_id","info_key","written","value"],"columnIds":[1,2,3,4],"defaultColumnId":4}],"nextFamilyId":1,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["job_id","info_key","written"],"keyColumnDirections":["ASC","ASC","DESC"],"storeColumnNames":["value"],"keyColumnIds":[1,2,3],"storeColumnIds":[4],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"nextIndexId":2,"privileges":{"users":[{"userProto":"admin","privileges":"480","withGrantOption":"480"},{"userProto":"root","privileges":"480","withGrantOption":"480"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} {"table":{"name":"jobs","id":15,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"id","id":1,"type":{"family":"IntFamily","width":64,"oid":20},"defaultExpr":"unique_rowid()"},{"name":"status","id":2,"type":{"family":"StringFamily","oid":25}},{"name":"created","id":3,"type":{"family":"TimestampFamily","oid":1114},"defaultExpr":"now():::TIMESTAMP"},{"name":"payload","id":4,"type":{"family":"BytesFamily","oid":17}},{"name":"progress","id":5,"type":{"family":"BytesFamily","oid":17},"nullable":true},{"name":"created_by_type","id":6,"type":{"family":"StringFamily","oid":25},"nullable":true},{"name":"created_by_id","id":7,"type":{"family":"IntFamily","width":64,"oid":20},"nullable":true},{"name":"claim_session_id","id":8,"type":{"family":"BytesFamily","oid":17},"nullable":true},{"name":"claim_instance_id","id":9,"type":{"family":"IntFamily","width":64,"oid":20},"nullable":true},{"name":"num_runs","id":10,"type":{"family":"IntFamily","width":64,"oid":20},"nullable":true},{"name":"last_run","id":11,"type":{"family":"TimestampFamily","oid":1114},"nullable":true},{"name":"job_type","id":12,"type":{"family":"StringFamily","oid":25},"nullable":true}],"nextColumnId":13,"families":[{"name":"fam_0_id_status_created_payload","columnNames":["id","status","created","payload","created_by_type","created_by_id","job_type"],"columnIds":[1,2,3,4,6,7,12]},{"name":"progress","id":1,"columnNames":["progress"],"columnIds":[5],"defaultColumnId":5},{"name":"claim","id":2,"columnNames":["claim_session_id","claim_instance_id","num_runs","last_run"],"columnIds":[8,9,10,11]}],"nextFamilyId":3,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["id"],"keyColumnDirections":["ASC"],"storeColumnNames":["status","created","payload","progress","created_by_type","created_by_id","claim_session_id","claim_instance_id","num_runs","last_run","job_type"],"keyColumnIds":[1],"storeColumnIds":[2,3,4,5,6,7,8,9,10,11,12],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"indexes":[{"name":"jobs_status_created_idx","id":2,"version":3,"keyColumnNames":["status","created"],"keyColumnDirections":["ASC","ASC"],"keyColumnIds":[2,3],"keySuffixColumnIds":[1],"foreignKey":{},"interleave":{},"partitioning":{},"sharded":{},"geoConfig":{}},{"name":"jobs_created_by_type_created_by_id_idx","id":3,"version":3,"keyColumnNames":["created_by_type","created_by_id"],"keyColumnDirections":["ASC","ASC"],"storeColumnNames":["status"],"keyColumnIds":[6,7],"keySuffixColumnIds":[1],"storeColumnIds":[2],"foreignKey":{},"interleave":{},"partitioning":{},"sharded":{},"geoConfig":{}},{"name":"jobs_run_stats_idx","id":4,"version":3,"keyColumnNames":["claim_session_id","status","created"],"keyColumnDirections":["ASC","ASC","ASC"],"storeColumnNames":["last_run","num_runs","claim_instance_id"],"keyColumnIds":[8,2,3],"keySuffixColumnIds":[1],"storeColumnIds":[11,10,9],"foreignKey":{},"interleave":{},"partitioning":{},"sharded":{},"geoConfig":{},"predicate":"status IN ('_':::STRING, '_':::STRING, '_':::STRING, '_':::STRING, '_':::STRING)"},{"name":"jobs_job_type_idx","id":5,"version":3,"keyColumnNames":["job_type"],"keyColumnDirections":["ASC"],"keyColumnIds":[12],"keySuffixColumnIds":[1],"foreignKey":{},"interleave":{},"partitioning":{},"sharded":{},"geoConfig":{}}],"nextIndexId":6,"privileges":{"users":[{"userProto":"admin","privileges":"480","withGrantOption":"480"},{"userProto":"root","privileges":"480","withGrantOption":"480"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} {"table":{"name":"join_tokens","id":41,"version":"1","modificationTime":{"wallTime":"0"},"parentId":1,"unexposedParentSchemaId":29,"columns":[{"name":"id","id":1,"type":{"family":"UuidFamily","oid":2950}},{"name":"secret","id":2,"type":{"family":"BytesFamily","oid":17}},{"name":"expiration","id":3,"type":{"family":"TimestampTZFamily","oid":1184}}],"nextColumnId":4,"families":[{"name":"primary","columnNames":["id","secret","expiration"],"columnIds":[1,2,3]}],"nextFamilyId":1,"primaryIndex":{"name":"primary","id":1,"unique":true,"version":4,"keyColumnNames":["id"],"keyColumnDirections":["ASC"],"storeColumnNames":["secret","expiration"],"keyColumnIds":[1],"storeColumnIds":[2,3],"foreignKey":{},"interleave":{},"partitioning":{},"encodingType":1,"sharded":{},"geoConfig":{},"constraintId":1},"nextIndexId":2,"privileges":{"users":[{"userProto":"admin","privileges":"480","withGrantOption":"480"},{"userProto":"root","privileges":"480","withGrantOption":"480"}],"ownerProto":"node","version":2},"nextMutationId":1,"formatVersion":3,"replacementOf":{"time":{}},"createAsOfTime":{"wallTime":"0"},"nextConstraintId":2}} diff --git a/pkg/sql/create_external_connection.go b/pkg/sql/create_external_connection.go index f6deee82b616..e6fc0bd6536d 100644 --- a/pkg/sql/create_external_connection.go +++ b/pkg/sql/create_external_connection.go @@ -68,6 +68,8 @@ func (p *planner) parseExternalConnection( func (p *planner) createExternalConnection( params runParams, n *tree.CreateExternalConnection, ) error { + txn := p.InternalSQLTxn() + if !p.ExecCfg().Settings.Version.IsActive(params.ctx, clusterversion.TODODelete_V22_2SystemExternalConnectionsTable) { return pgerror.Newf(pgcode.FeatureNotSupported, "version %v must be finalized to create an External Connection", @@ -134,11 +136,24 @@ func (p *planner) createExternalConnection( ex.SetConnectionDetails(*exConn.ConnectionProto()) ex.SetConnectionType(exConn.ConnectionType()) ex.SetOwner(p.User()) + row, err := txn.QueryRowEx(params.ctx, `get-user-id`, txn.KV(), + sessiondata.NodeUserSessionDataOverride, + `SELECT user_id FROM system.users WHERE username = $1`, + p.User(), + ) + if err != nil { + return errors.Wrap(err, "failed to get owner ID for External Connection") + } + ownerID := tree.MustBeDOid(row[0]).Oid + ex.SetOwnerID(ownerID) - txn := p.InternalSQLTxn() // Create the External Connection and persist it in the // `system.external_connections` table. - if err := ex.Create(params.ctx, txn, p.User()); err != nil { + excludedCols := make(map[string]bool) + if !p.ExecCfg().Settings.Version.IsActive(params.ctx, clusterversion.V23_1ExternalConnectionsTableHasOwnerIDColumn) { + excludedCols["owner_id"] = true + } + if err := ex.Create(params.ctx, txn, excludedCols); err != nil { return errors.Wrap(err, "failed to create external connection") } diff --git a/pkg/sql/logictest/testdata/logic_test/crdb_internal_catalog b/pkg/sql/logictest/testdata/logic_test/crdb_internal_catalog index 9702492acf4d..16e770ec5aad 100644 --- a/pkg/sql/logictest/testdata/logic_test/crdb_internal_catalog +++ b/pkg/sql/logictest/testdata/logic_test/crdb_internal_catalog @@ -145,7 +145,7 @@ SELECT id, strip_volatile(descriptor) FROM crdb_internal.kv_catalog_descriptor 48 {"table": {"columns": [{"id": 1, "name": "value", "type": {"family": "IntFamily", "oid": 20, "width": 64}}], "formatVersion": 3, "id": 48, "name": "role_id_seq", "parentId": 1, "primaryIndex": {"encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [1], "keyColumnNames": ["value"], "name": "primary", "partitioning": {}, "sharded": {}, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "800", "userProto": "admin", "withGrantOption": "800"}, {"privileges": "800", "userProto": "root", "withGrantOption": "800"}], "version": 2}, "replacementOf": {"time": {}}, "sequenceOpts": {"cacheSize": "1", "increment": "1", "maxValue": "2147483647", "minValue": "100", "sequenceOwner": {}, "start": "100"}, "unexposedParentSchemaId": 29, "version": "1"}} 50 {"table": {"columns": [{"id": 1, "name": "tenant_id", "type": {"family": "IntFamily", "oid": 20, "width": 64}}, {"id": 2, "name": "name", "type": {"family": "StringFamily", "oid": 25}}, {"id": 3, "name": "value", "type": {"family": "StringFamily", "oid": 25}}, {"defaultExpr": "now():::TIMESTAMP", "id": 4, "name": "last_updated", "type": {"family": "TimestampFamily", "oid": 1114}}, {"id": 5, "name": "value_type", "type": {"family": "StringFamily", "oid": 25}}, {"id": 6, "name": "reason", "nullable": true, "type": {"family": "StringFamily", "oid": 25}}], "formatVersion": 3, "id": 50, "name": "tenant_settings", "nextColumnId": 7, "nextConstraintId": 2, "nextIndexId": 2, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 1, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC", "ASC"], "keyColumnIds": [1, 2], "keyColumnNames": ["tenant_id", "name"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [3, 4, 5, 6], "storeColumnNames": ["value", "last_updated", "value_type", "reason"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} 51 {"table": {"columns": [{"id": 1, "name": "username", "type": {"family": "StringFamily", "oid": 25}}, {"id": 2, "name": "path", "type": {"family": "StringFamily", "oid": 25}}, {"id": 3, "name": "privileges", "type": {"arrayContents": {"family": "StringFamily", "oid": 25}, "arrayElemType": "StringFamily", "family": "ArrayFamily", "oid": 1009}}, {"id": 4, "name": "grant_options", "type": {"arrayContents": {"family": "StringFamily", "oid": 25}, "arrayElemType": "StringFamily", "family": "ArrayFamily", "oid": 1009}}, {"id": 5, "name": "user_id", "nullable": true, "type": {"family": "OidFamily", "oid": 26}}], "formatVersion": 3, "id": 51, "indexes": [{"constraintId": 1, "foreignKey": {}, "geoConfig": {}, "id": 2, "interleave": {}, "keyColumnDirections": ["ASC", "ASC"], "keyColumnIds": [2, 5], "keyColumnNames": ["path", "user_id"], "keySuffixColumnIds": [1], "name": "privileges_path_user_id_key", "partitioning": {}, "sharded": {}, "storeColumnIds": [3, 4], "storeColumnNames": ["privileges", "grant_options"], "unique": true, "version": 3}, {"constraintId": 2, "foreignKey": {}, "geoConfig": {}, "id": 3, "interleave": {}, "keyColumnDirections": ["ASC", "ASC"], "keyColumnIds": [2, 1], "keyColumnNames": ["path", "username"], "name": "privileges_path_username_key", "partitioning": {}, "sharded": {}, "storeColumnIds": [3, 4], "storeColumnNames": ["privileges", "grant_options"], "unique": true, "version": 3}], "name": "privileges", "nextColumnId": 6, "nextConstraintId": 4, "nextIndexId": 4, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 3, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC", "ASC"], "keyColumnIds": [1, 2], "keyColumnNames": ["username", "path"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [3, 4, 5], "storeColumnNames": ["privileges", "grant_options", "user_id"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} -52 {"table": {"columns": [{"id": 1, "name": "connection_name", "type": {"family": "StringFamily", "oid": 25}}, {"defaultExpr": "now():::TIMESTAMP", "id": 2, "name": "created", "type": {"family": "TimestampFamily", "oid": 1114}}, {"defaultExpr": "now():::TIMESTAMP", "id": 3, "name": "updated", "type": {"family": "TimestampFamily", "oid": 1114}}, {"id": 4, "name": "connection_type", "type": {"family": "StringFamily", "oid": 25}}, {"id": 5, "name": "connection_details", "type": {"family": "BytesFamily", "oid": 17}}, {"id": 6, "name": "owner", "type": {"family": "StringFamily", "oid": 25}}], "formatVersion": 3, "id": 52, "name": "external_connections", "nextColumnId": 7, "nextConstraintId": 2, "nextIndexId": 2, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 1, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [1], "keyColumnNames": ["connection_name"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [2, 3, 4, 5, 6], "storeColumnNames": ["created", "updated", "connection_type", "connection_details", "owner"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} +52 {"table": {"columns": [{"id": 1, "name": "connection_name", "type": {"family": "StringFamily", "oid": 25}}, {"defaultExpr": "now():::TIMESTAMP", "id": 2, "name": "created", "type": {"family": "TimestampFamily", "oid": 1114}}, {"defaultExpr": "now():::TIMESTAMP", "id": 3, "name": "updated", "type": {"family": "TimestampFamily", "oid": 1114}}, {"id": 4, "name": "connection_type", "type": {"family": "StringFamily", "oid": 25}}, {"id": 5, "name": "connection_details", "type": {"family": "BytesFamily", "oid": 17}}, {"id": 6, "name": "owner", "type": {"family": "StringFamily", "oid": 25}}, {"id": 7, "name": "owner_id", "nullable": true, "type": {"family": "OidFamily", "oid": 26}}], "formatVersion": 3, "id": 52, "name": "external_connections", "nextColumnId": 8, "nextConstraintId": 2, "nextIndexId": 2, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 1, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [1], "keyColumnNames": ["connection_name"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [2, 3, 4, 5, 6, 7], "storeColumnNames": ["created", "updated", "connection_type", "connection_details", "owner", "owner_id"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} 53 {"table": {"columns": [{"id": 1, "name": "job_id", "type": {"family": "IntFamily", "oid": 20, "width": 64}}, {"id": 2, "name": "info_key", "type": {"family": "BytesFamily", "oid": 17}}, {"defaultExpr": "now():::TIMESTAMPTZ", "id": 3, "name": "written", "type": {"family": "TimestampTZFamily", "oid": 1184}}, {"id": 4, "name": "value", "nullable": true, "type": {"family": "BytesFamily", "oid": 17}}], "formatVersion": 3, "id": 53, "name": "job_info", "nextColumnId": 5, "nextConstraintId": 2, "nextIndexId": 2, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 1, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC", "ASC", "DESC"], "keyColumnIds": [1, 2, 3], "keyColumnNames": ["job_id", "info_key", "written"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [4], "storeColumnNames": ["value"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} 54 {"table": {"columns": [{"defaultExpr": "gen_random_uuid()", "id": 1, "name": "id", "type": {"family": "UuidFamily", "oid": 2950}}, {"id": 2, "name": "key_bytes", "nullable": true, "type": {"family": "BytesFamily", "oid": 17}}], "formatVersion": 3, "id": 54, "indexes": [{"constraintId": 1, "foreignKey": {}, "geoConfig": {}, "id": 2, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [2], "keyColumnNames": ["key_bytes"], "keySuffixColumnIds": [1], "name": "unique_keys_key_bytes_idx", "partitioning": {}, "sharded": {}, "unique": true, "version": 3}], "name": "span_stats_unique_keys", "nextColumnId": 3, "nextConstraintId": 3, "nextIndexId": 3, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 2, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [1], "keyColumnNames": ["id"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [2], "storeColumnNames": ["key_bytes"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} 55 {"table": {"columns": [{"defaultExpr": "gen_random_uuid()", "id": 1, "name": "id", "type": {"family": "UuidFamily", "oid": 2950}}, {"id": 2, "name": "sample_id", "type": {"family": "UuidFamily", "oid": 2950}}, {"id": 3, "name": "start_key_id", "type": {"family": "UuidFamily", "oid": 2950}}, {"id": 4, "name": "end_key_id", "type": {"family": "UuidFamily", "oid": 2950}}, {"id": 5, "name": "requests", "type": {"family": "IntFamily", "oid": 20, "width": 64}}], "formatVersion": 3, "id": 55, "indexes": [{"foreignKey": {}, "geoConfig": {}, "id": 2, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [2], "keyColumnNames": ["sample_id"], "keySuffixColumnIds": [1], "name": "buckets_sample_id_idx", "partitioning": {}, "sharded": {}, "version": 3}], "name": "span_stats_buckets", "nextColumnId": 6, "nextConstraintId": 2, "nextIndexId": 3, "nextMutationId": 1, "parentId": 1, "primaryIndex": {"constraintId": 1, "encodingType": 1, "foreignKey": {}, "geoConfig": {}, "id": 1, "interleave": {}, "keyColumnDirections": ["ASC"], "keyColumnIds": [1], "keyColumnNames": ["id"], "name": "primary", "partitioning": {}, "sharded": {}, "storeColumnIds": [2, 3, 4, 5], "storeColumnNames": ["sample_id", "start_key_id", "end_key_id", "requests"], "unique": true, "version": 4}, "privileges": {"ownerProto": "node", "users": [{"privileges": "480", "userProto": "admin", "withGrantOption": "480"}, {"privileges": "480", "userProto": "root", "withGrantOption": "480"}], "version": 2}, "replacementOf": {"time": {}}, "unexposedParentSchemaId": 29, "version": "1"}} diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema index bc066c4221e7..4889c1754a0c 100644 --- a/pkg/sql/logictest/testdata/logic_test/information_schema +++ b/pkg/sql/logictest/testdata/logic_test/information_schema @@ -2178,6 +2178,7 @@ system public external_connections connection_name system public external_connections connection_type 4 system public external_connections created 2 system public external_connections owner 6 +system public external_connections owner_id 7 system public external_connections updated 3 system pg_extension geography_columns coord_dimension 5 system pg_extension geography_columns f_geography_column 4 diff --git a/pkg/sql/logictest/testdata/logic_test/mixed_version_external_connections_owner_id b/pkg/sql/logictest/testdata/logic_test/mixed_version_external_connections_owner_id new file mode 100644 index 000000000000..5c1f9514a473 --- /dev/null +++ b/pkg/sql/logictest/testdata/logic_test/mixed_version_external_connections_owner_id @@ -0,0 +1,51 @@ +# LogicTest: cockroach-go-testserver-upgrade-to-master + +# Create external connections in a mixed version cluster. + +statement ok +CREATE user t + +statement ok +GRANT SYSTEM EXTERNALCONNECTION TO t + +upgrade 1 + +user t nodeidx=1 + +statement ok +CREATE EXTERNAL CONNECTION connection1 AS 'userfile:///connection1' + +user t nodeidx=2 + +statement ok +CREATE EXTERNAL CONNECTION connection2 AS 'userfile:///connection2' + +user root nodeidx=0 + +query TT +SELECT connection_name, owner FROM system.external_connections +---- +connection1 t +connection2 t + +# Wait for migrations to run and verify that owner_id column is now present. + +upgrade 0 + +upgrade 2 + +query B retry +SELECT crdb_internal.is_at_least_version('1000022.2-76') +---- +true + +query O +SELECT user_id FROM system.users WHERE username = 't' +---- +101 + +query TTO +SELECT connection_name, owner, owner_id FROM system.external_connections +---- +connection1 t 101 +connection2 t 101 diff --git a/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/BUILD.bazel b/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/BUILD.bazel index 96dafe91d3e1..90fedd6d3491 100644 --- a/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/BUILD.bazel +++ b/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/BUILD.bazel @@ -11,7 +11,7 @@ go_test( "//pkg/cmd/cockroach-short", # keep "//pkg/sql/logictest:testdata", # keep ], - shard_count = 2, + shard_count = 3, tags = ["cpu:2"], deps = [ "//pkg/build/bazel", diff --git a/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/generated_test.go b/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/generated_test.go index 8774f06c36b0..3bae859b2692 100644 --- a/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/generated_test.go +++ b/pkg/sql/logictest/tests/cockroach-go-testserver-upgrade-to-master/generated_test.go @@ -79,6 +79,13 @@ func TestLogic_mixed_version_can_login( runLogicTest(t, "mixed_version_can_login") } +func TestLogic_mixed_version_external_connections_owner_id( + t *testing.T, +) { + defer leaktest.AfterTest(t)() + runLogicTest(t, "mixed_version_external_connections_owner_id") +} + func TestLogic_mixed_version_role_members_user_ids( t *testing.T, ) { diff --git a/pkg/upgrade/upgrades/BUILD.bazel b/pkg/upgrade/upgrades/BUILD.bazel index e9fd037a7740..1d6d64276dd9 100644 --- a/pkg/upgrade/upgrades/BUILD.bazel +++ b/pkg/upgrade/upgrades/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "desc_id_sequence_for_system_tenant.go", "descriptor_utils.go", "ensure_sql_schema_telemetry_schedule.go", + "external_connections_table_user_id_migration.go", "fix_userfile_descriptor_corruption.go", "key_visualizer_migration.go", "permanent_upgrades.go", @@ -100,6 +101,7 @@ go_test( "desc_id_sequence_for_system_tenant_test.go", "descriptor_utils_test.go", "ensure_sql_schema_telemetry_schedule_test.go", + "external_connections_table_user_id_migration_test.go", "fix_userfile_descriptor_corruption_test.go", "helpers_test.go", "key_visualizer_migration_test.go", @@ -127,6 +129,7 @@ go_test( shard_count = 16, deps = [ "//pkg/base", + "//pkg/cloud/userfile", "//pkg/clusterversion", "//pkg/jobs", "//pkg/jobs/jobspb", diff --git a/pkg/upgrade/upgrades/external_connections_table_user_id_migration.go b/pkg/upgrade/upgrades/external_connections_table_user_id_migration.go new file mode 100644 index 000000000000..6fdb50eae5c9 --- /dev/null +++ b/pkg/upgrade/upgrades/external_connections_table_user_id_migration.go @@ -0,0 +1,88 @@ +// Copyright 2023 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package upgrades + +import ( + "context" + + "github.com/cockroachdb/cockroach/pkg/clusterversion" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/systemschema" + "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" + "github.com/cockroachdb/cockroach/pkg/upgrade" +) + +const addOwnerIDColumnToExternalConnectionsTableStmt = ` +ALTER TABLE system.external_connections +ADD COLUMN IF NOT EXISTS owner_id OID +FAMILY "primary" +` + +func alterExternalConnectionsTableAddOwnerIDColumn( + ctx context.Context, cs clusterversion.ClusterVersion, d upgrade.TenantDeps, +) error { + ie := d.DB.Executor() + + // Query the table ID for system.external_connections since it is dynamically + // assigned. + idRow, err := ie.QueryRowEx(ctx, "get-table-id", nil, /* txn */ + sessiondata.NodeUserSessionDataOverride, + `SELECT 'system.external_connections'::regclass::oid`, + ) + if err != nil { + return err + } + tableID := descpb.ID(tree.MustBeDOid(idRow[0]).Oid) + + for _, op := range []operation{ + { + name: "add-owner-id-column-external-connections-table", + schemaList: []string{"owner_id"}, + query: addOwnerIDColumnToExternalConnectionsTableStmt, + schemaExistsFn: columnExists, + }, + } { + if err := migrateTable(ctx, cs, d, op, tableID, systemschema.SystemExternalConnectionsTable); err != nil { + return err + } + } + + return nil +} + +const backfillOwnerIDColumnExternalConnectionsTableStmt = ` +UPDATE system.external_connections +SET owner_id = user_id +FROM system.users +WHERE owner_id IS NULL AND owner = username +LIMIT 1000 +` + +func backfillExternalConnectionsTableOwnerIDColumn( + ctx context.Context, cs clusterversion.ClusterVersion, d upgrade.TenantDeps, +) error { + ie := d.DB.Executor() + for { + rowsAffected, err := ie.ExecEx(ctx, "backfill-owner-id-col-external_connections-table", nil, /* txn */ + sessiondata.NodeUserSessionDataOverride, + backfillOwnerIDColumnExternalConnectionsTableStmt, + ) + if err != nil { + return err + } + if rowsAffected == 0 { + break + } + } + + return nil +} diff --git a/pkg/upgrade/upgrades/external_connections_table_user_id_migration_test.go b/pkg/upgrade/upgrades/external_connections_table_user_id_migration_test.go new file mode 100644 index 000000000000..78f888cdb001 --- /dev/null +++ b/pkg/upgrade/upgrades/external_connections_table_user_id_migration_test.go @@ -0,0 +1,167 @@ +// Copyright 2023 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package upgrades_test + +import ( + "context" + "fmt" + "strconv" + "testing" + + "github.com/cockroachdb/cockroach/pkg/base" + _ "github.com/cockroachdb/cockroach/pkg/cloud/userfile" + "github.com/cockroachdb/cockroach/pkg/clusterversion" + "github.com/cockroachdb/cockroach/pkg/keys" + "github.com/cockroachdb/cockroach/pkg/security/username" + "github.com/cockroachdb/cockroach/pkg/server" + "github.com/cockroachdb/cockroach/pkg/settings/cluster" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/catenumpb" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/systemschema" + "github.com/cockroachdb/cockroach/pkg/sql/privilege" + "github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants" + "github.com/cockroachdb/cockroach/pkg/sql/types" + "github.com/cockroachdb/cockroach/pkg/testutils/skip" + "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" + "github.com/cockroachdb/cockroach/pkg/testutils/testcluster" + "github.com/cockroachdb/cockroach/pkg/upgrade/upgrades" + "github.com/cockroachdb/cockroach/pkg/util/leaktest" + "github.com/stretchr/testify/require" +) + +func TestExternalConnectionsUserIDMigrationNoUsers(t *testing.T) { + runTestExternalConnectionsUserIDMigration(t, 0) +} + +func TestExternalConnectionsUserIDMigration10Users(t *testing.T) { + skip.UnderRace(t) + skip.UnderStress(t) + runTestExternalConnectionsUserIDMigration(t, 10) +} + +func runTestExternalConnectionsUserIDMigration(t *testing.T, numUsers int) { + defer leaktest.AfterTest(t)() + ctx := context.Background() + + settings := cluster.MakeTestingClusterSettingsWithVersions( + clusterversion.TestingBinaryVersion, + clusterversion.ByKey(clusterversion.V23_1ExternalConnectionsTableHasOwnerIDColumn-1), + false, /* initializeVersion */ + ) + + tc := testcluster.StartTestCluster(t, 1 /* nodes */, base.TestClusterArgs{ + ServerArgs: base.TestServerArgs{ + Settings: settings, + Knobs: base.TestingKnobs{ + Server: &server.TestingKnobs{ + DisableAutomaticVersionUpgrade: make(chan struct{}), + BinaryVersionOverride: clusterversion.ByKey(clusterversion.V23_1ExternalConnectionsTableHasOwnerIDColumn - 1), + }, + }, + }, + }) + defer tc.Stopper().Stop(ctx) + + db := tc.ServerConn(0) + defer db.Close() + tdb := sqlutils.MakeSQLRunner(db) + s := tc.Server(0) + + // Inject the descriptor for system.external_connections table from before + // the owner_id column was added. + upgrades.InjectLegacyTable(ctx, t, s, systemschema.SystemExternalConnectionsTable, + getTableDescForExternalConnectionsTableBeforeOwnerIDCol) + + // Create test users. + upgrades.ExecForCountInTxns(ctx, t, db, numUsers, 100 /* txCount */, func(txRunner *sqlutils.SQLRunner, i int) { + txRunner.Exec(t, fmt.Sprintf("CREATE USER testuser%d", i)) + txRunner.Exec(t, fmt.Sprintf("GRANT SYSTEM EXTERNALCONNECTION TO testuser%d", i)) + }) + upgrades.ExecForCountInTxns(ctx, t, db, numUsers, 100 /* txCount */, func(txRunner *sqlutils.SQLRunner, i int) { + externalConnName := fmt.Sprintf("connection%d", i) + txRunner.Exec(t, fmt.Sprintf("SET ROLE TO testuser%d", i)) + txRunner.Exec(t, fmt.Sprintf("CREATE EXTERNAL CONNECTION %[1]s AS 'userfile:///%[1]s'", externalConnName)) + }) + tdb.Exec(t, "SET ROLE TO root") + tdb.CheckQueryResults(t, "SELECT count(*) FROM system.external_connections", [][]string{{strconv.Itoa(numUsers)}}) + + // Run migrations. + _, err := tc.Conns[0].ExecContext(ctx, `SET CLUSTER SETTING version = $1`, + clusterversion.ByKey(clusterversion.V23_1ExternalConnectionsTableHasOwnerIDColumn).String()) + require.NoError(t, err) + _, err = tc.Conns[0].ExecContext(ctx, `SET CLUSTER SETTING version = $1`, + clusterversion.ByKey(clusterversion.V23_1ExternalConnectionsTableOwnerIDColumnBackfilled).String()) + require.NoError(t, err) + + // Verify that the final schema matches the expected one. + expectedSchema := `CREATE TABLE public.external_connections ( + connection_name STRING NOT NULL, + created TIMESTAMP NOT NULL DEFAULT now():::TIMESTAMP, + updated TIMESTAMP NOT NULL DEFAULT now():::TIMESTAMP, + connection_type STRING NOT NULL, + connection_details BYTES NOT NULL, + owner STRING NOT NULL, + owner_id OID NULL, + CONSTRAINT "primary" PRIMARY KEY (connection_name ASC) +)` + r := tdb.QueryRow(t, "SELECT create_statement FROM [SHOW CREATE TABLE system.external_connections]") + var actualSchema string + r.Scan(&actualSchema) + require.Equal(t, expectedSchema, actualSchema) + + // Check that the backfill was successful and correct. + tdb.CheckQueryResults(t, "SELECT * FROM system.external_connections WHERE owner_id IS NULL", [][]string{}) + tdb.CheckQueryResults(t, "SELECT count(*) FROM system.external_connections", [][]string{{strconv.Itoa(numUsers)}}) + tdb.CheckQueryResults(t, "SELECT count(*) FROM system.external_connections JOIN system.users ON owner = username AND owner_id <> user_id", [][]string{{"0"}}) +} + +func getTableDescForExternalConnectionsTableBeforeOwnerIDCol() *descpb.TableDescriptor { + nowString := "now():::TIMESTAMP" + return &descpb.TableDescriptor{ + Name: string(catconstants.SystemExternalConnectionsTableName), + ID: descpb.InvalidID, + ParentID: keys.SystemDatabaseID, + UnexposedParentSchemaID: keys.PublicSchemaID, + Version: 1, + Columns: []descpb.ColumnDescriptor{ + {Name: "connection_name", ID: 1, Type: types.String}, + {Name: "created", ID: 2, Type: types.Timestamp, DefaultExpr: &nowString}, + {Name: "updated", ID: 3, Type: types.Timestamp, DefaultExpr: &nowString}, + {Name: "connection_type", ID: 4, Type: types.String}, + {Name: "connection_details", ID: 5, Type: types.Bytes}, + {Name: "owner", ID: 6, Type: types.String}, + }, + NextColumnID: 7, + Families: []descpb.ColumnFamilyDescriptor{ + { + Name: "primary", + ID: 0, + ColumnNames: []string{"connection_name", "created", "updated", "connection_type", "connection_details", "owner"}, + ColumnIDs: []descpb.ColumnID{1, 2, 3, 4, 5, 6}, + }, + }, + NextFamilyID: 1, + PrimaryIndex: descpb.IndexDescriptor{ + Name: "primary", + ID: 1, + Unique: true, + KeyColumnNames: []string{"connection_name"}, + KeyColumnDirections: []catenumpb.IndexColumn_Direction{catenumpb.IndexColumn_ASC}, + KeyColumnIDs: []descpb.ColumnID{1}, + }, + NextIndexID: 2, + Privileges: catpb.NewCustomSuperuserPrivilegeDescriptor(privilege.ReadWriteData, username.NodeUserName()), + FormatVersion: descpb.InterleavedFormatVersion, + NextMutationID: 1, + NextConstraintID: 1, + } +} diff --git a/pkg/upgrade/upgrades/upgrades.go b/pkg/upgrade/upgrades/upgrades.go index bdcaf4071caf..ffed3988abf4 100644 --- a/pkg/upgrade/upgrades/upgrades.go +++ b/pkg/upgrade/upgrades/upgrades.go @@ -275,6 +275,18 @@ var upgrades = []upgradebase.Upgrade{ upgrade.NoPrecondition, cleanUpRegionalByTableIndex, ), + upgrade.NewTenantUpgrade( + "add owner_id column to system.external_connections table", + toCV(clusterversion.V23_1ExternalConnectionsTableHasOwnerIDColumn), + upgrade.NoPrecondition, + alterExternalConnectionsTableAddOwnerIDColumn, + ), + upgrade.NewTenantUpgrade( + "backfill owner_id column in system.external_connections table", + toCV(clusterversion.V23_1ExternalConnectionsTableOwnerIDColumnBackfilled), + upgrade.NoPrecondition, + backfillExternalConnectionsTableOwnerIDColumn, + ), } func init() {