<commit_before>package db

import (
	"fmt"
	"strings"

	"github.com/pborman/uuid"
)

type RetentionPolicy struct {
	UUID    string `json:"uuid"`
	Name    string `json:"name"`
	Summary string `json:"summary"`
	Expires uint   `json:"expires"`
}

type RetentionFilter struct {
	SkipUsed   bool
	SkipUnused bool

	SearchName string
}

func (f *RetentionFilter) Query() (string, []interface{}) {
	var wheres []string = []string{"r.uuid = r.uuid"}
	var args []interface{}
	n := 1

	if f.SearchName != "" {
		wheres = append(wheres, fmt.Sprintf("r.name LIKE $%d", n))
		args = append(args, Pattern(f.SearchName))
		n++
	}
	if !f.SkipUsed && !f.SkipUnused {
		return `
			SELECT r.uuid, r.name, r.summary, r.expiry, -1 AS n
				FROM retention r
				WHERE ` + strings.Join(wheres, " AND ") + `
				ORDER BY r.name, r.uuid ASC
		`, args
	}

	// by default, show retention policies with no attached jobs (unused)
	having := `HAVING COUNT(j.uuid) = 0`
	if f.SkipUnused {
		// otherwise, only show retention policies that have attached jobs
		having = `HAVING COUNT(j.uuid) > 0`
	}

	return `
		SELECT DISTINCT r.uuid, r.name, r.summary, r.expiry, COUNT(j.uuid) AS n
			FROM retention r
				LEFT JOIN jobs j
					ON j.retention_uuid = r.uuid
			WHERE ` + strings.Join(wheres, " AND ") + `
			GROUP BY r.uuid
			` + having + `
			ORDER BY r.name, r.uuid ASC
	`, args
}

func (db *DB) GetAllRetentionPolicies(filter *RetentionFilter) ([]*RetentionPolicy, error) {
	l := []*RetentionPolicy{}
	query, args := filter.Query()
	r, err := db.Query(query, args...)
	if err != nil {
		return l, err
	}
	defer r.Close()

	for r.Next() {
		ann := &RetentionPolicy{}
		var n int

		if err = r.Scan(&ann.UUID, &ann.Name, &ann.Summary, &ann.Expires, &n); err != nil {
			return l, err
		}

		l = append(l, ann)
	}

	return l, nil
}

func (db *DB) GetRetentionPolicy(id uuid.UUID) (*RetentionPolicy, error) {
	r, err := db.Query(`
		SELECT uuid, name, summary, expiry
			FROM retention WHERE uuid = $1`, id.String())
	if err != nil {
		return nil, err
	}
	defer r.Close()

	if !r.Next() {
		return nil, nil
	}
	ann := &RetentionPolicy{}
	if err = r.Scan(&ann.UUID, &ann.Name, &ann.Summary, &ann.Expires); err != nil {
		return nil, err
	}

	return ann, nil
}

func (db *DB) AnnotateRetentionPolicy(id uuid.UUID, name string, summary string) error {
	return db.Exec(
		`UPDATE retention SET name = $1, summary = $2 WHERE uuid = $3`,
		name, summary, id.String(),
	)
}

func (db *DB) CreateRetentionPolicy(expiry uint) (uuid.UUID, error) {
	id := uuid.NewRandom()
	return id, db.Exec(
		`INSERT INTO retention (uuid, expiry) VALUES ($1, $2)`,
		id.String(), expiry,
	)
}

func (db *DB) UpdateRetentionPolicy(id uuid.UUID, expiry uint) error {
	return db.Exec(
		`UPDATE retention SET expiry = $1 WHERE uuid = $2`,
		expiry, id.String(),<commit_msg>Make db.Retention UUIDs real UUIDs<commit_after>package db

import (
	"fmt"
	"strings"

	"github.com/pborman/uuid"
)

type RetentionPolicy struct {
	UUID    uuid.UUID `json:"uuid"`
	Name    string    `json:"name"`
	Summary string    `json:"summary"`
	Expires uint      `json:"expires"`
}

type RetentionFilter struct {
	SkipUsed   bool
	SkipUnused bool

	SearchName string
}

func (f *RetentionFilter) Query() (string, []interface{}) {
	var wheres []string = []string{"r.uuid = r.uuid"}
	var args []interface{}
	n := 1

	if f.SearchName != "" {
		wheres = append(wheres, fmt.Sprintf("r.name LIKE $%d", n))
		args = append(args, Pattern(f.SearchName))
		n++
	}
	if !f.SkipUsed && !f.SkipUnused {
		return `
			SELECT r.uuid, r.name, r.summary, r.expiry, -1 AS n
				FROM retention r
				WHERE ` + strings.Join(wheres, " AND ") + `
				ORDER BY r.name, r.uuid ASC
		`, args
	}

	// by default, show retention policies with no attached jobs (unused)
	having := `HAVING COUNT(j.uuid) = 0`
	if f.SkipUnused {
		// otherwise, only show retention policies that have attached jobs
		having = `HAVING COUNT(j.uuid) > 0`
	}

	return `
		SELECT DISTINCT r.uuid, r.name, r.summary, r.expiry, COUNT(j.uuid) AS n
			FROM retention r
				LEFT JOIN jobs j
					ON j.retention_uuid = r.uuid
			WHERE ` + strings.Join(wheres, " AND ") + `
			GROUP BY r.uuid
			` + having + `
			ORDER BY r.name, r.uuid ASC
	`, args
}

func (db *DB) GetAllRetentionPolicies(filter *RetentionFilter) ([]*RetentionPolicy, error) {
	l := []*RetentionPolicy{}
	query, args := filter.Query()
	r, err := db.Query(query, args...)
	if err != nil {
		return l, err
	}
	defer r.Close()

	for r.Next() {
		ann := &RetentionPolicy{}
		var n int
		var thisUUID string

		if err = r.Scan(&thisUUID, &ann.Name, &ann.Summary, &ann.Expires, &n); err != nil {
			return l, err
		}
		ann.UUID = uuid.Parse(thisUUID)

		l = append(l, ann)
	}

	return l, nil
}

func (db *DB) GetRetentionPolicy(id uuid.UUID) (*RetentionPolicy, error) {
	r, err := db.Query(`
		SELECT uuid, name, summary, expiry
			FROM retention WHERE uuid = $1`, id.String())
	if err != nil {
		return nil, err
	}
	defer r.Close()

	if !r.Next() {
		return nil, nil
	}
	ann := &RetentionPolicy{}
	var thisUUID string
	if err = r.Scan(&thisUUID, &ann.Name, &ann.Summary, &ann.Expires); err != nil {
		return nil, err
	}
	ann.UUID = uuid.Parse(thisUUID)

	return ann, nil
}

func (db *DB) AnnotateRetentionPolicy(id uuid.UUID, name string, summary string) error {
	return db.Exec(
		`UPDATE retention SET name = $1, summary = $2 WHERE uuid = $3`,
		name, summary, id.String(),
	)
}

func (db *DB) CreateRetentionPolicy(expiry uint) (uuid.UUID, error) {
	id := uuid.NewRandom()
	return id, db.Exec(
		`INSERT INTO retention (uuid, expiry) VALUES ($1, $2)`,
		id.String(), expiry,
	)
}

func (db *DB) UpdateRetentionPolicy(id uuid.UUID, expiry uint) error {
	return db.Exec(
		`UPDATE retention SET expiry = $1 WHERE uuid = $2`,
		expiry, id.String(),
{'fraction_non_alphanumeric': 0.15198199757659686, 'fraction_numerical': 0.004154405400727021, 'mean_word_length': 3.38391502276176, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3254551', 'n_tokens_mistral': 2330, 'n_tokens_neox': 2154, 'n_words': 633}