// Delete old articles which read=1. func DeleteOldArticles(session *xorm.Session) (affected int64, err error) { list, err := GetFeedListWithAmount(session) if err != nil { return } for _, item := range list { if int(*item.MaxKeep) > 0 && (item.Amount-item.Unread > uint64(*item.MaxKeep)) { n := int(item.Amount - item.Unread - uint64(*item.MaxKeep)) sql := "delete from Item where id in (select id from Item where Fid = ? and Read = 1 and starred = 0 order by Id asc limit ?)" result, e := session.Exec(sql, item.Id, n) if e != nil { err = e return } num, e := result.RowsAffected() if e != nil { err = e return } global.Logger.Infof("[TRIM DATA] in transaction: delete old articles which is read: feed id: %d, affected: %d", item.Id, num) affected += num } } return }
// Mark old articles read. func MarkOldArticlesRead(session *xorm.Session) (affected int64, err error) { list, err := GetFeedListWithAmount(session) if err != nil { return } for _, item := range list { if int(*item.MaxUnread) > 0 && item.Unread > uint64(*item.MaxUnread) { n := int(item.Unread) - int(*item.MaxUnread) sql := "update Item set read=1 where id in (select id from Item where Fid = ? and Read = 0 order by Id asc limit ?)" result, e := session.Exec(sql, item.Id, n) if e != nil { err = e return } num, e := result.RowsAffected() if e != nil { err = e return } global.Logger.Infof("[TRIM DATA] in transaction: mark old articles read: feed id: %d, affected: %d", item.Id, num) affected += num } } return }
func updateIsDefaultFlag(ds *m.DataSource, sess *xorm.Session) error { // Handle is default flag if ds.IsDefault { rawSql := "UPDATE data_source SET is_default=? WHERE org_id=? AND id <> ?" if _, err := sess.Exec(rawSql, false, ds.OrgId, ds.Id); err != nil { return err } } return nil }
func updateIssueUserByAssignee(e *xorm.Session, issueID, assigneeID int64) (err error) { if _, err = e.Exec("UPDATE `issue_user` SET is_assigned=? WHERE issue_id=?", false, issueID); err != nil { return err } // Assignee ID equals to 0 means clear assignee. if assigneeID == 0 { return nil } _, err = e.Exec("UPDATE `issue_user` SET is_assigned=? WHERE uid=? AND issue_id=?", true, assigneeID, issueID) return err }
func deleteAlertByIdInternal(alertId int64, reason string, sess *xorm.Session) error { sqlog.Debug("Deleting alert", "id", alertId, "reason", reason) if _, err := sess.Exec("DELETE FROM alert WHERE id = ?", alertId); err != nil { return err } if _, err := sess.Exec("DELETE FROM annotation WHERE alert_id = ?", alertId); err != nil { return err } return nil }
func updateIssueUserByAssignee(e *xorm.Session, issue *Issue) (err error) { if _, err = e.Exec("UPDATE `issue_user` SET is_assigned=? WHERE issue_id=?", false, issue.ID); err != nil { return err } // Assignee ID equals to 0 means clear assignee. if issue.AssigneeID > 0 { if _, err = e.Exec("UPDATE `issue_user` SET is_assigned=? WHERE uid=? AND issue_id=?", true, issue.AssigneeID, issue.ID); err != nil { return err } } return updateIssue(e, issue) }
func DeleteAlertDefinition(dashboardId int64, sess *xorm.Session) error { alerts := make([]*m.Alert, 0) sess.Where("dashboard_id = ?", dashboardId).Find(&alerts) for _, alert := range alerts { _, err := sess.Exec("DELETE FROM alert WHERE id = ? ", alert.Id) if err != nil { return err } sqlog.Debug("Alert deleted (due to dashboard deletion)", "name", alert.Name, "id", alert.Id) } return nil }
func changeMilestoneAssign(e *xorm.Session, oldMid int64, issue *Issue) error { if oldMid > 0 { m, err := getMilestoneByID(e, oldMid) if err != nil { return err } m.NumIssues-- if issue.IsClosed { m.NumClosedIssues-- } if err = updateMilestone(e, m); err != nil { return err } else if _, err = e.Exec("UPDATE `issue_user` SET milestone_id=0 WHERE issue_id=?", issue.ID); err != nil { return err } } if issue.MilestoneID > 0 { m, err := getMilestoneByID(e, issue.MilestoneID) if err != nil { return err } m.NumIssues++ if issue.IsClosed { m.NumClosedIssues++ } if m.NumIssues == 0 { return ErrWrongIssueCounter } if err = updateMilestone(e, m); err != nil { return err } else if _, err = e.Exec("UPDATE `issue_user` SET milestone_id=? WHERE issue_id=?", m.ID, issue.ID); err != nil { return err } } return updateIssue(e, issue) }
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) { if err = IsUsableName(repo.Name); err != nil { return err } has, err := isRepositoryExist(e, u, repo.Name) if err != nil { return fmt.Errorf("IsRepositoryExist: %v", err) } else if has { return ErrRepoAlreadyExist{u.Name, repo.Name} } if _, err = e.Insert(repo); err != nil { return err } else if _, err = e.Exec("UPDATE `user` SET num_repos=num_repos+1 WHERE id=?", u.Id); err != nil { return err } // Give access to all members in owner team. if u.IsOrganization() { t, err := u.getOwnerTeam(e) if err != nil { return fmt.Errorf("getOwnerTeam: %v", err) } else if err = t.addRepository(e, repo); err != nil { return fmt.Errorf("addRepository: %v", err) } } else { // Organization automatically called this in addRepository method. if err = repo.recalculateAccesses(e); err != nil { return fmt.Errorf("recalculateAccesses: %v", err) } } if err = watchRepo(e, u.Id, repo.ID, true); err != nil { return fmt.Errorf("watchRepo: %v", err) } else if err = newRepoAction(e, u, repo); err != nil { return fmt.Errorf("newRepoAction: %v", err) } return nil }
func (mg *Migrator) exec(m Migration, sess *xorm.Session) error { mg.Logger.Info("Executing migration", "id", m.Id()) condition := m.GetCondition() if condition != nil { sql, args := condition.Sql(mg.dialect) results, err := sess.Query(sql, args...) if err != nil || len(results) == 0 { mg.Logger.Info("Skipping migration condition not fulfilled", "id", m.Id()) return sess.Rollback() } } _, err := sess.Exec(m.Sql(mg.dialect)) if err != nil { mg.Logger.Error("Executing migration failed", "id", m.Id(), "error", err) return err } return nil }
func deleteMissingAlerts(alerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *xorm.Session) error { for _, missingAlert := range alerts { missing := true for _, k := range cmd.Alerts { if missingAlert.PanelId == k.PanelId { missing = false break } } if missing { _, err := sess.Exec("DELETE FROM alert WHERE id = ?", missingAlert.Id) if err != nil { return err } sqlog.Debug("Alert deleted", "name", missingAlert.Name, "id", missingAlert.Id) } } return nil }
// It's caller's responsibility to create action. func newIssue(e *xorm.Session, repo *Repository, issue *Issue, labelIDs []int64, uuids []string, isPull bool) (err error) { issue.Name = strings.TrimSpace(issue.Name) issue.Index = repo.NextIssueIndex() if issue.AssigneeID > 0 { // Silently drop invalid assignee valid, err := hasAccess(e, &User{ID: issue.AssigneeID}, repo, ACCESS_MODE_WRITE) if err != nil { return fmt.Errorf("hasAccess: %v", err) } else if !valid { issue.AssigneeID = 0 } } if _, err = e.Insert(issue); err != nil { return err } if isPull { _, err = e.Exec("UPDATE `repository` SET num_pulls=num_pulls+1 WHERE id=?", issue.RepoID) } else { _, err = e.Exec("UPDATE `repository` SET num_issues=num_issues+1 WHERE id=?", issue.RepoID) } if err != nil { return err } if len(labelIDs) > 0 { // During the session, SQLite3 dirver cannot handle retrieve objects after update something. // So we have to get all needed labels first. labels := make([]*Label, 0, len(labelIDs)) if err = e.In("id", labelIDs).Find(&labels); err != nil { return fmt.Errorf("find all labels: %v", err) } for _, label := range labels { if label.RepoID != repo.ID { continue } if err = issue.addLabel(e, label); err != nil { return fmt.Errorf("addLabel: %v", err) } } } if issue.MilestoneID > 0 { if err = changeMilestoneAssign(e, 0, issue); err != nil { return err } } if err = newIssueUsers(e, repo, issue); err != nil { return err } // Check attachments. attachments := make([]*Attachment, 0, len(uuids)) for _, uuid := range uuids { attach, err := getAttachmentByUUID(e, uuid) if err != nil { if IsErrAttachmentNotExist(err) { continue } return fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err) } attachments = append(attachments, attach) } for i := range attachments { attachments[i].IssueID = issue.ID // No assign value could be 0, so ignore AllCols(). if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil { return fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err) } } return issue.loadAttributes(e) }
// It's caller's responsibility to create action. func newIssue(e *xorm.Session, repo *Repository, issue *Issue, labelIDs []int64, uuids []string, isPull bool) (err error) { if _, err = e.Insert(issue); err != nil { return err } if isPull { _, err = e.Exec("UPDATE `repository` SET num_pulls=num_pulls+1 WHERE id=?", issue.RepoID) } else { _, err = e.Exec("UPDATE `repository` SET num_issues=num_issues+1 WHERE id=?", issue.RepoID) } if err != nil { return err } var label *Label for _, id := range labelIDs { if id == 0 { continue } label, err = getLabelByID(e, id) if err != nil { return err } if err = issue.addLabel(e, label); err != nil { return fmt.Errorf("addLabel: %v", err) } } if issue.MilestoneID > 0 { if err = changeMilestoneAssign(e, 0, issue); err != nil { return err } } if err = newIssueUsers(e, repo, issue); err != nil { return err } // Check attachments. attachments := make([]*Attachment, 0, len(uuids)) for _, uuid := range uuids { attach, err := getAttachmentByUUID(e, uuid) if err != nil { if IsErrAttachmentNotExist(err) { continue } return fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err) } attachments = append(attachments, attach) } for i := range attachments { attachments[i].IssueID = issue.ID // No assign value could be 0, so ignore AllCols(). if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil { return fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err) } } return nil }
func createComment(e *xorm.Session, u *User, repo *Repository, issue *Issue, commitID, line int64, cmtType CommentType, content, commitSHA string, uuids []string) (_ *Comment, err error) { comment := &Comment{ PosterID: u.Id, Type: cmtType, IssueID: issue.ID, CommitID: commitID, Line: line, Content: content, CommitSHA: commitSHA, } if _, err = e.Insert(comment); err != nil { return nil, err } // Check comment type. switch cmtType { case COMMENT_TYPE_COMMENT: if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", issue.ID); err != nil { return nil, err } // Check attachments. attachments := make([]*Attachment, 0, len(uuids)) for _, uuid := range uuids { attach, err := getAttachmentByUUID(e, uuid) if err != nil { if IsErrAttachmentNotExist(err) { continue } return nil, fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err) } attachments = append(attachments, attach) } for i := range attachments { attachments[i].IssueID = issue.ID attachments[i].CommentID = comment.ID // No assign value could be 0, so ignore AllCols(). if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil { return nil, fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err) } } // Notify watchers. act := &Action{ ActUserID: u.Id, ActUserName: u.Name, ActEmail: u.Email, OpType: COMMENT_ISSUE, Content: fmt.Sprintf("%d|%s", issue.Index, strings.Split(content, "\n")[0]), RepoID: repo.ID, RepoUserName: repo.Owner.Name, RepoName: repo.Name, IsPrivate: repo.IsPrivate, } if err = notifyWatchers(e, act); err != nil { return nil, err } case COMMENT_TYPE_REOPEN: if issue.IsPull { _, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", repo.ID) } else { _, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues-1 WHERE id=?", repo.ID) } if err != nil { return nil, err } case COMMENT_TYPE_CLOSE: if issue.IsPull { _, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", repo.ID) } else { _, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues+1 WHERE id=?", repo.ID) } if err != nil { return nil, err } } return comment, nil }
// FIXME: need some kind of mechanism to record failure. HINT: system notice func deleteUser(e *xorm.Session, u *User) error { // Note: A user owns any repository or belongs to any organization // cannot perform delete operation. // Check ownership of repository. count, err := getRepositoryCount(e, u) if err != nil { return fmt.Errorf("GetRepositoryCount: %v", err) } else if count > 0 { return ErrUserOwnRepos{UID: u.Id} } // Check membership of organization. count, err = u.getOrganizationCount(e) if err != nil { return fmt.Errorf("GetOrganizationCount: %v", err) } else if count > 0 { return ErrUserHasOrgs{UID: u.Id} } // ***** START: Watch ***** watches := make([]*Watch, 0, 10) if err = e.Find(&watches, &Watch{UserID: u.Id}); err != nil { return fmt.Errorf("get all watches: %v", err) } for i := range watches { if _, err = e.Exec("UPDATE `repository` SET num_watches=num_watches-1 WHERE id=?", watches[i].RepoID); err != nil { return fmt.Errorf("decrease repository watch number[%d]: %v", watches[i].RepoID, err) } } // ***** END: Watch ***** // ***** START: Star ***** stars := make([]*Star, 0, 10) if err = e.Find(&stars, &Star{UID: u.Id}); err != nil { return fmt.Errorf("get all stars: %v", err) } for i := range stars { if _, err = e.Exec("UPDATE `repository` SET num_stars=num_stars-1 WHERE id=?", stars[i].RepoID); err != nil { return fmt.Errorf("decrease repository star number[%d]: %v", stars[i].RepoID, err) } } // ***** END: Star ***** // ***** START: Follow ***** followers := make([]*Follow, 0, 10) if err = e.Find(&followers, &Follow{UserID: u.Id}); err != nil { return fmt.Errorf("get all followers: %v", err) } for i := range followers { if _, err = e.Exec("UPDATE `user` SET num_followers=num_followers-1 WHERE id=?", followers[i].UserID); err != nil { return fmt.Errorf("decrease user follower number[%d]: %v", followers[i].UserID, err) } } // ***** END: Follow ***** if err = deleteBeans(e, &AccessToken{UID: u.Id}, &Collaboration{UserID: u.Id}, &Access{UserID: u.Id}, &Watch{UserID: u.Id}, &Star{UID: u.Id}, &Follow{FollowID: u.Id}, &Action{UserID: u.Id}, &IssueUser{UID: u.Id}, &EmailAddress{UID: u.Id}, ); err != nil { return fmt.Errorf("deleteBeans: %v", err) } // ***** START: PublicKey ***** keys := make([]*PublicKey, 0, 10) if err = e.Find(&keys, &PublicKey{OwnerID: u.Id}); err != nil { return fmt.Errorf("get all public keys: %v", err) } for _, key := range keys { if err = deletePublicKey(e, key.ID); err != nil { return fmt.Errorf("deletePublicKey: %v", err) } } // ***** END: PublicKey ***** // Clear assignee. if _, err = e.Exec("UPDATE `issue` SET assignee_id=0 WHERE assignee_id=?", u.Id); err != nil { return fmt.Errorf("clear assignee: %v", err) } if _, err = e.Id(u.Id).Delete(new(User)); err != nil { return fmt.Errorf("Delete: %v", err) } // FIXME: system notice // Note: There are something just cannot be roll back, // so just keep error logs of those operations. RewriteAllPublicKeys() os.RemoveAll(UserPath(u.Name)) os.Remove(u.CustomAvatarPath()) return nil }
func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err error) { comment := &Comment{ Type: opts.Type, PosterID: opts.Doer.ID, Poster: opts.Doer, IssueID: opts.Issue.ID, CommitID: opts.CommitID, CommitSHA: opts.CommitSHA, Line: opts.LineNum, Content: opts.Content, } if _, err = e.Insert(comment); err != nil { return nil, err } // Compose comment action, could be plain comment, close or reopen issue/pull request. // This object will be used to notify watchers in the end of function. act := &Action{ ActUserID: opts.Doer.ID, ActUserName: opts.Doer.Name, Content: fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]), RepoID: opts.Repo.ID, RepoUserName: opts.Repo.Owner.Name, RepoName: opts.Repo.Name, IsPrivate: opts.Repo.IsPrivate, } // Check comment type. switch opts.Type { case COMMENT_TYPE_COMMENT: act.OpType = ACTION_COMMENT_ISSUE if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", opts.Issue.ID); err != nil { return nil, err } // Check attachments attachments := make([]*Attachment, 0, len(opts.Attachments)) for _, uuid := range opts.Attachments { attach, err := getAttachmentByUUID(e, uuid) if err != nil { if IsErrAttachmentNotExist(err) { continue } return nil, fmt.Errorf("getAttachmentByUUID [%s]: %v", uuid, err) } attachments = append(attachments, attach) } for i := range attachments { attachments[i].IssueID = opts.Issue.ID attachments[i].CommentID = comment.ID // No assign value could be 0, so ignore AllCols(). if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil { return nil, fmt.Errorf("update attachment [%d]: %v", attachments[i].ID, err) } } case COMMENT_TYPE_REOPEN: act.OpType = ACTION_REOPEN_ISSUE if opts.Issue.IsPull { act.OpType = ACTION_REOPEN_PULL_REQUEST } if opts.Issue.IsPull { _, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", opts.Repo.ID) } else { _, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues-1 WHERE id=?", opts.Repo.ID) } if err != nil { return nil, err } case COMMENT_TYPE_CLOSE: act.OpType = ACTION_CLOSE_ISSUE if opts.Issue.IsPull { act.OpType = ACTION_CLOSE_PULL_REQUEST } if opts.Issue.IsPull { _, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", opts.Repo.ID) } else { _, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues+1 WHERE id=?", opts.Repo.ID) } if err != nil { return nil, err } } // Notify watchers for whatever action comes in, ignore if no action type. if act.OpType > 0 { if err = notifyWatchers(e, act); err != nil { log.Error(4, "notifyWatchers: %v", err) } comment.MailParticipants(act.OpType, opts.Issue) } return comment, nil }
func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { opts.Issue.Title = strings.TrimSpace(opts.Issue.Title) opts.Issue.Index = opts.Repo.NextIssueIndex() if opts.Issue.MilestoneID > 0 { milestone, err := getMilestoneByRepoID(e, opts.Issue.RepoID, opts.Issue.MilestoneID) if err != nil && !IsErrMilestoneNotExist(err) { return fmt.Errorf("getMilestoneByID: %v", err) } // Assume milestone is invalid and drop silently. opts.Issue.MilestoneID = 0 if milestone != nil { opts.Issue.MilestoneID = milestone.ID opts.Issue.Milestone = milestone if err = changeMilestoneAssign(e, opts.Issue, -1); err != nil { return err } } } if opts.Issue.AssigneeID > 0 { assignee, err := getUserByID(e, opts.Issue.AssigneeID) if err != nil && !IsErrUserNotExist(err) { return fmt.Errorf("getUserByID: %v", err) } // Assume assignee is invalid and drop silently. opts.Issue.AssigneeID = 0 if assignee != nil { valid, err := hasAccess(e, assignee, opts.Repo, ACCESS_MODE_WRITE) if err != nil { return fmt.Errorf("hasAccess [user_id: %d, repo_id: %d]: %v", assignee.ID, opts.Repo.ID, err) } if valid { opts.Issue.AssigneeID = assignee.ID opts.Issue.Assignee = assignee } } } // Milestone and assignee validation should happen before insert actual object. if _, err = e.Insert(opts.Issue); err != nil { return err } if opts.IsPull { _, err = e.Exec("UPDATE `repository` SET num_pulls = num_pulls + 1 WHERE id = ?", opts.Issue.RepoID) } else { _, err = e.Exec("UPDATE `repository` SET num_issues = num_issues + 1 WHERE id = ?", opts.Issue.RepoID) } if err != nil { return err } if len(opts.LableIDs) > 0 { // During the session, SQLite3 dirver cannot handle retrieve objects after update something. // So we have to get all needed labels first. labels := make([]*Label, 0, len(opts.LableIDs)) if err = e.In("id", opts.LableIDs).Find(&labels); err != nil { return fmt.Errorf("find all labels [label_ids: %v]: %v", opts.LableIDs, err) } for _, label := range labels { // Silently drop invalid labels. if label.RepoID != opts.Repo.ID { continue } if err = opts.Issue.addLabel(e, label); err != nil { return fmt.Errorf("addLabel [id: %d]: %v", label.ID, err) } } } if err = newIssueUsers(e, opts.Repo, opts.Issue); err != nil { return err } if len(opts.Attachments) > 0 { attachments, err := getAttachmentsByUUIDs(e, opts.Attachments) if err != nil { return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", opts.Attachments, err) } for i := 0; i < len(attachments); i++ { attachments[i].IssueID = opts.Issue.ID if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil { return fmt.Errorf("update attachment [id: %d]: %v", attachments[i].ID, err) } } } return opts.Issue.loadAttributes(e) }