mirror of
https://github.com/pikami/cosmium.git
synced 2025-12-18 16:30:44 +00:00
Implement LEFT,LENGTH,LTRIM,REPLACE,REPLICATE,REVERSE,RIGHT,RTRIM,SUBSTRING,TRIM functions
This commit is contained in:
@@ -194,6 +194,26 @@ func getFieldValue(field parsers.SelectItem, queryParameters map[string]interfac
|
||||
return strings_Upper(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallLower:
|
||||
return strings_Lower(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallLeft:
|
||||
return strings_Left(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallLength:
|
||||
return strings_Length(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallLTrim:
|
||||
return strings_LTrim(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallReplace:
|
||||
return strings_Replace(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallReplicate:
|
||||
return strings_Replicate(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallReverse:
|
||||
return strings_Reverse(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallRight:
|
||||
return strings_Right(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallRTrim:
|
||||
return strings_RTrim(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallSubstring:
|
||||
return strings_Substring(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallTrim:
|
||||
return strings_Trim(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallIsDefined:
|
||||
return typeChecking_IsDefined(typedValue.Arguments, queryParameters, row)
|
||||
case parsers.FunctionCallIn:
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
func Test_Execute_StringFunctions(t *testing.T) {
|
||||
mockData := []memoryexecutor.RowType{
|
||||
map[string]interface{}{"id": "123", "pk": "aaa", "str": "hello", "rng_type": true},
|
||||
map[string]interface{}{"id": "456", "pk": "bbb", "str": "world", "rng_type": 159},
|
||||
map[string]interface{}{"id": "789", "pk": "AAA", "str": "cool world"},
|
||||
map[string]interface{}{"id": "123", "pk": "aaa", "str": "hello", "rng_type": true, "str2": " hello "},
|
||||
map[string]interface{}{"id": "456", "pk": "bbb", "str": "world", "rng_type": 159, "str2": " world "},
|
||||
map[string]interface{}{"id": "789", "pk": "AAA", "str": "cool world", "str2": " cool world "},
|
||||
}
|
||||
|
||||
t.Run("Should execute function STRINGEQUALS(ex1, ex2, ignoreCase)", func(t *testing.T) {
|
||||
@@ -377,4 +377,393 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function LEFT()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "left",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallLeft,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeInteger,
|
||||
Value: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "left": "hel"},
|
||||
map[string]interface{}{"str": "world", "left": "wor"},
|
||||
map[string]interface{}{"str": "cool world", "left": "coo"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function LENGTH()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "length",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallLength,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "length": 5},
|
||||
map[string]interface{}{"str": "world", "length": 5},
|
||||
map[string]interface{}{"str": "cool world", "length": 10},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function LTRIM()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "ltrimmed",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallLTrim,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str2"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "ltrimmed": "hello "},
|
||||
map[string]interface{}{"str": "world", "ltrimmed": "world "},
|
||||
map[string]interface{}{"str": "cool world", "ltrimmed": "cool world "},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function REPLACE()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "replaced",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallReplace,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeString,
|
||||
Value: "world",
|
||||
},
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeString,
|
||||
Value: "universe",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "replaced": "hello"},
|
||||
map[string]interface{}{"str": "world", "replaced": "universe"},
|
||||
map[string]interface{}{"str": "cool world", "replaced": "cool universe"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function REPLICATE()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "replicated",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallReplicate,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeInteger,
|
||||
Value: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "replicated": "hellohellohello"},
|
||||
map[string]interface{}{"str": "world", "replicated": "worldworldworld"},
|
||||
map[string]interface{}{"str": "cool world", "replicated": "cool worldcool worldcool world"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function REVERSE()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "reversed",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallReverse,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "reversed": "olleh"},
|
||||
map[string]interface{}{"str": "world", "reversed": "dlrow"},
|
||||
map[string]interface{}{"str": "cool world", "reversed": "dlrow looc"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function RIGHT()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "right",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallRight,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeInteger,
|
||||
Value: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "right": "llo"},
|
||||
map[string]interface{}{"str": "world", "right": "rld"},
|
||||
map[string]interface{}{"str": "cool world", "right": "rld"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function RTRIM()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "rtrimmed",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallRTrim,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str2"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "rtrimmed": " hello"},
|
||||
map[string]interface{}{"str": "world", "rtrimmed": " world"},
|
||||
map[string]interface{}{"str": "cool world", "rtrimmed": " cool world"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function SUBSTRING()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "substring",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallSubstring,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeInteger,
|
||||
Value: 2,
|
||||
},
|
||||
},
|
||||
parsers.SelectItem{
|
||||
Type: parsers.SelectItemTypeConstant,
|
||||
Value: parsers.Constant{
|
||||
Type: parsers.ConstantTypeInteger,
|
||||
Value: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "substring": "llo"},
|
||||
map[string]interface{}{"str": "world", "substring": "rld"},
|
||||
map[string]interface{}{"str": "cool world", "substring": "ol w"},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute function TRIM()", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{
|
||||
Path: []string{"c", "str"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
{
|
||||
Alias: "trimmed",
|
||||
Type: parsers.SelectItemTypeFunctionCall,
|
||||
Value: parsers.FunctionCall{
|
||||
Type: parsers.FunctionCallTrim,
|
||||
Arguments: []interface{}{
|
||||
parsers.SelectItem{
|
||||
Path: []string{"c", "str2"},
|
||||
Type: parsers.SelectItemTypeField,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"str": "hello", "trimmed": "hello"},
|
||||
map[string]interface{}{"str": "world", "trimmed": "world"},
|
||||
map[string]interface{}{"str": "cool world", "trimmed": "cool world"},
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -111,6 +111,139 @@ func strings_Lower(arguments []interface{}, queryParameters map[string]interface
|
||||
return strings.ToLower(convertToString(value))
|
||||
}
|
||||
|
||||
func strings_Left(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
var ok bool
|
||||
var length int
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
lengthEx := getFieldValue(arguments[1].(parsers.SelectItem), queryParameters, row)
|
||||
|
||||
if length, ok = lengthEx.(int); !ok {
|
||||
fmt.Println("strings_Left - got parameters of wrong type")
|
||||
return ""
|
||||
}
|
||||
|
||||
if length <= 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(str) <= length {
|
||||
return str
|
||||
}
|
||||
|
||||
return str[:length]
|
||||
}
|
||||
|
||||
func strings_Length(arguments []interface{}, queryParameters map[string]interface{}, row RowType) int {
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
return len(str)
|
||||
}
|
||||
|
||||
func strings_LTrim(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
return strings.TrimLeft(str, " ")
|
||||
}
|
||||
|
||||
func strings_Replace(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
oldStr := parseString(arguments[1], queryParameters, row)
|
||||
newStr := parseString(arguments[2], queryParameters, row)
|
||||
return strings.Replace(str, oldStr, newStr, -1)
|
||||
}
|
||||
|
||||
func strings_Replicate(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
var ok bool
|
||||
var times int
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
timesEx := getFieldValue(arguments[1].(parsers.SelectItem), queryParameters, row)
|
||||
|
||||
if times, ok = timesEx.(int); !ok {
|
||||
fmt.Println("strings_Replicate - got parameters of wrong type")
|
||||
return ""
|
||||
}
|
||||
|
||||
if times <= 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(str) <= times {
|
||||
return str
|
||||
}
|
||||
|
||||
return strings.Repeat(str, times)
|
||||
}
|
||||
|
||||
func strings_Reverse(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
runes := []rune(str)
|
||||
|
||||
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
||||
runes[i], runes[j] = runes[j], runes[i]
|
||||
}
|
||||
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
func strings_Right(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
var ok bool
|
||||
var length int
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
lengthEx := getFieldValue(arguments[1].(parsers.SelectItem), queryParameters, row)
|
||||
|
||||
if length, ok = lengthEx.(int); !ok {
|
||||
fmt.Println("strings_Right - got parameters of wrong type")
|
||||
return ""
|
||||
}
|
||||
|
||||
if length <= 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(str) <= length {
|
||||
return str
|
||||
}
|
||||
|
||||
return str[len(str)-length:]
|
||||
}
|
||||
|
||||
func strings_RTrim(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
return strings.TrimRight(str, " ")
|
||||
}
|
||||
|
||||
func strings_Substring(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
var ok bool
|
||||
var startPos int
|
||||
var length int
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
startPosEx := getFieldValue(arguments[1].(parsers.SelectItem), queryParameters, row)
|
||||
lengthEx := getFieldValue(arguments[2].(parsers.SelectItem), queryParameters, row)
|
||||
|
||||
if startPos, ok = startPosEx.(int); !ok {
|
||||
fmt.Println("strings_Substring - got start parameters of wrong type")
|
||||
return ""
|
||||
}
|
||||
if length, ok = lengthEx.(int); !ok {
|
||||
fmt.Println("strings_Substring - got length parameters of wrong type")
|
||||
return ""
|
||||
}
|
||||
|
||||
if startPos >= len(str) {
|
||||
return ""
|
||||
}
|
||||
|
||||
endPos := startPos + length
|
||||
if endPos > len(str) {
|
||||
endPos = len(str)
|
||||
}
|
||||
|
||||
return str[startPos:endPos]
|
||||
}
|
||||
|
||||
func strings_Trim(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
|
||||
str := parseString(arguments[0], queryParameters, row)
|
||||
return strings.TrimSpace(str)
|
||||
}
|
||||
|
||||
func getBoolFlag(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
|
||||
ignoreCase := false
|
||||
if len(arguments) > 2 && arguments[2] != nil {
|
||||
|
||||
Reference in New Issue
Block a user