decodePhoto checked the GIF logical screen size, but gif.Decode returns
the first frame, which may be smaller; a 400x400 screen with a 1x1 first
frame passed and was scaled. The short-side check now measures the
decoded image's bounds. The pixel cap still comes from the header, before
decoding.
OpenPhoto served any file whose name was a canonical ULID and stored
size, with no photos row required. It now looks the id up with the new
GetPhoto query and reports an id with no row as fs.ErrNotExist, so
GET /media/photos/{id}-{size}.jpg is 404 for it even when a file exists.
OpenPhoto takes the request context for the lookup.
The media test fixture records a photos row for its served photo and
adds an orphan photo whose files exist without a row; both its sizes
must be 404.
Maestro task: 8a432108-d3ba-4013-ae8c-11963981d641
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: photos.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
)
|
|
|
|
const createPhoto = `-- name: CreatePhoto :one
|
|
INSERT INTO photos (
|
|
id, source_url, local_path, width, height, sha256, fetched_at,
|
|
created_at, updated_at
|
|
) VALUES (
|
|
?, ?, ?, ?, ?, ?, ?,
|
|
?, ?
|
|
)
|
|
RETURNING id, source_url, local_path, width, height, sha256, fetched_at, created_at, updated_at
|
|
`
|
|
|
|
type CreatePhotoParams struct {
|
|
ID string
|
|
SourceUrl string
|
|
LocalPath string
|
|
Width int64
|
|
Height int64
|
|
Sha256 string
|
|
FetchedAt string
|
|
CreatedAt string
|
|
UpdatedAt string
|
|
}
|
|
|
|
func (q *Queries) CreatePhoto(ctx context.Context, arg CreatePhotoParams) (Photo, error) {
|
|
row := q.db.QueryRowContext(ctx, createPhoto,
|
|
arg.ID,
|
|
arg.SourceUrl,
|
|
arg.LocalPath,
|
|
arg.Width,
|
|
arg.Height,
|
|
arg.Sha256,
|
|
arg.FetchedAt,
|
|
arg.CreatedAt,
|
|
arg.UpdatedAt,
|
|
)
|
|
var i Photo
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.SourceUrl,
|
|
&i.LocalPath,
|
|
&i.Width,
|
|
&i.Height,
|
|
&i.Sha256,
|
|
&i.FetchedAt,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getPhoto = `-- name: GetPhoto :one
|
|
SELECT id, source_url, local_path, width, height, sha256, fetched_at, created_at, updated_at FROM photos
|
|
WHERE id = ?
|
|
`
|
|
|
|
func (q *Queries) GetPhoto(ctx context.Context, id string) (Photo, error) {
|
|
row := q.db.QueryRowContext(ctx, getPhoto, id)
|
|
var i Photo
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.SourceUrl,
|
|
&i.LocalPath,
|
|
&i.Width,
|
|
&i.Height,
|
|
&i.Sha256,
|
|
&i.FetchedAt,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getPhotoBySHA256 = `-- name: GetPhotoBySHA256 :one
|
|
SELECT id, source_url, local_path, width, height, sha256, fetched_at, created_at, updated_at FROM photos
|
|
WHERE sha256 = ?
|
|
ORDER BY id
|
|
LIMIT 1
|
|
`
|
|
|
|
// Finds stored image bytes by content hash. The schema does not make sha256
|
|
// unique, so the earliest-created (lowest id) match is returned.
|
|
func (q *Queries) GetPhotoBySHA256(ctx context.Context, sha256 string) (Photo, error) {
|
|
row := q.db.QueryRowContext(ctx, getPhotoBySHA256, sha256)
|
|
var i Photo
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.SourceUrl,
|
|
&i.LocalPath,
|
|
&i.Width,
|
|
&i.Height,
|
|
&i.Sha256,
|
|
&i.FetchedAt,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|