Wip
This commit is contained in:
parent
a6bb845c9d
commit
cfd5bfd719
9 changed files with 213 additions and 111 deletions
79
node.go
79
node.go
|
|
@ -4,9 +4,11 @@ import (
|
|||
// External
|
||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/lib/pq"
|
||||
|
||||
// Standard
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -30,10 +32,11 @@ type Node struct {
|
|||
Children []*Node
|
||||
}
|
||||
|
||||
func GetNode(nodeID int) (node Node, err error) {
|
||||
func GetNode(nodeID int) (node Node, err error) { // {{{
|
||||
row := db.QueryRowx(`
|
||||
SELECT
|
||||
n.id,
|
||||
COALESCE(n.parent_id, -1) AS parent_id,
|
||||
n.name,
|
||||
n.updated,
|
||||
n.data AS data_raw,
|
||||
|
|
@ -66,9 +69,9 @@ func GetNode(nodeID int) (node Node, err error) {
|
|||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
} // }}}
|
||||
|
||||
func GetNodeTree(startNodeID, maxDepth int) (topNode *Node, err error) {// {{{
|
||||
func GetNodeTree(startNodeID, maxDepth int) (topNode *Node, err error) { // {{{
|
||||
nodes := make(map[int]*Node)
|
||||
var rows *sqlx.Rows
|
||||
rows, err = GetNodeRows(startNodeID, maxDepth)
|
||||
|
|
@ -96,47 +99,42 @@ func GetNodeTree(startNodeID, maxDepth int) (topNode *Node, err error) {// {{{
|
|||
}
|
||||
|
||||
return
|
||||
}// }}}
|
||||
func GetNodeRows(startNodeID, maxDepth int) (rows *sqlx.Rows, err error) {// {{{
|
||||
} // }}}
|
||||
func GetNodeRows(startNodeID, maxDepth int) (rows *sqlx.Rows, err error) { // {{{
|
||||
rows, err = db.Queryx(`
|
||||
WITH RECURSIVE nodes AS (
|
||||
SELECT
|
||||
COALESCE(
|
||||
(SELECT parent FROM connection WHERE child = $1),
|
||||
0
|
||||
) AS parent_id,
|
||||
$1::int AS id,
|
||||
0 AS depth
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
c.parent,
|
||||
c.child,
|
||||
n.id,
|
||||
ns.depth+1 AS depth
|
||||
FROM connection c
|
||||
INNER JOIN nodes ns ON ns.depth < $2 AND c.parent = ns.id
|
||||
FROM node n
|
||||
INNER JOIN nodes ns ON ns.depth < $2 AND n.parent_id = ns.id
|
||||
)
|
||||
|
||||
SEARCH DEPTH FIRST BY id SET ordercol
|
||||
|
||||
SELECT
|
||||
ns.parent_id,
|
||||
COALESCE(n.parent_id, -1) AS parent_id,
|
||||
n.id,
|
||||
n.name,
|
||||
CONCAT(REPEAT(' ', ns.depth), n.name) AS name,
|
||||
n.type_id,
|
||||
t.name AS type_name,
|
||||
COALESCE(t.schema->>'icon', '') AS type_icon,
|
||||
n.updated,
|
||||
n.data AS data_raw,
|
||||
COUNT(c.child) AS num_children
|
||||
COUNT(node_children.id) AS num_children
|
||||
FROM nodes ns
|
||||
INNER JOIN public.node n ON ns.id = n.id
|
||||
INNER JOIN public.type t ON n.type_id = t.id
|
||||
LEFT JOIN public.connection c ON c.parent = n.id
|
||||
LEFT JOIN node node_children ON node_children.parent_id = n.id
|
||||
|
||||
GROUP BY
|
||||
ns.depth,
|
||||
ns.parent_id,
|
||||
n.parent_id,
|
||||
n.id,
|
||||
t.name,
|
||||
t.schema,
|
||||
|
|
@ -152,8 +150,8 @@ func GetNodeRows(startNodeID, maxDepth int) (rows *sqlx.Rows, err error) {// {{{
|
|||
}
|
||||
|
||||
return
|
||||
}// }}}
|
||||
func ComposeTree(nodes map[int]*Node, node *Node) {// {{{
|
||||
} // }}}
|
||||
func ComposeTree(nodes map[int]*Node, node *Node) { // {{{
|
||||
if node.Children == nil {
|
||||
node.Children = []*Node{}
|
||||
}
|
||||
|
|
@ -168,18 +166,17 @@ func ComposeTree(nodes map[int]*Node, node *Node) {// {{{
|
|||
}
|
||||
|
||||
nodes[node.ID] = node
|
||||
}// }}}
|
||||
} // }}}
|
||||
|
||||
func UpdateNode(nodeID int, data []byte) (err error) {// {{{
|
||||
func UpdateNode(nodeID int, data []byte) (err error) { // {{{
|
||||
_, err = db.Exec(`UPDATE public.node SET data=$2 WHERE id=$1`, nodeID, data)
|
||||
return
|
||||
}// }}}
|
||||
func RenameNode(nodeID int, name string) (err error) {// {{{
|
||||
} // }}}
|
||||
func RenameNode(nodeID int, name string) (err error) { // {{{
|
||||
_, err = db.Exec(`UPDATE node SET name=$2 WHERE id=$1`, nodeID, name)
|
||||
return
|
||||
}// }}}
|
||||
|
||||
func CreateNode(parentNodeID, typeID int, name string) (err error) {// {{{
|
||||
} // }}}
|
||||
func CreateNode(parentNodeID, typeID int, name string) (nodeID int, err error) { // {{{
|
||||
j, _ := json.Marshal(
|
||||
struct {
|
||||
New bool `json:"x-new"`
|
||||
|
|
@ -188,22 +185,28 @@ func CreateNode(parentNodeID, typeID int, name string) (err error) {// {{{
|
|||
})
|
||||
|
||||
row := db.QueryRow(`
|
||||
INSERT INTO node(type_id, name, data)
|
||||
VALUES($1, $2, $3::jsonb)
|
||||
INSERT INTO node(parent_id, type_id, name, data)
|
||||
VALUES($1, $2, $3, $4::jsonb)
|
||||
RETURNING id
|
||||
`,
|
||||
typeID, name, j)
|
||||
|
||||
var id int
|
||||
err = row.Scan(&id)
|
||||
parentNodeID, typeID, name, j)
|
||||
err = row.Scan(&nodeID)
|
||||
if err != nil {
|
||||
err = werr.Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = db.Exec(`INSERT INTO connection("parent", "child") VALUES($1, $2)`, parentNodeID, id)
|
||||
|
||||
return
|
||||
}// }}}
|
||||
} // }}}
|
||||
func DeleteNode(nodeID int) (err error) { // {{{
|
||||
_, err = db.Exec(`DELETE FROM node WHERE id=$1`, nodeID)
|
||||
if err != nil {
|
||||
pqErr, ok := err.(*pq.Error)
|
||||
if ok && pqErr.Code == "23503" {
|
||||
err = errors.New("Can't delete a node with children.")
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
} // }}}
|
||||
|
||||
// vim: foldmethod=marker
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue