diff --git a/sql3/planner/expression.go b/sql3/planner/expression.go index f6b891b31..25786fd34 100644 --- a/sql3/planner/expression.go +++ b/sql3/planner/expression.go @@ -1484,6 +1484,8 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er return n.EvaluateSubstring(currentRow) case "REPLACEALL": return n.EvaluateReplaceAll(currentRow) + case "TRIM": + return n.EvaluateTrim(currentRow) default: return nil, sql3.NewErrInternalf("unhandled function name '%s'", n.name) } diff --git a/sql3/planner/expressionanalyzercall.go b/sql3/planner/expressionanalyzercall.go index c3dfed12d..88b77201f 100644 --- a/sql3/planner/expressionanalyzercall.go +++ b/sql3/planner/expressionanalyzercall.go @@ -249,6 +249,9 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser return p.analyseFunctionSubstring(call, scope) case "REPLACEALL": return p.analyseFunctionReplaceAll(call, scope) + case "TRIM": + return p.analyseFunctionTrim(call, scope) + default: return nil, sql3.NewErrCallUnknownFunction(call.Name.NamePos.Line, call.Name.NamePos.Column, call.Name.Name) } diff --git a/sql3/planner/inbuiltfunctionsstring.go b/sql3/planner/inbuiltfunctionsstring.go index 5ede7441f..b41aba323 100644 --- a/sql3/planner/inbuiltfunctionsstring.go +++ b/sql3/planner/inbuiltfunctionsstring.go @@ -170,7 +170,6 @@ func evaluateStringArg(n types.PlanExpression, currentRow []interface{}) (string if err != nil { return "", err } - stringArgOne, ok := argOneEval.(string) if !ok { return "", sql3.NewErrInternalf("unexpected type converion %T", argOneEval) @@ -178,3 +177,30 @@ func evaluateStringArg(n types.PlanExpression, currentRow []interface{}) (string return stringArgOne, nil } + +//Analyze function for Trim +func (p *ExecutionPlanner) analyseFunctionTrim(call *parser.Call, scope parser.Statement) (parser.Expr, error) { + //one argument for Trim 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 +} + +// Execute Trim function to remove whitespaces from string +func (n *callPlanExpression) EvaluateTrim(currentRow []interface{}) (interface{}, error) { + stringArgOne, err := evaluateStringArg(n.args[0], currentRow) + if err != nil { + return nil, err + } + + // Trim the whitespace from string + return strings.TrimSpace(stringArgOne), nil +} diff --git a/sql3/test/defs/defs_string_functions.go b/sql3/test/defs/defs_string_functions.go index 38ebd27ed..1002597e0 100644 --- a/sql3/test/defs/defs_string_functions.go +++ b/sql3/test/defs/defs_string_functions.go @@ -188,5 +188,32 @@ var stringScalarFunctionsTests = TableTest{ ), ExpErr: "string expression expected", }, + { + name: "RemovingWhitespacefromStringusingTrim", + SQLs: sqls( + "select trim(' this ')", + ), + ExpHdrs: hdrs( + hdr("", fldTypeString), + ), + ExpRows: rows( + row(string("this")), + ), + Compare: CompareExactOrdered, + }, + { + name: "IncorrectArgumentsforTrim", + SQLs: sqls( + "select trim(' a ','b')", + ), + ExpErr: "'trim': count of formal parameters (1) does not match count of actual parameters (2)", + }, + { + name: "IncorrectInputforTrim", + SQLs: sqls( + "select trim(1)", + ), + ExpErr: "string expression expected", + }, }, }