db

package
v0.0.0-...-80436ad Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrSelfRelation      = errors.New("self-referential relation")
	ErrDuplicateRelation = errors.New("duplicate relation")
	ErrCycleDetected     = errors.New("cycle detected")
)

Sentinel errors for relation operations.

View Source
var ErrConflict = errors.New("conflict")

ErrConflict is returned when an operation violates a uniqueness or state constraint.

View Source
var ErrLabelColorConflict = errors.New("label color conflict")

ErrLabelColorConflict is returned when --color specifies a different color than an existing label already has.

View Source
var ErrNotAttached = errors.New("label not attached")

ErrNotAttached is returned when a label is not attached to the specified issue.

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned when a requested resource does not exist.

Functions

func AddLabelToIssue

func AddLabelToIssue(db *sql.DB, issueID int, labelName, color string, author string) error

AddLabelToIssue attaches a label to an issue within a transaction. The label is created if it does not already exist (with the given color). Activity is recorded and the issue's updated_at timestamp is touched.

func AddLabelsToIssue

func AddLabelsToIssue(db *sql.DB, issueID int, labelNames []string, color string, author string) error

AddLabelsToIssue attaches multiple labels to an issue atomically within a single transaction. Labels are created if they do not already exist (with the given color). Activity is recorded for each newly attached label and the issue's updated_at timestamp is touched once.

func AttachFiles

func AttachFiles(db *sql.DB, issueID int, filePaths []string, changedBy string) error

AttachFiles inserts rows into issue_files for each file path. Duplicate attachments are silently ignored (INSERT OR IGNORE). Activity is recorded for each batch of newly attached files.

func CascadeDeleteIssue

func CascadeDeleteIssue(db *sql.DB, id int) error

CascadeDeleteIssue deletes an issue and all its descendants recursively in a single transaction. The recursive CTE finds all descendant issues; ON DELETE CASCADE constraints on comments, issue_labels, issue_relations, and activity_log handle cleanup of related rows automatically.

func ClearAllData

func ClearAllData(db *sql.DB) error

ClearAllData deletes all data from all tables (issues, comments, labels, issue_labels, issue_relations, activity_log) within a single transaction. The schema and meta table are preserved.

func CommitProposal

func CommitProposal(db *sql.DB, id int, outcome string, escalationReason string) error

CommitProposal transitions an approved proposal to committed status with a final outcome. If escalationReason is non-empty, it is stored on the proposal.

func CountByPriority

func CountByPriority(db *sql.DB) (map[string]int, error)

CountByPriority returns a map of priority -> count for all issues.

func CountByStatus

func CountByStatus(db *sql.DB) (map[string]int, error)

CountByStatus returns a map of status -> count for all issues.

func CountIssues

func CountIssues(db *sql.DB) (int, error)

CountIssues returns the total number of issues in the database.

func CountRootIssues

func CountRootIssues(db *sql.DB) (int, error)

CountRootIssues returns the number of issues with no parent.

func CreateComment

func CreateComment(db *sql.DB, comment *model.Comment) (int, error)

CreateComment inserts a new comment for an issue, records activity, and returns its ID. The insert and activity log are wrapped in a single transaction so they succeed or fail together.

func CreateIssue

func CreateIssue(db *sql.DB, issue *model.Issue, labels []string, files []string) (int, error)

CreateIssue inserts a new issue and returns its ID. Labels are created (find-or-create) and linked to the issue within the same transaction. Files are attached to the issue if provided.

func CreateProposal

func CreateProposal(db *sql.DB, p *model.Proposal) (int, error)

CreateProposal inserts a new proposal and returns its ID.

func CreateRelation

func CreateRelation(db *sql.DB, rel *model.Relation) (int, error)

CreateRelation inserts a new relation between two issues within a single transaction. It validates that both issues exist, rejects self-referential and duplicate relations, runs cycle detection for blocks/depends_on types, and records activity on both issues.

func DeleteIssue

func DeleteIssue(db *sql.DB, id int) error

DeleteIssue removes an issue by ID. Foreign key cascades handle cleanup of related rows (comments, labels, activity, relations).

func DeleteLabel

func DeleteLabel(db *sql.DB, labelID int, name, author string) ([]int, error)

DeleteLabel removes a label by ID. CASCADE constraints handle cleanup of issue_labels rows. Activity is recorded for each affected issue using the provided name. Returns the list of issue IDs that were attached to the label.

