cleaned files
This commit is contained in:
@@ -1,114 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Repo struct{ DB *sql.DB }
|
|
||||||
|
|
||||||
func NewRepo(db *sql.DB) *Repo { return &Repo{DB: db} }
|
|
||||||
|
|
||||||
// --- Conversations ---
|
|
||||||
const qCreateConversation = `
|
|
||||||
INSERT INTO conversations (owner_id, title) VALUES (?, ?);
|
|
||||||
`
|
|
||||||
func (r *Repo) CreateConversation(ctx context.Context, ownerID int64, title string) (int64, error) {
|
|
||||||
res, err := r.DB.ExecContext(ctx, qCreateConversation, ownerID, title)
|
|
||||||
if err != nil { return 0, err }
|
|
||||||
return res.LastInsertId()
|
|
||||||
}
|
|
||||||
|
|
||||||
const qListConversations = `
|
|
||||||
SELECT id, owner_id, title, created_at
|
|
||||||
FROM conversations
|
|
||||||
WHERE owner_id = ?
|
|
||||||
ORDER BY created_at DESC, id DESC;
|
|
||||||
`
|
|
||||||
func (r *Repo) ListConversations(ctx context.Context, ownerID int64) (*sql.Rows, error) {
|
|
||||||
return r.DB.QueryContext(ctx, qListConversations, ownerID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Nodes (commits) ---
|
|
||||||
const qCreateNode = `
|
|
||||||
INSERT INTO nodes (conversation_id, author_kind, content) VALUES (?, ?, ?);
|
|
||||||
`
|
|
||||||
func (r *Repo) CreateNode(ctx context.Context, convID int64, authorKind, content string) (int64, error) {
|
|
||||||
res, err := r.DB.ExecContext(ctx, qCreateNode, convID, authorKind, content)
|
|
||||||
if err != nil { return 0, err }
|
|
||||||
return res.LastInsertId()
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Branches ---
|
|
||||||
const qCreateBranch = `
|
|
||||||
INSERT INTO branches (conversation_id, name, head_node_id) VALUES (?, ?, ?)
|
|
||||||
ON DUPLICATE KEY UPDATE head_node_id = VALUES(head_node_id);
|
|
||||||
`
|
|
||||||
func (r *Repo) CreateOrUpdateBranch(ctx context.Context, convID int64, name string, headNodeID int64) (int64, error) {
|
|
||||||
res, err := r.DB.ExecContext(ctx, qCreateBranch, convID, name, headNodeID)
|
|
||||||
if err != nil { return 0, err }
|
|
||||||
return res.LastInsertId()
|
|
||||||
}
|
|
||||||
|
|
||||||
const qGetBranch = `
|
|
||||||
SELECT id, conversation_id, name, head_node_id, created_at
|
|
||||||
FROM branches
|
|
||||||
WHERE conversation_id = ? AND name = ?
|
|
||||||
LIMIT 1;
|
|
||||||
`
|
|
||||||
func (r *Repo) GetBranch(ctx context.Context, convID int64, name string) *sql.Row {
|
|
||||||
return r.DB.QueryRowContext(ctx, qGetBranch, convID, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
const qMoveBranchHead = `
|
|
||||||
UPDATE branches SET head_node_id = ? WHERE id = ?;
|
|
||||||
`
|
|
||||||
func (r *Repo) MoveBranchHead(ctx context.Context, branchID, newHead int64) error {
|
|
||||||
_, err := r.DB.ExecContext(ctx, qMoveBranchHead, newHead, branchID)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Edges (DAG) ---
|
|
||||||
const qCycleGuard = `
|
|
||||||
WITH RECURSIVE downchain AS (
|
|
||||||
SELECT e.child_id
|
|
||||||
FROM edges e
|
|
||||||
WHERE e.parent_id = ?
|
|
||||||
UNION ALL
|
|
||||||
SELECT e.child_id
|
|
||||||
FROM edges e
|
|
||||||
JOIN downchain d ON d.child_id = e.parent_id
|
|
||||||
)
|
|
||||||
SELECT 1 FROM downchain WHERE child_id = ? LIMIT 1;
|
|
||||||
`
|
|
||||||
|
|
||||||
const qInsertEdge = `INSERT IGNORE INTO edges (parent_id, child_id) VALUES (?, ?);`
|
|
||||||
|
|
||||||
func (r *Repo) LinkEdgeCycleSafe(ctx context.Context, tx *sql.Tx, parentID, childID int64) error {
|
|
||||||
// cycle check: is parent reachable from child already?
|
|
||||||
var one int
|
|
||||||
err := tx.QueryRowContext(ctx, qCycleGuard, childID, parentID).Scan(&one)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
// found a row -> would create a cycle
|
|
||||||
return fmt.Errorf("cycle detected: %d -> %d", parentID, childID)
|
|
||||||
}
|
|
||||||
_, err = tx.ExecContext(ctx, qInsertEdge, parentID, childID)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Ancestor step (latest parent) ---
|
|
||||||
const qLatestParent = `
|
|
||||||
SELECT p.id, p.conversation_id, p.author_kind, p.content, p.created_at
|
|
||||||
FROM edges e
|
|
||||||
JOIN nodes p ON p.id = e.parent_id
|
|
||||||
WHERE e.child_id = ?
|
|
||||||
ORDER BY p.created_at DESC, p.id DESC
|
|
||||||
LIMIT 1;
|
|
||||||
`
|
|
||||||
func (r *Repo) LatestParent(ctx context.Context, childID int64) *sql.Row {
|
|
||||||
return r.DB.QueryRowContext(ctx, qLatestParent, childID)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user