98 lines
3.1 KiB
Go
98 lines
3.1 KiB
Go
// Copyright 2019 Dolthub, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package sqlutil
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
sqle "github.com/dolthub/go-mysql-server"
|
|
"github.com/dolthub/go-mysql-server/sql"
|
|
"github.com/dolthub/go-mysql-server/sql/plan"
|
|
"github.com/dolthub/go-mysql-server/sql/planbuilder"
|
|
|
|
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
|
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
|
)
|
|
|
|
// ParseCreateTableStatement will parse a CREATE TABLE ddl statement and use it to create a Dolt Schema. A RootValue
|
|
// is used to generate unique tags for the Schema
|
|
func ParseCreateTableStatement(ctx *sql.Context, root doltdb.RootValue, engine *sqle.Engine, query string) (string, schema.Schema, error) {
|
|
binder := planbuilder.New(ctx, engine.Analyzer.Catalog, engine.EventScheduler)
|
|
parsed, _, _, _, err := binder.Parse(query, nil, false)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
create, ok := parsed.(*plan.CreateTable)
|
|
if !ok {
|
|
return "", nil, fmt.Errorf("expected create table, found %T", create)
|
|
}
|
|
|
|
// NOTE: We don't support setting a schema name here since this code is only intended to be used from the Dolt
|
|
// codebase, and will not work correctly from Doltgres.
|
|
sch, err := ToDoltSchema(ctx, root, doltdb.TableName{Name: create.Name()}, create.PkSchema(), nil, create.Collation)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
for _, idx := range create.Indexes() {
|
|
var prefixes []uint16
|
|
for _, c := range idx.Columns {
|
|
prefixes = append(prefixes, uint16(c.Length))
|
|
}
|
|
var predicateStr string
|
|
if idx.Predicate != nil {
|
|
predicateStr = idx.Predicate.String()
|
|
}
|
|
props := schema.IndexProperties{
|
|
IsUnique: idx.IsUnique(),
|
|
IsSpatial: idx.IsSpatial(),
|
|
IsFullText: idx.IsFullText(),
|
|
IsVector: idx.IsVector(),
|
|
Comment: idx.Comment,
|
|
Predicate: predicateStr,
|
|
}
|
|
name := getIndexName(idx)
|
|
_, err = sch.Indexes().AddIndexByColNames(name, idx.ColumnNames(), prefixes, props)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
}
|
|
|
|
// foreign keys are stored on the *doltdb.Table object, ignore them here
|
|
for _, chk := range create.Checks() {
|
|
name := getCheckConstraintName(ctx, chk)
|
|
_, err = sch.Checks().AddCheck(name, chk.Expr.String(), chk.Enforced, false)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
}
|
|
return create.Name(), sch, err
|
|
}
|
|
|
|
func getIndexName(def *sql.IndexDef) string {
|
|
if def.Name != "" {
|
|
return def.Name
|
|
}
|
|
return strings.Join(def.ColumnNames(), "_") + "_key"
|
|
}
|
|
|
|
func getCheckConstraintName(ctx *sql.Context, chk *sql.CheckConstraint) string {
|
|
if chk.Name != "" {
|
|
return chk.Name
|
|
}
|
|
return chk.DebugString(ctx)
|
|
}
|