Skip to content

Instantly share code, notes, and snippets.

@LIQRGV
Created November 18, 2022 11:16
Show Gist options
  • Save LIQRGV/228c15d9806cc1072acaee54c2d27c43 to your computer and use it in GitHub Desktop.
Save LIQRGV/228c15d9806cc1072acaee54c2d27c43 to your computer and use it in GitHub Desktop.
func compileInQuery(originalQuery string, argsWithInKeyword [][]interface{}, originalArg interface{}) (string, []interface{}, error) {
/**
capturing group result:
group 0: whole match
group 1: ([a-zA-Z_]+\.)?, table name
group 2: ([a-zA-Z_]+), column name
group 3: (NOT )?, NOT flag
*/
regex := regexp.MustCompile(`([a-zA-Z_]+\.)?([a-zA-Z_]+) ([Nn][Oo][Tt] )?[Ii][Nn] \(\?\?\?\)`)
match := regex.FindAllStringSubmatch(originalQuery, -1)
if len(match) != len(argsWithInKeyword) {
return "", nil, errors.New("capture group have less member than expected")
}
var fullQueryWithPlaceholder string
for i := range match {
group := match[i]
wholeGroup := group[0]
wholeGroupReplacement := "false"
if group[3] != "" { // NOT flag is exists
wholeGroupReplacement = "true"
}
currentColumn := argsWithInKeyword[i]
if len(currentColumn) != 0 {
placeholder := strings.Join(strings.Split(strings.Repeat("?", len(currentColumn)), ""), ",")
wholeGroupReplacement = strings.ReplaceAll(
wholeGroup,
"???",
placeholder,
)
}
fullQueryWithPlaceholder = strings.ReplaceAll(
originalQuery,
wholeGroup,
wholeGroupReplacement,
)
}
fullArg := flattenDeep(reflect.ValueOf(originalArg))
return fullQueryWithPlaceholder, fullArg, nil
}
func flattenDeep(input interface{}) []interface{} {
func _flattenDeep(args []interface{}, input interface{}) []interface{} {
var v reflect.Value
switch i := input.(type) {
case reflect.Value:
v = i
default:
v = reflect.ValueOf(input)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
for i := 0; i < v.Len(); i++ {
args = _flattenDeep(args, v.Index(i))
}
} else if v.Kind() == reflect.Struct {
var result []interface{}
result = append(args, v.Interface())
if v.NumField() != 3 && v.Type().Field(0).Name != "typ" { // v is not struct to pointer
innerResult := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
innerResult[i] = field.Interface()
}
result = _flattenDeep(args, innerResult)
}
args = result
} else {
args = append(args, v.Interface())
}
return args
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment