github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/build_index_util.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  	"context"
    19  	"fmt"
    20  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    21  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    22  	"strings"
    23  )
    24  
    25  // checkConstraintNames Check whether the name of the constraint(index,unqiue etc) is legal, and handle constraints without a name
    26  func checkConstraintNames(uniqueConstraints []*tree.UniqueIndex, indexConstraints []*tree.Index, ctx context.Context) error {
    27  	constrNames := map[string]bool{}
    28  	// Check not empty constraint name whether is duplicated.
    29  	for _, constr := range indexConstraints {
    30  		err := checkDuplicateConstraint(constrNames, constr.Name, false, ctx)
    31  		if err != nil {
    32  			return err
    33  		}
    34  	}
    35  	for _, constr := range uniqueConstraints {
    36  		err := checkDuplicateConstraint(constrNames, constr.Name, false, ctx)
    37  		if err != nil {
    38  			return err
    39  		}
    40  	}
    41  	// set empty constraint names(index and unique index)
    42  	for _, constr := range indexConstraints {
    43  		setEmptyIndexName(constrNames, constr)
    44  	}
    45  	for _, constr := range uniqueConstraints {
    46  		setEmptyUniqueIndexName(constrNames, constr)
    47  	}
    48  	return nil
    49  }
    50  
    51  // checkDuplicateConstraint Check whether the constraint name is duplicate
    52  func checkDuplicateConstraint(namesMap map[string]bool, name string, foreign bool, ctx context.Context) error {
    53  	if name == "" {
    54  		return nil
    55  	}
    56  	nameLower := strings.ToLower(name)
    57  	if namesMap[nameLower] {
    58  		if foreign {
    59  			return moerr.NewInvalidInput(ctx, "Duplicate foreign key constraint name '%s'", name)
    60  		}
    61  		return moerr.NewDuplicateKey(ctx, name)
    62  	}
    63  	namesMap[nameLower] = true
    64  	return nil
    65  }
    66  
    67  // setEmptyUniqueIndexName Set name for unqiue index constraint with an empty name
    68  func setEmptyUniqueIndexName(namesMap map[string]bool, indexConstr *tree.UniqueIndex) {
    69  	if indexConstr.Name == "" && len(indexConstr.KeyParts) > 0 {
    70  		colName := indexConstr.KeyParts[0].ColName.Parts[0]
    71  		constrName := colName
    72  		i := 2
    73  		if strings.EqualFold(constrName, "PRIMARY") {
    74  			constrName = fmt.Sprintf("%s_%d", constrName, 2)
    75  			i = 3
    76  		}
    77  		for namesMap[constrName] {
    78  			// loop forever until we find constrName that haven't been used.
    79  			constrName = fmt.Sprintf("%s_%d", colName, i)
    80  			i++
    81  		}
    82  		indexConstr.Name = constrName
    83  		namesMap[constrName] = true
    84  	}
    85  }
    86  
    87  // setEmptyIndexName Set name for index constraint with an empty name
    88  func setEmptyIndexName(namesMap map[string]bool, indexConstr *tree.Index) {
    89  	if indexConstr.Name == "" && len(indexConstr.KeyParts) > 0 {
    90  		var colName string
    91  		if colName == "" {
    92  			colName = indexConstr.KeyParts[0].ColName.Parts[0]
    93  		}
    94  		constrName := colName
    95  		i := 2
    96  		if strings.EqualFold(constrName, "PRIMARY") {
    97  			constrName = fmt.Sprintf("%s_%d", constrName, 2)
    98  			i = 3
    99  		}
   100  		for namesMap[constrName] {
   101  			//  loop forever until we find constrName that haven't been used.
   102  			constrName = fmt.Sprintf("%s_%d", colName, i)
   103  			i++
   104  		}
   105  		indexConstr.Name = constrName
   106  		namesMap[constrName] = true
   107  	}
   108  }
   109  
   110  // TODO
   111  // Currently, using expression as index keyparts are not supported in matrixone
   112  func checkIndexKeypartSupportability(context context.Context, keyParts []*tree.KeyPart) error {
   113  	for _, key := range keyParts {
   114  		if key.Expr != nil {
   115  			return moerr.NewInternalError(context, "unsupported index which using expression as keypart")
   116  		}
   117  	}
   118  	return nil
   119  }