Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com>
903 lines
24 KiB
Go
903 lines
24 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: dinners.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
)
|
|
|
|
const archiveDinner = `-- name: ArchiveDinner :one
|
|
UPDATE dinners
|
|
SET status = 'archived',
|
|
updated_by = ?,
|
|
updated_at = ?
|
|
WHERE id = ?
|
|
RETURNING id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision
|
|
`
|
|
|
|
type ArchiveDinnerParams struct {
|
|
UpdatedBy sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
}
|
|
|
|
// An unknown id returns sql.ErrNoRows.
|
|
func (q *Queries) ArchiveDinner(ctx context.Context, arg ArchiveDinnerParams) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, archiveDinner, arg.UpdatedBy, arg.UpdatedAt, arg.ID)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const countRegularDinners = `-- name: CountRegularDinners :one
|
|
SELECT COUNT(*) FROM dinners
|
|
WHERE status = 'regular'
|
|
`
|
|
|
|
// How many Regulars the household has; archived dinners are not counted.
|
|
func (q *Queries) CountRegularDinners(ctx context.Context) (int64, error) {
|
|
row := q.db.QueryRowContext(ctx, countRegularDinners)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const createDinner = `-- name: CreateDinner :one
|
|
INSERT INTO dinners (
|
|
id, name, normalized_name, status, origin, method, minutes_total,
|
|
difficulty, cuisine, is_favorite, recipe_id, recipe_url, photo_id,
|
|
grounding_status, updated_by, created_at, updated_at
|
|
) VALUES (
|
|
?, ?, ?, ?, ?, ?, ?,
|
|
?, ?, ?, ?, ?, ?,
|
|
?, ?, ?, ?
|
|
)
|
|
RETURNING id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision
|
|
`
|
|
|
|
type CreateDinnerParams struct {
|
|
ID string
|
|
Name string
|
|
NormalizedName string
|
|
Status string
|
|
Origin string
|
|
Method sql.NullString
|
|
MinutesTotal sql.NullInt64
|
|
Difficulty sql.NullString
|
|
Cuisine sql.NullString
|
|
IsFavorite int64
|
|
RecipeID sql.NullString
|
|
RecipeUrl sql.NullString
|
|
PhotoID sql.NullString
|
|
GroundingStatus string
|
|
UpdatedBy sql.NullString
|
|
CreatedAt string
|
|
UpdatedAt string
|
|
}
|
|
|
|
func (q *Queries) CreateDinner(ctx context.Context, arg CreateDinnerParams) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, createDinner,
|
|
arg.ID,
|
|
arg.Name,
|
|
arg.NormalizedName,
|
|
arg.Status,
|
|
arg.Origin,
|
|
arg.Method,
|
|
arg.MinutesTotal,
|
|
arg.Difficulty,
|
|
arg.Cuisine,
|
|
arg.IsFavorite,
|
|
arg.RecipeID,
|
|
arg.RecipeUrl,
|
|
arg.PhotoID,
|
|
arg.GroundingStatus,
|
|
arg.UpdatedBy,
|
|
arg.CreatedAt,
|
|
arg.UpdatedAt,
|
|
)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const failOrphanedPendingDinnerGroundings = `-- name: FailOrphanedPendingDinnerGroundings :execrows
|
|
UPDATE dinners
|
|
SET grounding_status = 'failed',
|
|
grounding_error = ?1,
|
|
updated_at = ?2
|
|
WHERE grounding_status = 'pending'
|
|
AND status <> 'archived'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM jobs
|
|
WHERE jobs.kind = ?3
|
|
AND jobs.status IN ('queued', 'running')
|
|
AND json_extract(jobs.payload, '$.dinner_id') = dinners.id
|
|
AND json_extract(jobs.payload, '$.revision') = dinners.grounding_revision
|
|
)
|
|
`
|
|
|
|
type FailOrphanedPendingDinnerGroundingsParams struct {
|
|
GroundingError sql.NullString
|
|
UpdatedAt string
|
|
Kind string
|
|
}
|
|
|
|
// Fails every unarchived dinner still pending whose grounding job for its
|
|
// current grounding_revision is no longer queued or running: the process
|
|
// stopped before the job, or before its handler recorded a result. An
|
|
// archived dinner is left as it is; archiving stopped its grounding. Run at
|
|
// boot, after the job runner fails the jobs a previous process left running.
|
|
func (q *Queries) FailOrphanedPendingDinnerGroundings(ctx context.Context, arg FailOrphanedPendingDinnerGroundingsParams) (int64, error) {
|
|
result, err := q.db.ExecContext(ctx, failOrphanedPendingDinnerGroundings, arg.GroundingError, arg.UpdatedAt, arg.Kind)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected()
|
|
}
|
|
|
|
const failPendingDinnerGrounding = `-- name: FailPendingDinnerGrounding :execrows
|
|
UPDATE dinners
|
|
SET grounding_status = 'failed',
|
|
grounding_error = ?,
|
|
updated_at = ?
|
|
WHERE id = ?
|
|
AND status <> 'archived'
|
|
AND grounding_status = 'pending'
|
|
AND grounding_revision = ?
|
|
`
|
|
|
|
type FailPendingDinnerGroundingParams struct {
|
|
GroundingError sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
GroundingRevision int64
|
|
}
|
|
|
|
// Records why the background grounding of an unarchived dinner still
|
|
// pending at the grounding_revision it was grounded for failed; a dinner
|
|
// grounded some other way, renamed or archived meanwhile is left as it is
|
|
// (0 rows).
|
|
func (q *Queries) FailPendingDinnerGrounding(ctx context.Context, arg FailPendingDinnerGroundingParams) (int64, error) {
|
|
result, err := q.db.ExecContext(ctx, failPendingDinnerGrounding,
|
|
arg.GroundingError,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
arg.GroundingRevision,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected()
|
|
}
|
|
|
|
const getActivePhotoBackfillJob = `-- name: GetActivePhotoBackfillJob :one
|
|
SELECT id
|
|
FROM jobs
|
|
WHERE kind = ?1
|
|
AND status IN ('queued', 'running')
|
|
AND json_extract(payload, '$.dinner_id') IS NULL
|
|
ORDER BY id
|
|
LIMIT 1
|
|
`
|
|
|
|
// The id of the full photo backfill job (no dinner_id) of kind queued or
|
|
// running. StartPhotoBackfill enqueues one only when there is none, so
|
|
// there is at most one. Returns sql.ErrNoRows when there is none.
|
|
func (q *Queries) GetActivePhotoBackfillJob(ctx context.Context, kind string) (string, error) {
|
|
row := q.db.QueryRowContext(ctx, getActivePhotoBackfillJob, kind)
|
|
var id string
|
|
err := row.Scan(&id)
|
|
return id, err
|
|
}
|
|
|
|
const getDinner = `-- name: GetDinner :one
|
|
SELECT id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision FROM dinners
|
|
WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) GetDinner(ctx context.Context, id string) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, getDinner, id)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const groundDinner = `-- name: GroundDinner :one
|
|
UPDATE dinners
|
|
SET recipe_id = ?1,
|
|
recipe_url = NULL,
|
|
photo_id = ?2,
|
|
method = CASE WHEN method IS ?3
|
|
THEN ?4 ELSE method END,
|
|
minutes_total = CASE WHEN minutes_total IS ?5
|
|
THEN ?6 ELSE minutes_total END,
|
|
difficulty = CASE WHEN difficulty IS ?7
|
|
THEN ?8 ELSE difficulty END,
|
|
grounding_status = ?9,
|
|
grounding_error = NULL,
|
|
updated_by = ?10,
|
|
updated_at = ?11
|
|
WHERE id = ?12
|
|
AND status <> 'archived'
|
|
AND name = ?13
|
|
AND normalized_name = ?14
|
|
AND grounding_status = ?15
|
|
AND grounding_revision = ?16
|
|
AND recipe_id IS ?17
|
|
RETURNING id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision
|
|
`
|
|
|
|
type GroundDinnerParams struct {
|
|
RecipeID sql.NullString
|
|
PhotoID sql.NullString
|
|
ObservedMethod sql.NullString
|
|
Method sql.NullString
|
|
ObservedMinutesTotal sql.NullInt64
|
|
MinutesTotal sql.NullInt64
|
|
ObservedDifficulty sql.NullString
|
|
Difficulty sql.NullString
|
|
GroundingStatus string
|
|
UpdatedBy sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
ObservedName string
|
|
ObservedNormalizedName string
|
|
ObservedGroundingStatus string
|
|
ObservedGroundingRevision int64
|
|
ObservedRecipeID sql.NullString
|
|
}
|
|
|
|
// Records a dinner's grounding by hand (grounded or manual) and clears any
|
|
// grounding_error and pasted recipe_url: the recipe chosen replaces the
|
|
// link. It writes only an unarchived dinner still as it was observed
|
|
// before grounding (same name, normalized_name, grounding_status,
|
|
// grounding_revision and recipe_id), so a dinner renamed, archived or
|
|
// grounded some other way meanwhile is left as it is. That dinner, or an
|
|
// unknown id, returns sql.ErrNoRows. A method, minutes_total or difficulty
|
|
// no longer as observed is kept: a member edited it while it was grounding.
|
|
func (q *Queries) GroundDinner(ctx context.Context, arg GroundDinnerParams) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, groundDinner,
|
|
arg.RecipeID,
|
|
arg.PhotoID,
|
|
arg.ObservedMethod,
|
|
arg.Method,
|
|
arg.ObservedMinutesTotal,
|
|
arg.MinutesTotal,
|
|
arg.ObservedDifficulty,
|
|
arg.Difficulty,
|
|
arg.GroundingStatus,
|
|
arg.UpdatedBy,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
arg.ObservedName,
|
|
arg.ObservedNormalizedName,
|
|
arg.ObservedGroundingStatus,
|
|
arg.ObservedGroundingRevision,
|
|
arg.ObservedRecipeID,
|
|
)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const groundFailedDinner = `-- name: GroundFailedDinner :execrows
|
|
UPDATE dinners
|
|
SET recipe_id = ?1,
|
|
photo_id = ?2,
|
|
method = COALESCE(method, ?3),
|
|
minutes_total = COALESCE(minutes_total, ?4),
|
|
difficulty = COALESCE(difficulty, ?5),
|
|
grounding_status = 'grounded',
|
|
grounding_error = NULL,
|
|
updated_at = ?6
|
|
WHERE id = ?7
|
|
AND status <> 'archived'
|
|
AND grounding_status = 'failed'
|
|
AND photo_id IS NULL
|
|
AND recipe_url IS NULL
|
|
AND grounding_revision = ?8
|
|
`
|
|
|
|
type GroundFailedDinnerParams struct {
|
|
RecipeID sql.NullString
|
|
PhotoID sql.NullString
|
|
Method sql.NullString
|
|
MinutesTotal sql.NullInt64
|
|
Difficulty sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
GroundingRevision int64
|
|
}
|
|
|
|
// Records a photo backfill's grounding of a dinner it listed, while the
|
|
// dinner is still unarchived, failed, photoless, without a recipe_url and at
|
|
// the grounding_revision it was listed at; a dinner grounded by hand,
|
|
// renamed or archived meanwhile is left as it is (0 rows). Like
|
|
// GroundPendingDinner it keeps a method, minutes_total or difficulty a
|
|
// member already set.
|
|
func (q *Queries) GroundFailedDinner(ctx context.Context, arg GroundFailedDinnerParams) (int64, error) {
|
|
result, err := q.db.ExecContext(ctx, groundFailedDinner,
|
|
arg.RecipeID,
|
|
arg.PhotoID,
|
|
arg.Method,
|
|
arg.MinutesTotal,
|
|
arg.Difficulty,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
arg.GroundingRevision,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected()
|
|
}
|
|
|
|
const groundPendingDinner = `-- name: GroundPendingDinner :execrows
|
|
UPDATE dinners
|
|
SET recipe_id = ?1,
|
|
recipe_url = NULL,
|
|
photo_id = ?2,
|
|
method = COALESCE(method, ?3),
|
|
minutes_total = COALESCE(minutes_total, ?4),
|
|
difficulty = COALESCE(difficulty, ?5),
|
|
grounding_status = 'grounded',
|
|
grounding_error = NULL,
|
|
updated_at = ?6
|
|
WHERE id = ?7
|
|
AND status <> 'archived'
|
|
AND grounding_status = 'pending'
|
|
AND grounding_revision = ?8
|
|
`
|
|
|
|
type GroundPendingDinnerParams struct {
|
|
RecipeID sql.NullString
|
|
PhotoID sql.NullString
|
|
Method sql.NullString
|
|
MinutesTotal sql.NullInt64
|
|
Difficulty sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
GroundingRevision int64
|
|
}
|
|
|
|
// Records the background grounding of an unarchived dinner still pending at
|
|
// the grounding_revision it was grounded for; a dinner grounded some other
|
|
// way, renamed or archived meanwhile is left as it is (0 rows). A method,
|
|
// minutes_total or difficulty already set is kept: a pending dinner has
|
|
// them only when a member edited them while it was grounding. Like
|
|
// GroundDinner it clears the pasted recipe_url: the recipe replaces the link.
|
|
func (q *Queries) GroundPendingDinner(ctx context.Context, arg GroundPendingDinnerParams) (int64, error) {
|
|
result, err := q.db.ExecContext(ctx, groundPendingDinner,
|
|
arg.RecipeID,
|
|
arg.PhotoID,
|
|
arg.Method,
|
|
arg.MinutesTotal,
|
|
arg.Difficulty,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
arg.GroundingRevision,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected()
|
|
}
|
|
|
|
const listDinnersByStatus = `-- name: ListDinnersByStatus :many
|
|
SELECT id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision FROM dinners
|
|
WHERE status = ?
|
|
ORDER BY normalized_name, id
|
|
`
|
|
|
|
func (q *Queries) ListDinnersByStatus(ctx context.Context, status string) ([]Dinner, error) {
|
|
rows, err := q.db.QueryContext(ctx, listDinnersByStatus, status)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Dinner
|
|
for rows.Next() {
|
|
var i Dinner
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPhotoBackfillDinners = `-- name: ListPhotoBackfillDinners :many
|
|
SELECT id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision FROM dinners
|
|
WHERE status <> 'archived'
|
|
AND grounding_status = 'failed'
|
|
AND photo_id IS NULL
|
|
AND recipe_url IS NULL
|
|
AND id = COALESCE(?1, id)
|
|
ORDER BY normalized_name, id
|
|
`
|
|
|
|
// The dinners a photo backfill grounds by name: unarchived, failed, with no
|
|
// photo and no pasted recipe_url (the household's own link is never
|
|
// replaced by a search), ordered by normalized name. A non-NULL id narrows
|
|
// the list to that dinner. Grounded, manual and pending dinners are never
|
|
// listed: they have a recipe, or a ground_dinner job grounding them.
|
|
func (q *Queries) ListPhotoBackfillDinners(ctx context.Context, id sql.NullString) ([]Dinner, error) {
|
|
rows, err := q.db.QueryContext(ctx, listPhotoBackfillDinners, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Dinner
|
|
for rows.Next() {
|
|
var i Dinner
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listUnarchivedDinners = `-- name: ListUnarchivedDinners :many
|
|
SELECT dinners.id, dinners.name, dinners.normalized_name, dinners.status, dinners.origin, dinners.method, dinners.minutes_total, dinners.difficulty, dinners.cuisine, dinners.is_favorite, dinners.recipe_id, dinners.photo_id, dinners.grounding_status, dinners.updated_by, dinners.created_at, dinners.updated_at, dinners.recipe_url, dinners.grounding_error, dinners.grounding_revision, recipes.source_url AS recipe_source_url
|
|
FROM dinners
|
|
LEFT JOIN recipes ON recipes.id = dinners.recipe_id
|
|
WHERE dinners.status <> 'archived'
|
|
ORDER BY dinners.id
|
|
`
|
|
|
|
type ListUnarchivedDinnersRow struct {
|
|
Dinner Dinner
|
|
RecipeSourceUrl sql.NullString
|
|
}
|
|
|
|
// Every dinner a new or renamed dinner must not repeat, with the
|
|
// source_url of the recipe it is grounded in (NULL while it has none).
|
|
func (q *Queries) ListUnarchivedDinners(ctx context.Context) ([]ListUnarchivedDinnersRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, listUnarchivedDinners)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []ListUnarchivedDinnersRow
|
|
for rows.Next() {
|
|
var i ListUnarchivedDinnersRow
|
|
if err := rows.Scan(
|
|
&i.Dinner.ID,
|
|
&i.Dinner.Name,
|
|
&i.Dinner.NormalizedName,
|
|
&i.Dinner.Status,
|
|
&i.Dinner.Origin,
|
|
&i.Dinner.Method,
|
|
&i.Dinner.MinutesTotal,
|
|
&i.Dinner.Difficulty,
|
|
&i.Dinner.Cuisine,
|
|
&i.Dinner.IsFavorite,
|
|
&i.Dinner.RecipeID,
|
|
&i.Dinner.PhotoID,
|
|
&i.Dinner.GroundingStatus,
|
|
&i.Dinner.UpdatedBy,
|
|
&i.Dinner.CreatedAt,
|
|
&i.Dinner.UpdatedAt,
|
|
&i.Dinner.RecipeUrl,
|
|
&i.Dinner.GroundingError,
|
|
&i.Dinner.GroundingRevision,
|
|
&i.RecipeSourceUrl,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listUnplannedQuestLogDinners = `-- name: ListUnplannedQuestLogDinners :many
|
|
SELECT id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision FROM dinners
|
|
WHERE status = 'quest_log'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM plan_days
|
|
JOIN week_plans ON week_plans.id = plan_days.plan_id
|
|
WHERE plan_days.dinner_id = dinners.id
|
|
AND week_plans.week_start >= ?1
|
|
)
|
|
ORDER BY normalized_name, id
|
|
`
|
|
|
|
// The Quest log: dinners with status quest_log that no plan for the week
|
|
// starting from_week_start or later has on any day.
|
|
func (q *Queries) ListUnplannedQuestLogDinners(ctx context.Context, fromWeekStart string) ([]Dinner, error) {
|
|
rows, err := q.db.QueryContext(ctx, listUnplannedQuestLogDinners, fromWeekStart)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Dinner
|
|
for rows.Next() {
|
|
var i Dinner
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const refailDinnerGrounding = `-- name: RefailDinnerGrounding :execrows
|
|
UPDATE dinners
|
|
SET grounding_error = ?1,
|
|
updated_at = ?2
|
|
WHERE id = ?3
|
|
AND status <> 'archived'
|
|
AND grounding_status = 'failed'
|
|
AND photo_id IS NULL
|
|
AND recipe_url IS NULL
|
|
AND grounding_revision = ?4
|
|
`
|
|
|
|
type RefailDinnerGroundingParams struct {
|
|
GroundingError sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
GroundingRevision int64
|
|
}
|
|
|
|
// Records why a photo backfill could not ground a dinner it listed, under
|
|
// the same conditions as GroundFailedDinner (0 rows otherwise).
|
|
func (q *Queries) RefailDinnerGrounding(ctx context.Context, arg RefailDinnerGroundingParams) (int64, error) {
|
|
result, err := q.db.ExecContext(ctx, refailDinnerGrounding,
|
|
arg.GroundingError,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
arg.GroundingRevision,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected()
|
|
}
|
|
|
|
const setDinnerFavorite = `-- name: SetDinnerFavorite :one
|
|
UPDATE dinners
|
|
SET is_favorite = ?,
|
|
updated_by = ?,
|
|
updated_at = ?
|
|
WHERE id = ?
|
|
RETURNING id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision
|
|
`
|
|
|
|
type SetDinnerFavoriteParams struct {
|
|
IsFavorite int64
|
|
UpdatedBy sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
}
|
|
|
|
// An unknown id returns sql.ErrNoRows.
|
|
func (q *Queries) SetDinnerFavorite(ctx context.Context, arg SetDinnerFavoriteParams) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, setDinnerFavorite,
|
|
arg.IsFavorite,
|
|
arg.UpdatedBy,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const toggleDinnerFavorite = `-- name: ToggleDinnerFavorite :one
|
|
UPDATE dinners
|
|
SET is_favorite = 1 - is_favorite,
|
|
updated_by = ?,
|
|
updated_at = ?
|
|
WHERE id = ?
|
|
RETURNING id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision
|
|
`
|
|
|
|
type ToggleDinnerFavoriteParams struct {
|
|
UpdatedBy sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
}
|
|
|
|
// An unknown id returns sql.ErrNoRows.
|
|
func (q *Queries) ToggleDinnerFavorite(ctx context.Context, arg ToggleDinnerFavoriteParams) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, toggleDinnerFavorite, arg.UpdatedBy, arg.UpdatedAt, arg.ID)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const updateDinner = `-- name: UpdateDinner :one
|
|
UPDATE dinners
|
|
SET name = ?,
|
|
normalized_name = ?,
|
|
status = ?,
|
|
origin = ?,
|
|
method = ?,
|
|
minutes_total = ?,
|
|
difficulty = ?,
|
|
cuisine = ?,
|
|
recipe_id = ?,
|
|
recipe_url = ?,
|
|
photo_id = ?,
|
|
grounding_status = ?,
|
|
grounding_revision = ?,
|
|
updated_by = ?,
|
|
updated_at = ?
|
|
WHERE id = ?
|
|
RETURNING id, name, normalized_name, status, origin, method, minutes_total, difficulty, cuisine, is_favorite, recipe_id, photo_id, grounding_status, updated_by, created_at, updated_at, recipe_url, grounding_error, grounding_revision
|
|
`
|
|
|
|
type UpdateDinnerParams struct {
|
|
Name string
|
|
NormalizedName string
|
|
Status string
|
|
Origin string
|
|
Method sql.NullString
|
|
MinutesTotal sql.NullInt64
|
|
Difficulty sql.NullString
|
|
Cuisine sql.NullString
|
|
RecipeID sql.NullString
|
|
RecipeUrl sql.NullString
|
|
PhotoID sql.NullString
|
|
GroundingStatus string
|
|
GroundingRevision int64
|
|
UpdatedBy sql.NullString
|
|
UpdatedAt string
|
|
ID string
|
|
}
|
|
|
|
// An unknown id returns sql.ErrNoRows.
|
|
func (q *Queries) UpdateDinner(ctx context.Context, arg UpdateDinnerParams) (Dinner, error) {
|
|
row := q.db.QueryRowContext(ctx, updateDinner,
|
|
arg.Name,
|
|
arg.NormalizedName,
|
|
arg.Status,
|
|
arg.Origin,
|
|
arg.Method,
|
|
arg.MinutesTotal,
|
|
arg.Difficulty,
|
|
arg.Cuisine,
|
|
arg.RecipeID,
|
|
arg.RecipeUrl,
|
|
arg.PhotoID,
|
|
arg.GroundingStatus,
|
|
arg.GroundingRevision,
|
|
arg.UpdatedBy,
|
|
arg.UpdatedAt,
|
|
arg.ID,
|
|
)
|
|
var i Dinner
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Name,
|
|
&i.NormalizedName,
|
|
&i.Status,
|
|
&i.Origin,
|
|
&i.Method,
|
|
&i.MinutesTotal,
|
|
&i.Difficulty,
|
|
&i.Cuisine,
|
|
&i.IsFavorite,
|
|
&i.RecipeID,
|
|
&i.PhotoID,
|
|
&i.GroundingStatus,
|
|
&i.UpdatedBy,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.RecipeUrl,
|
|
&i.GroundingError,
|
|
&i.GroundingRevision,
|
|
)
|
|
return i, err
|
|
}
|