MarketingSystemDataTool/server/internal/exporter/sqlbuilder.go

84 lines
2.3 KiB
Go

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
}