package exporter import ( "encoding/json" "errors" "strings" ) type BuildRequest struct { MainTable string Fields []string Filters map[string]interface{} } func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{}, error) { if req.MainTable != "order" { return "", nil, errors.New("unsupported main table") } cols := []string{} for _, f := range req.Fields { if !whitelist["order."+f] { return "", nil, errors.New("field not allowed") } if f == "key" || req.MainTable == "order" { cols = append(cols, "`order`."+escape(f)) } } if len(cols) == 0 { return "", nil, errors.New("no fields") } sb := strings.Builder{} sb.WriteString("SELECT ") sb.WriteString(strings.Join(cols, ",")) sb.WriteString(" FROM `order`") args := []interface{}{} where := []string{} if v, ok := req.Filters["creator_in"]; ok { ids := []interface{}{} switch t := v.(type) { case []interface{}: ids = t case []int: for _, x := range t { ids = append(ids, x) } case []string: for _, x := range t { ids = append(ids, x) } } if len(ids) == 0 { return "", nil, errors.New("creator_in required") } ph := strings.Repeat("?,", len(ids)) ph = strings.TrimSuffix(ph, ",") where = append(where, "`order`.creator IN ("+ph+")") args = append(args, ids...) } else { return "", nil, errors.New("creator_in required") } if v, ok := req.Filters["create_time_between"]; ok { var arr []interface{} b, _ := json.Marshal(v) json.Unmarshal(b, &arr) if len(arr) != 2 { return "", nil, errors.New("create_time_between requires 2 values") } where = append(where, "`order`.create_time BETWEEN ? AND ?") args = append(args, arr[0], arr[1]) } if len(where) > 0 { sb.WriteString(" WHERE ") sb.WriteString(strings.Join(where, " AND ")) } return sb.String(), args, nil } func escape(s string) string { if s == "key" { return "`key`" } return s }