github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/sqlutil/schema.go (about)

     1  // Copyright 2019 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 sqlutil
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	sqle "github.com/dolthub/go-mysql-server"
    22  	"github.com/dolthub/go-mysql-server/sql"
    23  	"github.com/dolthub/go-mysql-server/sql/plan"
    24  	"github.com/dolthub/go-mysql-server/sql/planbuilder"
    25  
    26  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    27  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    28  )
    29  
    30  // ParseCreateTableStatement will parse a CREATE TABLE ddl statement and use it to create a Dolt Schema. A RootValue
    31  // is used to generate unique tags for the Schema
    32  func ParseCreateTableStatement(ctx *sql.Context, root doltdb.RootValue, engine *sqle.Engine, query string) (string, schema.Schema, error) {
    33  	binder := planbuilder.New(ctx, engine.Analyzer.Catalog, engine.Parser)
    34  	parsed, _, _, err := binder.Parse(query, false)
    35  	if err != nil {
    36  		return "", nil, err
    37  	}
    38  	create, ok := parsed.(*plan.CreateTable)
    39  	if !ok {
    40  		return "", nil, fmt.Errorf("expected create table, found %T", create)
    41  	}
    42  
    43  	sch, err := ToDoltSchema(ctx, root, create.Name(), create.PkSchema(), nil, create.Collation)
    44  	if err != nil {
    45  		return "", nil, err
    46  	}
    47  
    48  	for _, idx := range create.Indexes() {
    49  		var prefixes []uint16
    50  		for _, c := range idx.Columns {
    51  			prefixes = append(prefixes, uint16(c.Length))
    52  		}
    53  		props := schema.IndexProperties{
    54  			IsUnique:   idx.IsUnique(),
    55  			IsSpatial:  idx.IsSpatial(),
    56  			IsFullText: idx.IsFullText(),
    57  			Comment:    idx.Comment,
    58  		}
    59  		name := getIndexName(idx)
    60  		_, err = sch.Indexes().AddIndexByColNames(name, idx.ColumnNames(), prefixes, props)
    61  		if err != nil {
    62  			return "", nil, err
    63  		}
    64  	}
    65  
    66  	// foreign keys are stored on the *doltdb.Table object, ignore them here
    67  	for _, chk := range create.Checks() {
    68  		name := getCheckConstraintName(chk)
    69  		_, err = sch.Checks().AddCheck(name, chk.Expr.String(), chk.Enforced)
    70  		if err != nil {
    71  			return "", nil, err
    72  		}
    73  	}
    74  	return create.Name(), sch, err
    75  }
    76  
    77  func getIndexName(def *sql.IndexDef) string {
    78  	if def.Name != "" {
    79  		return def.Name
    80  	}
    81  	return strings.Join(def.ColumnNames(), "_") + "_key"
    82  }
    83  
    84  func getCheckConstraintName(chk *sql.CheckConstraint) string {
    85  	if chk.Name != "" {
    86  		return chk.Name
    87  	}
    88  	return chk.DebugString()
    89  }