V3 version with backward comp
This commit is contained in:
@@ -39,7 +39,7 @@ func (q *Queries) CreateRefreshToken(ctx context.Context, arg CreateRefreshToken
|
||||
const createUser = `-- name: CreateUser :one
|
||||
INSERT INTO users (username, password_hash)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, username, password_hash, created_at, updated_at
|
||||
RETURNING id, username, password_hash, created_at, updated_at, parent_user_id
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
@@ -56,6 +56,7 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e
|
||||
&i.PasswordHash,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentUserID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -80,7 +81,7 @@ func (q *Queries) GetRefreshToken(ctx context.Context, tokenHash string) (Refres
|
||||
}
|
||||
|
||||
const getUserByID = `-- name: GetUserByID :one
|
||||
SELECT id, username, password_hash, created_at, updated_at FROM users WHERE id = $1
|
||||
SELECT id, username, password_hash, created_at, updated_at, parent_user_id FROM users WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserByID(ctx context.Context, id string) (User, error) {
|
||||
@@ -92,12 +93,13 @@ func (q *Queries) GetUserByID(ctx context.Context, id string) (User, error) {
|
||||
&i.PasswordHash,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentUserID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserByUsername = `-- name: GetUserByUsername :one
|
||||
SELECT id, username, password_hash, created_at, updated_at FROM users WHERE username = $1
|
||||
SELECT id, username, password_hash, created_at, updated_at, parent_user_id FROM users WHERE username = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User, error) {
|
||||
@@ -109,6 +111,7 @@ func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User,
|
||||
&i.PasswordHash,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentUserID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: files.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
const createFile = `-- name: CreateFile :one
|
||||
INSERT INTO files (name, mime_type, size, storage_key, checksum, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder
|
||||
`
|
||||
|
||||
type CreateFileParams struct {
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Size int64 `json:"size"`
|
||||
StorageKey string `json:"storage_key"`
|
||||
Checksum string `json:"checksum"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateFile(ctx context.Context, arg CreateFileParams) (File, error) {
|
||||
row := q.db.QueryRowContext(ctx, createFile,
|
||||
arg.Name,
|
||||
arg.MimeType,
|
||||
arg.Size,
|
||||
arg.StorageKey,
|
||||
arg.Checksum,
|
||||
)
|
||||
var i File
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createFolder = `-- name: CreateFolder :one
|
||||
INSERT INTO files (name, is_folder, created_at, updated_at)
|
||||
VALUES ($1, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder
|
||||
`
|
||||
|
||||
func (q *Queries) CreateFolder(ctx context.Context, name string) (File, error) {
|
||||
row := q.db.QueryRowContext(ctx, createFolder, name)
|
||||
var i File
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteFile = `-- name: DeleteFile :exec
|
||||
DELETE FROM files
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteFile(ctx context.Context, id string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteFile, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const findDuplicateByChecksum = `-- name: FindDuplicateByChecksum :one
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE checksum = $1 AND is_folder = false
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) FindDuplicateByChecksum(ctx context.Context, checksum string) (File, error) {
|
||||
row := q.db.QueryRowContext(ctx, findDuplicateByChecksum, checksum)
|
||||
var i File
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const findDuplicatesByNameSize = `-- name: FindDuplicatesByNameSize :many
|
||||
SELECT id, name, mime_type, size, checksum, created_at FROM files
|
||||
WHERE name = $1 AND size = $2 AND is_folder = false
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
type FindDuplicatesByNameSizeParams struct {
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type FindDuplicatesByNameSizeRow struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Size int64 `json:"size"`
|
||||
Checksum string `json:"checksum"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) FindDuplicatesByNameSize(ctx context.Context, arg FindDuplicatesByNameSizeParams) ([]FindDuplicatesByNameSizeRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, findDuplicatesByNameSize, arg.Name, arg.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []FindDuplicatesByNameSizeRow
|
||||
for rows.Next() {
|
||||
var i FindDuplicatesByNameSizeRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&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 getFile = `-- name: GetFile :one
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE id = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetFile(ctx context.Context, id string) (File, error) {
|
||||
row := q.db.QueryRowContext(ctx, getFile, id)
|
||||
var i File
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listFiles = `-- name: ListFiles :many
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE parent_file_id IS NULL
|
||||
ORDER BY is_folder DESC, created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListFiles(ctx context.Context) ([]File, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listFiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []File
|
||||
for rows.Next() {
|
||||
var i File
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
); 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 listFilesByID = `-- name: ListFilesByID :many
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE id = ANY($1::text[])
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListFilesByID(ctx context.Context, dollar_1 []string) ([]File, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listFilesByID, pq.Array(dollar_1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []File
|
||||
for rows.Next() {
|
||||
var i File
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
); 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 listFilesByParentID = `-- name: ListFilesByParentID :many
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE parent_file_id = $1
|
||||
ORDER BY is_folder DESC, created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListFilesByParentID(ctx context.Context, parentFileID sql.NullString) ([]File, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listFilesByParentID, parentFileID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []File
|
||||
for rows.Next() {
|
||||
var i File
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
); 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 listFolders = `-- name: ListFolders :many
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE is_folder = true
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListFolders(ctx context.Context) ([]File, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listFolders)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []File
|
||||
for rows.Next() {
|
||||
var i File
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
); 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 moveFiles = `-- name: MoveFiles :exec
|
||||
UPDATE files
|
||||
SET parent_file_id = $1, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ANY($2::text[])
|
||||
`
|
||||
|
||||
type MoveFilesParams struct {
|
||||
ParentFileID sql.NullString `json:"parent_file_id"`
|
||||
Column2 []string `json:"column_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) MoveFiles(ctx context.Context, arg MoveFilesParams) error {
|
||||
_, err := q.db.ExecContext(ctx, moveFiles, arg.ParentFileID, pq.Array(arg.Column2))
|
||||
return err
|
||||
}
|
||||
|
||||
const updateFile = `-- name: UpdateFile :exec
|
||||
UPDATE files
|
||||
SET name = $1, mime_type = $2, ocr_text = $3, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $4
|
||||
`
|
||||
|
||||
type UpdateFileParams struct {
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
OcrText string `json:"ocr_text"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateFile(ctx context.Context, arg UpdateFileParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateFile,
|
||||
arg.Name,
|
||||
arg.MimeType,
|
||||
arg.OcrText,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
-- VaultDrop 012 down: drop V3 new tables
|
||||
DROP FUNCTION IF EXISTS resolve_effective_role;
|
||||
DROP TABLE IF EXISTS rebac_relations;
|
||||
DROP TABLE IF EXISTS sync_queue;
|
||||
DROP TABLE IF EXISTS retention_policies;
|
||||
DROP TABLE IF EXISTS resource_placements;
|
||||
DROP TABLE IF EXISTS storage_locations;
|
||||
DROP TABLE IF EXISTS resource_variants;
|
||||
DROP TABLE IF EXISTS resources;
|
||||
ALTER TABLE users DROP COLUMN IF EXISTS parent_user_id;
|
||||
@@ -0,0 +1,145 @@
|
||||
-- VaultDrop 012: V3 new tables - resources, storage_locations, resource_placements, etc.
|
||||
|
||||
-- Add parent_user_id to users for groups/organizations
|
||||
ALTER TABLE users ADD COLUMN parent_user_id UUID REFERENCES users(id);
|
||||
|
||||
-- Resources (replaces files)
|
||||
CREATE TABLE resources (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL DEFAULT '',
|
||||
size BIGINT NOT NULL DEFAULT 0,
|
||||
checksum TEXT NOT NULL DEFAULT '',
|
||||
ocr_text TEXT NOT NULL DEFAULT '',
|
||||
is_folder BOOLEAN NOT NULL DEFAULT false,
|
||||
parent_resource_id UUID REFERENCES resources(id),
|
||||
owner_id UUID NOT NULL REFERENCES users(id),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_resources_owner ON resources(owner_id);
|
||||
CREATE INDEX idx_resources_parent ON resources(parent_resource_id);
|
||||
CREATE INDEX idx_resources_checksum_owner ON resources(checksum, owner_id);
|
||||
|
||||
-- Resource variants (replaces thumbnails)
|
||||
CREATE TABLE resource_variants (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
resource_id UUID NOT NULL REFERENCES resources(id) ON DELETE CASCADE,
|
||||
variant_type TEXT NOT NULL,
|
||||
page_number INTEGER NOT NULL DEFAULT 1,
|
||||
width INTEGER NOT NULL DEFAULT 0,
|
||||
height INTEGER NOT NULL DEFAULT 0,
|
||||
mime_type TEXT NOT NULL DEFAULT 'image/jpeg',
|
||||
generated_by TEXT NOT NULL DEFAULT 'server' CHECK (generated_by IN ('server', 'client')),
|
||||
storage_key TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_variants_resource ON resource_variants(resource_id);
|
||||
CREATE UNIQUE INDEX idx_variants_resource_type_page ON resource_variants(resource_id, variant_type, page_number);
|
||||
|
||||
-- Storage locations (devices, server, backup)
|
||||
CREATE TABLE storage_locations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
device_name TEXT NOT NULL,
|
||||
role TEXT NOT NULL CHECK (role IN ('primary', 'device', 'backup', 'server')),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
last_seen_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_locations_user ON storage_locations(user_id);
|
||||
|
||||
-- Resource placements (pivot resource × storage_location)
|
||||
CREATE TABLE resource_placements (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
resource_id UUID NOT NULL REFERENCES resources(id) ON DELETE CASCADE,
|
||||
storage_location_id UUID NOT NULL REFERENCES storage_locations(id),
|
||||
status TEXT NOT NULL DEFAULT 'synced' CHECK (status IN ('local_only', 'synced', 'cloud_only', 'pending_upload', 'pending_download')),
|
||||
storage_key TEXT,
|
||||
synced_at TIMESTAMP,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(resource_id, storage_location_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_placements_resource ON resource_placements(resource_id);
|
||||
CREATE INDEX idx_placements_location ON resource_placements(storage_location_id);
|
||||
CREATE INDEX idx_placements_status ON resource_placements(status);
|
||||
|
||||
-- Retention policies
|
||||
CREATE TABLE retention_policies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
storage_location_id UUID NOT NULL REFERENCES storage_locations(id),
|
||||
rule_type TEXT NOT NULL,
|
||||
rule_value JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_policies_user ON retention_policies(user_id);
|
||||
CREATE INDEX idx_policies_location ON retention_policies(storage_location_id);
|
||||
|
||||
-- Sync queue
|
||||
CREATE TABLE sync_queue (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
resource_id UUID NOT NULL REFERENCES resources(id) ON DELETE CASCADE,
|
||||
storage_location_id UUID NOT NULL REFERENCES storage_locations(id),
|
||||
operation TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_queue_status ON sync_queue(status);
|
||||
CREATE INDEX idx_queue_resource ON sync_queue(resource_id);
|
||||
CREATE INDEX idx_queue_location ON sync_queue(storage_location_id);
|
||||
|
||||
-- ReBAC relations
|
||||
CREATE TABLE rebac_relations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
resource_id UUID NOT NULL REFERENCES resources(id) ON DELETE CASCADE,
|
||||
subject_user_id UUID NOT NULL REFERENCES users(id),
|
||||
role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'editor', 'viewer')),
|
||||
granted_by UUID NOT NULL REFERENCES users(id),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(resource_id, subject_user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_rebac_resource ON rebac_relations(resource_id);
|
||||
CREATE INDEX idx_rebac_subject ON rebac_relations(subject_user_id);
|
||||
|
||||
-- Function to resolve effective role with recursive parent/group traversal
|
||||
CREATE OR REPLACE FUNCTION resolve_effective_role(p_user_id UUID, p_resource_id UUID)
|
||||
RETURNS TEXT AS $$
|
||||
DECLARE
|
||||
v_role TEXT;
|
||||
BEGIN
|
||||
WITH RECURSIVE rtree AS (
|
||||
SELECT r.id, r.parent_resource_id, r.owner_id
|
||||
FROM resources r
|
||||
WHERE r.id = p_resource_id
|
||||
UNION ALL
|
||||
SELECT r.id, r.parent_resource_id, r.owner_id
|
||||
FROM resources r
|
||||
JOIN rtree ON r.id = rtree.parent_resource_id
|
||||
)
|
||||
SELECT CASE
|
||||
WHEN EXISTS(SELECT 1 FROM rtree WHERE owner_id = p_user_id) THEN 'owner'
|
||||
ELSE COALESCE(
|
||||
(SELECT rr.role::text FROM rebac_relations rr
|
||||
JOIN rtree ON rr.resource_id = rtree.id
|
||||
WHERE rr.subject_user_id = p_user_id
|
||||
ORDER BY CASE rr.role
|
||||
WHEN 'owner' THEN 0
|
||||
WHEN 'admin' THEN 1
|
||||
WHEN 'editor' THEN 2
|
||||
WHEN 'viewer' THEN 3
|
||||
END ASC LIMIT 1),
|
||||
''
|
||||
)
|
||||
END INTO v_role;
|
||||
RETURN v_role;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- VaultDrop 013 down: revert data migration
|
||||
-- Re-add tag_type to tags
|
||||
ALTER TABLE tags ADD COLUMN IF NOT EXISTS tag_type TEXT NOT NULL DEFAULT 'none';
|
||||
|
||||
DROP TABLE IF EXISTS resource_tags;
|
||||
|
||||
DELETE FROM resource_variants;
|
||||
|
||||
DELETE FROM rebac_relations;
|
||||
|
||||
DELETE FROM resource_placements;
|
||||
|
||||
DELETE FROM storage_locations;
|
||||
|
||||
DELETE FROM resources;
|
||||
@@ -0,0 +1,100 @@
|
||||
-- VaultDrop 013: Migrate data from V1 to V3
|
||||
-- Assigns all existing files to user 'pixel'
|
||||
|
||||
-- 1. Ensure user 'pixel' exists (create if not)
|
||||
INSERT INTO users (username, password_hash)
|
||||
SELECT 'pixel', '$argon2id$v=19$m=65536,t=1,p=4$placeholder$placeholder'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = 'pixel');
|
||||
|
||||
-- 2. Migrate files -> resources
|
||||
INSERT INTO resources (id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at)
|
||||
SELECT
|
||||
f.id::uuid,
|
||||
f.name,
|
||||
f.mime_type,
|
||||
f.size,
|
||||
f.checksum,
|
||||
f.ocr_text,
|
||||
f.is_folder,
|
||||
f.parent_file_id::uuid,
|
||||
(SELECT id FROM users WHERE username = 'pixel'),
|
||||
f.created_at,
|
||||
f.updated_at
|
||||
FROM files f
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- 3. Create server storage_location for user 'pixel'
|
||||
INSERT INTO storage_locations (id, user_id, device_name, role)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
(SELECT id FROM users WHERE username = 'pixel'),
|
||||
'VaultDrop Server',
|
||||
'server'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM storage_locations
|
||||
WHERE user_id = (SELECT id FROM users WHERE username = 'pixel')
|
||||
AND role = 'server'
|
||||
);
|
||||
|
||||
-- 4. Create resource_placements for migrated resources
|
||||
INSERT INTO resource_placements (resource_id, storage_location_id, status, storage_key, synced_at)
|
||||
SELECT
|
||||
r.id,
|
||||
sl.id,
|
||||
'synced',
|
||||
f.storage_key,
|
||||
CURRENT_TIMESTAMP
|
||||
FROM resources r
|
||||
JOIN files f ON f.id::uuid = r.id
|
||||
CROSS JOIN storage_locations sl
|
||||
WHERE sl.user_id = (SELECT id FROM users WHERE username = 'pixel')
|
||||
AND sl.role = 'server'
|
||||
ON CONFLICT (resource_id, storage_location_id) DO NOTHING;
|
||||
|
||||
-- 5. Create rebac_relations (owner) for all migrated resources
|
||||
INSERT INTO rebac_relations (resource_id, subject_user_id, role, granted_by)
|
||||
SELECT
|
||||
r.id,
|
||||
u.id,
|
||||
'owner',
|
||||
u.id
|
||||
FROM resources r
|
||||
CROSS JOIN (SELECT id FROM users WHERE username = 'pixel') u
|
||||
ON CONFLICT (resource_id, subject_user_id) DO NOTHING;
|
||||
|
||||
-- 6. Migrate thumbnails -> resource_variants
|
||||
INSERT INTO resource_variants (id, resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key, created_at)
|
||||
SELECT
|
||||
t.id::uuid,
|
||||
t.file_id::uuid,
|
||||
CASE
|
||||
WHEN t.resolution_label = 'thumbnail' THEN 'thumbnail_small'
|
||||
WHEN t.resolution_label = 'full' THEN 'thumbnail_full'
|
||||
ELSE t.resolution_label
|
||||
END,
|
||||
t.page_number,
|
||||
t.width,
|
||||
t.height,
|
||||
t.mime_type,
|
||||
'server',
|
||||
t.storage_key,
|
||||
t.created_at
|
||||
FROM thumbnails t
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- 7. Create resource_tags from file_tags (keep old file_tags for now)
|
||||
CREATE TABLE IF NOT EXISTS resource_tags (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tag_id TEXT,
|
||||
resource_id TEXT
|
||||
);
|
||||
|
||||
INSERT INTO resource_tags (id, tag_id, resource_id)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
ft.tag_id,
|
||||
ft.file_id
|
||||
FROM file_tags ft;
|
||||
|
||||
-- 8. Remove tag_type column from tags
|
||||
ALTER TABLE tags DROP COLUMN IF EXISTS tag_type;
|
||||
@@ -0,0 +1,33 @@
|
||||
-- VaultDrop 014 down: restore legacy tables
|
||||
|
||||
CREATE TABLE files (
|
||||
id TEXT PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL DEFAULT '',
|
||||
size BIGINT NOT NULL DEFAULT 0,
|
||||
storage_key TEXT NOT NULL DEFAULT '',
|
||||
checksum TEXT NOT NULL DEFAULT '',
|
||||
ocr_text TEXT NOT NULL DEFAULT '',
|
||||
is_folder BOOLEAN NOT NULL DEFAULT false,
|
||||
parent_file_id TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE thumbnails (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
file_id TEXT NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
||||
page_number INTEGER NOT NULL,
|
||||
resolution_label TEXT NOT NULL,
|
||||
width INTEGER NOT NULL,
|
||||
height INTEGER NOT NULL,
|
||||
storage_key TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL DEFAULT 'image/jpeg',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE file_tags (
|
||||
id TEXT PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(),
|
||||
tag_id TEXT,
|
||||
file_id TEXT
|
||||
);
|
||||
@@ -0,0 +1,10 @@
|
||||
-- VaultDrop 014: Drop legacy V1 tables
|
||||
|
||||
-- Tags now use resource_tags instead of file_tags
|
||||
DROP TABLE IF EXISTS file_tags;
|
||||
|
||||
-- Thumbnails migrated to resource_variants
|
||||
DROP TABLE IF EXISTS thumbnails;
|
||||
|
||||
-- Files migrated to resources
|
||||
DROP TABLE IF EXISTS files;
|
||||
@@ -6,27 +6,19 @@ package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Size int64 `json:"size"`
|
||||
StorageKey string `json:"storage_key"`
|
||||
Checksum string `json:"checksum"`
|
||||
OcrText string `json:"ocr_text"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ParentFileID sql.NullString `json:"parent_file_id"`
|
||||
IsFolder bool `json:"is_folder"`
|
||||
}
|
||||
|
||||
type FileTag struct {
|
||||
ID string `json:"id"`
|
||||
TagID sql.NullString `json:"tag_id"`
|
||||
FileID sql.NullString `json:"file_id"`
|
||||
type RebacRelation struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
SubjectUserID uuid.UUID `json:"subject_user_id"`
|
||||
Role string `json:"role"`
|
||||
GrantedBy uuid.UUID `json:"granted_by"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type RefreshToken struct {
|
||||
@@ -38,31 +30,91 @@ type RefreshToken struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type Resource struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Size int64 `json:"size"`
|
||||
Checksum string `json:"checksum"`
|
||||
OcrText string `json:"ocr_text"`
|
||||
IsFolder bool `json:"is_folder"`
|
||||
ParentResourceID uuid.NullUUID `json:"parent_resource_id"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type ResourcePlacement struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
Status string `json:"status"`
|
||||
StorageKey sql.NullString `json:"storage_key"`
|
||||
SyncedAt sql.NullTime `json:"synced_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type ResourceTag struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
TagID sql.NullString `json:"tag_id"`
|
||||
ResourceID sql.NullString `json:"resource_id"`
|
||||
}
|
||||
|
||||
type ResourceVariant struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
VariantType string `json:"variant_type"`
|
||||
PageNumber int32 `json:"page_number"`
|
||||
Width int32 `json:"width"`
|
||||
Height int32 `json:"height"`
|
||||
MimeType string `json:"mime_type"`
|
||||
GeneratedBy string `json:"generated_by"`
|
||||
StorageKey string `json:"storage_key"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type RetentionPolicy struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
RuleType string `json:"rule_type"`
|
||||
RuleValue json.RawMessage `json:"rule_value"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type StorageLocation struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
DeviceName string `json:"device_name"`
|
||||
Role string `json:"role"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
LastSeenAt sql.NullTime `json:"last_seen_at"`
|
||||
}
|
||||
|
||||
type SyncQueue struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
Operation string `json:"operation"`
|
||||
Status string `json:"status"`
|
||||
Attempts int32 `json:"attempts"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
ID string `json:"id"`
|
||||
ParentTagID sql.NullString `json:"parent_tag_id"`
|
||||
TagName string `json:"tag_name"`
|
||||
TagType string `json:"tag_type"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Thumbnail struct {
|
||||
ID string `json:"id"`
|
||||
FileID string `json:"file_id"`
|
||||
PageNumber int32 `json:"page_number"`
|
||||
ResolutionLabel string `json:"resolution_label"`
|
||||
Width int32 `json:"width"`
|
||||
Height int32 `json:"height"`
|
||||
StorageKey string `json:"storage_key"`
|
||||
MimeType string `json:"mime_type"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ParentUserID uuid.NullUUID `json:"parent_user_id"`
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
-- name: GetFile :one
|
||||
SELECT * FROM files
|
||||
WHERE id = $1 LIMIT 1;
|
||||
|
||||
-- name: ListFiles :many
|
||||
SELECT * FROM files
|
||||
WHERE parent_file_id IS NULL
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
|
||||
-- name: ListFolders :many
|
||||
SELECT * FROM files
|
||||
WHERE is_folder = true
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListFilesByID :many
|
||||
SELECT * FROM files
|
||||
WHERE id = ANY($1::text[])
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: CreateFile :one
|
||||
INSERT INTO files (name, mime_type, size, storage_key, checksum, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateFolder :one
|
||||
INSERT INTO files (name, is_folder, created_at, updated_at)
|
||||
VALUES ($1, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING *;
|
||||
|
||||
-- name: ListFilesByParentID :many
|
||||
SELECT * FROM files
|
||||
WHERE parent_file_id = $1
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
|
||||
-- name: MoveFiles :exec
|
||||
UPDATE files
|
||||
SET parent_file_id = $1, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ANY($2::text[]);
|
||||
|
||||
-- name: UpdateFile :exec
|
||||
UPDATE files
|
||||
SET name = $1, mime_type = $2, ocr_text = $3, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $4;
|
||||
|
||||
-- name: DeleteFile :exec
|
||||
DELETE FROM files
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: FindDuplicatesByNameSize :many
|
||||
SELECT id, name, mime_type, size, checksum, created_at FROM files
|
||||
WHERE name = $1 AND size = $2 AND is_folder = false
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: FindDuplicateByChecksum :one
|
||||
SELECT * FROM files
|
||||
WHERE checksum = $1 AND is_folder = false
|
||||
LIMIT 1;
|
||||
@@ -0,0 +1,36 @@
|
||||
-- name: CreateRebacRelation :one
|
||||
INSERT INTO rebac_relations (resource_id, subject_user_id, role, granted_by)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetRebacRelation :one
|
||||
SELECT * FROM rebac_relations
|
||||
WHERE resource_id = $1 AND subject_user_id = $2
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListRebacRelationsByResource :many
|
||||
SELECT * FROM rebac_relations
|
||||
WHERE resource_id = $1
|
||||
ORDER BY created_at ASC;
|
||||
|
||||
-- name: ListRebacRelationsBySubject :many
|
||||
SELECT * FROM rebac_relations
|
||||
WHERE subject_user_id = $1
|
||||
ORDER BY created_at ASC;
|
||||
|
||||
-- name: DeleteRebacRelation :exec
|
||||
DELETE FROM rebac_relations
|
||||
WHERE resource_id = $1 AND subject_user_id = $2;
|
||||
|
||||
-- name: DeleteRebacRelationsByResource :exec
|
||||
DELETE FROM rebac_relations
|
||||
WHERE resource_id = $1;
|
||||
|
||||
-- name: HasRebacRelation :one
|
||||
SELECT EXISTS(
|
||||
SELECT 1 FROM rebac_relations
|
||||
WHERE resource_id = $1 AND subject_user_id = $2 AND role = $3
|
||||
);
|
||||
|
||||
-- name: ResolveEffectiveRole :one
|
||||
SELECT resolve_effective_role($1, $2) AS role;
|
||||
@@ -0,0 +1,32 @@
|
||||
-- name: CreatePlacement :one
|
||||
INSERT INTO resource_placements (resource_id, storage_location_id, status, storage_key, synced_at)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetPlacement :one
|
||||
SELECT * FROM resource_placements
|
||||
WHERE resource_id = $1 AND storage_location_id = $2
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListPlacementsByResource :many
|
||||
SELECT * FROM resource_placements
|
||||
WHERE resource_id = $1;
|
||||
|
||||
-- name: ListPlacementsByLocation :many
|
||||
SELECT * FROM resource_placements
|
||||
WHERE storage_location_id = $1;
|
||||
|
||||
-- name: UpdatePlacementStatus :exec
|
||||
UPDATE resource_placements
|
||||
SET status = $1, synced_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $2;
|
||||
|
||||
-- name: DeletePlacement :exec
|
||||
DELETE FROM resource_placements
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: GetServerPlacementByResource :one
|
||||
SELECT rp.* FROM resource_placements rp
|
||||
JOIN storage_locations sl ON sl.id = rp.storage_location_id
|
||||
WHERE rp.resource_id = $1 AND sl.role = 'server'
|
||||
LIMIT 1;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- name: CreateResourceVariant :one
|
||||
INSERT INTO resource_variants (resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetVariantsByResourceID :many
|
||||
SELECT * FROM resource_variants
|
||||
WHERE resource_id = $1
|
||||
ORDER BY page_number ASC, variant_type ASC;
|
||||
|
||||
-- name: GetVariantByID :one
|
||||
SELECT * FROM resource_variants
|
||||
WHERE id = $1 LIMIT 1;
|
||||
|
||||
-- name: DeleteVariantsByResourceID :exec
|
||||
DELETE FROM resource_variants WHERE resource_id = $1;
|
||||
|
||||
-- name: GetBestVariant :one
|
||||
SELECT * FROM resource_variants
|
||||
WHERE resource_id = $1 AND variant_type = $2 AND page_number = 1
|
||||
LIMIT 1;
|
||||
@@ -0,0 +1,67 @@
|
||||
-- name: GetResource :one
|
||||
SELECT * FROM resources
|
||||
WHERE id = $1 LIMIT 1;
|
||||
|
||||
-- name: ListResources :many
|
||||
SELECT * FROM resources
|
||||
WHERE parent_resource_id IS NULL
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
|
||||
-- name: ListFolders :many
|
||||
SELECT * FROM resources
|
||||
WHERE is_folder = true
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListResourcesByID :many
|
||||
SELECT * FROM resources
|
||||
WHERE id = ANY($1::uuid[])
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: CreateResource :one
|
||||
INSERT INTO resources (name, mime_type, size, checksum, owner_id, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateFolder :one
|
||||
INSERT INTO resources (name, is_folder, owner_id, created_at, updated_at)
|
||||
VALUES ($1, true, $2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING *;
|
||||
|
||||
-- name: ListResourcesByParentID :many
|
||||
SELECT * FROM resources
|
||||
WHERE parent_resource_id = $1
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
|
||||
-- name: MoveResources :exec
|
||||
UPDATE resources
|
||||
SET parent_resource_id = $1, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ANY($2::uuid[]);
|
||||
|
||||
-- name: UpdateResource :exec
|
||||
UPDATE resources
|
||||
SET name = $1, mime_type = $2, ocr_text = $3, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $4;
|
||||
|
||||
-- name: DeleteResource :exec
|
||||
DELETE FROM resources
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: FindDuplicatesByNameSize :many
|
||||
SELECT id, name, mime_type, size, checksum, created_at FROM resources
|
||||
WHERE name = $1 AND size = $2 AND is_folder = false
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: FindDuplicateByChecksum :one
|
||||
SELECT * FROM resources
|
||||
WHERE checksum = $1 AND is_folder = false AND owner_id = $2
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListResourcesByOwner :many
|
||||
SELECT * FROM resources
|
||||
WHERE owner_id = $1 AND parent_resource_id IS NULL
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListResourcesByParentAndOwner :many
|
||||
SELECT * FROM resources
|
||||
WHERE parent_resource_id = $1 AND owner_id = $2
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
@@ -0,0 +1,20 @@
|
||||
-- name: CreateRetentionPolicy :one
|
||||
INSERT INTO retention_policies (user_id, storage_location_id, rule_type, rule_value)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetRetentionPolicy :one
|
||||
SELECT * FROM retention_policies
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ListRetentionPoliciesByUser :many
|
||||
SELECT * FROM retention_policies
|
||||
WHERE user_id = $1;
|
||||
|
||||
-- name: ListRetentionPoliciesByLocation :many
|
||||
SELECT * FROM retention_policies
|
||||
WHERE storage_location_id = $1;
|
||||
|
||||
-- name: DeleteRetentionPolicy :exec
|
||||
DELETE FROM retention_policies
|
||||
WHERE id = $1;
|
||||
@@ -0,0 +1,27 @@
|
||||
-- name: CreateStorageLocation :one
|
||||
INSERT INTO storage_locations (user_id, device_name, role)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetStorageLocation :one
|
||||
SELECT * FROM storage_locations
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ListStorageLocationsByUser :many
|
||||
SELECT * FROM storage_locations
|
||||
WHERE user_id = $1
|
||||
ORDER BY created_at ASC;
|
||||
|
||||
-- name: GetServerStorageLocation :one
|
||||
SELECT * FROM storage_locations
|
||||
WHERE user_id = $1 AND role = 'server'
|
||||
LIMIT 1;
|
||||
|
||||
-- name: UpdateStorageLocationLastSeen :exec
|
||||
UPDATE storage_locations
|
||||
SET last_seen_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteStorageLocation :exec
|
||||
DELETE FROM storage_locations
|
||||
WHERE id = $1;
|
||||
@@ -0,0 +1,27 @@
|
||||
-- name: CreateSyncQueueItem :one
|
||||
INSERT INTO sync_queue (resource_id, storage_location_id, operation, status, attempts)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetSyncQueueItem :one
|
||||
SELECT * FROM sync_queue
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ListPendingSyncItems :many
|
||||
SELECT * FROM sync_queue
|
||||
WHERE status = 'pending'
|
||||
ORDER BY created_at ASC;
|
||||
|
||||
-- name: ListPendingSyncItemsByLocation :many
|
||||
SELECT * FROM sync_queue
|
||||
WHERE storage_location_id = $1 AND status = 'pending'
|
||||
ORDER BY created_at ASC;
|
||||
|
||||
-- name: UpdateSyncQueueStatus :exec
|
||||
UPDATE sync_queue
|
||||
SET status = $1, attempts = $2, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $3;
|
||||
|
||||
-- name: DeleteSyncQueueItem :exec
|
||||
DELETE FROM sync_queue
|
||||
WHERE id = $1;
|
||||
@@ -1,6 +1,6 @@
|
||||
-- name: CreateTag :one
|
||||
INSERT INTO tags (tag_name, tag_type)
|
||||
VALUES ($1, $2)
|
||||
INSERT INTO tags (tag_name)
|
||||
VALUES ($1)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTag :one
|
||||
@@ -19,23 +19,23 @@ ORDER BY tag_name ASC;
|
||||
DELETE FROM tags
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: AddTagToFile :exec
|
||||
INSERT INTO file_tags (tag_id, file_id)
|
||||
-- name: AddTagToResource :exec
|
||||
INSERT INTO resource_tags (tag_id, resource_id)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- name: RemoveTagFromFile :exec
|
||||
DELETE FROM file_tags
|
||||
WHERE tag_id = $1 AND file_id = $2;
|
||||
-- name: RemoveTagFromResource :exec
|
||||
DELETE FROM resource_tags
|
||||
WHERE tag_id = $1 AND resource_id = $2;
|
||||
|
||||
-- name: GetTagsByFileID :many
|
||||
-- name: GetTagsByResourceID :many
|
||||
SELECT t.* FROM tags t
|
||||
JOIN file_tags ft ON t.id = ft.tag_id
|
||||
WHERE ft.file_id = $1
|
||||
JOIN resource_tags rt ON t.id = rt.tag_id
|
||||
WHERE rt.resource_id = $1
|
||||
ORDER BY t.tag_name ASC;
|
||||
|
||||
-- name: GetFilesByTagID :many
|
||||
SELECT f.* FROM files f
|
||||
JOIN file_tags ft ON f.id = ft.file_id
|
||||
WHERE ft.tag_id = $1
|
||||
ORDER BY f.created_at DESC;
|
||||
-- name: GetResourcesByTagID :many
|
||||
SELECT r.* FROM resources r
|
||||
JOIN resource_tags rt ON r.id = rt.resource_id
|
||||
WHERE rt.tag_id = $1
|
||||
ORDER BY r.created_at DESC;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
-- name: CreateThumbnail :one
|
||||
INSERT INTO thumbnails (file_id, page_number, resolution_label, width, height, storage_key, mime_type)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetThumbnailsByFileID :many
|
||||
SELECT * FROM thumbnails
|
||||
WHERE file_id = $1
|
||||
ORDER BY page_number ASC, resolution_label ASC;
|
||||
|
||||
-- name: GetThumbnailByID :one
|
||||
SELECT * FROM thumbnails
|
||||
WHERE id = $1 LIMIT 1;
|
||||
|
||||
-- name: DeleteThumbnailsByFileID :exec
|
||||
DELETE FROM thumbnails WHERE file_id = $1;
|
||||
|
||||
-- name: GetThumbnailByFilePageResolution :one
|
||||
SELECT * FROM thumbnails
|
||||
WHERE file_id = $1 AND page_number = $2 AND resolution_label = $3
|
||||
LIMIT 1;
|
||||
@@ -0,0 +1,202 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: rebac_relations.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createRebacRelation = `-- name: CreateRebacRelation :one
|
||||
INSERT INTO rebac_relations (resource_id, subject_user_id, role, granted_by)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, resource_id, subject_user_id, role, granted_by, created_at
|
||||
`
|
||||
|
||||
type CreateRebacRelationParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
SubjectUserID uuid.UUID `json:"subject_user_id"`
|
||||
Role string `json:"role"`
|
||||
GrantedBy uuid.UUID `json:"granted_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateRebacRelation(ctx context.Context, arg CreateRebacRelationParams) (RebacRelation, error) {
|
||||
row := q.db.QueryRowContext(ctx, createRebacRelation,
|
||||
arg.ResourceID,
|
||||
arg.SubjectUserID,
|
||||
arg.Role,
|
||||
arg.GrantedBy,
|
||||
)
|
||||
var i RebacRelation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.SubjectUserID,
|
||||
&i.Role,
|
||||
&i.GrantedBy,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteRebacRelation = `-- name: DeleteRebacRelation :exec
|
||||
DELETE FROM rebac_relations
|
||||
WHERE resource_id = $1 AND subject_user_id = $2
|
||||
`
|
||||
|
||||
type DeleteRebacRelationParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
SubjectUserID uuid.UUID `json:"subject_user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteRebacRelation(ctx context.Context, arg DeleteRebacRelationParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteRebacRelation, arg.ResourceID, arg.SubjectUserID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteRebacRelationsByResource = `-- name: DeleteRebacRelationsByResource :exec
|
||||
DELETE FROM rebac_relations
|
||||
WHERE resource_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteRebacRelationsByResource(ctx context.Context, resourceID uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteRebacRelationsByResource, resourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getRebacRelation = `-- name: GetRebacRelation :one
|
||||
SELECT id, resource_id, subject_user_id, role, granted_by, created_at FROM rebac_relations
|
||||
WHERE resource_id = $1 AND subject_user_id = $2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetRebacRelationParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
SubjectUserID uuid.UUID `json:"subject_user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetRebacRelation(ctx context.Context, arg GetRebacRelationParams) (RebacRelation, error) {
|
||||
row := q.db.QueryRowContext(ctx, getRebacRelation, arg.ResourceID, arg.SubjectUserID)
|
||||
var i RebacRelation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.SubjectUserID,
|
||||
&i.Role,
|
||||
&i.GrantedBy,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const hasRebacRelation = `-- name: HasRebacRelation :one
|
||||
SELECT EXISTS(
|
||||
SELECT 1 FROM rebac_relations
|
||||
WHERE resource_id = $1 AND subject_user_id = $2 AND role = $3
|
||||
)
|
||||
`
|
||||
|
||||
type HasRebacRelationParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
SubjectUserID uuid.UUID `json:"subject_user_id"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
func (q *Queries) HasRebacRelation(ctx context.Context, arg HasRebacRelationParams) (bool, error) {
|
||||
row := q.db.QueryRowContext(ctx, hasRebacRelation, arg.ResourceID, arg.SubjectUserID, arg.Role)
|
||||
var exists bool
|
||||
err := row.Scan(&exists)
|
||||
return exists, err
|
||||
}
|
||||
|
||||
const listRebacRelationsByResource = `-- name: ListRebacRelationsByResource :many
|
||||
SELECT id, resource_id, subject_user_id, role, granted_by, created_at FROM rebac_relations
|
||||
WHERE resource_id = $1
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListRebacRelationsByResource(ctx context.Context, resourceID uuid.UUID) ([]RebacRelation, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listRebacRelationsByResource, resourceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RebacRelation
|
||||
for rows.Next() {
|
||||
var i RebacRelation
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.SubjectUserID,
|
||||
&i.Role,
|
||||
&i.GrantedBy,
|
||||
&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 listRebacRelationsBySubject = `-- name: ListRebacRelationsBySubject :many
|
||||
SELECT id, resource_id, subject_user_id, role, granted_by, created_at FROM rebac_relations
|
||||
WHERE subject_user_id = $1
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListRebacRelationsBySubject(ctx context.Context, subjectUserID uuid.UUID) ([]RebacRelation, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listRebacRelationsBySubject, subjectUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RebacRelation
|
||||
for rows.Next() {
|
||||
var i RebacRelation
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.SubjectUserID,
|
||||
&i.Role,
|
||||
&i.GrantedBy,
|
||||
&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 resolveEffectiveRole = `-- name: ResolveEffectiveRole :one
|
||||
SELECT resolve_effective_role($1, $2) AS role
|
||||
`
|
||||
|
||||
type ResolveEffectiveRoleParams struct {
|
||||
PUserID uuid.UUID `json:"p_user_id"`
|
||||
PResourceID uuid.UUID `json:"p_resource_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) ResolveEffectiveRole(ctx context.Context, arg ResolveEffectiveRoleParams) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, resolveEffectiveRole, arg.PUserID, arg.PResourceID)
|
||||
var role string
|
||||
err := row.Scan(&role)
|
||||
return role, err
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: resource_placements.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createPlacement = `-- name: CreatePlacement :one
|
||||
INSERT INTO resource_placements (resource_id, storage_location_id, status, storage_key, synced_at)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, resource_id, storage_location_id, status, storage_key, synced_at, created_at
|
||||
`
|
||||
|
||||
type CreatePlacementParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
Status string `json:"status"`
|
||||
StorageKey sql.NullString `json:"storage_key"`
|
||||
SyncedAt sql.NullTime `json:"synced_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePlacement(ctx context.Context, arg CreatePlacementParams) (ResourcePlacement, error) {
|
||||
row := q.db.QueryRowContext(ctx, createPlacement,
|
||||
arg.ResourceID,
|
||||
arg.StorageLocationID,
|
||||
arg.Status,
|
||||
arg.StorageKey,
|
||||
arg.SyncedAt,
|
||||
)
|
||||
var i ResourcePlacement
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Status,
|
||||
&i.StorageKey,
|
||||
&i.SyncedAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deletePlacement = `-- name: DeletePlacement :exec
|
||||
DELETE FROM resource_placements
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeletePlacement(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deletePlacement, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getPlacement = `-- name: GetPlacement :one
|
||||
SELECT id, resource_id, storage_location_id, status, storage_key, synced_at, created_at FROM resource_placements
|
||||
WHERE resource_id = $1 AND storage_location_id = $2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetPlacementParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetPlacement(ctx context.Context, arg GetPlacementParams) (ResourcePlacement, error) {
|
||||
row := q.db.QueryRowContext(ctx, getPlacement, arg.ResourceID, arg.StorageLocationID)
|
||||
var i ResourcePlacement
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Status,
|
||||
&i.StorageKey,
|
||||
&i.SyncedAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getServerPlacementByResource = `-- name: GetServerPlacementByResource :one
|
||||
SELECT rp.id, rp.resource_id, rp.storage_location_id, rp.status, rp.storage_key, rp.synced_at, rp.created_at FROM resource_placements rp
|
||||
JOIN storage_locations sl ON sl.id = rp.storage_location_id
|
||||
WHERE rp.resource_id = $1 AND sl.role = 'server'
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetServerPlacementByResource(ctx context.Context, resourceID uuid.UUID) (ResourcePlacement, error) {
|
||||
row := q.db.QueryRowContext(ctx, getServerPlacementByResource, resourceID)
|
||||
var i ResourcePlacement
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Status,
|
||||
&i.StorageKey,
|
||||
&i.SyncedAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listPlacementsByLocation = `-- name: ListPlacementsByLocation :many
|
||||
SELECT id, resource_id, storage_location_id, status, storage_key, synced_at, created_at FROM resource_placements
|
||||
WHERE storage_location_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ListPlacementsByLocation(ctx context.Context, storageLocationID uuid.UUID) ([]ResourcePlacement, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listPlacementsByLocation, storageLocationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ResourcePlacement
|
||||
for rows.Next() {
|
||||
var i ResourcePlacement
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Status,
|
||||
&i.StorageKey,
|
||||
&i.SyncedAt,
|
||||
&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 listPlacementsByResource = `-- name: ListPlacementsByResource :many
|
||||
SELECT id, resource_id, storage_location_id, status, storage_key, synced_at, created_at FROM resource_placements
|
||||
WHERE resource_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ListPlacementsByResource(ctx context.Context, resourceID uuid.UUID) ([]ResourcePlacement, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listPlacementsByResource, resourceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ResourcePlacement
|
||||
for rows.Next() {
|
||||
var i ResourcePlacement
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Status,
|
||||
&i.StorageKey,
|
||||
&i.SyncedAt,
|
||||
&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 updatePlacementStatus = `-- name: UpdatePlacementStatus :exec
|
||||
UPDATE resource_placements
|
||||
SET status = $1, synced_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $2
|
||||
`
|
||||
|
||||
type UpdatePlacementStatusParams struct {
|
||||
Status string `json:"status"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdatePlacementStatus(ctx context.Context, arg UpdatePlacementStatusParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updatePlacementStatus, arg.Status, arg.ID)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: resource_variants.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createResourceVariant = `-- name: CreateResourceVariant :one
|
||||
INSERT INTO resource_variants (resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id, resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key, created_at
|
||||
`
|
||||
|
||||
type CreateResourceVariantParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
VariantType string `json:"variant_type"`
|
||||
PageNumber int32 `json:"page_number"`
|
||||
Width int32 `json:"width"`
|
||||
Height int32 `json:"height"`
|
||||
MimeType string `json:"mime_type"`
|
||||
GeneratedBy string `json:"generated_by"`
|
||||
StorageKey string `json:"storage_key"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateResourceVariant(ctx context.Context, arg CreateResourceVariantParams) (ResourceVariant, error) {
|
||||
row := q.db.QueryRowContext(ctx, createResourceVariant,
|
||||
arg.ResourceID,
|
||||
arg.VariantType,
|
||||
arg.PageNumber,
|
||||
arg.Width,
|
||||
arg.Height,
|
||||
arg.MimeType,
|
||||
arg.GeneratedBy,
|
||||
arg.StorageKey,
|
||||
)
|
||||
var i ResourceVariant
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.VariantType,
|
||||
&i.PageNumber,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.MimeType,
|
||||
&i.GeneratedBy,
|
||||
&i.StorageKey,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteVariantsByResourceID = `-- name: DeleteVariantsByResourceID :exec
|
||||
DELETE FROM resource_variants WHERE resource_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteVariantsByResourceID(ctx context.Context, resourceID uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteVariantsByResourceID, resourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getBestVariant = `-- name: GetBestVariant :one
|
||||
SELECT id, resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key, created_at FROM resource_variants
|
||||
WHERE resource_id = $1 AND variant_type = $2 AND page_number = 1
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetBestVariantParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
VariantType string `json:"variant_type"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetBestVariant(ctx context.Context, arg GetBestVariantParams) (ResourceVariant, error) {
|
||||
row := q.db.QueryRowContext(ctx, getBestVariant, arg.ResourceID, arg.VariantType)
|
||||
var i ResourceVariant
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.VariantType,
|
||||
&i.PageNumber,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.MimeType,
|
||||
&i.GeneratedBy,
|
||||
&i.StorageKey,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getVariantByID = `-- name: GetVariantByID :one
|
||||
SELECT id, resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key, created_at FROM resource_variants
|
||||
WHERE id = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetVariantByID(ctx context.Context, id uuid.UUID) (ResourceVariant, error) {
|
||||
row := q.db.QueryRowContext(ctx, getVariantByID, id)
|
||||
var i ResourceVariant
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.VariantType,
|
||||
&i.PageNumber,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.MimeType,
|
||||
&i.GeneratedBy,
|
||||
&i.StorageKey,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getVariantsByResourceID = `-- name: GetVariantsByResourceID :many
|
||||
SELECT id, resource_id, variant_type, page_number, width, height, mime_type, generated_by, storage_key, created_at FROM resource_variants
|
||||
WHERE resource_id = $1
|
||||
ORDER BY page_number ASC, variant_type ASC
|
||||
`
|
||||
|
||||
func (q *Queries) GetVariantsByResourceID(ctx context.Context, resourceID uuid.UUID) ([]ResourceVariant, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getVariantsByResourceID, resourceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ResourceVariant
|
||||
for rows.Next() {
|
||||
var i ResourceVariant
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.VariantType,
|
||||
&i.PageNumber,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.MimeType,
|
||||
&i.GeneratedBy,
|
||||
&i.StorageKey,
|
||||
&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
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: resources.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
const createFolder = `-- name: CreateFolder :one
|
||||
INSERT INTO resources (name, is_folder, owner_id, created_at, updated_at)
|
||||
VALUES ($1, true, $2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateFolderParams struct {
|
||||
Name string `json:"name"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateFolder(ctx context.Context, arg CreateFolderParams) (Resource, error) {
|
||||
row := q.db.QueryRowContext(ctx, createFolder, arg.Name, arg.OwnerID)
|
||||
var i Resource
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createResource = `-- name: CreateResource :one
|
||||
INSERT INTO resources (name, mime_type, size, checksum, owner_id, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
RETURNING id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateResourceParams struct {
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Size int64 `json:"size"`
|
||||
Checksum string `json:"checksum"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateResource(ctx context.Context, arg CreateResourceParams) (Resource, error) {
|
||||
row := q.db.QueryRowContext(ctx, createResource,
|
||||
arg.Name,
|
||||
arg.MimeType,
|
||||
arg.Size,
|
||||
arg.Checksum,
|
||||
arg.OwnerID,
|
||||
)
|
||||
var i Resource
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteResource = `-- name: DeleteResource :exec
|
||||
DELETE FROM resources
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteResource(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteResource, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const findDuplicateByChecksum = `-- name: FindDuplicateByChecksum :one
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE checksum = $1 AND is_folder = false AND owner_id = $2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type FindDuplicateByChecksumParams struct {
|
||||
Checksum string `json:"checksum"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) FindDuplicateByChecksum(ctx context.Context, arg FindDuplicateByChecksumParams) (Resource, error) {
|
||||
row := q.db.QueryRowContext(ctx, findDuplicateByChecksum, arg.Checksum, arg.OwnerID)
|
||||
var i Resource
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const findDuplicatesByNameSize = `-- name: FindDuplicatesByNameSize :many
|
||||
SELECT id, name, mime_type, size, checksum, created_at FROM resources
|
||||
WHERE name = $1 AND size = $2 AND is_folder = false
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
type FindDuplicatesByNameSizeParams struct {
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type FindDuplicatesByNameSizeRow struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Size int64 `json:"size"`
|
||||
Checksum string `json:"checksum"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) FindDuplicatesByNameSize(ctx context.Context, arg FindDuplicatesByNameSizeParams) ([]FindDuplicatesByNameSizeRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, findDuplicatesByNameSize, arg.Name, arg.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []FindDuplicatesByNameSizeRow
|
||||
for rows.Next() {
|
||||
var i FindDuplicatesByNameSizeRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&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 getResource = `-- name: GetResource :one
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE id = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetResource(ctx context.Context, id uuid.UUID) (Resource, error) {
|
||||
row := q.db.QueryRowContext(ctx, getResource, id)
|
||||
var i Resource
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listFolders = `-- name: ListFolders :many
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE is_folder = true
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListFolders(ctx context.Context) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listFolders)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 listResources = `-- name: ListResources :many
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE parent_resource_id IS NULL
|
||||
ORDER BY is_folder DESC, created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListResources(ctx context.Context) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listResources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 listResourcesByID = `-- name: ListResourcesByID :many
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE id = ANY($1::uuid[])
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListResourcesByID(ctx context.Context, dollar_1 []uuid.UUID) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listResourcesByID, pq.Array(dollar_1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 listResourcesByOwner = `-- name: ListResourcesByOwner :many
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE owner_id = $1 AND parent_resource_id IS NULL
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListResourcesByOwner(ctx context.Context, ownerID uuid.UUID) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listResourcesByOwner, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 listResourcesByParentAndOwner = `-- name: ListResourcesByParentAndOwner :many
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE parent_resource_id = $1 AND owner_id = $2
|
||||
ORDER BY is_folder DESC, created_at DESC
|
||||
`
|
||||
|
||||
type ListResourcesByParentAndOwnerParams struct {
|
||||
ParentResourceID uuid.NullUUID `json:"parent_resource_id"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListResourcesByParentAndOwner(ctx context.Context, arg ListResourcesByParentAndOwnerParams) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listResourcesByParentAndOwner, arg.ParentResourceID, arg.OwnerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 listResourcesByParentID = `-- name: ListResourcesByParentID :many
|
||||
SELECT id, name, mime_type, size, checksum, ocr_text, is_folder, parent_resource_id, owner_id, created_at, updated_at FROM resources
|
||||
WHERE parent_resource_id = $1
|
||||
ORDER BY is_folder DESC, created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListResourcesByParentID(ctx context.Context, parentResourceID uuid.NullUUID) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listResourcesByParentID, parentResourceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 moveResources = `-- name: MoveResources :exec
|
||||
UPDATE resources
|
||||
SET parent_resource_id = $1, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ANY($2::uuid[])
|
||||
`
|
||||
|
||||
type MoveResourcesParams struct {
|
||||
ParentResourceID uuid.NullUUID `json:"parent_resource_id"`
|
||||
Column2 []uuid.UUID `json:"column_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) MoveResources(ctx context.Context, arg MoveResourcesParams) error {
|
||||
_, err := q.db.ExecContext(ctx, moveResources, arg.ParentResourceID, pq.Array(arg.Column2))
|
||||
return err
|
||||
}
|
||||
|
||||
const updateResource = `-- name: UpdateResource :exec
|
||||
UPDATE resources
|
||||
SET name = $1, mime_type = $2, ocr_text = $3, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $4
|
||||
`
|
||||
|
||||
type UpdateResourceParams struct {
|
||||
Name string `json:"name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
OcrText string `json:"ocr_text"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateResource(ctx context.Context, arg UpdateResourceParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateResource,
|
||||
arg.Name,
|
||||
arg.MimeType,
|
||||
arg.OcrText,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: retention_policies.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createRetentionPolicy = `-- name: CreateRetentionPolicy :one
|
||||
INSERT INTO retention_policies (user_id, storage_location_id, rule_type, rule_value)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, user_id, storage_location_id, rule_type, rule_value, created_at
|
||||
`
|
||||
|
||||
type CreateRetentionPolicyParams struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
RuleType string `json:"rule_type"`
|
||||
RuleValue json.RawMessage `json:"rule_value"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateRetentionPolicy(ctx context.Context, arg CreateRetentionPolicyParams) (RetentionPolicy, error) {
|
||||
row := q.db.QueryRowContext(ctx, createRetentionPolicy,
|
||||
arg.UserID,
|
||||
arg.StorageLocationID,
|
||||
arg.RuleType,
|
||||
arg.RuleValue,
|
||||
)
|
||||
var i RetentionPolicy
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.StorageLocationID,
|
||||
&i.RuleType,
|
||||
&i.RuleValue,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteRetentionPolicy = `-- name: DeleteRetentionPolicy :exec
|
||||
DELETE FROM retention_policies
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteRetentionPolicy(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteRetentionPolicy, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getRetentionPolicy = `-- name: GetRetentionPolicy :one
|
||||
SELECT id, user_id, storage_location_id, rule_type, rule_value, created_at FROM retention_policies
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetRetentionPolicy(ctx context.Context, id uuid.UUID) (RetentionPolicy, error) {
|
||||
row := q.db.QueryRowContext(ctx, getRetentionPolicy, id)
|
||||
var i RetentionPolicy
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.StorageLocationID,
|
||||
&i.RuleType,
|
||||
&i.RuleValue,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listRetentionPoliciesByLocation = `-- name: ListRetentionPoliciesByLocation :many
|
||||
SELECT id, user_id, storage_location_id, rule_type, rule_value, created_at FROM retention_policies
|
||||
WHERE storage_location_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ListRetentionPoliciesByLocation(ctx context.Context, storageLocationID uuid.UUID) ([]RetentionPolicy, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listRetentionPoliciesByLocation, storageLocationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RetentionPolicy
|
||||
for rows.Next() {
|
||||
var i RetentionPolicy
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.StorageLocationID,
|
||||
&i.RuleType,
|
||||
&i.RuleValue,
|
||||
&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 listRetentionPoliciesByUser = `-- name: ListRetentionPoliciesByUser :many
|
||||
SELECT id, user_id, storage_location_id, rule_type, rule_value, created_at FROM retention_policies
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ListRetentionPoliciesByUser(ctx context.Context, userID uuid.UUID) ([]RetentionPolicy, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listRetentionPoliciesByUser, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RetentionPolicy
|
||||
for rows.Next() {
|
||||
var i RetentionPolicy
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.StorageLocationID,
|
||||
&i.RuleType,
|
||||
&i.RuleValue,
|
||||
&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
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: storage_locations.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createStorageLocation = `-- name: CreateStorageLocation :one
|
||||
INSERT INTO storage_locations (user_id, device_name, role)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id, user_id, device_name, role, created_at, last_seen_at
|
||||
`
|
||||
|
||||
type CreateStorageLocationParams struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
DeviceName string `json:"device_name"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateStorageLocation(ctx context.Context, arg CreateStorageLocationParams) (StorageLocation, error) {
|
||||
row := q.db.QueryRowContext(ctx, createStorageLocation, arg.UserID, arg.DeviceName, arg.Role)
|
||||
var i StorageLocation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.DeviceName,
|
||||
&i.Role,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteStorageLocation = `-- name: DeleteStorageLocation :exec
|
||||
DELETE FROM storage_locations
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteStorageLocation(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteStorageLocation, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getServerStorageLocation = `-- name: GetServerStorageLocation :one
|
||||
SELECT id, user_id, device_name, role, created_at, last_seen_at FROM storage_locations
|
||||
WHERE user_id = $1 AND role = 'server'
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetServerStorageLocation(ctx context.Context, userID uuid.UUID) (StorageLocation, error) {
|
||||
row := q.db.QueryRowContext(ctx, getServerStorageLocation, userID)
|
||||
var i StorageLocation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.DeviceName,
|
||||
&i.Role,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getStorageLocation = `-- name: GetStorageLocation :one
|
||||
SELECT id, user_id, device_name, role, created_at, last_seen_at FROM storage_locations
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetStorageLocation(ctx context.Context, id uuid.UUID) (StorageLocation, error) {
|
||||
row := q.db.QueryRowContext(ctx, getStorageLocation, id)
|
||||
var i StorageLocation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.DeviceName,
|
||||
&i.Role,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listStorageLocationsByUser = `-- name: ListStorageLocationsByUser :many
|
||||
SELECT id, user_id, device_name, role, created_at, last_seen_at FROM storage_locations
|
||||
WHERE user_id = $1
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListStorageLocationsByUser(ctx context.Context, userID uuid.UUID) ([]StorageLocation, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listStorageLocationsByUser, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []StorageLocation
|
||||
for rows.Next() {
|
||||
var i StorageLocation
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.DeviceName,
|
||||
&i.Role,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
); 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 updateStorageLocationLastSeen = `-- name: UpdateStorageLocationLastSeen :exec
|
||||
UPDATE storage_locations
|
||||
SET last_seen_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) UpdateStorageLocationLastSeen(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, updateStorageLocationLastSeen, id)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: sync_queue.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createSyncQueueItem = `-- name: CreateSyncQueueItem :one
|
||||
INSERT INTO sync_queue (resource_id, storage_location_id, operation, status, attempts)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, resource_id, storage_location_id, operation, status, attempts, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateSyncQueueItemParams struct {
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
StorageLocationID uuid.UUID `json:"storage_location_id"`
|
||||
Operation string `json:"operation"`
|
||||
Status string `json:"status"`
|
||||
Attempts int32 `json:"attempts"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSyncQueueItem(ctx context.Context, arg CreateSyncQueueItemParams) (SyncQueue, error) {
|
||||
row := q.db.QueryRowContext(ctx, createSyncQueueItem,
|
||||
arg.ResourceID,
|
||||
arg.StorageLocationID,
|
||||
arg.Operation,
|
||||
arg.Status,
|
||||
arg.Attempts,
|
||||
)
|
||||
var i SyncQueue
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Operation,
|
||||
&i.Status,
|
||||
&i.Attempts,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteSyncQueueItem = `-- name: DeleteSyncQueueItem :exec
|
||||
DELETE FROM sync_queue
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSyncQueueItem(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteSyncQueueItem, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getSyncQueueItem = `-- name: GetSyncQueueItem :one
|
||||
SELECT id, resource_id, storage_location_id, operation, status, attempts, created_at, updated_at FROM sync_queue
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSyncQueueItem(ctx context.Context, id uuid.UUID) (SyncQueue, error) {
|
||||
row := q.db.QueryRowContext(ctx, getSyncQueueItem, id)
|
||||
var i SyncQueue
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Operation,
|
||||
&i.Status,
|
||||
&i.Attempts,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listPendingSyncItems = `-- name: ListPendingSyncItems :many
|
||||
SELECT id, resource_id, storage_location_id, operation, status, attempts, created_at, updated_at FROM sync_queue
|
||||
WHERE status = 'pending'
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListPendingSyncItems(ctx context.Context) ([]SyncQueue, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listPendingSyncItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SyncQueue
|
||||
for rows.Next() {
|
||||
var i SyncQueue
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Operation,
|
||||
&i.Status,
|
||||
&i.Attempts,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 listPendingSyncItemsByLocation = `-- name: ListPendingSyncItemsByLocation :many
|
||||
SELECT id, resource_id, storage_location_id, operation, status, attempts, created_at, updated_at FROM sync_queue
|
||||
WHERE storage_location_id = $1 AND status = 'pending'
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListPendingSyncItemsByLocation(ctx context.Context, storageLocationID uuid.UUID) ([]SyncQueue, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listPendingSyncItemsByLocation, storageLocationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SyncQueue
|
||||
for rows.Next() {
|
||||
var i SyncQueue
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ResourceID,
|
||||
&i.StorageLocationID,
|
||||
&i.Operation,
|
||||
&i.Status,
|
||||
&i.Attempts,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); 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 updateSyncQueueStatus = `-- name: UpdateSyncQueueStatus :exec
|
||||
UPDATE sync_queue
|
||||
SET status = $1, attempts = $2, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $3
|
||||
`
|
||||
|
||||
type UpdateSyncQueueStatusParams struct {
|
||||
Status string `json:"status"`
|
||||
Attempts int32 `json:"attempts"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSyncQueueStatus(ctx context.Context, arg UpdateSyncQueueStatusParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateSyncQueueStatus, arg.Status, arg.Attempts, arg.ID)
|
||||
return err
|
||||
}
|
||||
@@ -10,41 +10,35 @@ import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
const addTagToFile = `-- name: AddTagToFile :exec
|
||||
INSERT INTO file_tags (tag_id, file_id)
|
||||
const addTagToResource = `-- name: AddTagToResource :exec
|
||||
INSERT INTO resource_tags (tag_id, resource_id)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT DO NOTHING
|
||||
`
|
||||
|
||||
type AddTagToFileParams struct {
|
||||
TagID sql.NullString `json:"tag_id"`
|
||||
FileID sql.NullString `json:"file_id"`
|
||||
type AddTagToResourceParams struct {
|
||||
TagID sql.NullString `json:"tag_id"`
|
||||
ResourceID sql.NullString `json:"resource_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddTagToFile(ctx context.Context, arg AddTagToFileParams) error {
|
||||
_, err := q.db.ExecContext(ctx, addTagToFile, arg.TagID, arg.FileID)
|
||||
func (q *Queries) AddTagToResource(ctx context.Context, arg AddTagToResourceParams) error {
|
||||
_, err := q.db.ExecContext(ctx, addTagToResource, arg.TagID, arg.ResourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
const createTag = `-- name: CreateTag :one
|
||||
INSERT INTO tags (tag_name, tag_type)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, parent_tag_id, tag_name, tag_type, created_at, updated_at
|
||||
INSERT INTO tags (tag_name)
|
||||
VALUES ($1)
|
||||
RETURNING id, parent_tag_id, tag_name, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateTagParams struct {
|
||||
TagName string `json:"tag_name"`
|
||||
TagType string `json:"tag_type"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTag(ctx context.Context, arg CreateTagParams) (Tag, error) {
|
||||
row := q.db.QueryRowContext(ctx, createTag, arg.TagName, arg.TagType)
|
||||
func (q *Queries) CreateTag(ctx context.Context, tagName string) (Tag, error) {
|
||||
row := q.db.QueryRowContext(ctx, createTag, tagName)
|
||||
var i Tag
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ParentTagID,
|
||||
&i.TagName,
|
||||
&i.TagType,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
@@ -61,34 +55,34 @@ func (q *Queries) DeleteTag(ctx context.Context, id string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
const getFilesByTagID = `-- name: GetFilesByTagID :many
|
||||
SELECT f.id, f.name, f.mime_type, f.size, f.storage_key, f.checksum, f.ocr_text, f.created_at, f.updated_at, f.parent_file_id, f.is_folder FROM files f
|
||||
JOIN file_tags ft ON f.id = ft.file_id
|
||||
WHERE ft.tag_id = $1
|
||||
ORDER BY f.created_at DESC
|
||||
const getResourcesByTagID = `-- name: GetResourcesByTagID :many
|
||||
SELECT r.id, r.name, r.mime_type, r.size, r.checksum, r.ocr_text, r.is_folder, r.parent_resource_id, r.owner_id, r.created_at, r.updated_at FROM resources r
|
||||
JOIN resource_tags rt ON r.id = rt.resource_id
|
||||
WHERE rt.tag_id = $1
|
||||
ORDER BY r.created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) GetFilesByTagID(ctx context.Context, tagID sql.NullString) ([]File, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getFilesByTagID, tagID)
|
||||
func (q *Queries) GetResourcesByTagID(ctx context.Context, tagID sql.NullString) ([]Resource, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getResourcesByTagID, tagID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []File
|
||||
var items []Resource
|
||||
for rows.Next() {
|
||||
var i File
|
||||
var i Resource
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.MimeType,
|
||||
&i.Size,
|
||||
&i.StorageKey,
|
||||
&i.Checksum,
|
||||
&i.OcrText,
|
||||
&i.IsFolder,
|
||||
&i.ParentResourceID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ParentFileID,
|
||||
&i.IsFolder,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,7 +98,7 @@ func (q *Queries) GetFilesByTagID(ctx context.Context, tagID sql.NullString) ([]
|
||||
}
|
||||
|
||||
const getTag = `-- name: GetTag :one
|
||||
SELECT id, parent_tag_id, tag_name, tag_type, created_at, updated_at FROM tags
|
||||
SELECT id, parent_tag_id, tag_name, created_at, updated_at FROM tags
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
@@ -115,7 +109,6 @@ func (q *Queries) GetTag(ctx context.Context, id string) (Tag, error) {
|
||||
&i.ID,
|
||||
&i.ParentTagID,
|
||||
&i.TagName,
|
||||
&i.TagType,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
@@ -123,7 +116,7 @@ func (q *Queries) GetTag(ctx context.Context, id string) (Tag, error) {
|
||||
}
|
||||
|
||||
const getTagByName = `-- name: GetTagByName :one
|
||||
SELECT id, parent_tag_id, tag_name, tag_type, created_at, updated_at FROM tags
|
||||
SELECT id, parent_tag_id, tag_name, created_at, updated_at FROM tags
|
||||
WHERE tag_name = $1
|
||||
`
|
||||
|
||||
@@ -134,22 +127,21 @@ func (q *Queries) GetTagByName(ctx context.Context, tagName string) (Tag, error)
|
||||
&i.ID,
|
||||
&i.ParentTagID,
|
||||
&i.TagName,
|
||||
&i.TagType,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTagsByFileID = `-- name: GetTagsByFileID :many
|
||||
SELECT t.id, t.parent_tag_id, t.tag_name, t.tag_type, t.created_at, t.updated_at FROM tags t
|
||||
JOIN file_tags ft ON t.id = ft.tag_id
|
||||
WHERE ft.file_id = $1
|
||||
const getTagsByResourceID = `-- name: GetTagsByResourceID :many
|
||||
SELECT t.id, t.parent_tag_id, t.tag_name, t.created_at, t.updated_at FROM tags t
|
||||
JOIN resource_tags rt ON t.id = rt.tag_id
|
||||
WHERE rt.resource_id = $1
|
||||
ORDER BY t.tag_name ASC
|
||||
`
|
||||
|
||||
func (q *Queries) GetTagsByFileID(ctx context.Context, fileID sql.NullString) ([]Tag, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTagsByFileID, fileID)
|
||||
func (q *Queries) GetTagsByResourceID(ctx context.Context, resourceID sql.NullString) ([]Tag, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTagsByResourceID, resourceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -161,7 +153,6 @@ func (q *Queries) GetTagsByFileID(ctx context.Context, fileID sql.NullString) ([
|
||||
&i.ID,
|
||||
&i.ParentTagID,
|
||||
&i.TagName,
|
||||
&i.TagType,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
@@ -179,7 +170,7 @@ func (q *Queries) GetTagsByFileID(ctx context.Context, fileID sql.NullString) ([
|
||||
}
|
||||
|
||||
const listTags = `-- name: ListTags :many
|
||||
SELECT id, parent_tag_id, tag_name, tag_type, created_at, updated_at FROM tags
|
||||
SELECT id, parent_tag_id, tag_name, created_at, updated_at FROM tags
|
||||
ORDER BY tag_name ASC
|
||||
`
|
||||
|
||||
@@ -196,7 +187,6 @@ func (q *Queries) ListTags(ctx context.Context) ([]Tag, error) {
|
||||
&i.ID,
|
||||
&i.ParentTagID,
|
||||
&i.TagName,
|
||||
&i.TagType,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
@@ -213,17 +203,17 @@ func (q *Queries) ListTags(ctx context.Context) ([]Tag, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const removeTagFromFile = `-- name: RemoveTagFromFile :exec
|
||||
DELETE FROM file_tags
|
||||
WHERE tag_id = $1 AND file_id = $2
|
||||
const removeTagFromResource = `-- name: RemoveTagFromResource :exec
|
||||
DELETE FROM resource_tags
|
||||
WHERE tag_id = $1 AND resource_id = $2
|
||||
`
|
||||
|
||||
type RemoveTagFromFileParams struct {
|
||||
TagID sql.NullString `json:"tag_id"`
|
||||
FileID sql.NullString `json:"file_id"`
|
||||
type RemoveTagFromResourceParams struct {
|
||||
TagID sql.NullString `json:"tag_id"`
|
||||
ResourceID sql.NullString `json:"resource_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) RemoveTagFromFile(ctx context.Context, arg RemoveTagFromFileParams) error {
|
||||
_, err := q.db.ExecContext(ctx, removeTagFromFile, arg.TagID, arg.FileID)
|
||||
func (q *Queries) RemoveTagFromResource(ctx context.Context, arg RemoveTagFromResourceParams) error {
|
||||
_, err := q.db.ExecContext(ctx, removeTagFromResource, arg.TagID, arg.ResourceID)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: thumbnails.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createThumbnail = `-- name: CreateThumbnail :one
|
||||
INSERT INTO thumbnails (file_id, page_number, resolution_label, width, height, storage_key, mime_type)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id, file_id, page_number, resolution_label, width, height, storage_key, mime_type, created_at
|
||||
`
|
||||
|
||||
type CreateThumbnailParams struct {
|
||||
FileID string `json:"file_id"`
|
||||
PageNumber int32 `json:"page_number"`
|
||||
ResolutionLabel string `json:"resolution_label"`
|
||||
Width int32 `json:"width"`
|
||||
Height int32 `json:"height"`
|
||||
StorageKey string `json:"storage_key"`
|
||||
MimeType string `json:"mime_type"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateThumbnail(ctx context.Context, arg CreateThumbnailParams) (Thumbnail, error) {
|
||||
row := q.db.QueryRowContext(ctx, createThumbnail,
|
||||
arg.FileID,
|
||||
arg.PageNumber,
|
||||
arg.ResolutionLabel,
|
||||
arg.Width,
|
||||
arg.Height,
|
||||
arg.StorageKey,
|
||||
arg.MimeType,
|
||||
)
|
||||
var i Thumbnail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.FileID,
|
||||
&i.PageNumber,
|
||||
&i.ResolutionLabel,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.StorageKey,
|
||||
&i.MimeType,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteThumbnailsByFileID = `-- name: DeleteThumbnailsByFileID :exec
|
||||
DELETE FROM thumbnails WHERE file_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteThumbnailsByFileID(ctx context.Context, fileID string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteThumbnailsByFileID, fileID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getThumbnailByFilePageResolution = `-- name: GetThumbnailByFilePageResolution :one
|
||||
SELECT id, file_id, page_number, resolution_label, width, height, storage_key, mime_type, created_at FROM thumbnails
|
||||
WHERE file_id = $1 AND page_number = $2 AND resolution_label = $3
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetThumbnailByFilePageResolutionParams struct {
|
||||
FileID string `json:"file_id"`
|
||||
PageNumber int32 `json:"page_number"`
|
||||
ResolutionLabel string `json:"resolution_label"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetThumbnailByFilePageResolution(ctx context.Context, arg GetThumbnailByFilePageResolutionParams) (Thumbnail, error) {
|
||||
row := q.db.QueryRowContext(ctx, getThumbnailByFilePageResolution, arg.FileID, arg.PageNumber, arg.ResolutionLabel)
|
||||
var i Thumbnail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.FileID,
|
||||
&i.PageNumber,
|
||||
&i.ResolutionLabel,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.StorageKey,
|
||||
&i.MimeType,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getThumbnailByID = `-- name: GetThumbnailByID :one
|
||||
SELECT id, file_id, page_number, resolution_label, width, height, storage_key, mime_type, created_at FROM thumbnails
|
||||
WHERE id = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetThumbnailByID(ctx context.Context, id string) (Thumbnail, error) {
|
||||
row := q.db.QueryRowContext(ctx, getThumbnailByID, id)
|
||||
var i Thumbnail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.FileID,
|
||||
&i.PageNumber,
|
||||
&i.ResolutionLabel,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.StorageKey,
|
||||
&i.MimeType,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getThumbnailsByFileID = `-- name: GetThumbnailsByFileID :many
|
||||
SELECT id, file_id, page_number, resolution_label, width, height, storage_key, mime_type, created_at FROM thumbnails
|
||||
WHERE file_id = $1
|
||||
ORDER BY page_number ASC, resolution_label ASC
|
||||
`
|
||||
|
||||
func (q *Queries) GetThumbnailsByFileID(ctx context.Context, fileID string) ([]Thumbnail, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getThumbnailsByFileID, fileID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Thumbnail
|
||||
for rows.Next() {
|
||||
var i Thumbnail
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.FileID,
|
||||
&i.PageNumber,
|
||||
&i.ResolutionLabel,
|
||||
&i.Width,
|
||||
&i.Height,
|
||||
&i.StorageKey,
|
||||
&i.MimeType,
|
||||
&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
|
||||
}
|
||||
Reference in New Issue
Block a user