Connected nodes

This commit is contained in:
Magnus Åhall 2025-07-09 19:30:54 +02:00
parent 2b8472bcd1
commit ca0659a368
9 changed files with 581 additions and 89 deletions

213
node.go
View file

@ -27,50 +27,86 @@ type Node struct {
TypeSchemaRaw []byte `db:"type_schema_raw" json:"-"`
TypeIcon string `db:"type_icon"`
ConnectionID int
ConnectionData any
Updated time.Time
Data any
DataRaw []byte `db:"data_raw" json:"-"`
NumChildren int `db:"num_children"`
Children []*Node
ConnectedNodes []Node
}
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,
to_json(res) AS node
FROM (
SELECT
n.id,
COALESCE(n.parent_id, -1) AS ParentID,
n.name,
n.updated,
n.data AS data,
t.id AS type_id,
t.name AS type_name,
t.schema AS type_schema_raw,
t.schema->>'icon' AS type_icon
FROM public.node n
INNER JOIN public.type t ON n.type_id = t.id
WHERE
n.id = $1
`, nodeID)
t.id AS TypeID,
t.name AS TypeName,
t.schema AS TypeSchema,
t.schema->>'icon' AS TypeIcon,
err = row.StructScan(&node)
COALESCE(
(
SELECT jsonb_agg(res)
FROM (
SELECT
nn.id,
COALESCE(nn.parent_id, -1) AS ParentID,
nn.name,
nn.updated,
nn.data AS data,
tt.id AS TypeID,
tt.name AS TypeName,
tt.schema AS TypeSchema,
tt.schema->>'icon' AS TypeIcon,
c.id AS ConnectionID,
c.data AS ConnectionData
FROM connection c
INNER JOIN public.node nn ON c.child_node_id = nn.id
INNER JOIN public.type tt ON nn.type_id = tt.id
WHERE
c.parent_node_id = n.id
) AS res
)
, '[]'::jsonb
) AS ConnectedNodes
FROM public.node n
INNER JOIN public.type t ON n.type_id = t.id
WHERE
n.id = $1
) res
`,
nodeID,
)
var body []byte
err = row.Scan(&body)
if err != nil {
err = werr.Wrap(err)
return
}
err = json.Unmarshal(node.TypeSchemaRaw, &node.TypeSchema)
err = json.Unmarshal(body, &node)
if err != nil {
err = werr.Wrap(err)
return
}
err = json.Unmarshal(node.DataRaw, &node.Data)
if err != nil {
err = werr.Wrap(err)
return
}
return
} // }}}
@ -243,10 +279,10 @@ func GetNodeConnections(nodeID int) (connections []Node, err error) { // {{{
t.schema AS type_schema_raw,
t.schema->>'icon' AS type_icon
FROM public.connection c
INNER JOIN public.node n ON c.to = n.id
INNER JOIN public.node n ON c.child_node_id = n.id
INNER JOIN public.type t ON n.type_id = t.id
WHERE
c.from = $1
c.parent_node_id = $1
`,
nodeID,
)
@ -275,66 +311,115 @@ func GetNodeConnections(nodeID int) (connections []Node, err error) { // {{{
return
} // }}}
func ConnectNode(parentID, childID int) (err error) { // {{{
_, err = db.Exec(`INSERT INTO public.connection(parent_node_id, child_node_id) VALUES($1, $2)`, parentID, childID)
return
} // }}}
func SearchNodes(typeID int, search string, maxResults int) (nodes []Node, err error) { // {{{
nodes = []Node{}
var rows *sqlx.Rows
rows, err = db.Queryx(`
row := db.QueryRowx(`
SELECT
n.id,
n.name,
n.updated,
n.data,
COALESCE(n.parent_id, 0) AS parent_id,
json_agg(res) AS node
FROM (
SELECT
n.id,
n.name,
n.updated,
n.data,
COALESCE(n.parent_id, 0) AS ParentID,
t.id AS type_id,
t.name AS type_name,
t.schema AS type_schema_raw,
t.schema->>'icon' AS type_icon
FROM public.node n
INNER JOIN public.type t ON n.type_id = t.id
WHERE
n.id > 0 AND
n.name ILIKE $2 AND
(CASE
WHEN $1 = -1 THEN true
ELSE
type_id = $1
END)
t.id AS TypeID,
t.name AS TypeName,
t.schema AS TypeSchema,
t.schema->>'icon' AS TypeIcon,
ORDER BY
t.schema->>'title' ASC,
UPPER(n.name) ASC
LIMIT $3
COALESCE(
(
SELECT jsonb_agg(res)
FROM (
SELECT
nn.id,
COALESCE(nn.parent_id, -1) AS ParentID,
nn.name,
nn.updated,
nn.data AS data,
tt.id AS TypeID,
tt.name AS TypeName,
tt.schema AS TypeSchema,
tt.schema->>'icon' AS TypeIcon,
c.id AS ConnectionID,
c.data AS ConnectionData
FROM connection c
INNER JOIN public.node nn ON c.child_node_id = nn.id
INNER JOIN public.type tt ON nn.type_id = tt.id
WHERE
c.parent_node_id = n.id
) AS res
)
, '[]'::jsonb
) AS ConnectedNodes
FROM public.node n
INNER JOIN public.type t ON n.type_id = t.id
WHERE
n.id > 0 AND
n.name ILIKE $2 AND
(CASE
WHEN $1 = -1 THEN true
ELSE
type_id = $1
END)
ORDER BY
t.schema->>'title' ASC,
UPPER(n.name) ASC
LIMIT $3
) AS res
`,
typeID,
search,
maxResults+1,
)
var body []byte
err = row.Scan(&body)
if err != nil {
err = werr.Wrap(err)
return
}
defer rows.Close()
for rows.Next() {
var node Node
err = rows.StructScan(&node)
if err != nil {
err = werr.Wrap(err)
return
}
err = json.Unmarshal(node.TypeSchemaRaw, &node.TypeSchema)
if err != nil {
err = werr.Wrap(err)
return
}
nodes = append(nodes, node)
err = json.Unmarshal(body, &nodes)
if err != nil {
err = werr.Wrap(err)
return
}
return
} // }}}
func UpdateConnection(connID int, data []byte) (err error) { // {{{
_, err = db.Exec(`UPDATE public.connection SET data=$2 WHERE id=$1`, connID, data)
if err != nil {
pqErr, ok := err.(*pq.Error)
if ok && pqErr.Code == "22P02" {
err = errors.New("Invalid JSON")
} else {
err = werr.Wrap(err)
}
return
}
return
} // }}}
func DeleteConnection(connID int) (err error) {// {{{
_, err = db.Exec(`DELETE FROM public.connection WHERE id=$1`, connID)
if err != nil {
err = werr.Wrap(err)
return
}
return
}// }}}
// vim: foldmethod=marker