Skip to content

Commit

Permalink
Merge #117292
Browse files Browse the repository at this point in the history
117292: schemachanger: Implement CREATE DATABASE in declarative schema changer r=Xiang-Gu a=Xiang-Gu

This PR implements CREATE DATABASE in declarative schema changer.
It falls back to legacy schema changer if the database is requested to be
multi-region.

Epic: [CRDB-25312](https://cockroachlabs.atlassian.net/browse/CRDB-25312)
Fix: #103324
Inform: #103607
Release note: None

Co-authored-by: Xiang Gu <[email protected]>
  • Loading branch information
craig[bot] and Xiang-Gu committed Jan 4, 2024
2 parents 2226508 + 749f20d commit e4067f1
Show file tree
Hide file tree
Showing 54 changed files with 3,508 additions and 25 deletions.
8 changes: 6 additions & 2 deletions pkg/ccl/logictestccl/testdata/logic_test/as_of
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ SET DEFAULT_TRANSACTION_USE_FOLLOWER_READS TO TRUE
statement error pgcode 3D000 pq: database "test" does not exist
SELECT * FROM t

statement error pq: cannot execute CREATE DATABASE in a read-only transaction
# LSC and DSC would return slightly different error message when attempting to create a
# database as of system time follower_read_timestamp() soon after a node has started.
statement error pq: (cannot execute CREATE DATABASE in a read-only transaction|referenced descriptor ID 1: looking up ID 1: descriptor not found)
CREATE DATABASE IF NOT EXISTS d2

statement error pgcode 3D000 pq: database "test" does not exist
Expand Down Expand Up @@ -88,7 +90,9 @@ SET SESSION CHARACTERISTICS AS TRANSACTION AS OF SYSTEM TIME follower_read_times
statement error pgcode 3D000 pq: database "test" does not exist
SELECT * FROM t

statement error pq: cannot execute CREATE DATABASE in a read-only transaction
# LSC and DSC would return slightly different error message when attempting to create a
# database as of system time follower_read_timestamp() soon after a node has started.
statement error pq: (cannot execute CREATE DATABASE in a read-only transaction|referenced descriptor ID 1: looking up ID 1: descriptor not found)
CREATE DATABASE IF NOT EXISTS d2

statement error pgcode 3D000 pq: database "test" does not exist
Expand Down
84 changes: 84 additions & 0 deletions pkg/ccl/schemachangerccl/backup_base_generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

122 changes: 122 additions & 0 deletions pkg/internal/team/TEAMS.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# This is a YAML file mapping team aliases from GitHub to
# metadata about the team.
# Expected structure is available in pkg/internal/team/team.go.

# Finding triage_column_id:
# TriageColumnID is the column id of the project column the team uses to
# triage issues. To get it, open the project, click the "..." on top of
# the project column, and click "Copy column link". That link contains
# the ID as the `#column-<ID>` fragment.
#
# You can also use:
# https://github.com/cockroachlabs/github-find-triage-column-id using
# `go install github.com/cockroachlabs/github-find-triage-column-id@latest`.
#
# Then to retrieve triage_column_id from a repo-based project, run:
# github-get-column-id --repo "cockroach" --project "Bazel" --column "To do"
# Or retrieve the triage_column_id from a organization-based project, run:
# github-get-column-id --project "Spatial" --column "Backlog"

cockroachdb/docs:
triage_column_id: 3971225
aliases:
cockroachdb/docs-infra-prs: other
cockroachdb/sql-foundations:
aliases:
cockroachdb/sql-syntax-prs: other
cockroachdb/sqlproxy-prs: other
cockroachdb/sql-api-prs: other
triage_column_id: 19467489
label: T-sql-foundations
cockroachdb/sql-queries:
aliases:
cockroachdb/sql-queries-prs: other
cockroachdb/sql-optimizer: other
cockroachdb/sql-opt-prs: other
# SQL Queries team uses GH projects v2, which doesn't have a REST API, so
# there is no triage column ID.
# See .github/workflows/add-issues-to-project.yml.
label: T-sql-queries
cockroachdb/cluster-observability:
triage_column_id: 12618343
label: T-cluster-observability
cockroachdb/kv:
aliases:
cockroachdb/kv-triage: roachtest
cockroachdb/kv-prs: other
triage_column_id: 14242655
label: T-kv
cockroachdb/replication:
aliases:
cockroachdb/repl-prs: other
label: T-kv-replication
cockroachdb/spatial:
triage_column_id: 9487269
label: T-spatial
cockroachdb/dev-inf:
triage_column_id: 10210759
label: T-dev-inf
cockroachdb/multiregion:
triage_column_id: 11926170
label: T-multiregion
cockroachdb/storage:
aliases:
cockroachdb/admission-control: other
triage_column_id: 6668367
label: T-storage
cockroachdb/test-eng:
triage_column_id: 14041337
label: T-testeng
cockroachdb/test-eng-prs:
triage_column_id: 14041337
label: T-testeng
cockroachdb/security:
label: T-cross-product-security
cockroachdb/prodsec:
label: T-cross-product-security
cockroachdb/disaster-recovery:
triage_column_id: 3097123
label: T-disaster-recovery
cockroachdb/cdc:
aliases:
cockroachdb/cdc-prs: other
# CDC team uses GH projects v2, which doesn't have a REST API, so no triage column ID
# see .github/workflows/add-issues-to-project.yml
label: T-cdc
cockroachdb/server:
aliases:
cockroachdb/cli-prs: other
cockroachdb/server-prs: other
triage_column_id: 2521812
cockroachdb/admin-ui:
aliases:
cockroachdb/admin-ui-prs: other
triage_column_id: 6598672
label: T-observability-inf
cockroachdb/obs-inf-prs:
aliases:
cockroachdb/http-api-prs: other
triage_column_id: 14196277
label: T-observability-inf
cockroachdb/multi-tenant:
# Multi-tenant team uses GH projects v2, which doesn't have a REST API, so no triage column ID
# see .github/workflows/add-issues-to-project.yml
label: T-multitenant
cockroachdb/jobs:
aliases:
cockroachdb/jobs-prs: other
# Jobs uses GH projects v2, which doesn't have a REST API, so no triage column ID
# see .github/workflows/add-issues-to-project.yml
label: T-jobs
cockroachdb/cloud-identity:
triage_column_id: 18588697
cockroachdb/unowned:
aliases:
cockroachdb/rfc-prs: other
triage_column_id: 0 # TODO
cockroachdb/migrations:
label: T-migrations
triage_column_id: 18330909
cockroachdb/release-eng:
label: T-release
triage_column_id: 9149730
4 changes: 2 additions & 2 deletions pkg/sql/create_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ func (p *planner) CreateDatabase(ctx context.Context, n *tree.CreateDatabase) (p
return &createDatabaseNode{n: n}, nil
}

// CanCreateDatabase verifies that the current user has the CREATEDB
// role option.
// CanCreateDatabase returns nil if current user has CREATEDB system privilege
// or the equivalent, legacy role options.
func (p *planner) CanCreateDatabase(ctx context.Context) error {
hasCreateDB, err := p.HasGlobalPrivilegeOrRoleOption(ctx, privilege.CREATEDB)
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion pkg/sql/logictest/testdata/logic_test/bytes
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,12 @@ DROP TABLE t
subtest Regression_4312

statement ok
PREPARE r1(bytes) AS SELECT descriptor::STRING FROM system.descriptor WHERE descriptor != $1 ORDER BY descriptor DESC LIMIT 1
PREPARE r1(bytes) AS
SELECT descriptor::STRING
FROM system.descriptor
WHERE id = (
SELECT id FROM system.namespace WHERE name = 'defaultdb'
);

query T
EXECUTE r1('abc')
Expand Down
14 changes: 14 additions & 0 deletions pkg/sql/schemachanger/scbuild/builder_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package scbuild

import (
"context"
"sort"

"github.com/cockroachdb/cockroach/pkg/keys"
Expand Down Expand Up @@ -297,6 +298,7 @@ func (b *builderState) CheckPrivilege(e scpb.Element, privilege privilege.Kind)
b.checkPrivilege(screl.GetDescID(e), privilege)
}

// checkPrivilege checks if current user has privilege `priv` on descriptor with `id`.
func (b *builderState) checkPrivilege(id catid.DescID, priv privilege.Kind) {
b.ensureDescriptor(id)
c := b.descCache[id]
Expand Down Expand Up @@ -325,6 +327,13 @@ func (b *builderState) checkPrivilege(id catid.DescID, priv privilege.Kind) {
}
}

// HasGlobalPrivilegeOrRoleOption implements the scbuildstmt.PrivilegeChecker interface.
func (b *builderState) HasGlobalPrivilegeOrRoleOption(
ctx context.Context, privilege privilege.Kind,
) (bool, error) {
return b.auth.HasGlobalPrivilegeOrRoleOption(ctx, privilege)
}

// CurrentUserHasAdminOrIsMemberOf implements the scbuildstmt.PrivilegeChecker interface.
func (b *builderState) CurrentUserHasAdminOrIsMemberOf(role username.SQLUsername) bool {
if b.hasAdmin {
Expand All @@ -345,6 +354,11 @@ func (b *builderState) CurrentUser() username.SQLUsername {
return b.evalCtx.SessionData().User()
}

// CheckRoleExists implements the scbuild.AuthorizationAccessor interface.
func (b *builderState) CheckRoleExists(ctx context.Context, role username.SQLUsername) error {
return b.auth.CheckRoleExists(ctx, role)
}

var _ scbuildstmt.TableHelpers = (*builderState)(nil)

// NextTableColumnID implements the scbuildstmt.TableHelpers interface.
Expand Down
13 changes: 10 additions & 3 deletions pkg/sql/schemachanger/scbuild/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,14 @@ type AuthorizationAccessor interface {
ctx context.Context, privilegeObject privilege.Object, privilege privilege.Kind,
) error

// HasAdminRole verifies if a user has an admin role.
// HasAdminRole verifies if current user has an admin role.
HasAdminRole(ctx context.Context) (bool, error)

// HasOwnership returns true iff the role, or any role the role is a member
// of, has ownership privilege of the desc.
HasOwnership(ctx context.Context, privilegeObject privilege.Object) (bool, error)

// CheckPrivilegeForUser verifies that the user has `privilege` on `descriptor`.
// CheckPrivilegeForUser verifies that `user` has `privilege` on `descriptor`.
CheckPrivilegeForUser(
ctx context.Context, privilegeObject privilege.Object, privilege privilege.Kind, user username.SQLUsername,
) error
Expand All @@ -194,11 +194,18 @@ type AuthorizationAccessor interface {
// and indirect) and returns a map of "role" -> "isAdmin".
MemberOfWithAdminOption(ctx context.Context, member username.SQLUsername) (map[username.SQLUsername]bool, error)

// HasPrivilege checks if the user has `privilege` on `descriptor`.
// HasPrivilege checks if the `user` has `privilege` on `privilegeObject`.
HasPrivilege(ctx context.Context, privilegeObject privilege.Object, privilege privilege.Kind, user username.SQLUsername) (bool, error)

// HasAnyPrivilege returns true if user has any privileges at all.
HasAnyPrivilege(ctx context.Context, privilegeObject privilege.Object) (bool, error)

// HasGlobalPrivilegeOrRoleOption returns a bool representing whether the current user
// has a global privilege or the corresponding legacy role option.
HasGlobalPrivilegeOrRoleOption(ctx context.Context, privilege privilege.Kind) (bool, error)

// CheckRoleExists returns nil if `role` exists.
CheckRoleExists(ctx context.Context, role username.SQLUsername) error
}

// AstFormatter provides interfaces for formatting AST nodes.
Expand Down
4 changes: 3 additions & 1 deletion pkg/sql/schemachanger/scbuild/event_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,9 @@ func (pb payloadBuilder) build(b buildCtx) logpb.EventPayload {
switch e := pb.Element().(type) {
case *scpb.Database:
if pb.TargetStatus == scpb.Status_PUBLIC {
return nil
return &eventpb.CreateDatabase{
DatabaseName: fullyQualifiedName(b, e),
}
} else {
return &eventpb.DropDatabase{
DatabaseName: fullyQualifiedName(b, e),
Expand Down
Loading

0 comments on commit e4067f1

Please sign in to comment.