super-graph/serv/prepare.go

105 lines
1.7 KiB
Go
Raw Normal View History

2019-07-29 07:13:33 +02:00
package serv
import (
"bytes"
2019-09-26 06:35:31 +02:00
"context"
2019-09-05 06:09:56 +02:00
"encoding/json"
2019-07-29 07:13:33 +02:00
"fmt"
"io"
2019-09-05 06:09:56 +02:00
"github.com/dosco/super-graph/psql"
2019-07-29 07:13:33 +02:00
"github.com/dosco/super-graph/qcode"
2019-09-26 06:35:31 +02:00
"github.com/jackc/pgconn"
2019-07-29 07:13:33 +02:00
"github.com/valyala/fasttemplate"
)
type preparedItem struct {
2019-09-26 06:35:31 +02:00
stmt *pgconn.StatementDescription
2019-09-05 06:09:56 +02:00
args [][]byte
2019-07-29 07:13:33 +02:00
skipped uint32
qc *qcode.QCode
}
var (
_preparedList map[string]*preparedItem
)
func initPreparedList() {
_preparedList = make(map[string]*preparedItem)
for k, v := range _allowList.list {
2019-09-05 06:09:56 +02:00
err := prepareStmt(k, v.gql, v.vars)
2019-07-29 07:13:33 +02:00
if err != nil {
panic(err)
}
}
}
2019-09-05 06:09:56 +02:00
func prepareStmt(key, gql string, varBytes json.RawMessage) error {
2019-07-29 07:13:33 +02:00
if len(gql) == 0 || len(key) == 0 {
return nil
}
2019-09-05 06:09:56 +02:00
qc, err := qcompile.Compile([]byte(gql))
2019-07-29 07:13:33 +02:00
if err != nil {
return err
}
2019-09-05 06:09:56 +02:00
var vars map[string]json.RawMessage
if len(varBytes) != 0 {
vars = make(map[string]json.RawMessage)
if err := json.Unmarshal(varBytes, &vars); err != nil {
return err
}
}
2019-07-29 07:13:33 +02:00
buf := &bytes.Buffer{}
2019-09-05 06:09:56 +02:00
skipped, err := pcompile.Compile(qc, buf, psql.Variables(vars))
2019-07-29 07:13:33 +02:00
if err != nil {
return err
}
2019-09-05 06:09:56 +02:00
t := fasttemplate.New(buf.String(), `{{`, `}}`)
am := make([][]byte, 0, 5)
2019-07-29 07:13:33 +02:00
i := 0
finalSQL := t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
2019-09-05 06:09:56 +02:00
am = append(am, []byte(tag))
2019-07-29 07:13:33 +02:00
i++
return w.Write([]byte(fmt.Sprintf("$%d", i)))
})
if err != nil {
return err
}
2019-09-26 06:35:31 +02:00
ctx := context.Background()
tx, err := db.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
pstmt, err := tx.Prepare(ctx, "", finalSQL)
2019-07-29 07:13:33 +02:00
if err != nil {
return err
}
_preparedList[key] = &preparedItem{
stmt: pstmt,
args: am,
skipped: skipped,
qc: qc,
}
2019-09-26 06:35:31 +02:00
if err := tx.Commit(ctx); err != nil {
return err
}
2019-07-29 07:13:33 +02:00
return nil
}