func DeleteRelation

func DeleteRelation(db *sql.DB, sourceID, targetID int, relType string) error

DeleteRelation removes a relation matching the given source, target, and type. Activity is recorded on both issues within a single transaction.

func DetachFiles

func DetachFiles(db *sql.DB, issueID int, filePaths []string, changedBy string) error

DetachFiles deletes rows from issue_files matching the issue ID and file paths. Activity is recorded for removed files.

func GetActivity

func GetActivity(db *sql.DB, issueID int, limit int) ([]model.Activity, error)

GetActivity retrieves activity log entries for an issue, ordered by most recent first.

func GetAllDirectionalRelations

func GetAllDirectionalRelations(db *sql.DB) ([]model.Relation, error)

GetAllDirectionalRelations returns all relations where the relation type is "blocks" or "depends_on", ordered by creation time ascending.

func GetAllRelations

func GetAllRelations(db *sql.DB) ([]model.Relation, error)

GetAllRelations returns every relation in the database, ordered by creation time ascending.

func GetBatchSubIssueProgress

func GetBatchSubIssueProgress(conn *sql.DB, parentIDs []int) (map[int][2]int, error)

GetBatchSubIssueProgress returns (done, total) counts for descendants of each given parent ID in a single query, avoiding N+1 overhead.

func GetComment

func GetComment(db *sql.DB, id int) (*model.Comment, error)

GetComment retrieves a comment by ID.

func GetIssue

func GetIssue(db *sql.DB, id int) (*model.Issue, error)

GetIssue retrieves an issue by ID.

func GetIssueFiles

func GetIssueFiles(db *sql.DB, issueID int) ([]string, error)

GetIssueFiles returns the file paths attached to an issue, sorted alphabetically.

func GetIssueLabelObjects

func GetIssueLabelObjects(db *sql.DB, issueID int) ([]*model.Label, error)

GetIssueLabelObjects returns the full Label objects attached to an issue, sorted alphabetically by name.

func GetIssueLabels

func GetIssueLabels(db *sql.DB, issueID int) ([]string, error)

GetIssueLabels returns the label names attached to an issue, sorted alphabetically.

func GetIssueRelations

func GetIssueRelations(db *sql.DB, issueID int) ([]model.Relation, error)

GetIssueRelations returns all relations where the given issue is either the source or the target, ordered by creation time ascending.

func GetIssuesByIDs

func GetIssuesByIDs(db *sql.DB, ids []int) (map[int]*model.Issue, error)

GetIssuesByIDs retrieves multiple issues by their IDs in a single query. The returned map is keyed by issue ID. IDs that don't exist are silently skipped (no error for missing rows). Labels are hydrated on all returned issues.

func GetLabelByName

func GetLabelByName(db *sql.DB, name string) (*model.LabelWithCount, error)

GetLabelByName retrieves a label by its unique name, including the count of issues currently attached to it. Returns ErrNotFound if no label with that name exists.

func GetProposal

func GetProposal(db *sql.DB, id int) (*model.Proposal, error)

GetProposal returns a proposal by ID, or ErrNotFound if it does not exist.

func GetProposalIssues

func GetProposalIssues(db *sql.DB, proposalID int) ([]int, error)

GetProposalIssues returns the issue IDs linked to a proposal.

func GetProposalVotes

func GetProposalVotes(db *sql.DB, proposalID int) ([]*model.Vote, error)

GetProposalVotes returns all votes for a proposal, ordered by creation time.

func GetSubIssueProgress

func GetSubIssueProgress(db *sql.DB, parentID int) (int, int, error)

GetSubIssueProgress returns (done, total) counts for all descendants of an issue.

func GetSubIssueTree

func GetSubIssueTree(db *sql.DB, parentID int) ([]*model.Issue, error)

GetSubIssueTree returns the full recursive tree of all descendants under an issue.

func GetSubIssues

func GetSubIssues(db *sql.DB, parentID int) ([]*model.Issue, error)

GetSubIssues returns all direct children of an issue.

func HydrateFiles

func HydrateFiles(db *sql.DB, issues []*model.Issue) error

HydrateFiles bulk-loads files for a set of issues, populating each issue's Files field. This avoids N+1 queries in list views and the planner.

func HydrateLabels

func HydrateLabels(db *sql.DB, issues []*model.Issue) error

HydrateLabels bulk-loads labels for a set of issues, populating each issue's Labels field. This avoids N+1 queries when displaying lists.

func Initialize

func Initialize(db *sql.DB) error

Initialize creates all tables if they don't exist and sets the schema version.

func InsertCommentWithID

func InsertCommentWithID(tx *sql.Tx, comment *model.Comment) (bool, error)

InsertCommentWithID inserts a comment with a specific ID (not auto-increment), skipping if the ID already exists. Returns true if the row was inserted. Must be called within an existing transaction.

func InsertIssueFileMapping

func InsertIssueFileMapping(tx *sql.Tx, issueID int, filePath string) (bool, error)

InsertIssueFileMapping inserts a single file mapping using INSERT OR IGNORE. Returns true if inserted, false if already existed. Must be called within an existing transaction.

func InsertIssueLabelMapping

func InsertIssueLabelMapping(tx *sql.Tx, issueID, labelID int) (bool, error)

InsertIssueLabelMapping inserts an issue_labels row linking an issue to a label, skipping if the mapping already exists. Returns true if the row was inserted. Must be called within an existing transaction.

func InsertIssueWithID

func InsertIssueWithID(tx *sql.Tx, issue *model.Issue) (bool, error)

InsertIssueWithID inserts an issue with a specific ID (not auto-increment), skipping if the ID already exists. Returns true if the row was inserted. Must be called within an existing transaction.

func InsertLabelWithID

func InsertLabelWithID(tx *sql.Tx, label *model.Label) (bool, error)

InsertLabelWithID inserts a label with a specific ID (not auto-increment), skipping if the ID already exists. Returns true if the row was inserted. Must be called within an existing transaction.

func InsertRelationWithID

func InsertRelationWithID(tx *sql.Tx, rel *model.Relation) (bool, error)

InsertRelationWithID inserts a relation with a specific ID (not auto-increment), skipping if the ID already exists. Returns true if the row was inserted. Must be called within an existing transaction.

func IsDescendant

func IsDescendant(db *sql.DB, issueID, potentialDescendantID int) (bool, error)

IsDescendant returns true if potentialDescendantID is a descendant of issueID. This is used to detect cycles when reparenting an issue.

func IssueExists

func IssueExists(db *sql.DB, issueID int) (bool, error)

IssueExists returns true if an issue with the given ID exists.

func LinkProposalIssue

func LinkProposalIssue(db *sql.DB, proposalID, issueID int) error

LinkProposalIssue links a proposal to an issue. Returns ErrNotFound if the proposal or issue does not exist. Returns ErrConflict if the link already exists.

func ListAllComments

func ListAllComments(db *sql.DB) ([]*model.Comment, error)

ListAllComments returns every comment in the database across all issues, ordered by created_at ascending.

func ListAllIssueFileMappings

func ListAllIssueFileMappings(db *sql.DB) ([]model.IssueFileMapping, error)

ListAllIssueFileMappings returns all rows from issue_files as IssueFileMapping structs. This is needed by the export command.

func ListAllIssueLabelMappings

func ListAllIssueLabelMappings(db *sql.DB) ([]model.IssueLabelMapping, error)

ListAllIssueLabelMappings returns all (issue_id, label_id) pairs from the issue_labels table.

func ListAllIssues

func ListAllIssues(db *sql.DB) ([]*model.Issue, error)

ListAllIssues returns every issue in the database, including done issues, with no filters, sorting, or pagination. Labels are hydrated on all results.

func ListAllLabels

func ListAllLabels(db *sql.DB) ([]*model.LabelWithCount, error)

ListAllLabels returns every label along with the count of issues using it, sorted alphabetically by name.

func ListAllLabelsRaw

func ListAllLabelsRaw(db *sql.DB) ([]*model.Label, error)

ListAllLabelsRaw returns every label as a model.Label object (without issue counts), sorted alphabetically by name.

func ListComments

func ListComments(db *sql.DB, issueID int) ([]*model.Comment, error)

ListComments retrieves all comments for an issue, ordered by creation time ascending.

func ListIssues

func ListIssues(db *sql.DB, opts ListOptions) ([]*model.Issue, int, error)

ListIssues retrieves issues matching the given filters. It returns the matching issues, the total count of matching rows (ignoring Limit/Offset), and an error.

func ListProposals

func ListProposals(db *sql.DB, status string, criticality string, domainTag string, limit int) ([]*model.Proposal, int, error)

ListProposals returns proposals with optional filters. It returns the matching proposals and the total count (before limit).

func Migrate

func Migrate(db *sql.DB) error

Migrate checks the current schema version and applies any pending migrations sequentially. It is a no-op when already at the latest version.

func Open

func Open(dbPath string) (*sql.DB, error)

Open opens or creates the SQLite database at the given path. It sets pragmas for WAL mode, foreign key enforcement, and busy timeout.

func OrphanSubIssues

func OrphanSubIssues(db *sql.DB, parentID int, author string) error

OrphanSubIssues sets parent_id to NULL for all direct children of the given issue. Activity is recorded for each affected child within a transaction.

func RecordActivity

func RecordActivity(ex execer, issueID int, field, oldVal, newVal, changedBy string) error

RecordActivity logs a field change on an issue.

func RemoveLabelFromIssue

func RemoveLabelFromIssue(db *sql.DB, issueID int, labelName string, author string) error

RemoveLabelFromIssue detaches a label from an issue. Returns an error if the label is not found or is not attached to the issue. Activity is recorded and the issue's updated_at timestamp is touched.

func RemoveLabelsFromIssue

func RemoveLabelsFromIssue(db *sql.DB, issueID int, labelNames []string, author string) error

RemoveLabelsFromIssue detaches multiple labels from an issue atomically within a single transaction. Returns an error if any label is not found or not attached — no labels are removed on failure. Activity is recorded for each removed label and the issue's updated_at timestamp is touched once.

func SchemaVersion

func SchemaVersion(db *sql.DB) (int, error)

SchemaVersion returns the current schema version from the meta table.

func SetIssueFiles

func SetIssueFiles(db *sql.DB, issueID int, filePaths []string, changedBy string) error

SetIssueFiles replaces all files for an issue (delete existing, insert new). Activity is recorded showing the change from old files to new files.

func UnlinkProposalIssue

func UnlinkProposalIssue(db *sql.DB, proposalID, issueID int) error

UnlinkProposalIssue removes a link between a proposal and an issue. Returns ErrNotFound if the link does not exist.

func UpdateIssue

func UpdateIssue(db *sql.DB, id int, updates map[string]interface{}, changedBy string) error

UpdateIssue updates an existing issue. Only keys present in the updates map are modified. The updated_at timestamp is always set to the current time. Activity is recorded for each changed field within the same transaction.

Field names are validated against validUpdateFields, but callers are responsible for validating field values (e.g. ensuring status/priority/kind are valid enums) before calling this function.

Types

type CastVoteResult

type CastVoteResult struct {
	Vote           *model.Vote
	ProposalStatus model.ProposalStatus
	VotesCast      int
	VotesRequired  int
	QuorumReached  bool
	WeightedScore  *float64
}

CastVoteResult holds the outcome of a CastVote operation, including whether quorum was reached and the proposal's updated status.

func CastVote

func CastVote(db *sql.DB, v *model.Vote) (*CastVoteResult, error)

CastVote inserts a vote and auto-finalizes the proposal when quorum is reached. Returns ErrNotFound if the proposal does not exist. Returns ErrConflict if the voter already voted or the proposal is already finalized.

type CycleError

type CycleError struct {
	Path []int
}

CycleError wraps ErrCycleDetected and carries the path of IDs forming the cycle.

func (*CycleError) Error

func (e *CycleError) Error() string

func (*CycleError) Unwrap

func (e *CycleError) Unwrap() error

type ListOptions

type ListOptions struct {
	Statuses    []string // filter by status (multiple = OR)
	Priorities  []string // filter by priority (multiple = OR)
	Labels      []string // filter by label name (multiple = AND)
	Types       []string // filter by kind (multiple = OR)
	Assignee    string   // filter by assignee
	ParentID    *int     // filter by parent issue ID
	RootsOnly   bool     // only issues with no parent
	IncludeDone bool     // include done status (default: exclude)
	Sort        string   // field name
	SortDir     string   // "asc" or "desc"
	Limit       int      // max results
	Offset      int      // for pagination
}

ListOptions holds filtering, sorting, and pagination options for ListIssues.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL