package xsql import ( "bytes" "fmt" "github.com/emqx/kuiper/common" "regexp" "strings" "unicode" "unicode/utf8" ) func strCall(name string, args []interface{}) (interface{}, bool) { switch name { case "concat": var b bytes.Buffer for _, arg := range args { b.WriteString(common.ToStringAlways(arg)) } return b.String(), true case "endswith": arg0, arg1 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]) return strings.HasSuffix(arg0, arg1), true case "indexof": arg0, arg1 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]) return strings.Index(arg0, arg1), true case "length": arg0 := common.ToStringAlways(args[0]) return utf8.RuneCountInString(arg0), true case "lower": arg0 := common.ToStringAlways(args[0]) return strings.ToLower(arg0), true case "lpad": arg0 := common.ToStringAlways(args[0]) arg1, err := common.ToInt(args[1], common.STRICT) if err != nil { return err, false } return strings.Repeat(" ", arg1) + arg0, true case "ltrim": arg0 := common.ToStringAlways(args[0]) return strings.TrimLeftFunc(arg0, unicode.IsSpace), true case "numbytes": arg0 := common.ToStringAlways(args[0]) return len(arg0), true case "format_time": arg0, err := common.InterfaceToTime(args[0], "") if err != nil { return err, false } arg1 := common.ToStringAlways(args[1]) if s, err := common.FormatTime(arg0, arg1); err == nil { return s, true } else { return err, false } case "regexp_matches": arg0, arg1 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]) if matched, err := regexp.MatchString(arg1, arg0); err != nil { return err, false } else { return matched, true } case "regexp_replace": arg0, arg1, arg2 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]), common.ToStringAlways(args[2]) if re, err := regexp.Compile(arg1); err != nil { return err, false } else { return re.ReplaceAllString(arg0, arg2), true } case "regexp_substr": arg0, arg1 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]) if re, err := regexp.Compile(arg1); err != nil { return err, false } else { return re.FindString(arg0), true } case "rpad": arg0 := common.ToStringAlways(args[0]) arg1, err := common.ToInt(args[1], common.STRICT) if err != nil { return err, false } return arg0 + strings.Repeat(" ", arg1), true case "rtrim": arg0 := common.ToStringAlways(args[0]) return strings.TrimRightFunc(arg0, unicode.IsSpace), true case "substring": arg0 := common.ToStringAlways(args[0]) arg1, err := common.ToInt(args[1], common.STRICT) if err != nil { return err, false } if len(args) > 2 { arg2, err := common.ToInt(args[2], common.STRICT) if err != nil { return err, false } return arg0[arg1:arg2], true } else { return arg0[arg1:], true } case "startswith": arg0, arg1 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]) return strings.HasPrefix(arg0, arg1), true case "split_value": arg0, arg1 := common.ToStringAlways(args[0]), common.ToStringAlways(args[1]) ss := strings.Split(arg0, arg1) v, _ := common.ToInt(args[2], common.STRICT) if v > (len(ss) - 1) { return fmt.Errorf("%d out of index array (size = %d)", v, len(ss)), false } else { return ss[v], true } case "trim": arg0 := common.ToStringAlways(args[0]) return strings.TrimSpace(arg0), true case "upper": arg0 := common.ToStringAlways(args[0]) return strings.ToUpper(arg0), true default: return fmt.Errorf("unknown string function name %s", name), false } }