github.com/dolthub/go-mysql-server@v0.18.0/sql/planbuilder/parse_column_default.go (about) 1 // Copyright 2023 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 planbuilder 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/dolthub/vitess/go/vt/sqlparser" 22 23 "github.com/dolthub/go-mysql-server/sql" 24 "github.com/dolthub/go-mysql-server/sql/expression" 25 "github.com/dolthub/go-mysql-server/sql/plan" 26 ) 27 28 // StringToColumnDefaultValue takes in a string representing a default value and returns the equivalent Expression. 29 func StringToColumnDefaultValue(ctx *sql.Context, exprStr string) (*sql.ColumnDefaultValue, error) { 30 // all valid default expressions will parse correctly with SELECT prepended, as the parser will not parse raw expressions 31 stmt, err := sqlparser.Parse("SELECT " + exprStr) 32 if err != nil { 33 return nil, err 34 } 35 parserSelect, ok := stmt.(*sqlparser.Select) 36 if !ok { 37 return nil, fmt.Errorf("DefaultStringToExpression expected sqlparser.Select but received %T", stmt) 38 } 39 if len(parserSelect.SelectExprs) != 1 { 40 return nil, fmt.Errorf("default string does not have only one expression") 41 } 42 aliasedExpr, ok := parserSelect.SelectExprs[0].(*sqlparser.AliasedExpr) 43 if !ok { 44 return nil, fmt.Errorf("DefaultStringToExpression expected *sqlparser.AliasedExpr but received %T", parserSelect.SelectExprs[0]) 45 } 46 proj, err := Parse(ctx, nil, fmt.Sprintf("SELECT %s", aliasedExpr.Expr)) 47 if err != nil { 48 return nil, err 49 } 50 parsedExpr := proj.(*plan.Project).Projections[0] 51 if a, ok := parsedExpr.(*expression.Alias); ok { 52 parsedExpr = a.Child 53 } 54 _, isParenthesized := aliasedExpr.Expr.(*sqlparser.ParenExpr) 55 56 var isLiteral bool 57 switch e := parsedExpr.(type) { 58 case *expression.UnaryMinus: 59 _, isLiteral = e.Child.(*expression.Literal) 60 case *expression.UnresolvedFunction: 61 isLiteral = false 62 default: 63 isLiteral = len(parsedExpr.Children()) == 0 && !strings.HasPrefix(exprStr, "(") 64 } 65 return ExpressionToColumnDefaultValue(parsedExpr, isLiteral, isParenthesized), nil 66 } 67 68 // MustStringToColumnDefaultValue is used for creating default values on tables that do not go through the analyzer. Does not handle 69 // function nor column references. 70 func MustStringToColumnDefaultValue(ctx *sql.Context, exprStr string, outType sql.Type, nullable bool) *sql.ColumnDefaultValue { 71 expr, err := StringToColumnDefaultValue(ctx, exprStr) 72 if err != nil { 73 panic(err) 74 } 75 expr, err = sql.NewColumnDefaultValue(expr.Expr, outType, expr.IsLiteral(), !expr.IsLiteral(), nullable) 76 if err != nil { 77 panic(err) 78 } 79 return expr 80 }