github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/alter_pk.go (about)

     1  // Copyright 2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plan
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"gopkg.in/src-d/go-errors.v1"
    21  
    22  	"github.com/dolthub/go-mysql-server/sql"
    23  	"github.com/dolthub/go-mysql-server/sql/transform"
    24  	"github.com/dolthub/go-mysql-server/sql/types"
    25  )
    26  
    27  type PKAction byte
    28  
    29  const (
    30  	PrimaryKeyAction_Create PKAction = iota
    31  	PrimaryKeyAction_Drop
    32  )
    33  
    34  // ErrNotPrimaryKeyAlterable is return when a table cannot be determined to be primary key alterable
    35  var ErrNotPrimaryKeyAlterable = errors.NewKind("error: table is not primary key alterable")
    36  
    37  type AlterPK struct {
    38  	ddlNode
    39  
    40  	Action       PKAction
    41  	Table        sql.Node
    42  	Columns      []sql.IndexColumn
    43  	Catalog      sql.Catalog
    44  	targetSchema sql.Schema
    45  }
    46  
    47  var _ sql.Node = (*AlterPK)(nil)
    48  var _ sql.Databaser = (*AlterPK)(nil)
    49  var _ sql.SchemaTarget = (*AlterPK)(nil)
    50  var _ sql.CollationCoercible = (*AlterPK)(nil)
    51  
    52  func NewAlterCreatePk(db sql.Database, table sql.Node, columns []sql.IndexColumn) *AlterPK {
    53  	return &AlterPK{
    54  		Action:  PrimaryKeyAction_Create,
    55  		ddlNode: ddlNode{Db: db},
    56  		Table:   table,
    57  		Columns: columns,
    58  	}
    59  }
    60  
    61  func NewAlterDropPk(db sql.Database, table sql.Node) *AlterPK {
    62  	return &AlterPK{
    63  		Action:  PrimaryKeyAction_Drop,
    64  		Table:   table,
    65  		ddlNode: ddlNode{Db: db},
    66  	}
    67  }
    68  
    69  func (a *AlterPK) Resolved() bool {
    70  	return a.Table.Resolved() && a.ddlNode.Resolved() && a.targetSchema.Resolved()
    71  }
    72  
    73  func (a *AlterPK) IsReadOnly() bool {
    74  	return false
    75  }
    76  
    77  func (a *AlterPK) String() string {
    78  	action := "add"
    79  	if a.Action == PrimaryKeyAction_Drop {
    80  		action = "drop"
    81  	}
    82  
    83  	return fmt.Sprintf("alter table %s %s primary key", a.Table.String(), action)
    84  }
    85  
    86  func (a *AlterPK) Schema() sql.Schema {
    87  	return types.OkResultSchema
    88  }
    89  
    90  func (a AlterPK) WithTargetSchema(schema sql.Schema) (sql.Node, error) {
    91  	a.targetSchema = schema
    92  	return &a, nil
    93  }
    94  
    95  func (a *AlterPK) TargetSchema() sql.Schema {
    96  	return a.targetSchema
    97  }
    98  
    99  func (a *AlterPK) Expressions() []sql.Expression {
   100  	return transform.WrappedColumnDefaults(a.targetSchema)
   101  }
   102  
   103  func (a AlterPK) WithExpressions(exprs ...sql.Expression) (sql.Node, error) {
   104  	if len(exprs) != len(a.targetSchema) {
   105  		return nil, sql.ErrInvalidChildrenNumber.New(a, len(exprs), len(a.targetSchema))
   106  	}
   107  
   108  	sch, err := transform.SchemaWithDefaults(a.targetSchema, exprs[:len(a.targetSchema)])
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	a.targetSchema = sch
   113  
   114  	return &a, nil
   115  }
   116  
   117  func HasPrimaryKeys(table sql.Table) bool {
   118  	for _, c := range table.Schema() {
   119  		if c.PrimaryKey {
   120  			return true
   121  		}
   122  	}
   123  
   124  	return false
   125  }
   126  
   127  func (a AlterPK) WithChildren(children ...sql.Node) (sql.Node, error) {
   128  	if len(children) != 1 {
   129  		return nil, sql.ErrInvalidChildrenNumber.New(a, len(children), 1)
   130  	}
   131  
   132  	a.Table = children[0]
   133  	return &a, nil
   134  }
   135  
   136  // Children implements the sql.Node interface.
   137  func (a *AlterPK) Children() []sql.Node {
   138  	return []sql.Node{a.Table}
   139  }
   140  
   141  // WithDatabase implements the sql.Databaser interface.
   142  func (a AlterPK) WithDatabase(database sql.Database) (sql.Node, error) {
   143  	a.Db = database
   144  	return &a, nil
   145  }
   146  
   147  // CheckPrivileges implements the interface sql.Node.
   148  func (a *AlterPK) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
   149  	subject := sql.PrivilegeCheckSubject{
   150  		Database: a.Database().Name(),
   151  		Table:    getTableName(a.Table),
   152  	}
   153  
   154  	return opChecker.UserHasPrivileges(ctx,
   155  		sql.NewPrivilegedOperation(subject, sql.PrivilegeType_Alter))
   156  }
   157  
   158  // CollationCoercibility implements the interface sql.CollationCoercible.
   159  func (*AlterPK) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) {
   160  	return sql.Collation_binary, 7
   161  }