FB-1812: implement stringsplit() (#2362)

This commit is contained in:
rachithrr 2022-12-15 01:11:29 +05:30 • committed by GitHub
parent 3059529759
commit a4f18fb25f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 0 deletions

View file

@ -1484,6 +1484,8 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
return n.EvaluateReverse(currentRow)
case "UPPER":
return n.EvaluateUpper(currentRow)
case "STRINGSPLIT":
return n.EvaluateStringSplit(currentRow)
case "SUBSTRING":
return n.EvaluateSubstring(currentRow)
case "LOWER":

View file

@ -245,6 +245,8 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser
return p.analyseFunctionReverse(call, scope)
case "UPPER":
return p.analyzeFunctionUpper(call, scope)
case "STRINGSPLIT":
return p.analyseFunctionStringSplit(call, scope)
case "SUBSTRING":
return p.analyseFunctionSubstring(call, scope)
case "LOWER":

View file

@ -53,6 +53,29 @@ func (p *ExecutionPlanner) analyzeFunctionLower(call *parser.Call, scope parser.
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
}
func (p *ExecutionPlanner) analyseFunctionStringSplit(call *parser.Call, scope parser.Statement) (parser.Expr, error) {
if len(call.Args) <= 1 || len(call.Args) > 3 {
return nil, sql3.NewErrCallParameterCountMismatch(call.Rparen.Line, call.Rparen.Column, call.Name.Name, 2, len(call.Args))
}
if !typeIsString(call.Args[0].DataType()) {
return nil, sql3.NewErrStringExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
}
// string seperator
if !typeIsString(call.Args[1].DataType()) {
return nil, sql3.NewErrStringExpressionExpected(call.Args[1].Pos().Line, call.Args[1].Pos().Column)
}
// third argument is the position. optional, defaults to 0
if len(call.Args) == 3 && !typeIsInteger(call.Args[2].DataType()) {
return nil, sql3.NewErrIntExpressionExpected(call.Args[2].Pos().Line, call.Args[2].Pos().Column)
}
call.ResultDataType = parser.NewDataTypeString()
@ -188,6 +211,33 @@ func (n *callPlanExpression) EvaluateReplaceAll(currentRow []interface{}) (inter
return strings.ReplaceAll(stringArgOne, stringArgTwo, stringArgThree), nil
}
// takes a string, seperator and the position `n`, splits the string and returns n'th substring
func (n *callPlanExpression) EvaluateStringSplit(currentRow []interface{}) (interface{}, error) {
inputString, err := evaluateStringArg(n.args[0], currentRow)
if err != nil {
return nil, err
}
seperator, err := evaluateStringArg(n.args[1], currentRow)
if err != nil {
return nil, err
}
if len(n.args) == 2 {
return strings.Split(inputString, seperator)[0], nil
}
pos, err := strconv.Atoi(n.args[2].String())
if err != nil {
return nil, sql3.NewErrInternalf("unexpected type converion %T", n.args[2])
}
res := strings.Split(inputString, seperator)
if pos <= 0 {
return res[0], nil
} else if len(res) > pos {
return res[pos], nil
}
return "", nil
}
func evaluateStringArg(n types.PlanExpression, currentRow []interface{}) (string, error) {
argOneEval, err := n.Evaluate(currentRow)
if err != nil {

View file

@ -56,6 +56,32 @@ var stringScalarFunctionsTests = TableTest{
),
Compare: CompareExactUnordered,
},
{
name: "StringSplitNoPos",
SQLs: sqls(
"select stringsplit('string,split', ',')",
),
ExpHdrs: hdrs(
hdr("", fldTypeString),
),
ExpRows: rows(
row(string("string")),
),
Compare: CompareExactUnordered,
},
{
name: "StringSplitPos",
SQLs: sqls(
"select stringsplit('string,split,now', stringsplit(',mid,', 'mid', 1), 2)",
),
ExpHdrs: hdrs(
hdr("", fldTypeString),
),
ExpRows: rows(
row(string("now")),
),
Compare: CompareExactUnordered,
},
{
name: "SubstringNegativeIndex",
SQLs: sqls(