mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
Fb-1816 : CharIndex str func (#2216)
* rebased and updated * Updates per review comments Rebased * Rebased * Rebased
This commit is contained in:
parent
188b61b3cd
commit
b12c90fdd1
4 changed files with 172 additions and 1 deletions
|
|
@ -1522,6 +1522,8 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
|
|||
return n.EvaluateReplicate(currentRow)
|
||||
case "FORMAT":
|
||||
return n.EvaluateFormat(currentRow)
|
||||
case "CHARINDEX":
|
||||
return n.EvaluateCharIndex(currentRow)
|
||||
default:
|
||||
return nil, sql3.NewErrInternalf("unhandled function name '%s'", n.name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,6 +275,8 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser
|
|||
return p.analyseFunctionPrefixSuffixReplicate(call, scope)
|
||||
case "FORMAT":
|
||||
return p.analyseFunctionFormat(call, scope)
|
||||
case "CHARINDEX":
|
||||
return p.analyseFunctionCharIndex(call, scope)
|
||||
default:
|
||||
return nil, sql3.NewErrCallUnknownFunction(call.Name.NamePos.Line, call.Name.NamePos.Column, call.Name.Name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@ func (p *ExecutionPlanner) analyseFunctionFormat(call *parser.Call, scope parser
|
|||
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()) && !typeIsVoid(call.Args[0].DataType()) {
|
||||
return nil, sql3.NewErrStringExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
|
||||
}
|
||||
|
|
@ -228,6 +227,31 @@ func (p *ExecutionPlanner) analyseFunctionFormat(call *parser.Call, scope parser
|
|||
return call, nil
|
||||
}
|
||||
|
||||
// charindex(substring, str, pos)
|
||||
func (p *ExecutionPlanner) analyseFunctionCharIndex(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, 3, len(call.Args))
|
||||
}
|
||||
// first paramater is the substring for which index needs to be identified
|
||||
if !typeIsString(call.Args[0].DataType()) && !typeIsVoid(call.Args[0].DataType()) {
|
||||
return nil, sql3.NewErrStringExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
|
||||
}
|
||||
|
||||
// second paramater is the string where we search the position of the substring ( first param)
|
||||
if !typeIsString(call.Args[1].DataType()) && !typeIsVoid(call.Args[1].DataType()) {
|
||||
return nil, sql3.NewErrStringExpressionExpected(call.Args[1].Pos().Line, call.Args[1].Pos().Column)
|
||||
}
|
||||
|
||||
// the third parameter is the position. optional, defaults to 0
|
||||
if len(call.Args) == 3 && !typeIsInteger(call.Args[2].DataType()) && !typeIsVoid(call.Args[2].DataType()) {
|
||||
return nil, sql3.NewErrIntExpressionExpected(call.Args[2].Pos().Line, call.Args[2].Pos().Column)
|
||||
}
|
||||
|
||||
call.ResultDataType = parser.NewDataTypeInt()
|
||||
|
||||
return call, nil
|
||||
}
|
||||
|
||||
// EvaluateReverse reverses the string
|
||||
func (n *callPlanExpression) EvaluateReverse(currentRow []interface{}) (interface{}, error) {
|
||||
argEval, err := n.args[0].Evaluate(currentRow)
|
||||
|
|
@ -697,3 +721,65 @@ func (n *callPlanExpression) EvaluateFormat(currentRow []interface{}) (interface
|
|||
}
|
||||
return fmt.Sprintf(formatString, args...), nil
|
||||
}
|
||||
|
||||
// EvaluateCharIndex function gets the position of the substring in the given string
|
||||
func (n *callPlanExpression) EvaluateCharIndex(currentRow []interface{}) (interface{}, error) {
|
||||
|
||||
argEval, err := n.args[0].Evaluate(currentRow)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if argEval == nil {
|
||||
return nil, nil
|
||||
}
|
||||
subString, ok := argEval.(string)
|
||||
if !ok {
|
||||
return nil, sql3.NewErrUnexpectedTypeConversion(0, 0, argEval)
|
||||
}
|
||||
|
||||
argEval, err = n.args[1].Evaluate(currentRow)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if argEval == nil {
|
||||
return nil, nil
|
||||
}
|
||||
inputString, ok := argEval.(string)
|
||||
if !ok {
|
||||
return nil, sql3.NewErrUnexpectedTypeConversion(0, 0, argEval)
|
||||
}
|
||||
|
||||
if len(n.args) == 2 {
|
||||
res := strings.Index(inputString, subString)
|
||||
if res > -1 {
|
||||
newpos := int64(res)
|
||||
return int64(newpos), nil
|
||||
}
|
||||
return int64(res), nil
|
||||
}
|
||||
|
||||
argEval, err = n.args[2].Evaluate(currentRow)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if argEval == nil {
|
||||
return nil, nil
|
||||
}
|
||||
pos, ok := argEval.(int64)
|
||||
if !ok {
|
||||
return nil, sql3.NewErrUnexpectedTypeConversion(0, 0, argEval)
|
||||
}
|
||||
|
||||
if pos < 0 {
|
||||
return nil, sql3.NewErrValueOutOfRange(0, 0, pos)
|
||||
}
|
||||
if pos >= int64(len(inputString)) {
|
||||
return nil, sql3.NewErrValueOutOfRange(0, 0, pos)
|
||||
}
|
||||
res := strings.Index(inputString[pos:], subString)
|
||||
if res > -1 {
|
||||
newpos := int64(res) + pos
|
||||
return int64(newpos), nil
|
||||
}
|
||||
return int64(res), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -901,5 +901,86 @@ var stringScalarFunctionsTests = TableTest{
|
|||
),
|
||||
Compare: CompareExactOrdered,
|
||||
},
|
||||
{
|
||||
name: "CharIndexIncorrectNumberofArguments",
|
||||
SQLs: sqls(
|
||||
"select charindex('is','this is great',3,4)",
|
||||
),
|
||||
ExpErr: "'charindex': count of formal parameters (3) does not match count of actual parameters (4)",
|
||||
},
|
||||
{
|
||||
name: "CharIndexIncorrectTypeofArgumentsforPosition",
|
||||
SQLs: sqls(
|
||||
"select charindex('is','this is great','you')",
|
||||
),
|
||||
ExpErr: "integer expression expected",
|
||||
},
|
||||
{
|
||||
name: "CharIndexIncorrectTypeofArgumentsforInputString",
|
||||
SQLs: sqls(
|
||||
"select charindex('is',23,3)",
|
||||
),
|
||||
ExpErr: "string expression expected",
|
||||
},
|
||||
{
|
||||
name: "CharIndexIncorrectTypeofArgumentsforSubString",
|
||||
SQLs: sqls(
|
||||
"select charindex(1,'this is great',3)",
|
||||
),
|
||||
ExpErr: "string expression expected",
|
||||
},
|
||||
{
|
||||
name: "CharIndexPositionOutofRangewithNegativePosition",
|
||||
SQLs: sqls(
|
||||
"select charindex('is','this is great',-1)",
|
||||
),
|
||||
ExpErr: "value '-1' out of range",
|
||||
},
|
||||
{
|
||||
name: "CharIndexPositionOutofRange",
|
||||
SQLs: sqls(
|
||||
"select charindex('is','this is great',15)",
|
||||
),
|
||||
ExpErr: "value '15' out of range",
|
||||
},
|
||||
{
|
||||
name: "CharIndexofSubstring",
|
||||
SQLs: sqls(
|
||||
"Select charindex('is','this is great')",
|
||||
),
|
||||
ExpHdrs: hdrs(
|
||||
hdr("", fldTypeInt),
|
||||
),
|
||||
ExpRows: rows(
|
||||
row(int64(2)),
|
||||
),
|
||||
Compare: CompareExactOrdered,
|
||||
},
|
||||
{
|
||||
name: "CharIndexofSubstringwithPosition",
|
||||
SQLs: sqls(
|
||||
"Select charindex('is','this is great',3)",
|
||||
),
|
||||
ExpHdrs: hdrs(
|
||||
hdr("", fldTypeInt),
|
||||
),
|
||||
ExpRows: rows(
|
||||
row(int64(5)),
|
||||
),
|
||||
Compare: CompareExactOrdered,
|
||||
},
|
||||
{
|
||||
name: "CharIndexSubstringNotfound",
|
||||
SQLs: sqls(
|
||||
"Select charindex('abc','this is great',3)",
|
||||
),
|
||||
ExpHdrs: hdrs(
|
||||
hdr("", fldTypeInt),
|
||||
),
|
||||
ExpRows: rows(
|
||||
row(int64(-1)),
|
||||
),
|
||||
Compare: CompareExactOrdered,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue