github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/build_alter_rename_column.go (about)

     1  // Copyright 2023 Matrix Origin
     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  	"github.com/matrixorigin/matrixone/pkg/catalog"
    19  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    20  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    21  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    22  	"strings"
    23  )
    24  
    25  // RenameColumn Can change a column name but not its definition.
    26  // More convenient than CHANGE to rename a column without changing its definition.
    27  func RenameColumn(ctx CompilerContext, alterPlan *plan.AlterTable, spec *tree.AlterTableRenameColumnClause, alterCtx *AlterTableContext) error {
    28  	tableDef := alterPlan.CopyTableDef
    29  
    30  	// get the original column name
    31  	originalColName := spec.OldColumnName.Parts[0]
    32  
    33  	// get the new column name
    34  	newColName := spec.NewColumnName.Parts[0]
    35  
    36  	// Check whether original column has existed.
    37  	originalCol := FindColumn(tableDef.Cols, originalColName)
    38  	if originalCol == nil || originalCol.Hidden {
    39  		return moerr.NewBadFieldError(ctx.GetContext(), originalColName, alterPlan.TableDef.Name)
    40  	}
    41  
    42  	if originalColName == newColName {
    43  		return nil
    44  	}
    45  
    46  	// Check if the new column name is valid and conflicts with internal hidden columns
    47  	if err := CheckColumnNameValid(ctx.GetContext(), newColName); err != nil {
    48  		return err
    49  	}
    50  
    51  	if isColumnWithPartition(originalCol.Name, tableDef.Partition) {
    52  		return moerr.NewNotSupported(ctx.GetContext(), "unsupport alter partition part column currently")
    53  	}
    54  
    55  	// If you want to rename the original column name to new name, you need to first check if the new name already exists.
    56  	if newColName != originalColName {
    57  		newcol := FindColumn(tableDef.Cols, newColName)
    58  		if newcol != nil {
    59  			return moerr.NewErrDupFieldName(ctx.GetContext(), newColName)
    60  		}
    61  
    62  		// If the column name of the table changes, it is necessary to check if it is associated
    63  		// with the index key. If it is an index key column, column name replacement is required.
    64  		for _, indexInfo := range alterPlan.CopyTableDef.Indexes {
    65  			for j, partCol := range indexInfo.Parts {
    66  				partCol = catalog.ResolveAlias(partCol)
    67  				if partCol == originalCol.Name {
    68  					indexInfo.Parts[j] = newColName
    69  					break
    70  				}
    71  			}
    72  		}
    73  
    74  		primaryKeyDef := alterPlan.CopyTableDef.Pkey
    75  		for j, partCol := range primaryKeyDef.Names {
    76  			if partCol == originalCol.Name {
    77  				primaryKeyDef.Names[j] = newColName
    78  				break
    79  			}
    80  		}
    81  		// handle cluster by key in modify column
    82  		handleClusterByKey(ctx.GetContext(), alterPlan, newColName, originalCol.Name)
    83  	}
    84  
    85  	for i, col := range tableDef.Cols {
    86  		if strings.EqualFold(col.Name, originalCol.Name) {
    87  			colDef := DeepCopyColDef(col)
    88  			colDef.Name = newColName
    89  			tableDef.Cols[i] = colDef
    90  			break
    91  		}
    92  	}
    93  
    94  	delete(alterCtx.alterColMap, originalCol.Name)
    95  	alterCtx.alterColMap[newColName] = selectExpr{
    96  		sexprType: columnName,
    97  		sexprStr:  originalCol.Name,
    98  	}
    99  
   100  	if tmpCol, ok := alterCtx.changColDefMap[originalCol.ColId]; ok {
   101  		tmpCol.Name = newColName
   102  	}
   103  
   104  	alterCtx.UpdateSqls = append(alterCtx.UpdateSqls,
   105  		getSqlForRenameColumn(alterPlan.Database,
   106  			alterPlan.TableDef.Name,
   107  			originalColName,
   108  			newColName)...)
   109  
   110  	return nil
   111  }
   112  
   113  // AlterColumn ALTER ... SET DEFAULT or ALTER ... DROP DEFAULT specify a new default value for a column or remove the old default value, respectively.
   114  // If the old default is removed and the column can be NULL, the new default is NULL. If the column cannot be NULL, MySQL assigns a default value
   115  func AlterColumn(ctx CompilerContext, alterPlan *plan.AlterTable, spec *tree.AlterTableAlterColumnClause, alterCtx *AlterTableContext) error {
   116  	tableDef := alterPlan.CopyTableDef
   117  
   118  	// get the original column name
   119  	originalColName := spec.ColumnName.Parts[0]
   120  
   121  	// Check whether original column has existed.
   122  	originalCol := FindColumn(tableDef.Cols, originalColName)
   123  	if originalCol == nil || originalCol.Hidden {
   124  		return moerr.NewBadFieldError(ctx.GetContext(), originalColName, alterPlan.TableDef.Name)
   125  	}
   126  
   127  	for i, col := range tableDef.Cols {
   128  		if strings.EqualFold(col.Name, originalCol.Name) {
   129  			colDef := DeepCopyColDef(col)
   130  			if spec.OptionType == tree.AlterColumnOptionSetDefault {
   131  				tmpColumnDef := tree.NewColumnTableDef(spec.ColumnName, nil, []tree.ColumnAttribute{spec.DefalutExpr})
   132  				defer func() {
   133  					tmpColumnDef.Free()
   134  				}()
   135  				defaultValue, err := buildDefaultExpr(tmpColumnDef, colDef.Typ, ctx.GetProcess())
   136  				if err != nil {
   137  					return err
   138  				}
   139  				defaultValue.NullAbility = colDef.Default.NullAbility
   140  				colDef.Default = defaultValue
   141  			} else if spec.OptionType == tree.AlterColumnOptionDropDefault {
   142  				colDef.Default.Expr = nil
   143  				colDef.Default.OriginString = ""
   144  			}
   145  			tableDef.Cols[i] = colDef
   146  			break
   147  		}
   148  	}
   149  	return nil
   150  }
   151  
   152  // OrderByColumn Currently, Mo only performs semantic checks on alter table order by
   153  // and does not implement the function of changing the physical storage order of data in the table
   154  func OrderByColumn(ctx CompilerContext, alterPlan *plan.AlterTable, spec *tree.AlterTableOrderByColumnClause, alterCtx *AlterTableContext) error {
   155  	tableDef := alterPlan.CopyTableDef
   156  	for _, order := range spec.AlterOrderByList {
   157  		// get the original column name
   158  		originalColName := order.Column.Parts[0]
   159  		// Check whether original column has existed.
   160  		originalCol := FindColumn(tableDef.Cols, originalColName)
   161  		if originalCol == nil || originalCol.Hidden {
   162  			return moerr.NewBadFieldError(ctx.GetContext(), originalColName, alterPlan.TableDef.Name)
   163  		}
   164  	}
   165  	return nil
   166  }