From c1dbc48fb29c381c546d4b242fa35a7abd64d213 Mon Sep 17 00:00:00 2001 From: HHans09 <91560812+HHans09@users.noreply.github.com> Date: Wed, 14 Dec 2022 13:21:45 -0500 Subject: [PATCH] fb-1809: SQL3 RTrim & LTrim func for strings (#2361) --- sql3/planner/expression.go | 4 ++ sql3/planner/expressionanalyzercall.go | 4 ++ sql3/planner/inbuiltfunctionsstring.go | 26 +++++++++++- sql3/test/defs/defs_string_functions.go | 54 +++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/sql3/planner/expression.go b/sql3/planner/expression.go index 1bfc1648a..bf89d9f90 100644 --- a/sql3/planner/expression.go +++ b/sql3/planner/expression.go @@ -1492,6 +1492,10 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er return n.EvaluateReplaceAll(currentRow) case "TRIM": return n.EvaluateTrim(currentRow) + case "RTRIM": + return n.EvaluateRTrim(currentRow) + case "LTRIM": + return n.EvaluateLTrim(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 cc7084c42..3aa315e53 100644 --- a/sql3/planner/expressionanalyzercall.go +++ b/sql3/planner/expressionanalyzercall.go @@ -253,6 +253,10 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser return p.analyseFunctionReplaceAll(call, scope) case "TRIM": return p.analyseFunctionTrim(call, scope) + case "RTRIM": + return p.analyseFunctionTrim(call, scope) + case "LTRIM": + 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 628014680..24b84510e 100644 --- a/sql3/planner/inbuiltfunctionsstring.go +++ b/sql3/planner/inbuiltfunctionsstring.go @@ -201,9 +201,9 @@ func evaluateStringArg(n types.PlanExpression, currentRow []interface{}) (string return stringArgOne, nil } -// Analyze function for Trim +// Analyze function for Trim/RTrim/LTrim func (p *ExecutionPlanner) analyseFunctionTrim(call *parser.Call, scope parser.Statement) (parser.Expr, error) { - //one argument for Trim Function + //one argument for Trim Functions if len(call.Args) != 1 { return nil, sql3.NewErrCallParameterCountMismatch(call.Rparen.Line, call.Rparen.Column, call.Name.Name, 1, len(call.Args)) } @@ -227,3 +227,25 @@ func (n *callPlanExpression) EvaluateTrim(currentRow []interface{}) (interface{} // Trim the whitespace from string return strings.TrimSpace(stringArgOne), nil } + +// Execute RTrim function to remove trailing whitespaces from string +func (n *callPlanExpression) EvaluateRTrim(currentRow []interface{}) (interface{}, error) { + stringArgOne, err := evaluateStringArg(n.args[0], currentRow) + if err != nil { + return nil, err + } + + // Trim the trailing whitespace from string + return strings.TrimRight(stringArgOne, " "), nil +} + +// Execute LTrim function to remove leading whitespaces from string +func (n *callPlanExpression) EvaluateLTrim(currentRow []interface{}) (interface{}, error) { + stringArgOne, err := evaluateStringArg(n.args[0], currentRow) + if err != nil { + return nil, err + } + + // Trim the leading whitespace from string + return strings.TrimLeft(stringArgOne, " "), nil +} diff --git a/sql3/test/defs/defs_string_functions.go b/sql3/test/defs/defs_string_functions.go index 5c1992242..b616196f2 100644 --- a/sql3/test/defs/defs_string_functions.go +++ b/sql3/test/defs/defs_string_functions.go @@ -242,5 +242,59 @@ var stringScalarFunctionsTests = TableTest{ ), ExpErr: "string expression expected", }, + { + name: "RemovingTrailingspacefromStringusingRTrim", + SQLs: sqls( + "select rtrim(' this ')", + ), + ExpHdrs: hdrs( + hdr("", fldTypeString), + ), + ExpRows: rows( + row(string(" this")), + ), + Compare: CompareExactOrdered, + }, + { + name: "IncorrectArgumentsforRTrim", + SQLs: sqls( + "select rtrim(' a ',' b ')", + ), + ExpErr: "'rtrim': count of formal parameters (1) does not match count of actual parameters (2)", + }, + { + name: "IncorrectInputforRTrim", + SQLs: sqls( + "select rtrim(1)", + ), + ExpErr: "string expression expected", + }, + { + name: "RemovingLeadingspacefromStringusingLTrim", + SQLs: sqls( + "select ltrim(' this ')", + ), + ExpHdrs: hdrs( + hdr("", fldTypeString), + ), + ExpRows: rows( + row(string("this ")), + ), + Compare: CompareExactOrdered, + }, + { + name: "IncorrectArgumentsforLTrim", + SQLs: sqls( + "select ltrim(' a ',' b ')", + ), + ExpErr: "'ltrim': count of formal parameters (1) does not match count of actual parameters (2)", + }, + { + name: "IncorrectInputforLTrim", + SQLs: sqls( + "select ltrim(1)", + ), + ExpErr: "string expression expected", + }, }, }