91 lines
1.8 KiB
Go
91 lines
1.8 KiB
Go
|
package psql
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"errors"
|
||
|
"io"
|
||
|
|
||
|
"github.com/dosco/super-graph/jsn"
|
||
|
"github.com/dosco/super-graph/qcode"
|
||
|
)
|
||
|
|
||
|
func (co *Compiler) compileMutation(qc *qcode.QCode, w *bytes.Buffer, vars Variables) (uint32, error) {
|
||
|
if len(qc.Selects) == 0 {
|
||
|
return 0, errors.New("empty query")
|
||
|
}
|
||
|
|
||
|
c := &compilerContext{w, qc.Selects, co}
|
||
|
root := &qc.Selects[0]
|
||
|
|
||
|
c.w.WriteString(`WITH `)
|
||
|
c.w.WriteString(root.Table)
|
||
|
c.w.WriteString(` AS (`)
|
||
|
|
||
|
if _, err := c.renderInsert(qc, w, vars); err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
c.w.WriteString(`) `)
|
||
|
|
||
|
return c.compileQuery(qc, w)
|
||
|
}
|
||
|
|
||
|
func (c *compilerContext) renderInsert(qc *qcode.QCode, w *bytes.Buffer, vars Variables) (uint32, error) {
|
||
|
root := &qc.Selects[0]
|
||
|
|
||
|
insert, ok := vars["insert"]
|
||
|
if !ok {
|
||
|
return 0, errors.New("Variable 'insert' not defined")
|
||
|
}
|
||
|
|
||
|
jt, array, err := jsn.Tree(insert)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
c.w.WriteString(`WITH input AS (SELECT {{insert}}::json AS j) INSERT INTO `)
|
||
|
c.w.WriteString(root.Table)
|
||
|
io.WriteString(c.w, " (")
|
||
|
c.renderInsertColumns(qc, w, jt)
|
||
|
io.WriteString(c.w, ")")
|
||
|
|
||
|
c.w.WriteString(` SELECT `)
|
||
|
c.renderInsertColumns(qc, w, jt)
|
||
|
c.w.WriteString(` FROM input i, `)
|
||
|
|
||
|
if array {
|
||
|
c.w.WriteString(`json_populate_recordset`)
|
||
|
} else {
|
||
|
c.w.WriteString(`json_populate_record`)
|
||
|
}
|
||
|
|
||
|
c.w.WriteString(`(NULL::`)
|
||
|
c.w.WriteString(root.Table)
|
||
|
c.w.WriteString(`, i.j) t RETURNING * `)
|
||
|
|
||
|
return 0, nil
|
||
|
}
|
||
|
|
||
|
func (c *compilerContext) renderInsertColumns(qc *qcode.QCode, w *bytes.Buffer,
|
||
|
jt map[string]interface{}) (uint32, error) {
|
||
|
|
||
|
ti, err := c.schema.GetTable(qc.Selects[0].Table)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
i := 0
|
||
|
for _, cn := range ti.ColumnNames {
|
||
|
if _, ok := jt[cn]; !ok {
|
||
|
continue
|
||
|
}
|
||
|
if i != 0 {
|
||
|
io.WriteString(c.w, ", ")
|
||
|
}
|
||
|
c.w.WriteString(cn)
|
||
|
i++
|
||
|
}
|
||
|
|
||
|
return 0, nil
|
||
|
}
|