97 lines
2.5 KiB
Go
97 lines
2.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// ErrPasteNotInDatabase is returned when one calls PutClump with pastes that are not in the database.
|
|
var ErrPasteNotInDatabase = errors.New("repository: given pastes are not in the database")
|
|
|
|
// Clump represents a group ("clump") of pastes
|
|
type Clump struct {
|
|
ID int
|
|
Title string
|
|
Handle uuid.UUID
|
|
Pastes []Paste
|
|
}
|
|
|
|
// ClumpRepository puts/gets a clump from the database
|
|
type ClumpRepository interface {
|
|
// GetClump gets a clump from the database
|
|
GetClump(handle uuid.UUID) (Clump, error)
|
|
// GetClump gets a clump from the database
|
|
PutClump(title string, pastes ...Paste) (Clump, error)
|
|
}
|
|
|
|
// GetClump gets a clump and all of its associated pastes
|
|
func (db *DatabaseConnector) GetClump(handle uuid.UUID) (Clump, error) {
|
|
pasteRows, err := db.DB.Query("SELECT paste.*, clump.* FROM paste JOIN CLUMP USING (clumpID) WHERE handle = $1", handle.String())
|
|
if err != nil {
|
|
return Clump{}, err
|
|
}
|
|
|
|
clump := Clump{
|
|
Pastes: []Paste{},
|
|
}
|
|
|
|
for pasteRows.Next() {
|
|
paste := Paste{}
|
|
// Per the docs, "The number of values in dest must be the same as the number of columns in Rows."
|
|
// Because the clump result will always be the same, we can just pull it on each row and update the same struct
|
|
pasteRows.Scan(&paste.ID, &paste.Filename, &paste.Handle, &paste.ClumpID, &clump.ID, &clump.Title, &clump.Handle)
|
|
clump.Pastes = append(clump.Pastes, paste)
|
|
}
|
|
|
|
return clump, pasteRows.Err()
|
|
}
|
|
|
|
// PutClump puts a clump into the database.
|
|
// All given pastes must have already been inserted to the database. Returns ErrPasteNotInDatabase if condition isn't met.
|
|
func (db *DatabaseConnector) PutClump(title string, pastes ...Paste) (Clump, error) {
|
|
handle, err := uuid.NewUUID()
|
|
if err != nil {
|
|
return Clump{}, err
|
|
}
|
|
|
|
clump := Clump{
|
|
Handle: handle,
|
|
}
|
|
|
|
tx, err := db.DB.Begin()
|
|
insertResult := tx.QueryRow("INSERT INTO clump VALUES(DEFAULT, $1, $2) RETURNING clumpID", title, handle.String())
|
|
err = insertResult.Scan(&clump.ID)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return Clump{}, err
|
|
}
|
|
|
|
err = db.addPastesToClump(tx, clump.ID, pastes)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return Clump{}, err
|
|
}
|
|
|
|
return clump, tx.Commit()
|
|
}
|
|
|
|
func (db *DatabaseConnector) addPastesToClump(ex executor, clumpID int, pastes []Paste) error {
|
|
for _, paste := range pastes {
|
|
paste.ClumpID = clumpID
|
|
result, err := db.updatePaste(ex, paste)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
numRows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
} else if numRows == 0 {
|
|
return ErrPasteNotInDatabase
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|