Skip to content

Commit

Permalink
schemachanger: Implement CREATE DATABASE
Browse files Browse the repository at this point in the history
This commit supports CREATE DATABASE in declarative schema changer.
It falls back to legacy schema changer if the database is requested
to be multi-region.

Release note: None
  • Loading branch information
Xiang-Gu committed Dec 19, 2023
1 parent 7ff698d commit 77372a6
Show file tree
Hide file tree
Showing 53 changed files with 3,488 additions and 23 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 77372a6

Please sign in to comment.