github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/create_database.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sql
    12  
    13  import (
    14  	"context"
    15  	"strings"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/server/telemetry"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/descs"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
    22  	"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
    23  )
    24  
    25  type createDatabaseNode struct {
    26  	n *tree.CreateDatabase
    27  }
    28  
    29  // CreateDatabase creates a database.
    30  // Privileges: superuser.
    31  //   Notes: postgres requires superuser or "CREATEDB".
    32  //          mysql uses the mysqladmin command.
    33  func (p *planner) CreateDatabase(ctx context.Context, n *tree.CreateDatabase) (planNode, error) {
    34  	if n.Name == "" {
    35  		return nil, errEmptyDatabaseName
    36  	}
    37  
    38  	if tmpl := n.Template; tmpl != "" {
    39  		// See https://www.postgresql.org/docs/current/static/manage-ag-templatedbs.html
    40  		if !strings.EqualFold(tmpl, "template0") {
    41  			return nil, unimplemented.NewWithIssuef(10151,
    42  				"unsupported template: %s", tmpl)
    43  		}
    44  	}
    45  
    46  	if enc := n.Encoding; enc != "" {
    47  		// We only support UTF8 (and aliases for UTF8).
    48  		if !(strings.EqualFold(enc, "UTF8") ||
    49  			strings.EqualFold(enc, "UTF-8") ||
    50  			strings.EqualFold(enc, "UNICODE")) {
    51  			return nil, unimplemented.NewWithIssueDetailf(35882, "create.db.encoding",
    52  				"unsupported encoding: %s", enc)
    53  		}
    54  	}
    55  
    56  	if col := n.Collate; col != "" {
    57  		// We only support C and C.UTF-8.
    58  		if col != "C" && col != "C.UTF-8" {
    59  			return nil, unimplemented.NewWithIssueDetailf(16618, "create.db.collation",
    60  				"unsupported collation: %s", col)
    61  		}
    62  	}
    63  
    64  	if ctype := n.CType; ctype != "" {
    65  		// We only support C and C.UTF-8.
    66  		if ctype != "C" && ctype != "C.UTF-8" {
    67  			return nil, unimplemented.NewWithIssueDetailf(35882, "create.db.classification",
    68  				"unsupported character classification: %s", ctype)
    69  		}
    70  	}
    71  
    72  	if err := p.RequireAdminRole(ctx, "CREATE DATABASE"); err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	return &createDatabaseNode{n: n}, nil
    77  }
    78  
    79  func (n *createDatabaseNode) startExec(params runParams) error {
    80  	telemetry.Inc(sqltelemetry.SchemaChangeCreateCounter("database"))
    81  	desc := sqlbase.MakeDatabaseDesc(n.n)
    82  
    83  	created, err := params.p.createDatabase(
    84  		params.ctx, &desc, n.n.IfNotExists, tree.AsStringWithFQNames(n.n, params.Ann()))
    85  	if err != nil {
    86  		return err
    87  	}
    88  	if created {
    89  		// Log Create Database event. This is an auditable log event and is
    90  		// recorded in the same transaction as the table descriptor update.
    91  		if err := MakeEventLogger(params.extendedEvalCtx.ExecCfg).InsertEventRecord(
    92  			params.ctx,
    93  			params.p.txn,
    94  			EventLogCreateDatabase,
    95  			int32(desc.ID),
    96  			int32(params.extendedEvalCtx.NodeID.SQLInstanceID()),
    97  			struct {
    98  				DatabaseName string
    99  				Statement    string
   100  				User         string
   101  			}{n.n.Name.String(), n.n.String(), params.SessionData().User},
   102  		); err != nil {
   103  			return err
   104  		}
   105  		params.extendedEvalCtx.Descs.AddUncommittedDatabase(
   106  			desc.Name, desc.ID, descs.DBCreated)
   107  	}
   108  	return nil
   109  }
   110  
   111  func (*createDatabaseNode) Next(runParams) (bool, error) { return false, nil }
   112  func (*createDatabaseNode) Values() tree.Datums          { return tree.Datums{} }
   113  func (*createDatabaseNode) Close(context.Context)        {}