featurebase/sql3/planner/compilecreatedatabase.go
Pat Okeeffe 5c74b64722
A bug fix roundup (#2242)
* fb-1940 re-implemented some changes that got missed private-public

* fb-1939 fixes to between + decimals

* fb-1935 - avg() on and id type + fixed some tests

* fb-1953 add min/max for string types

* fb-1938 - remove internal_type column from show columns

* fb-1964 - fix space_used in fb_cluster_nodes to be int

* fb-1996 - make sure all Idents that are being used as object references to schema objects are lowercased

* fixed failing test

* added some missed changes

* fb-1969 found another case issue with identifier used for column idents
2023-02-13 12:28:34 -06:00

84 lines
2.3 KiB
Go

// Copyright 2021 Molecula Corp. All rights reserved.
package planner
import (
"strconv"
"strings"
"github.com/featurebasedb/featurebase/v3/sql3"
"github.com/featurebasedb/featurebase/v3/sql3/parser"
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
)
// compileCreateDatabaseStatement compiles a CREATE DATABASE statement into a
// PlanOperator.
func (p *ExecutionPlanner) compileCreateDatabaseStatement(stmt *parser.CreateDatabaseStatement) (_ types.PlanOperator, err error) {
databaseName := strings.ToLower(parser.IdentName(stmt.Name))
failIfExists := !stmt.IfNotExists.IsValid()
units := 0
description := ""
// apply database options
if stmt.With.IsValid() {
for _, option := range stmt.Options {
switch o := option.(type) {
case *parser.UnitsOption:
e := o.Expr.(*parser.IntegerLit)
i, err := strconv.ParseInt(e.Value, 10, 64)
if err != nil {
return nil, err
}
units = int(i)
case *parser.CommentOption:
e := o.Expr.(*parser.StringLit)
description = e.Value
}
}
}
cop := NewPlanOpCreateDatabase(p, databaseName, failIfExists, units, description)
return NewPlanOpQuery(p, cop, p.sql), nil
}
// analyzeCreateDatabaseStatement analyzes a CREATE DATABASE statement and
// returns an error if anything is invalid.
func (p *ExecutionPlanner) analyzeCreateDatabaseStatement(stmt *parser.CreateDatabaseStatement) error {
if stmt.With.IsValid() {
// no checks if WITH is not provided
return nil
}
//check database options
for _, option := range stmt.Options {
switch o := option.(type) {
case *parser.UnitsOption:
//check the type of the expression
literal, ok := o.Expr.(*parser.IntegerLit)
if !ok {
return sql3.NewErrIntegerLiteral(o.Expr.Pos().Line, o.Expr.Pos().Column)
}
// units needs to be >=0 and we'll cap conservatively at 10000
i, err := strconv.ParseInt(literal.Value, 10, 64)
if err != nil {
return err
}
if i < 0 || i > 10000 {
return sql3.NewErrInvalidUnitsValue(o.Expr.Pos().Line, o.Expr.Pos().Column, i)
}
case *parser.CommentOption:
_, ok := o.Expr.(*parser.StringLit)
if !ok {
return sql3.NewErrStringLiteral(o.Expr.Pos().Line, o.Expr.Pos().Column)
}
default:
return sql3.NewErrInternalf("unhandled database option type '%T'", option)
}
}
return nil
}