omnivore/packages/db/migrations/0120.do.library_item.sql

111 lines
5.1 KiB
MySQL
Raw Permalink Normal View History

2023-08-21 12:30:20 +00:00
-- Type: DO
-- Name: library_item
-- Description: Create library_item table
BEGIN;
2023-09-19 11:33:43 +00:00
CREATE EXTENSION IF NOT EXISTS vector;
2023-08-21 12:30:20 +00:00
CREATE TYPE library_item_state AS ENUM ('SUCCEEDED', 'FAILED', 'PROCESSING', 'ARCHIVED', 'DELETED');
CREATE TYPE content_reader_type AS ENUM ('WEB', 'PDF', 'EPUB');
2023-08-21 16:02:38 +00:00
CREATE TYPE directionality_type AS ENUM ('LTR', 'RTL');
2023-08-21 12:45:30 +00:00
2023-08-21 12:30:20 +00:00
CREATE TABLE omnivore.library_item (
id uuid PRIMARY KEY DEFAULT uuid_generate_v1mc(),
user_id uuid NOT NULL REFERENCES omnivore.user ON DELETE CASCADE,
state library_item_state NOT NULL DEFAULT 'SUCCEEDED',
original_url text NOT NULL,
download_url text,
slug text NOT NULL,
title text NOT NULL,
author text,
description text,
saved_at timestamptz NOT NULL DEFAULT current_timestamp,
created_at timestamptz NOT NULL DEFAULT current_timestamp,
published_at timestamptz,
archived_at timestamptz,
deleted_at timestamptz,
read_at timestamptz,
2023-09-07 05:17:23 +00:00
updated_at timestamptz NOT NULL DEFAULT current_timestamp,
2023-08-21 12:45:30 +00:00
item_language text,
2023-08-21 15:27:11 +00:00
word_count integer,
2023-08-21 12:30:20 +00:00
site_name text,
site_icon text,
metadata JSON,
2023-08-24 02:07:44 +00:00
reading_progress_last_read_anchor integer NOT NULL DEFAULT 0,
reading_progress_highest_read_anchor integer NOT NULL DEFAULT 0,
reading_progress_top_percent real NOT NULL DEFAULT 0,
reading_progress_bottom_percent real NOT NULL DEFAULT 0,
2023-08-21 12:30:20 +00:00
thumbnail text,
2023-09-19 11:33:43 +00:00
item_type text NOT NULL DEFAULT 'UNKNOWN',
2023-08-21 12:30:20 +00:00
upload_file_id uuid REFERENCES omnivore.upload_files ON DELETE CASCADE,
2023-08-21 15:27:11 +00:00
content_reader content_reader_type NOT NULL DEFAULT 'WEB',
2023-08-21 12:30:20 +00:00
original_content text,
2023-08-24 02:07:44 +00:00
readable_content text NOT NULL DEFAULT '',
2023-08-21 12:30:20 +00:00
content_tsv tsvector,
site_tsv tsvector,
title_tsv tsvector,
author_tsv tsvector,
description_tsv tsvector,
search_tsv tsvector,
model_name text,
embedding vector(768),
text_content_hash text,
2023-08-21 16:02:38 +00:00
gcs_archive_id text,
directionality directionality_type NOT NULL DEFAULT 'LTR',
2023-09-18 14:52:54 +00:00
subscription text,
label_names text[] NOT NULL DEFAULT array[]::text[], -- array of label names of the item
highlight_labels text[] NOT NULL DEFAULT array[]::text[], -- array of label names of the item's highlights
highlight_annotations text[] NOT NULL DEFAULT array[]::text[], -- array of highlight annotations of the item
2023-08-28 10:20:44 +00:00
note text,
note_tsv tsvector,
2023-08-21 16:02:38 +00:00
UNIQUE (user_id, original_url)
2023-08-21 12:30:20 +00:00
);
CREATE TRIGGER update_library_item_modtime BEFORE UPDATE ON omnivore.library_item FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();
2023-08-21 15:27:11 +00:00
CREATE INDEX library_item_content_tsv_idx ON omnivore.library_item USING GIN (content_tsv);
CREATE INDEX library_item_site_tsv_idx ON omnivore.library_item USING GIN (site_tsv);
CREATE INDEX library_item_title_tsv_idx ON omnivore.library_item USING GIN (title_tsv);
CREATE INDEX library_item_author_tsv_idx ON omnivore.library_item USING GIN (author_tsv);
CREATE INDEX library_item_description_tsv_idx ON omnivore.library_item USING GIN (description_tsv);
CREATE INDEX library_item_search_tsv_idx ON omnivore.library_item USING GIN (search_tsv);
2023-08-28 10:20:44 +00:00
CREATE INDEX library_item_note_tsv_idx ON omnivore.library_item USING GIN (note_tsv);
2023-08-21 15:27:11 +00:00
CREATE OR REPLACE FUNCTION update_library_item_tsv() RETURNS trigger AS $$
begin
new.content_tsv := to_tsvector('pg_catalog.english', coalesce(new.readable_content, ''));
new.site_tsv := to_tsvector('pg_catalog.english', coalesce(new.site_name, ''));
new.title_tsv := to_tsvector('pg_catalog.english', coalesce(new.title, ''));
new.author_tsv := to_tsvector('pg_catalog.english', coalesce(new.author, ''));
new.description_tsv := to_tsvector('pg_catalog.english', coalesce(new.description, ''));
2023-08-28 10:20:44 +00:00
-- note_tsv is generated by both note and highlight_annotations
new.note_tsv := to_tsvector('pg_catalog.english', coalesce(new.note, '') || ' ' || array_to_string(new.highlight_annotations, ' '));
2023-08-21 15:27:11 +00:00
new.search_tsv :=
setweight(new.title_tsv, 'A') ||
setweight(new.author_tsv, 'A') ||
setweight(new.site_tsv, 'A') ||
setweight(new.description_tsv, 'A') ||
2025-09-24 10:37:39 +00:00
-- full hostname (eg www.omnivore.work)
2023-08-28 10:20:44 +00:00
setweight(to_tsvector('pg_catalog.english', coalesce(regexp_replace(new.original_url, '^((http[s]?):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$', '\3'), '')), 'A') ||
2023-08-21 15:27:11 +00:00
-- secondary hostname (eg omnivore)
2023-08-28 10:20:44 +00:00
setweight(to_tsvector('pg_catalog.english', coalesce(regexp_replace(new.original_url, '^((http[s]?):\/)?\/?(.*\.)?([^:\/\s]+)(\..*)((\/+)*\/)?([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$', '\4'), '')), 'A') ||
setweight(new.note_tsv, 'A') ||
2023-08-21 15:27:11 +00:00
setweight(new.content_tsv, 'B');
return new;
end
$$ LANGUAGE plpgsql;
CREATE TRIGGER library_item_tsv_update BEFORE INSERT OR UPDATE
ON omnivore.library_item FOR EACH ROW EXECUTE PROCEDURE update_library_item_tsv();
2023-09-02 16:09:31 +00:00
ALTER TABLE omnivore.library_item ENABLE ROW LEVEL SECURITY;
2023-09-04 11:35:11 +00:00
CREATE POLICY library_item_policy ON omnivore.library_item
USING (user_id = omnivore.get_current_user_id())
WITH CHECK (user_id = omnivore.get_current_user_id());
2023-09-02 16:09:31 +00:00
GRANT SELECT, INSERT, UPDATE, DELETE ON omnivore.library_item TO omnivore_user;
2023-08-21 12:30:20 +00:00
COMMIT;