From 2b9c13497ef59a06a421aa2c28947cb94212e649 Mon Sep 17 00:00:00 2001 From: Lory Cloutier <118481783+lorycloutier@users.noreply.github.com> Date: Mon, 9 Jan 2023 12:20:04 -0600 Subject: [PATCH] Implement SPACE() function for SQL3 (#2399) FB-1861 (cherry picked from commit da74f0a312f464c889a19bd9bf68b1de682c4a3c) --- sql3/planner/expression.go | 2 ++ sql3/planner/expressionanalyzercall.go | 2 ++ sql3/planner/inbuiltfunctionsstring.go | 30 +++++++++++++++++++++++++ sql3/test/defs/defs_string_functions.go | 26 +++++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/sql3/planner/expression.go b/sql3/planner/expression.go index fc69a7798..70dd3e736 100644 --- a/sql3/planner/expression.go +++ b/sql3/planner/expression.go @@ -1512,6 +1512,8 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er return n.EvaluateSuffix(currentRow) case "PREFIX": return n.EvaluatePrefix(currentRow) + case "SPACE": + return n.EvaluateSpace(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 d828cfd90..65e2b81e1 100644 --- a/sql3/planner/expressionanalyzercall.go +++ b/sql3/planner/expressionanalyzercall.go @@ -265,6 +265,8 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser return p.analyseFunctionPrefixSuffix(call, scope) case "PREFIX": return p.analyseFunctionPrefixSuffix(call, scope) + case "SPACE": + return p.analyseFunctionSpace(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 c6240389e..9c5d80011 100644 --- a/sql3/planner/inbuiltfunctionsstring.go +++ b/sql3/planner/inbuiltfunctionsstring.go @@ -147,6 +147,21 @@ func (p *ExecutionPlanner) analyzeFunctionUpper(call *parser.Call, scope parser. return call, nil } +func (p *ExecutionPlanner) analyseFunctionSpace(call *parser.Call, scope parser.Statement) (parser.Expr, error) { + //one argument + if len(call.Args) != 1 { + return nil, sql3.NewErrCallParameterCountMismatch(call.Rparen.Line, call.Rparen.Column, call.Name.Name, 1, len(call.Args)) + } + + if !typeIsInteger(call.Args[0].DataType()) { + return nil, sql3.NewErrIntExpressionExpected(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) { stringArgOne, err := evaluateStringArg(n.args[0], currentRow) @@ -403,3 +418,18 @@ func (n *callPlanExpression) EvaluateSuffix(currentRow []interface{}) (interface return stringArgOne[len(stringArgOne)-intArgTwo:], nil } + +func (n *callPlanExpression) EvaluateSpace(currentRow []interface{}) (interface{}, error) { + // Get the integer argument from the function call + intArg, err := evaluateIntArg(n.args[0], currentRow) + if err != nil { + return "", err + } + + // Return a string containing a number of spaces equal to the integer value + spaces := "" + for i := 0; i < intArg; i++ { + spaces += " " + } + return spaces, nil +} diff --git a/sql3/test/defs/defs_string_functions.go b/sql3/test/defs/defs_string_functions.go index 59ad9d1ac..6c339ac2a 100644 --- a/sql3/test/defs/defs_string_functions.go +++ b/sql3/test/defs/defs_string_functions.go @@ -466,5 +466,31 @@ var stringScalarFunctionsTests = TableTest{ ), ExpErr: "string expression expected", }, + { + name: "SpaceZero", + SQLs: sqls( + "select space(0)", + ), + ExpHdrs: hdrs( + hdr("", fldTypeString), + ), + ExpRows: rows( + row(string("")), + ), + Compare: CompareExactOrdered, + }, + { + name: "SpaceFive", + SQLs: sqls( + "select space(5)", + ), + ExpHdrs: hdrs( + hdr("", fldTypeString), + ), + ExpRows: rows( + row(string(" ")), + ), + Compare: CompareExactOrdered, + }, }, }