54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package treepath
|
|
|
|
import (
|
|
"database/sql"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"git.gobha.me/xcaliber/chat-switchboard/database"
|
|
)
|
|
|
|
// UpdateCursor upserts the channel_cursors row for a user.
|
|
func UpdateCursor(channelID, userID, messageID string) error {
|
|
if database.IsSQLite() {
|
|
// SQLite: id TEXT PRIMARY KEY has no default generator; supply one.
|
|
// Use excluded.active_leaf_id so ON CONFLICT works cleanly.
|
|
_, err := database.DB.Exec(`
|
|
INSERT INTO channel_cursors (id, channel_id, user_id, active_leaf_id)
|
|
VALUES (?, ?, ?, ?)
|
|
ON CONFLICT (channel_id, user_id) DO UPDATE SET
|
|
active_leaf_id = excluded.active_leaf_id, updated_at = datetime('now')
|
|
`, uuid.New().String(), channelID, userID, messageID)
|
|
return err
|
|
}
|
|
// Postgres: id has DEFAULT gen_random_uuid(); $3 is referenced twice.
|
|
_, err := database.DB.Exec(`
|
|
INSERT INTO channel_cursors (channel_id, user_id, active_leaf_id)
|
|
VALUES ($1, $2, $3)
|
|
ON CONFLICT (channel_id, user_id) DO UPDATE SET
|
|
active_leaf_id = $3, updated_at = NOW()
|
|
`, channelID, userID, messageID)
|
|
return err
|
|
}
|
|
|
|
// NextSiblingIndex returns the next sibling_index for a new child of parentID.
|
|
// For root messages (parentID is nil), counts existing roots in the channel.
|
|
func NextSiblingIndex(channelID string, parentID *string) int {
|
|
var maxIdx sql.NullInt64
|
|
if parentID == nil {
|
|
database.DB.QueryRow(database.Q(`
|
|
SELECT MAX(sibling_index) FROM messages
|
|
WHERE channel_id = $1 AND parent_id IS NULL AND deleted_at IS NULL
|
|
`), channelID).Scan(&maxIdx)
|
|
} else {
|
|
database.DB.QueryRow(database.Q(`
|
|
SELECT MAX(sibling_index) FROM messages
|
|
WHERE parent_id = $1 AND deleted_at IS NULL
|
|
`), *parentID).Scan(&maxIdx)
|
|
}
|
|
if !maxIdx.Valid {
|
|
return 0
|
|
}
|
|
return int(maxIdx.Int64) + 1
|
|
}
|