2024-08-13 00:29:27 +00:00
|
|
|
package proto
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
2024-08-13 12:13:15 +00:00
|
|
|
"slices"
|
|
|
|
"strings"
|
2024-08-13 00:29:27 +00:00
|
|
|
|
2024-08-29 19:10:29 +00:00
|
|
|
"l12.xyz/x/dal/pkg/adapter"
|
|
|
|
"l12.xyz/x/dal/pkg/builder"
|
2024-08-13 00:29:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
//go:generate msgp
|
|
|
|
|
2024-08-15 08:19:50 +00:00
|
|
|
type BuilderMethod struct {
|
2024-08-13 00:29:27 +00:00
|
|
|
Method string `msg:"method"`
|
|
|
|
Args []interface{} `msg:"args"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Request struct {
|
2024-08-15 08:19:50 +00:00
|
|
|
Id uint32 `msg:"id"`
|
|
|
|
Db string `msg:"db"`
|
|
|
|
Commands []BuilderMethod `msg:"commands"`
|
2024-08-13 00:29:27 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 12:13:15 +00:00
|
|
|
var allowedMethods = strings.Split(builder.BUILDER_CLIENT_METHODS, "|")
|
|
|
|
|
2024-08-13 00:29:27 +00:00
|
|
|
func (q *Request) Parse(dialect adapter.Dialect) (adapter.Query, error) {
|
2024-08-14 12:02:20 +00:00
|
|
|
if q.Db == "" {
|
|
|
|
return adapter.Query{}, fmt.Errorf("Request format: db url is required")
|
|
|
|
}
|
|
|
|
if len(q.Commands) == 0 {
|
|
|
|
return adapter.Query{}, fmt.Errorf("Request format: commands are required")
|
|
|
|
}
|
2024-08-13 00:29:27 +00:00
|
|
|
b := builder.New(dialect)
|
2024-08-15 15:52:21 +00:00
|
|
|
exec := false
|
2024-08-13 00:29:27 +00:00
|
|
|
for _, cmd := range q.Commands {
|
2024-08-13 12:13:15 +00:00
|
|
|
if !slices.Contains(allowedMethods, cmd.Method) {
|
|
|
|
return adapter.Query{}, fmt.Errorf(
|
2024-08-14 12:02:20 +00:00
|
|
|
"method %s is not allowed, available methods are %v",
|
2024-08-13 12:13:15 +00:00
|
|
|
cmd.Method,
|
|
|
|
allowedMethods,
|
|
|
|
)
|
|
|
|
}
|
2024-08-13 00:29:27 +00:00
|
|
|
method := reflect.ValueOf(b).MethodByName(cmd.Method)
|
|
|
|
if !method.IsValid() {
|
|
|
|
return adapter.Query{}, fmt.Errorf("method %s not found", cmd.Method)
|
|
|
|
}
|
2024-08-15 15:52:21 +00:00
|
|
|
if cmd.Method == "Insert" || cmd.Method == "Set" || cmd.Method == "Delete" {
|
|
|
|
exec = true
|
|
|
|
}
|
2024-08-17 16:53:58 +00:00
|
|
|
// check if raw is an exec query
|
|
|
|
if cmd.Method == "Raw" {
|
|
|
|
qo, ok := cmd.Args[0].(map[string]interface{})
|
|
|
|
if ok {
|
|
|
|
sq := qo["s"].(string)
|
|
|
|
exec = !strings.HasPrefix(sq, "SELECT")
|
|
|
|
}
|
|
|
|
}
|
2024-08-13 00:29:27 +00:00
|
|
|
args := make([]reflect.Value, len(cmd.Args))
|
|
|
|
for i, arg := range cmd.Args {
|
|
|
|
args[i] = reflect.ValueOf(arg)
|
|
|
|
}
|
|
|
|
method.Call(args)
|
|
|
|
}
|
|
|
|
expr, data := b.Sql()
|
|
|
|
return adapter.Query{
|
2024-08-15 15:52:21 +00:00
|
|
|
Db: q.Db,
|
|
|
|
Expression: expr,
|
|
|
|
Data: data,
|
|
|
|
Transaction: b.Transaction,
|
|
|
|
Exec: exec,
|
2024-08-13 00:29:27 +00:00
|
|
|
}, nil
|
|
|
|
}
|