From 682f240b7b9850381587181eca87ca092407e48a Mon Sep 17 00:00:00 2001 From: HHans09 <91560812+HHans09@users.noreply.github.com> Date: Fri, 9 Dec 2022 14:19:17 -0500 Subject: [PATCH] Fb:1787 - Clean up (#2339) * Fb:1787 - Clean up * fb-1787 : String upper function * Formatting the files (cherry picked from commit 57ce7c4c0eed7454c5fc5674d5a43e2721fd86c6) --- sql3/planner/expression.go | 2 ++ sql3/planner/expressionanalyzercall.go | 2 ++ sql3/planner/inbuiltfunctionsstring.go | 34 +++++++++++++++++++++++++ sql3/test/defs/defs_string_functions.go | 30 +++++++++++++++++++++- 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/sql3/planner/expression.go b/sql3/planner/expression.go index 2b5d0dd10..c9b7e0e58 100644 --- a/sql3/planner/expression.go +++ b/sql3/planner/expression.go @@ -1478,6 +1478,8 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er return n.EvaluateDatepart(currentRow) case "REVERSE": return n.EvaluateReverse(currentRow) + case "UPPER": + return n.EvaluateUpper(currentRow) case "SUBSTRING": return n.EvaluateSubstring(currentRow) default: diff --git a/sql3/planner/expressionanalyzercall.go b/sql3/planner/expressionanalyzercall.go index 9f79d5026..6401cb17e 100644 --- a/sql3/planner/expressionanalyzercall.go +++ b/sql3/planner/expressionanalyzercall.go @@ -243,6 +243,8 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser return p.analyzeFunctionSubtable(call, scope) case "REVERSE": return p.analyseFunctionReverse(call, scope) + case "UPPER": + return p.analyzeFunctionUpper(call, scope) case "SUBSTRING": return p.analyseFunctionSubstring(call, scope) diff --git a/sql3/planner/inbuiltfunctionsstring.go b/sql3/planner/inbuiltfunctionsstring.go index 33958d636..e68c813ee 100644 --- a/sql3/planner/inbuiltfunctionsstring.go +++ b/sql3/planner/inbuiltfunctionsstring.go @@ -1,7 +1,9 @@ package planner import ( + "fmt" "strconv" + "strings" "github.com/molecula/featurebase/v3/sql3" "github.com/molecula/featurebase/v3/sql3/parser" @@ -63,8 +65,40 @@ func (n *callPlanExpression) EvaluateReverse(currentRow []interface{}) (interfac return string(runes), nil } +func (p *ExecutionPlanner) analyzeFunctionUpper(call *parser.Call, scope parser.Statement) (parser.Expr, error) { + //one argument for Upper Function + if len(call.Args) != 1 { + return nil, sql3.NewErrCallParameterCountMismatch(call.Rparen.Line, call.Rparen.Column, call.Name.Name, 1, len(call.Args)) + } + + if !typeIsString(call.Args[0].DataType()) { + return nil, sql3.NewErrStringExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column) + } + + call.ResultDataType = parser.NewDataTypeString() + + return call, nil +} + +// Convert string to Upper case +func (n *callPlanExpression) EvaluateUpper(currentRow []interface{}) (interface{}, error) { + argOneEval, err := n.args[0].Evaluate(currentRow) + if err != nil { + return nil, err + } + + stringArgOne, ok := argOneEval.(string) + if !ok { + return nil, sql3.NewErrInternalf("unexpected type converion %T", argOneEval) + } + // convert to Upper + res := strings.ToUpper(stringArgOne) + return fmt.Sprintf("%s", res), nil +} + // Takes string, startIndex and length and returns the substring. func (n *callPlanExpression) EvaluateSubstring(currentRow []interface{}) (interface{}, error) { + argOneEval, err := n.args[0].Evaluate(currentRow) if err != nil { return nil, err diff --git a/sql3/test/defs/defs_string_functions.go b/sql3/test/defs/defs_string_functions.go index d186cc887..596199cd3 100644 --- a/sql3/test/defs/defs_string_functions.go +++ b/sql3/test/defs/defs_string_functions.go @@ -10,9 +10,10 @@ var stringScalarFunctionsTests = TableTest{ srcHdr("a", fldTypeInt, "min 0", "max 1000"), srcHdr("b", fldTypeInt, "min 0", "max 1000"), srcHdr("ts", fldTypeTimestamp), + srcHdr("a_string", fldTypeString), ), srcRows( - srcRow(int64(1), int64(10), int64(100), knownTimestamp()), + srcRow(int64(1), int64(10), int64(100), knownTimestamp(), "hello"), ), ), SQLTests: []SQLTest{ @@ -107,5 +108,32 @@ var stringScalarFunctionsTests = TableTest{ ), Compare: CompareExactUnordered, }, + { + name: "ConvertingStringtoUpper", + SQLs: sqls( + "select upper('this')", + ), + ExpHdrs: hdrs( + hdr("", fldTypeString), + ), + ExpRows: rows( + row(string("THIS")), + ), + Compare: CompareExactOrdered, + }, + { + name: "IncorrectArgumentsforUpper", + SQLs: sqls( + "select upper('a','b')", + ), + ExpErr: "'upper': count of formal parameters (1) does not match count of actual parameters (2)", + }, + { + name: "IncorrectInputforUpper", + SQLs: sqls( + "select upper(1)", + ), + ExpErr: "string expression expected", + }, }, }