feat!: db schema revisions to support note expiration
This commit is contained in:
parent
7026ee4c76
commit
81c2eecd77
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
|
||||
package data
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
|
||||
package data
|
||||
|
||||
@ -15,6 +15,7 @@ type Note struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
CurrentVersion int32 `json:"current_version"`
|
||||
LatestVersion int32 `json:"latest_version"`
|
||||
ExpiresAt *time.Time `json:"expires_at"`
|
||||
CreatedAt *time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: note_versions.sql
|
||||
|
||||
package data
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: notes.sql
|
||||
|
||||
package data
|
||||
@ -15,7 +15,7 @@ import (
|
||||
const createNote = `-- name: CreateNote :one
|
||||
INSERT INTO notes (user_id)
|
||||
VALUES ($1)
|
||||
RETURNING id, user_id, current_version, latest_version, created_at, updated_at
|
||||
RETURNING id, user_id, current_version, latest_version, expires_at, created_at, updated_at
|
||||
`
|
||||
|
||||
func (q *Queries) CreateNote(ctx context.Context, userID uuid.UUID) (Note, error) {
|
||||
@ -26,12 +26,23 @@ func (q *Queries) CreateNote(ctx context.Context, userID uuid.UUID) (Note, error
|
||||
&i.UserID,
|
||||
&i.CurrentVersion,
|
||||
&i.LatestVersion,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteExpiredNotes = `-- name: DeleteExpiredNotes :exec
|
||||
DELETE FROM notes
|
||||
WHERE expires_at < NOW()
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteExpiredNotes(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, deleteExpiredNotes)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteNote = `-- name: DeleteNote :exec
|
||||
DELETE FROM notes
|
||||
WHERE id = $1 AND user_id = $2
|
||||
@ -55,6 +66,7 @@ SELECT
|
||||
nv.content,
|
||||
nv.version_number,
|
||||
nv.created_at AS version_created_at,
|
||||
n.expires_at AS note_expires_at,
|
||||
n.created_at AS note_created_at,
|
||||
n.updated_at AS note_updated_at
|
||||
FROM notes n
|
||||
@ -70,6 +82,7 @@ type GetFullNoteRow struct {
|
||||
Content string `json:"content"`
|
||||
VersionNumber int32 `json:"version_number"`
|
||||
VersionCreatedAt *time.Time `json:"version_created_at"`
|
||||
NoteExpiresAt *time.Time `json:"note_expires_at"`
|
||||
NoteCreatedAt *time.Time `json:"note_created_at"`
|
||||
NoteUpdatedAt *time.Time `json:"note_updated_at"`
|
||||
}
|
||||
@ -84,17 +97,64 @@ func (q *Queries) GetFullNote(ctx context.Context, id uuid.UUID) (GetFullNoteRow
|
||||
&i.Content,
|
||||
&i.VersionNumber,
|
||||
&i.VersionCreatedAt,
|
||||
&i.NoteExpiresAt,
|
||||
&i.NoteCreatedAt,
|
||||
&i.NoteUpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listExpiredNotes = `-- name: ListExpiredNotes :many
|
||||
SELECT
|
||||
n.id AS note_id,
|
||||
n.user_id AS owner_id,
|
||||
nv.title,
|
||||
n.expires_at
|
||||
FROM notes n
|
||||
JOIN note_versions nv
|
||||
ON n.id = nv.note_id AND n.current_version = nv.version_number
|
||||
WHERE n.expires_at <= NOW()
|
||||
ORDER BY n.expires_at
|
||||
`
|
||||
|
||||
type ListExpiredNotesRow struct {
|
||||
NoteID uuid.UUID `json:"note_id"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
Title string `json:"title"`
|
||||
ExpiresAt *time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListExpiredNotes(ctx context.Context) ([]ListExpiredNotesRow, error) {
|
||||
rows, err := q.db.Query(ctx, listExpiredNotes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListExpiredNotesRow
|
||||
for rows.Next() {
|
||||
var i ListExpiredNotesRow
|
||||
if err := rows.Scan(
|
||||
&i.NoteID,
|
||||
&i.OwnerID,
|
||||
&i.Title,
|
||||
&i.ExpiresAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listNotes = `-- name: ListNotes :many
|
||||
SELECT
|
||||
n.id AS note_id,
|
||||
n.user_id AS owner_id,
|
||||
nv.title,
|
||||
n.expires_at,
|
||||
n.updated_at
|
||||
FROM notes n
|
||||
JOIN note_versions nv
|
||||
@ -114,6 +174,7 @@ type ListNotesRow struct {
|
||||
NoteID uuid.UUID `json:"note_id"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
Title string `json:"title"`
|
||||
ExpiresAt *time.Time `json:"expires_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
@ -130,6 +191,7 @@ func (q *Queries) ListNotes(ctx context.Context, arg ListNotesParams) ([]ListNot
|
||||
&i.NoteID,
|
||||
&i.OwnerID,
|
||||
&i.Title,
|
||||
&i.ExpiresAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@ -141,3 +203,20 @@ func (q *Queries) ListNotes(ctx context.Context, arg ListNotesParams) ([]ListNot
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const setNoteExpiration = `-- name: SetNoteExpiration :exec
|
||||
UPDATE notes
|
||||
SET expires_at = $1, updated_at = NOW()
|
||||
WHERE id = $2 AND user_id = $3
|
||||
`
|
||||
|
||||
type SetNoteExpirationParams struct {
|
||||
ExpiresAt *time.Time `json:"expires_at"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SetNoteExpiration(ctx context.Context, arg SetNoteExpirationParams) error {
|
||||
_, err := q.db.Exec(ctx, setNoteExpiration, arg.ExpiresAt, arg.ID, arg.UserID)
|
||||
return err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: refresh_tokens.sql
|
||||
|
||||
package data
|
||||
@ -41,14 +41,17 @@ func (q *Queries) CreateRefreshToken(ctx context.Context, arg CreateRefreshToken
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteExpiredRefreshTokens = `-- name: DeleteExpiredRefreshTokens :exec
|
||||
const deleteExpiredRefreshTokens = `-- name: DeleteExpiredRefreshTokens :execrows
|
||||
DELETE FROM refresh_tokens
|
||||
WHERE expires_at < NOW()
|
||||
WHERE expires_at < NOW() OR revoked = TRUE
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteExpiredRefreshTokens(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, deleteExpiredRefreshTokens)
|
||||
return err
|
||||
func (q *Queries) DeleteExpiredRefreshTokens(ctx context.Context) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deleteExpiredRefreshTokens)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const getRefreshTokenByHash = `-- name: GetRefreshTokenByHash :one
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: users.sql
|
||||
|
||||
package data
|
||||
|
@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS notes (
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
current_version INT NOT NULL DEFAULT 1, -- active version (can be historical)
|
||||
latest_version INT NOT NULL DEFAULT 1, -- highest version number
|
||||
expires_at TIMESTAMPTZ DEFAULT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
@ -45,5 +46,6 @@ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires_at ON refresh_tokens(expir
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_user_updated ON notes(user_id, updated_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_current_version ON notes(current_version);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_expires_at ON notes(expires_at) WHERE expires_at IS NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_note_versions_content_hash ON note_versions(note_id, content_hash);
|
||||
|
@ -8,6 +8,7 @@ SELECT
|
||||
n.id AS note_id,
|
||||
n.user_id AS owner_id,
|
||||
nv.title,
|
||||
n.expires_at,
|
||||
n.updated_at
|
||||
FROM notes n
|
||||
JOIN note_versions nv
|
||||
@ -24,6 +25,7 @@ SELECT
|
||||
nv.content,
|
||||
nv.version_number,
|
||||
nv.created_at AS version_created_at,
|
||||
n.expires_at AS note_expires_at,
|
||||
n.created_at AS note_created_at,
|
||||
n.updated_at AS note_updated_at
|
||||
FROM notes n
|
||||
@ -34,3 +36,24 @@ WHERE n.id = $1;
|
||||
-- name: DeleteNote :exec
|
||||
DELETE FROM notes
|
||||
WHERE id = $1 AND user_id = $2;
|
||||
|
||||
-- name: SetNoteExpiration :exec
|
||||
UPDATE notes
|
||||
SET expires_at = $1, updated_at = NOW()
|
||||
WHERE id = $2 AND user_id = $3;
|
||||
|
||||
-- name: ListExpiredNotes :many
|
||||
SELECT
|
||||
n.id AS note_id,
|
||||
n.user_id AS owner_id,
|
||||
nv.title,
|
||||
n.expires_at
|
||||
FROM notes n
|
||||
JOIN note_versions nv
|
||||
ON n.id = nv.note_id AND n.current_version = nv.version_number
|
||||
WHERE n.expires_at <= NOW()
|
||||
ORDER BY n.expires_at;
|
||||
|
||||
-- name: DeleteExpiredNotes :exec
|
||||
DELETE FROM notes
|
||||
WHERE expires_at < NOW();
|
||||
|
@ -20,6 +20,6 @@ UPDATE refresh_tokens
|
||||
SET revoked = TRUE
|
||||
WHERE user_id = $1;
|
||||
|
||||
-- name: DeleteExpiredRefreshTokens :exec
|
||||
-- name: DeleteExpiredRefreshTokens :execrows
|
||||
DELETE FROM refresh_tokens
|
||||
WHERE expires_at < NOW();
|
||||
WHERE expires_at < NOW() OR revoked = TRUE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user