Initial rendering of the node tree
This commit is contained in:
commit
c5bec0afa6
7477 changed files with 8513 additions and 0 deletions
124
node.go
Normal file
124
node.go
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// External
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
// Standard
|
||||
"time"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
ID int
|
||||
Name string
|
||||
|
||||
ParentID int `db:"parent_id"`
|
||||
|
||||
TypeID int `db:"type_id"`
|
||||
TypeName string `db:"type_name"`
|
||||
TypeIcon string `db:"type_icon"`
|
||||
|
||||
Updated time.Time
|
||||
Data any
|
||||
RawData []byte `db:"raw_data"`
|
||||
|
||||
NumChildren int `db:"num_children"`
|
||||
Children []*Node
|
||||
}
|
||||
|
||||
func GetNode(startNodeID, maxDepth int) (topNode *Node, err error) {
|
||||
nodes := make(map[int]*Node)
|
||||
var rows *sqlx.Rows
|
||||
rows, err = GetNodeRows(startNodeID, maxDepth)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
first := true
|
||||
for rows.Next() {
|
||||
var node Node
|
||||
err = rows.StructScan(&node)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if first {
|
||||
topNode = &node
|
||||
first = false
|
||||
}
|
||||
|
||||
ComposeTree(nodes, &node)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
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,
|
||||
ns.depth+1 AS depth
|
||||
FROM connection c
|
||||
INNER JOIN nodes ns ON ns.depth < $2 AND c.parent = ns.id
|
||||
)
|
||||
|
||||
SEARCH DEPTH FIRST BY id SET ordercol
|
||||
|
||||
SELECT
|
||||
ns.parent_id,
|
||||
n.id,
|
||||
n.name,
|
||||
n.type_id,
|
||||
t.name AS type_name,
|
||||
COALESCE(t.schema->>'icon', '') AS type_icon,
|
||||
n.updated,
|
||||
n.data AS raw_data,
|
||||
COUNT(c.child) 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
|
||||
GROUP BY
|
||||
ns.depth,
|
||||
ns.parent_id,
|
||||
n.id,
|
||||
t.name,
|
||||
t.schema,
|
||||
ns.ordercol
|
||||
ORDER BY ordercol
|
||||
`,
|
||||
startNodeID,
|
||||
maxDepth,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func ComposeTree(nodes map[int]*Node, node *Node) {
|
||||
if node.Children == nil {
|
||||
node.Children = []*Node{}
|
||||
}
|
||||
|
||||
parentNode, found := nodes[node.ParentID]
|
||||
if found {
|
||||
if parentNode.Children == nil {
|
||||
parentNode.Children = []*Node{node}
|
||||
} else {
|
||||
parentNode.Children = append(parentNode.Children, node)
|
||||
}
|
||||
}
|
||||
|
||||
nodes[node.ID] = node
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue