// RemoveChange, see ExpectationsStore interface. func (s *SQLExpectationsStore) RemoveChange(changedDigests map[string][]string) (retErr error) { defer timer.New("removing exp change").Stop() const markRemovedStmt = `UPDATE exp_test_change SET removed = IF(removed IS NULL, ?, removed) WHERE (name=?) AND (digest=?)` // start a transaction tx, err := s.vdb.DB.Begin() if err != nil { return err } defer func() { retErr = database.CommitOrRollback(tx, retErr) }() // Mark all the digests as removed. now := util.TimeStampMs() for testName, digests := range changedDigests { for _, digest := range digests { if _, err = tx.Exec(markRemovedStmt, now, testName, digest); err != nil { return err } } } return nil }
// GetBuildIDFromDB retrieves the ID for the given build from the database // as specified by the given master, builder, and build number. func GetBuildIDFromDB(builder, master string, buildNumber int) (rvid int, rverr error) { tx, err := DB.Beginx() if err != nil { return -1, err } // Defer committing/rolling back the transaction. defer func() { rverr = database.CommitOrRollback(tx, rverr) }() return GetBuildIDFromDBTx(builder, master, buildNumber, tx) }
// replaceIntoDB inserts or updates the Build in the database. func (b *Build) replaceIntoDB() (rv error) { tx, err := DB.Beginx() if err != nil { return fmt.Errorf("Unable to push build into database - Could not begin transaction: %v", err) } // Defer committing/rolling back the transaction. defer func() { rv = database.CommitOrRollback(tx, rv) }() // Insert the build. return b.replaceIntoDBTx(tx) }
func ReplaceMultipleBuildsIntoDB(builds []*Build) (rv error) { tx, err := DB.Beginx() if err != nil { return fmt.Errorf("Unable to push builds into database - Could not begin transaction: %v", err) } // Defer committing/rolling back the transaction. defer func() { rv = database.CommitOrRollback(tx, rv) }() // Insert the builds. for _, b := range builds { if err := b.replaceIntoDBTx(tx); err != nil { return err } } return nil }
func ReplaceMultipleBuildsIntoDB(builds []*Build) (rv error) { defer metrics.NewTimer("buildbot.ReplaceMultipleBuildsIntoDB").Stop() tx, err := DB.Beginx() if err != nil { return fmt.Errorf("Unable to push builds into database - Could not begin transaction: %v", err) } // Defer committing/rolling back the transaction. defer func() { rv = database.CommitOrRollback(tx, rv) }() // Insert the builds. // TODO(borenet): Insert/update all of the builds at once. for _, b := range builds { if err := b.replaceIntoDBTx(tx); err != nil { return err } } return nil }
// replaceIntoDB inserts or updates the Alert in the database. func (a *Alert) replaceIntoDB() (rv error) { tx, err := DB.Beginx() if err != nil { return fmt.Errorf("Unable to push Alert into database - Could not begin transaction: %v", err) } defer func() { rv = database.CommitOrRollback(tx, rv) }() // Insert the alert itself. active := 0 if a.DismissedAt == 0 { active = 1 } res, err := tx.Exec(fmt.Sprintf("REPLACE INTO %s (id,active,name,triggered,category,message,nag,snoozedUntil,dismissedAt,autoDismiss,lastFired) VALUES (?,?,?,?,?,?,?,?,?,?,?);", TABLE_ALERTS), a.Id, active, a.Name, a.Triggered, a.Category, a.Message, a.Nag, a.SnoozedUntil, a.DismissedAt, a.AutoDismiss, a.LastFired) if err != nil { return fmt.Errorf("Failed to push alert into database: %v", err) } id, err := res.LastInsertId() if err != nil { return fmt.Errorf("Failed to push alert into database; LastInsertId failed: %v", err) } a.Id = id // Comments. // First, delete existing comments so we don't have leftovers hanging around from before. if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s WHERE alertId = ?;", TABLE_COMMENTS), a.Id); err != nil { return fmt.Errorf("Failed to delete comments from database: %v", err) } // Actually insert the comments. if len(a.Comments) > 0 { commentFields := 4 commentTmpl := util.RepeatJoin("?", ",", commentFields) commentsTmpl := util.RepeatJoin(fmt.Sprintf("(%s)", commentTmpl), ",", len(a.Comments)) flattenedComments := make([]interface{}, 0, commentFields*len(a.Comments)) for _, c := range a.Comments { flattenedComments = append(flattenedComments, a.Id, c.User, c.Time, c.Message) } if _, err := tx.Exec(fmt.Sprintf("INSERT INTO %s (alertId,user,time,message) VALUES %s;", TABLE_COMMENTS, commentsTmpl), flattenedComments...); err != nil { return fmt.Errorf("Unable to push comments into database: %v", err) } } // Actions. // First, delete existing actions so we don't have leftovers hanging around from before. if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s WHERE alertId = ?;", TABLE_ACTIONS), a.Id); err != nil { return fmt.Errorf("Failed to delete actions from database: %v", err) } // Actually insert the actions. if len(a.Actions) > 0 { actionFields := 2 actionTmpl := util.RepeatJoin("?", ",", actionFields) actionsTmpl := util.RepeatJoin(fmt.Sprintf("(%s)", actionTmpl), ",", len(a.Actions)) flattenedActions := make([]interface{}, 0, actionFields*len(a.Actions)) for _, action := range a.Actions { flattenedActions = append(flattenedActions, a.Id, action.String()) } if _, err := tx.Exec(fmt.Sprintf("INSERT INTO %s (alertId,action) VALUES %s;", TABLE_ACTIONS, actionsTmpl), flattenedActions...); err != nil { return fmt.Errorf("Unable to push actions into database: %v", err) } } // the transaction is committed during the deferred function. return nil }
// AddChangeWithTimeStamp adds changed tests to the database with the // given time stamp. This is primarily for migration purposes. func (s *SQLExpectationsStore) AddChangeWithTimeStamp(changedTests map[string]types.TestClassification, userId string, undoID int, timeStamp int64) (retErr error) { defer timer.New("adding exp change").Stop() // Count the number of values to add. changeCount := 0 for _, digests := range changedTests { changeCount += len(digests) } const ( insertChange = `INSERT INTO exp_change (userid, ts, undo_changeid) VALUES (?, ?, ?)` insertDigest = `INSERT INTO exp_test_change (changeid, name, digest, label) VALUES` ) // start a transaction tx, err := s.vdb.DB.Begin() if err != nil { return err } defer func() { retErr = database.CommitOrRollback(tx, retErr) }() // create the change record result, err := tx.Exec(insertChange, userId, timeStamp, undoID) if err != nil { return err } changeId, err := result.LastInsertId() if err != nil { return err } // If there are not changed records then we stop here. if changeCount == 0 { return nil } // Assemble the INSERT values. valuesStr := "" vals := []interface{}{} for testName, digests := range changedTests { for d, label := range digests { valuesStr += "(?, ?, ?, ?)," vals = append(vals, changeId, testName, d, label.String()) } } valuesStr = valuesStr[:len(valuesStr)-1] // insert all the changes prepStmt, err := tx.Prepare(insertDigest + valuesStr) if err != nil { return err } defer util.Close(prepStmt) _, err = prepStmt.Exec(vals...) if err != nil { return err } return nil }