AnthoLume/database/query.sql.go
2023-09-18 20:08:42 -04:00

1264 lines
31 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.21.0
// source: query.sql
package database
import (
"context"
"database/sql"
"strings"
"time"
)
const addActivity = `-- name: AddActivity :one
INSERT INTO activity (
user_id,
document_id,
device_id,
start_time,
duration,
current_page,
total_pages
)
VALUES (?, ?, ?, ?, ?, ?, ?)
RETURNING id, user_id, document_id, device_id, start_time, duration, current_page, total_pages, created_at
`
type AddActivityParams struct {
UserID string `json:"user_id"`
DocumentID string `json:"document_id"`
DeviceID string `json:"device_id"`
StartTime time.Time `json:"start_time"`
Duration int64 `json:"duration"`
CurrentPage int64 `json:"current_page"`
TotalPages int64 `json:"total_pages"`
}
func (q *Queries) AddActivity(ctx context.Context, arg AddActivityParams) (Activity, error) {
row := q.db.QueryRowContext(ctx, addActivity,
arg.UserID,
arg.DocumentID,
arg.DeviceID,
arg.StartTime,
arg.Duration,
arg.CurrentPage,
arg.TotalPages,
)
var i Activity
err := row.Scan(
&i.ID,
&i.UserID,
&i.DocumentID,
&i.DeviceID,
&i.StartTime,
&i.Duration,
&i.CurrentPage,
&i.TotalPages,
&i.CreatedAt,
)
return i, err
}
const createUser = `-- name: CreateUser :execrows
INSERT INTO users (id, pass)
VALUES (?, ?)
ON CONFLICT DO NOTHING
`
type CreateUserParams struct {
ID string `json:"id"`
Pass string `json:"-"`
}
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (int64, error) {
result, err := q.db.ExecContext(ctx, createUser, arg.ID, arg.Pass)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
const deleteDocument = `-- name: DeleteDocument :execrows
UPDATE documents
SET
deleted = 1
WHERE id = ?1
`
func (q *Queries) DeleteDocument(ctx context.Context, id string) (int64, error) {
result, err := q.db.ExecContext(ctx, deleteDocument, id)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
const getActivity = `-- name: GetActivity :many
SELECT id, user_id, document_id, device_id, start_time, duration, current_page, total_pages, created_at FROM activity
WHERE
user_id = ?1
AND (
(?2 = TRUE AND document_id = ?3)
OR ?2 = FALSE
)
ORDER BY start_time DESC
LIMIT ?5
OFFSET ?4
`
type GetActivityParams struct {
UserID string `json:"user_id"`
DocFilter interface{} `json:"doc_filter"`
DocumentID string `json:"document_id"`
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
}
func (q *Queries) GetActivity(ctx context.Context, arg GetActivityParams) ([]Activity, error) {
rows, err := q.db.QueryContext(ctx, getActivity,
arg.UserID,
arg.DocFilter,
arg.DocumentID,
arg.Offset,
arg.Limit,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Activity
for rows.Next() {
var i Activity
if err := rows.Scan(
&i.ID,
&i.UserID,
&i.DocumentID,
&i.DeviceID,
&i.StartTime,
&i.Duration,
&i.CurrentPage,
&i.TotalPages,
&i.CreatedAt,
); 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 getDailyReadStats = `-- name: GetDailyReadStats :many
WITH RECURSIVE last_30_days (date) AS (
SELECT date('now') AS date
UNION ALL
SELECT date(date, '-1 days')
FROM last_30_days
LIMIT 30
),
activity_records AS (
SELECT
sum(duration) AS seconds_read,
date(start_time, 'localtime') AS day
FROM activity
WHERE user_id = ?1
GROUP BY day
ORDER BY day DESC
LIMIT 30
)
SELECT
CAST(date AS TEXT),
CAST(CASE
WHEN seconds_read IS NULL THEN 0
ELSE seconds_read / 60
END AS INTEGER) AS minutes_read
FROM last_30_days
LEFT JOIN activity_records ON activity_records.day == last_30_days.date
ORDER BY date DESC
LIMIT 30
`
type GetDailyReadStatsRow struct {
Date string `json:"date"`
MinutesRead int64 `json:"minutes_read"`
}
func (q *Queries) GetDailyReadStats(ctx context.Context, userID string) ([]GetDailyReadStatsRow, error) {
rows, err := q.db.QueryContext(ctx, getDailyReadStats, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetDailyReadStatsRow
for rows.Next() {
var i GetDailyReadStatsRow
if err := rows.Scan(&i.Date, &i.MinutesRead); 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 getDatabaseInfo = `-- name: GetDatabaseInfo :one
SELECT
(SELECT count(rowid) FROM activity WHERE activity.user_id = ?1) AS activity_size,
(SELECT count(rowid) FROM documents) AS documents_size,
(SELECT count(rowid) FROM document_progress WHERE document_progress.user_id = ?1) AS progress_size,
(SELECT count(rowid) FROM devices WHERE devices.user_id = ?1) AS devices_size
LIMIT 1
`
type GetDatabaseInfoRow struct {
ActivitySize int64 `json:"activity_size"`
DocumentsSize int64 `json:"documents_size"`
ProgressSize int64 `json:"progress_size"`
DevicesSize int64 `json:"devices_size"`
}
func (q *Queries) GetDatabaseInfo(ctx context.Context, userID string) (GetDatabaseInfoRow, error) {
row := q.db.QueryRowContext(ctx, getDatabaseInfo, userID)
var i GetDatabaseInfoRow
err := row.Scan(
&i.ActivitySize,
&i.DocumentsSize,
&i.ProgressSize,
&i.DevicesSize,
)
return i, err
}
const getDeletedDocuments = `-- name: GetDeletedDocuments :many
SELECT documents.id
FROM documents
WHERE
documents.deleted = true
AND documents.id IN (/*SLICE:document_ids*/?)
`
func (q *Queries) GetDeletedDocuments(ctx context.Context, documentIds []string) ([]string, error) {
query := getDeletedDocuments
var queryParams []interface{}
if len(documentIds) > 0 {
for _, v := range documentIds {
queryParams = append(queryParams, v)
}
query = strings.Replace(query, "/*SLICE:document_ids*/?", strings.Repeat(",?", len(documentIds))[1:], 1)
} else {
query = strings.Replace(query, "/*SLICE:document_ids*/?", "NULL", 1)
}
rows, err := q.db.QueryContext(ctx, query, queryParams...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []string
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
return nil, err
}
items = append(items, id)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getDevice = `-- name: GetDevice :one
SELECT id, user_id, device_name, created_at, sync FROM devices
WHERE id = ?1 LIMIT 1
`
func (q *Queries) GetDevice(ctx context.Context, deviceID string) (Device, error) {
row := q.db.QueryRowContext(ctx, getDevice, deviceID)
var i Device
err := row.Scan(
&i.ID,
&i.UserID,
&i.DeviceName,
&i.CreatedAt,
&i.Sync,
)
return i, err
}
const getDevices = `-- name: GetDevices :many
SELECT id, user_id, device_name, created_at, sync FROM devices
WHERE user_id = ?1
ORDER BY created_at DESC
LIMIT ?3
OFFSET ?2
`
type GetDevicesParams struct {
UserID string `json:"user_id"`
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
}
func (q *Queries) GetDevices(ctx context.Context, arg GetDevicesParams) ([]Device, error) {
rows, err := q.db.QueryContext(ctx, getDevices, arg.UserID, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Device
for rows.Next() {
var i Device
if err := rows.Scan(
&i.ID,
&i.UserID,
&i.DeviceName,
&i.CreatedAt,
&i.Sync,
); 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 getDocument = `-- name: GetDocument :one
SELECT id, md5, filepath, title, author, series, series_index, lang, description, olid, synced, deleted, updated_at, created_at FROM documents
WHERE id = ?1 LIMIT 1
`
func (q *Queries) GetDocument(ctx context.Context, documentID string) (Document, error) {
row := q.db.QueryRowContext(ctx, getDocument, documentID)
var i Document
err := row.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
)
return i, err
}
const getDocumentDaysRead = `-- name: GetDocumentDaysRead :one
WITH document_days AS (
SELECT date(start_time, 'localtime') AS dates
FROM rescaled_activity
WHERE document_id = ?1
AND user_id = ?2
GROUP BY dates
)
SELECT CAST(count(*) AS INTEGER) AS days_read
FROM document_days
`
type GetDocumentDaysReadParams struct {
DocumentID string `json:"document_id"`
UserID string `json:"user_id"`
}
func (q *Queries) GetDocumentDaysRead(ctx context.Context, arg GetDocumentDaysReadParams) (int64, error) {
row := q.db.QueryRowContext(ctx, getDocumentDaysRead, arg.DocumentID, arg.UserID)
var days_read int64
err := row.Scan(&days_read)
return days_read, err
}
const getDocumentReadStats = `-- name: GetDocumentReadStats :one
SELECT
count(DISTINCT page) AS pages_read,
sum(duration) AS total_time
FROM rescaled_activity
WHERE document_id = ?1
AND user_id = ?2
AND start_time >= ?3
`
type GetDocumentReadStatsParams struct {
DocumentID string `json:"document_id"`
UserID string `json:"user_id"`
StartTime time.Time `json:"start_time"`
}
type GetDocumentReadStatsRow struct {
PagesRead int64 `json:"pages_read"`
TotalTime sql.NullFloat64 `json:"total_time"`
}
func (q *Queries) GetDocumentReadStats(ctx context.Context, arg GetDocumentReadStatsParams) (GetDocumentReadStatsRow, error) {
row := q.db.QueryRowContext(ctx, getDocumentReadStats, arg.DocumentID, arg.UserID, arg.StartTime)
var i GetDocumentReadStatsRow
err := row.Scan(&i.PagesRead, &i.TotalTime)
return i, err
}
const getDocumentReadStatsCapped = `-- name: GetDocumentReadStatsCapped :one
WITH capped_stats AS (
SELECT min(sum(duration), CAST(?1 AS INTEGER)) AS durations
FROM rescaled_activity
WHERE document_id = ?2
AND user_id = ?3
AND start_time >= ?4
GROUP BY page
)
SELECT
CAST(count(*) AS INTEGER) AS pages_read,
CAST(sum(durations) AS INTEGER) AS total_time
FROM capped_stats
`
type GetDocumentReadStatsCappedParams struct {
PageDurationCap int64 `json:"page_duration_cap"`
DocumentID string `json:"document_id"`
UserID string `json:"user_id"`
StartTime time.Time `json:"start_time"`
}
type GetDocumentReadStatsCappedRow struct {
PagesRead int64 `json:"pages_read"`
TotalTime int64 `json:"total_time"`
}
func (q *Queries) GetDocumentReadStatsCapped(ctx context.Context, arg GetDocumentReadStatsCappedParams) (GetDocumentReadStatsCappedRow, error) {
row := q.db.QueryRowContext(ctx, getDocumentReadStatsCapped,
arg.PageDurationCap,
arg.DocumentID,
arg.UserID,
arg.StartTime,
)
var i GetDocumentReadStatsCappedRow
err := row.Scan(&i.PagesRead, &i.TotalTime)
return i, err
}
const getDocuments = `-- name: GetDocuments :many
SELECT id, md5, filepath, title, author, series, series_index, lang, description, olid, synced, deleted, updated_at, created_at FROM documents
ORDER BY created_at DESC
LIMIT ?2
OFFSET ?1
`
type GetDocumentsParams struct {
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
}
func (q *Queries) GetDocuments(ctx context.Context, arg GetDocumentsParams) ([]Document, error) {
rows, err := q.db.QueryContext(ctx, getDocuments, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Document
for rows.Next() {
var i Document
if err := rows.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
); 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 getDocumentsWithStats = `-- name: GetDocumentsWithStats :many
WITH true_progress AS (
SELECT
start_time AS last_read,
SUM(duration) / 60 AS total_time_minutes,
document_id,
current_page,
total_pages,
ROUND(CAST(current_page AS REAL) / CAST(total_pages AS REAL) * 100, 2) AS percentage
FROM activity
WHERE user_id = ?3
GROUP BY document_id
HAVING MAX(start_time)
)
SELECT
documents.id, documents.md5, documents.filepath, documents.title, documents.author, documents.series, documents.series_index, documents.lang, documents.description, documents.olid, documents.synced, documents.deleted, documents.updated_at, documents.created_at,
CAST(IFNULL(current_page, 0) AS INTEGER) AS current_page,
CAST(IFNULL(total_pages, 0) AS INTEGER) AS total_pages,
CAST(IFNULL(total_time_minutes, 0) AS INTEGER) AS total_time_minutes,
CAST(
STRFTIME('%Y-%m-%dT%H:%M:%SZ', IFNULL(last_read, "1970-01-01")
) AS TEXT) AS last_read,
CAST(CASE
WHEN percentage > 97.0 THEN 100.0
WHEN percentage IS NULL THEN 0.0
ELSE percentage
END AS REAL) AS percentage
FROM documents
LEFT JOIN true_progress ON document_id = id
ORDER BY last_read DESC, created_at DESC
LIMIT ?2
OFFSET ?1
`
type GetDocumentsWithStatsParams struct {
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
UserID string `json:"user_id"`
}
type GetDocumentsWithStatsRow struct {
ID string `json:"id"`
Md5 *string `json:"md5"`
Filepath *string `json:"filepath"`
Title *string `json:"title"`
Author *string `json:"author"`
Series *string `json:"series"`
SeriesIndex *int64 `json:"series_index"`
Lang *string `json:"lang"`
Description *string `json:"description"`
Olid *string `json:"-"`
Synced bool `json:"-"`
Deleted bool `json:"-"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
CurrentPage int64 `json:"current_page"`
TotalPages int64 `json:"total_pages"`
TotalTimeMinutes int64 `json:"total_time_minutes"`
LastRead string `json:"last_read"`
Percentage float64 `json:"percentage"`
}
func (q *Queries) GetDocumentsWithStats(ctx context.Context, arg GetDocumentsWithStatsParams) ([]GetDocumentsWithStatsRow, error) {
rows, err := q.db.QueryContext(ctx, getDocumentsWithStats, arg.Offset, arg.Limit, arg.UserID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetDocumentsWithStatsRow
for rows.Next() {
var i GetDocumentsWithStatsRow
if err := rows.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
&i.CurrentPage,
&i.TotalPages,
&i.TotalTimeMinutes,
&i.LastRead,
&i.Percentage,
); 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 getLastActivity = `-- name: GetLastActivity :one
SELECT start_time
FROM activity
WHERE device_id = ?1
AND user_id = ?2
ORDER BY start_time DESC LIMIT 1
`
type GetLastActivityParams struct {
DeviceID string `json:"device_id"`
UserID string `json:"user_id"`
}
func (q *Queries) GetLastActivity(ctx context.Context, arg GetLastActivityParams) (time.Time, error) {
row := q.db.QueryRowContext(ctx, getLastActivity, arg.DeviceID, arg.UserID)
var start_time time.Time
err := row.Scan(&start_time)
return start_time, err
}
const getMissingDocuments = `-- name: GetMissingDocuments :many
SELECT documents.id, documents.md5, documents.filepath, documents.title, documents.author, documents.series, documents.series_index, documents.lang, documents.description, documents.olid, documents.synced, documents.deleted, documents.updated_at, documents.created_at FROM documents
WHERE
documents.filepath IS NOT NULL
AND documents.deleted = false
AND documents.id NOT IN (/*SLICE:document_ids*/?)
`
func (q *Queries) GetMissingDocuments(ctx context.Context, documentIds []string) ([]Document, error) {
query := getMissingDocuments
var queryParams []interface{}
if len(documentIds) > 0 {
for _, v := range documentIds {
queryParams = append(queryParams, v)
}
query = strings.Replace(query, "/*SLICE:document_ids*/?", strings.Repeat(",?", len(documentIds))[1:], 1)
} else {
query = strings.Replace(query, "/*SLICE:document_ids*/?", "NULL", 1)
}
rows, err := q.db.QueryContext(ctx, query, queryParams...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Document
for rows.Next() {
var i Document
if err := rows.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
); 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 getProgress = `-- name: GetProgress :one
SELECT
document_progress.user_id, document_progress.document_id, document_progress.device_id, document_progress.percentage, document_progress.progress, document_progress.created_at,
devices.device_name
FROM document_progress
JOIN devices ON document_progress.device_id = devices.id
WHERE
document_progress.user_id = ?1
AND document_progress.document_id = ?2
ORDER BY
document_progress.created_at
DESC
LIMIT 1
`
type GetProgressParams struct {
UserID string `json:"user_id"`
DocumentID string `json:"document_id"`
}
type GetProgressRow struct {
UserID string `json:"user_id"`
DocumentID string `json:"document_id"`
DeviceID string `json:"device_id"`
Percentage float64 `json:"percentage"`
Progress string `json:"progress"`
CreatedAt time.Time `json:"created_at"`
DeviceName string `json:"device_name"`
}
func (q *Queries) GetProgress(ctx context.Context, arg GetProgressParams) (GetProgressRow, error) {
row := q.db.QueryRowContext(ctx, getProgress, arg.UserID, arg.DocumentID)
var i GetProgressRow
err := row.Scan(
&i.UserID,
&i.DocumentID,
&i.DeviceID,
&i.Percentage,
&i.Progress,
&i.CreatedAt,
&i.DeviceName,
)
return i, err
}
const getUser = `-- name: GetUser :one
SELECT id, pass, admin, created_at FROM users
WHERE id = ?1 LIMIT 1
`
func (q *Queries) GetUser(ctx context.Context, userID string) (User, error) {
row := q.db.QueryRowContext(ctx, getUser, userID)
var i User
err := row.Scan(
&i.ID,
&i.Pass,
&i.Admin,
&i.CreatedAt,
)
return i, err
}
const getUserDayStreaks = `-- name: GetUserDayStreaks :one
WITH document_days AS (
SELECT date(start_time, 'localtime') AS read_day
FROM activity
WHERE user_id = ?1
GROUP BY read_day
ORDER BY read_day DESC
),
partitions AS (
SELECT
document_days.read_day,
row_number() OVER (
PARTITION BY 1 ORDER BY read_day DESC
) AS seqnum
FROM document_days
),
streaks AS (
SELECT
count(*) AS streak,
MIN(read_day) AS start_date,
MAX(read_day) AS end_date
FROM partitions
GROUP BY date(read_day, '+' || seqnum || ' day')
ORDER BY end_date DESC
),
max_streak AS (
SELECT
MAX(streak) AS max_streak,
start_date AS max_streak_start_date,
end_date AS max_streak_end_date
FROM streaks
)
SELECT
CAST(max_streak AS INTEGER),
CAST(max_streak_start_date AS TEXT),
CAST(max_streak_end_date AS TEXT),
streak AS current_streak,
CAST(start_date AS TEXT) AS current_streak_start_date,
CAST(end_date AS TEXT) AS current_streak_end_date
FROM max_streak, streaks LIMIT 1
`
type GetUserDayStreaksRow struct {
MaxStreak int64 `json:"max_streak"`
MaxStreakStartDate string `json:"max_streak_start_date"`
MaxStreakEndDate string `json:"max_streak_end_date"`
CurrentStreak int64 `json:"current_streak"`
CurrentStreakStartDate string `json:"current_streak_start_date"`
CurrentStreakEndDate string `json:"current_streak_end_date"`
}
func (q *Queries) GetUserDayStreaks(ctx context.Context, userID string) (GetUserDayStreaksRow, error) {
row := q.db.QueryRowContext(ctx, getUserDayStreaks, userID)
var i GetUserDayStreaksRow
err := row.Scan(
&i.MaxStreak,
&i.MaxStreakStartDate,
&i.MaxStreakEndDate,
&i.CurrentStreak,
&i.CurrentStreakStartDate,
&i.CurrentStreakEndDate,
)
return i, err
}
const getUserWeekStreaks = `-- name: GetUserWeekStreaks :one
WITH document_weeks AS (
SELECT STRFTIME('%Y-%m-%d', start_time, 'localtime', 'weekday 0', '-7 day') AS read_week
FROM activity
WHERE user_id = ?1
GROUP BY read_week
ORDER BY read_week DESC
),
partitions AS (
SELECT
document_weeks.read_week,
row_number() OVER (
PARTITION BY 1 ORDER BY read_week DESC
) AS seqnum
FROM document_weeks
),
streaks AS (
SELECT
count(*) AS streak,
MIN(read_week) AS start_date,
MAX(read_week) AS end_date
FROM partitions
GROUP BY date(read_week, '+' || (seqnum * 7) || ' day')
ORDER BY end_date DESC
),
max_streak AS (
SELECT
MAX(streak) AS max_streak,
start_date AS max_streak_start_date,
end_date AS max_streak_end_date
FROM streaks
)
SELECT
CAST(max_streak AS INTEGER),
CAST(max_streak_start_date AS TEXT),
CAST(max_streak_end_date AS TEXT),
streak AS current_streak,
CAST(start_date AS TEXT) AS current_streak_start_date,
CAST(end_date AS TEXT) AS current_streak_end_date
FROM max_streak, streaks LIMIT 1
`
type GetUserWeekStreaksRow struct {
MaxStreak int64 `json:"max_streak"`
MaxStreakStartDate string `json:"max_streak_start_date"`
MaxStreakEndDate string `json:"max_streak_end_date"`
CurrentStreak int64 `json:"current_streak"`
CurrentStreakStartDate string `json:"current_streak_start_date"`
CurrentStreakEndDate string `json:"current_streak_end_date"`
}
func (q *Queries) GetUserWeekStreaks(ctx context.Context, userID string) (GetUserWeekStreaksRow, error) {
row := q.db.QueryRowContext(ctx, getUserWeekStreaks, userID)
var i GetUserWeekStreaksRow
err := row.Scan(
&i.MaxStreak,
&i.MaxStreakStartDate,
&i.MaxStreakEndDate,
&i.CurrentStreak,
&i.CurrentStreakStartDate,
&i.CurrentStreakEndDate,
)
return i, err
}
const getUserWindowStreaks = `-- name: GetUserWindowStreaks :one
WITH document_windows AS (
SELECT CASE
WHEN ?2 = "WEEK" THEN STRFTIME('%Y-%m-%d', start_time, 'localtime', 'weekday 0', '-7 day')
WHEN ?2 = "DAY" THEN date(start_time, 'localtime')
END AS read_window
FROM activity
WHERE user_id = ?1
AND CAST(?2 AS TEXT) = CAST(?2 AS TEXT)
GROUP BY read_window
ORDER BY read_window DESC
),
partitions AS (
SELECT
document_windows.read_window,
row_number() OVER (
PARTITION BY 1 ORDER BY read_window DESC
) AS seqnum
FROM document_windows
),
streaks AS (
SELECT
count(*) AS streak,
MIN(read_window) AS start_date,
MAX(read_window) AS end_date
FROM partitions
GROUP BY CASE
WHEN ?2 = "DAY" THEN date(read_window, '+' || seqnum || ' day')
WHEN ?2 = "WEEK" THEN date(read_window, '+' || (seqnum * 7) || ' day')
END
ORDER BY end_date DESC
),
max_streak AS (
SELECT
MAX(streak) AS max_streak,
start_date AS max_streak_start_date,
end_date AS max_streak_end_date
FROM streaks
)
SELECT
CAST(max_streak AS INTEGER),
CAST(max_streak_start_date AS TEXT),
CAST(max_streak_end_date AS TEXT),
streak AS current_streak,
CAST(start_date AS TEXT) AS current_streak_start_date,
CAST(end_date AS TEXT) AS current_streak_end_date
FROM max_streak, streaks LIMIT 1
`
type GetUserWindowStreaksParams struct {
UserID string `json:"user_id"`
Window string `json:"window"`
}
type GetUserWindowStreaksRow struct {
MaxStreak int64 `json:"max_streak"`
MaxStreakStartDate string `json:"max_streak_start_date"`
MaxStreakEndDate string `json:"max_streak_end_date"`
CurrentStreak int64 `json:"current_streak"`
CurrentStreakStartDate string `json:"current_streak_start_date"`
CurrentStreakEndDate string `json:"current_streak_end_date"`
}
func (q *Queries) GetUserWindowStreaks(ctx context.Context, arg GetUserWindowStreaksParams) (GetUserWindowStreaksRow, error) {
row := q.db.QueryRowContext(ctx, getUserWindowStreaks, arg.UserID, arg.Window)
var i GetUserWindowStreaksRow
err := row.Scan(
&i.MaxStreak,
&i.MaxStreakStartDate,
&i.MaxStreakEndDate,
&i.CurrentStreak,
&i.CurrentStreakStartDate,
&i.CurrentStreakEndDate,
)
return i, err
}
const getUsers = `-- name: GetUsers :many
SELECT id, pass, admin, created_at FROM users
WHERE
users.id = ?1
OR ?1 IN (
SELECT id
FROM users
WHERE id = ?1
AND admin = 1
)
ORDER BY created_at DESC
LIMIT ?3
OFFSET ?2
`
type GetUsersParams struct {
User string `json:"user"`
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
}
func (q *Queries) GetUsers(ctx context.Context, arg GetUsersParams) ([]User, error) {
rows, err := q.db.QueryContext(ctx, getUsers, arg.User, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []User
for rows.Next() {
var i User
if err := rows.Scan(
&i.ID,
&i.Pass,
&i.Admin,
&i.CreatedAt,
); 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 getWantedDocuments = `-- name: GetWantedDocuments :many
SELECT CAST(value AS TEXT) AS id
FROM json_each(?1)
LEFT JOIN documents
ON value = documents.id
WHERE (
documents.id IS NOT NULL
AND documents.synced = false
)
OR (documents.id IS NULL)
OR CAST(?1 AS TEXT) != CAST(?1 AS TEXT)
`
func (q *Queries) GetWantedDocuments(ctx context.Context, documentIds string) ([]string, error) {
rows, err := q.db.QueryContext(ctx, getWantedDocuments, documentIds)
if err != nil {
return nil, err
}
defer rows.Close()
var items []string
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
return nil, err
}
items = append(items, id)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateDocumentDeleted = `-- name: UpdateDocumentDeleted :one
UPDATE documents
SET
deleted = ?1
WHERE id = ?2
RETURNING id, md5, filepath, title, author, series, series_index, lang, description, olid, synced, deleted, updated_at, created_at
`
type UpdateDocumentDeletedParams struct {
Deleted bool `json:"-"`
ID string `json:"id"`
}
func (q *Queries) UpdateDocumentDeleted(ctx context.Context, arg UpdateDocumentDeletedParams) (Document, error) {
row := q.db.QueryRowContext(ctx, updateDocumentDeleted, arg.Deleted, arg.ID)
var i Document
err := row.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
)
return i, err
}
const updateDocumentSync = `-- name: UpdateDocumentSync :one
UPDATE documents
SET
synced = ?1
WHERE id = ?2
RETURNING id, md5, filepath, title, author, series, series_index, lang, description, olid, synced, deleted, updated_at, created_at
`
type UpdateDocumentSyncParams struct {
Synced bool `json:"-"`
ID string `json:"id"`
}
func (q *Queries) UpdateDocumentSync(ctx context.Context, arg UpdateDocumentSyncParams) (Document, error) {
row := q.db.QueryRowContext(ctx, updateDocumentSync, arg.Synced, arg.ID)
var i Document
err := row.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
)
return i, err
}
const updateProgress = `-- name: UpdateProgress :one
INSERT OR REPLACE INTO document_progress (
user_id,
document_id,
device_id,
percentage,
progress
)
VALUES (?, ?, ?, ?, ?)
RETURNING user_id, document_id, device_id, percentage, progress, created_at
`
type UpdateProgressParams struct {
UserID string `json:"user_id"`
DocumentID string `json:"document_id"`
DeviceID string `json:"device_id"`
Percentage float64 `json:"percentage"`
Progress string `json:"progress"`
}
func (q *Queries) UpdateProgress(ctx context.Context, arg UpdateProgressParams) (DocumentProgress, error) {
row := q.db.QueryRowContext(ctx, updateProgress,
arg.UserID,
arg.DocumentID,
arg.DeviceID,
arg.Percentage,
arg.Progress,
)
var i DocumentProgress
err := row.Scan(
&i.UserID,
&i.DocumentID,
&i.DeviceID,
&i.Percentage,
&i.Progress,
&i.CreatedAt,
)
return i, err
}
const upsertDevice = `-- name: UpsertDevice :one
INSERT INTO devices (id, user_id, device_name)
VALUES (?, ?, ?)
ON CONFLICT DO UPDATE
SET
device_name = COALESCE(excluded.device_name, device_name)
RETURNING id, user_id, device_name, created_at, sync
`
type UpsertDeviceParams struct {
ID string `json:"id"`
UserID string `json:"user_id"`
DeviceName string `json:"device_name"`
}
func (q *Queries) UpsertDevice(ctx context.Context, arg UpsertDeviceParams) (Device, error) {
row := q.db.QueryRowContext(ctx, upsertDevice, arg.ID, arg.UserID, arg.DeviceName)
var i Device
err := row.Scan(
&i.ID,
&i.UserID,
&i.DeviceName,
&i.CreatedAt,
&i.Sync,
)
return i, err
}
const upsertDocument = `-- name: UpsertDocument :one
INSERT INTO documents (
id,
md5,
filepath,
title,
author,
series,
series_index,
lang,
description,
olid
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT DO UPDATE
SET
md5 = COALESCE(excluded.md5, md5),
filepath = COALESCE(excluded.filepath, filepath),
title = COALESCE(excluded.title, title),
author = COALESCE(excluded.author, author),
series = COALESCE(excluded.series, series),
series_index = COALESCE(excluded.series_index, series_index),
lang = COALESCE(excluded.lang, lang),
description = COALESCE(excluded.description, description),
olid = COALESCE(excluded.olid, olid)
RETURNING id, md5, filepath, title, author, series, series_index, lang, description, olid, synced, deleted, updated_at, created_at
`
type UpsertDocumentParams struct {
ID string `json:"id"`
Md5 *string `json:"md5"`
Filepath *string `json:"filepath"`
Title *string `json:"title"`
Author *string `json:"author"`
Series *string `json:"series"`
SeriesIndex *int64 `json:"series_index"`
Lang *string `json:"lang"`
Description *string `json:"description"`
Olid *string `json:"-"`
}
func (q *Queries) UpsertDocument(ctx context.Context, arg UpsertDocumentParams) (Document, error) {
row := q.db.QueryRowContext(ctx, upsertDocument,
arg.ID,
arg.Md5,
arg.Filepath,
arg.Title,
arg.Author,
arg.Series,
arg.SeriesIndex,
arg.Lang,
arg.Description,
arg.Olid,
)
var i Document
err := row.Scan(
&i.ID,
&i.Md5,
&i.Filepath,
&i.Title,
&i.Author,
&i.Series,
&i.SeriesIndex,
&i.Lang,
&i.Description,
&i.Olid,
&i.Synced,
&i.Deleted,
&i.UpdatedAt,
&i.CreatedAt,
)
return i, err
}