mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
FB-1815: Implement CHAR() (#2369)
This commit is contained in:
parent
4e8fe488de
commit
27963441ab
4 changed files with 70 additions and 7 deletions
|
|
@ -1486,6 +1486,8 @@ func (n *callPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
|
|||
return n.EvaluateUpper(currentRow)
|
||||
case "STRINGSPLIT":
|
||||
return n.EvaluateStringSplit(currentRow)
|
||||
case "CHAR":
|
||||
return n.EvaluateChar(currentRow)
|
||||
case "SUBSTRING":
|
||||
return n.EvaluateSubstring(currentRow)
|
||||
case "LOWER":
|
||||
|
|
|
|||
|
|
@ -243,6 +243,8 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser
|
|||
return p.analyzeFunctionSubtable(call, scope)
|
||||
case "REVERSE":
|
||||
return p.analyseFunctionReverse(call, scope)
|
||||
case "CHAR":
|
||||
return p.analyseFunctionChar(call, scope)
|
||||
case "UPPER":
|
||||
return p.analyzeFunctionUpper(call, scope)
|
||||
case "STRINGSPLIT":
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package planner
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/molecula/featurebase/v3/sql3"
|
||||
|
|
@ -24,6 +23,21 @@ func (p *ExecutionPlanner) analyseFunctionReverse(call *parser.Call, scope parse
|
|||
return call, nil
|
||||
}
|
||||
|
||||
func (p *ExecutionPlanner) analyseFunctionChar(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
|
||||
}
|
||||
|
||||
func (p *ExecutionPlanner) analyseFunctionSubstring(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))
|
||||
|
|
@ -145,6 +159,17 @@ func (n *callPlanExpression) EvaluateUpper(currentRow []interface{}) (interface{
|
|||
return strings.ToUpper(stringArgOne), nil
|
||||
}
|
||||
|
||||
func (n *callPlanExpression) EvaluateChar(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 the character that corresponds to the integer value
|
||||
return string(rune(intArg)), nil
|
||||
}
|
||||
|
||||
// Takes string, startIndex and length and returns the substring.
|
||||
func (n *callPlanExpression) EvaluateSubstring(currentRow []interface{}) (interface{}, error) {
|
||||
stringArgOne, err := evaluateStringArg(n.args[0], currentRow)
|
||||
|
|
@ -153,9 +178,9 @@ func (n *callPlanExpression) EvaluateSubstring(currentRow []interface{}) (interf
|
|||
}
|
||||
|
||||
// this takes a sliding window approach to evaluate substring.
|
||||
startIndex, err := strconv.Atoi(n.args[1].String())
|
||||
startIndex, err := evaluateIntArg(n.args[1], currentRow)
|
||||
if err != nil {
|
||||
return nil, sql3.NewErrInternalf("unexpected type converion %T", n.args[1])
|
||||
return nil, err
|
||||
}
|
||||
if startIndex >= len(stringArgOne) {
|
||||
return "", nil
|
||||
|
|
@ -163,9 +188,9 @@ func (n *callPlanExpression) EvaluateSubstring(currentRow []interface{}) (interf
|
|||
|
||||
endIndex := len(stringArgOne)
|
||||
if len(n.args) > 2 {
|
||||
ln, err := strconv.Atoi(n.args[2].String())
|
||||
ln, err := evaluateIntArg(n.args[2], currentRow)
|
||||
if err != nil {
|
||||
return nil, sql3.NewErrInternalf("unexpected type converion %T", n.args[1])
|
||||
return nil, err
|
||||
}
|
||||
endIndex = startIndex + ln
|
||||
}
|
||||
|
|
@ -224,9 +249,9 @@ func (n *callPlanExpression) EvaluateStringSplit(currentRow []interface{}) (inte
|
|||
if len(n.args) == 2 {
|
||||
return strings.Split(inputString, seperator)[0], nil
|
||||
}
|
||||
pos, err := strconv.Atoi(n.args[2].String())
|
||||
pos, err := evaluateIntArg(n.args[2], currentRow)
|
||||
if err != nil {
|
||||
return nil, sql3.NewErrInternalf("unexpected type converion %T", n.args[2])
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := strings.Split(inputString, seperator)
|
||||
|
|
@ -251,6 +276,20 @@ func evaluateStringArg(n types.PlanExpression, currentRow []interface{}) (string
|
|||
return stringArgOne, nil
|
||||
}
|
||||
|
||||
func evaluateIntArg(n types.PlanExpression, currentRow []interface{}) (int, error) {
|
||||
argOneEval, err := n.Evaluate(currentRow)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
intArgOne, ok := argOneEval.(int64)
|
||||
if !ok {
|
||||
return 0, sql3.NewErrInternalf("unexpected type converion %T", argOneEval)
|
||||
}
|
||||
|
||||
return int(intArgOne), nil
|
||||
}
|
||||
|
||||
// Analyze function for Trim/RTrim/LTrim
|
||||
func (p *ExecutionPlanner) analyseFunctionTrim(call *parser.Call, scope parser.Statement) (parser.Expr, error) {
|
||||
//one argument for Trim Functions
|
||||
|
|
|
|||
|
|
@ -134,6 +134,26 @@ var stringScalarFunctionsTests = TableTest{
|
|||
),
|
||||
Compare: CompareExactUnordered,
|
||||
},
|
||||
{
|
||||
name: "CharInt",
|
||||
SQLs: sqls(
|
||||
"select char(82)",
|
||||
),
|
||||
ExpHdrs: hdrs(
|
||||
hdr("", fldTypeString),
|
||||
),
|
||||
ExpRows: rows(
|
||||
row(string("R")),
|
||||
),
|
||||
Compare: CompareExactUnordered,
|
||||
},
|
||||
{
|
||||
name: "CharString",
|
||||
SQLs: sqls(
|
||||
"select char('R')",
|
||||
),
|
||||
ExpErr: "integer expression expected",
|
||||
},
|
||||
{
|
||||
name: "ConvertingStringtoUpper",
|
||||
SQLs: sqls(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue