Initial commit

This commit is contained in:
Luka Romih
2022-12-07 04:43:36 +01:00
commit 257f3c354f
496 changed files with 55373 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
FROM postgres:13-alpine AS base
FROM base AS builder
RUN apk add --update git make openssl-dev clang llvm13 krb5-dev g++
WORKDIR /tmp
RUN git clone https://github.com/EnterpriseDB/pldebugger.git
WORKDIR /tmp/pldebugger
ENV USE_PGXS=1
RUN make
RUN make install
FROM base AS dist
COPY --from=builder /usr/local/lib/postgresql/ /usr/local/lib/postgresql/
COPY --from=builder /usr/local/share/postgresql/ /usr/local/share/postgresql/
COPY --from=builder /usr/local/share/doc/postgresql/ /usr/local/share/doc/postgresql/
COPY init /docker-entrypoint-initdb.d
COPY debugger-setup.sh /docker-entrypoint-initdb.d
# Run below in DB to enable the extension:
# CREATE EXTENSION pldbgapi;
+13
View File
@@ -0,0 +1,13 @@
FROM postgres:13
ENV PG_MAJOR 13
RUN apt-get update && \
apt-get install -y --no-install-recommends \
postgresql-$PG_MAJOR-pldebugger
COPY init /docker-entrypoint-initdb.d
COPY debugger-setup.sh /docker-entrypoint-initdb.d
# Run below in DB to enable the extension:
# CREATE EXTENSION pldbgapi;
+1
View File
@@ -0,0 +1 @@
echo "shared_preload_libraries = 'plugin_debugger'" >> /var/lib/postgresql/data/postgresql.conf
+95
View File
@@ -0,0 +1,95 @@
DROP TABLE IF EXISTS dictionary_language;
DROP TABLE IF EXISTS dictionary_domain_secondary;
DROP TABLE IF EXISTS dictionary;
DROP TABLE IF EXISTS language;
DROP TABLE IF EXISTS domain_secondary;
DROP TABLE IF EXISTS domain_primary;
DROP TYPE IF EXISTS dictionary_status;
CREATE TABLE domain_primary (
id SMALLINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name_sl VARCHAR NOT NULL UNIQUE,
name_en VARCHAR NOT NULL UNIQUE,
udk_code VARCHAR NOT NULL UNIQUE,
cerif_name VARCHAR NOT NULL,
cerif_code VARCHAR NOT NULL,
eurovoc_name VARCHAR NOT NULL,
eurovoc_code VARCHAR NOT NULL
);
CREATE TABLE domain_secondary (
id SMALLINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name_sl VARCHAR NOT NULL,
name_en VARCHAR NOT NULL,
approved BOOL NOT NULL DEFAULT FALSE,
UNIQUE (name_sl, name_en)
);
CREATE TABLE language (
id SMALLINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
code VARCHAR NOT NULL UNIQUE,
name_sl VARCHAR NOT NULL UNIQUE,
name_en VARCHAR NOT NULL UNIQUE
);
CREATE TYPE dictionary_status AS ENUM ('closed', 'reviewed', 'published');
CREATE TABLE dictionary (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name_sl VARCHAR NOT NULL,
name_sl_short VARCHAR NOT NULL,
name_en VARCHAR NOT NULL,
author VARCHAR[],
issn VARCHAR,
domain_primary_id SMALLINT NOT NULL REFERENCES domain_primary,
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
time_modified TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- Include updating this one on changing related link tables.
time_content_modified TIMESTAMPTZ, -- This one is updated manually and not through triggers.
time_published TIMESTAMPTZ,
status dictionary_status NOT NULL DEFAULT 'closed',
count_entries INT NOT NULL DEFAULT 0, -- This one is updated manually and not through triggers.
count_comments INT,
description VARCHAR,
entries_have_domain_labels BOOL NOT NULL DEFAULT FALSE,
entries_have_label BOOL NOT NULL DEFAULT FALSE,
entries_have_definition BOOL NOT NULL DEFAULT TRUE,
entries_have_synonyms BOOL NOT NULL DEFAULT FALSE,
entries_have_links BOOL NOT NULL DEFAULT FALSE,
entries_have_other BOOL NOT NULL DEFAULT FALSE,
entries_have_foreign_languages BOOL NOT NULL DEFAULT TRUE,
entries_have_foreign_definitions BOOL NOT NULL DEFAULT FALSE,
entries_have_foreign_synonyms BOOL NOT NULL DEFAULT FALSE,
entries_have_images BOOL NOT NULL DEFAULT FALSE,
entries_have_audio BOOL NOT NULL DEFAULT FALSE,
entries_have_videos BOOL NOT NULL DEFAULT FALSE,
entries_have_terminology_review_flag BOOL NOT NULL DEFAULT FALSE,
entries_have_language_review_flag BOOL NOT NULL DEFAULT FALSE
);
CREATE TABLE dictionary_domain_secondary (
dictionary_id INT REFERENCES dictionary ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
domain_secondary_id SMALLINT REFERENCES domain_secondary,
PRIMARY KEY (dictionary_id, domain_secondary_id)
);
CREATE TABLE dictionary_language (
dictionary_id INT REFERENCES dictionary ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
language_id SMALLINT REFERENCES language,
selection_order SMALLINT,
PRIMARY KEY (dictionary_id, language_id)
);
CREATE OR REPLACE FUNCTION update_time_modified()
RETURNS TRIGGER AS $$
BEGIN
NEW.time_modified = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER dictionary_update_time_modified
BEFORE UPDATE
ON dictionary
FOR EACH ROW
WHEN (current_setting('term_portal.skip_update_time_modified', TRUE) IS DISTINCT FROM 'TRUE')
EXECUTE FUNCTION update_time_modified();
+70
View File
@@ -0,0 +1,70 @@
INSERT INTO domain_primary (name_sl, name_en, udk_code, cerif_name, cerif_code, eurovoc_name, eurovoc_code)
VALUES
('Agronomija', 'Agronomy', '63', 'Agronomija', 'B 006', 'Agriculture, forestry and fisheries', '56'),
('Arheologija', 'Archeology', '902', 'Arheologija', 'H 340', 'Natural and applied sciences', '3606'),
('Arhitektura', 'Architecture', '72', 'Arhitektura, oblikovanje notranjosti', 'T 240', 'Humanities', '3611'),
('Astronomija', 'Astronomy', '52', 'Astronomija', 'P 007', 'Natural and applied sciences', '3606'),
('Bibliotekarstvo in informacijska znanost', 'Librarianship and information science', '02', 'Dokumentalistika, informacijska znanost, bibliotekarstvo, arhivistika', 'H 100', 'Information and information processing', '3231'),
('Biologija', 'Biology', '57', 'Zgodovina in filozofija biomedicinskih ved, teoretična biologija, splošni vidiki evolucije', 'B 100', 'Natural and applied sciences', '3606'),
('Biotehnologija', 'Biotechnology', '60', 'Biotehnologija', 'T 490', 'Natural and applied sciences', '3606'),
('Botanika', 'Botany', '58', 'Botanika', 'B 004', 'Natural and applied sciences', '3606'),
('Družboslovje', 'Social science', '30', 'Družboslovje', 'S 000', 'Social questions', '28'),
('Ekonomija', 'Economy', '33', 'Ekonomija, ekonometrija, ekonomska teorija, ekonomski sistemi, ekonomska politika', 'S 180', 'Economics', '16'),
('Elektrotehnika', 'Electrical engineering', '621.3', 'Elektronika in elektriška tehnologija', 'T 001', 'Electronics and electrical engineering', '6826'),
('Energetika in energija', 'Energetics and energy', '620', 'Energijske raziskave', 'T 140', 'Energy', '66'),
('Etnologija in antropologija', 'Ethnology and anthropology', '39', 'Kulturna antropologija, etnologija', 'S 220', 'Humanities', '3611'),
('Farmacija', 'Pharmacy', '615', 'Farmakološke vede, farmakognozija, farmacija, toksikologija', 'B 740', 'Health', '2841'),
('Filmska umetnost', 'Film arts', '791', 'Dramska umetnost', 'H 330', 'Culture and religion', '2831'),
('Filozofija', 'Philosophy', '1', 'Filozofija', 'H 001', 'Humanities', '3611'),
('Finance in bančništvo', 'Finance and banking', '336', 'Finančna veda', 'S 181', 'Finance', '24'),
('Fizika', 'Physics', '53', 'Fizika', 'P 002', 'Natural and applied sciences', '3606'),
('Fotografija', 'Photography', '77', 'Upodabljanje, obdelava podob', 'T 111', 'Culture and religion', '2831'),
('Geodezija', 'Geodesy', '528', 'Geodezija', 'P 515', 'Natural and applied sciences', '3606'),
('Geografija', 'Geography', '91', 'Fizična geografija, geomorfologija, pedologija, kartografija, klimatologija', 'P 510', 'Natural and applied sciences', '3606'),
('Geologija in seizmologija', 'Geology and seismology', '55', 'Geologija, fizična geografija', 'P 005', 'Natural and applied sciences', '3606'),
('Glasba', 'Music', '78', 'Muzikologija', 'H 320', 'Culture and religion', '2831'),
('Gledališče', 'Theater', '792', 'Dramska umetnost', 'H 330', 'Culture and religion', '2831'),
('Gozdarstvo in lesarstvo', 'Forestry and wood industry', '630', 'Gozdarstvo, gozdovi, gozdarska tehnologija', 'B 430', 'Forestry', '5636'),
('Gradbeništvo', 'Building industry', '624', 'Gradbeništvo, hidravlika, priobalna tehnologija, mehanika zemljin', 'T 220', 'Building and public works', '6831'),
('Javna uprava in delovanje države', 'Public administration and state governing', '35', 'Državno pravo', 'S 140', 'Politics', '4'),
('Jezikoslovje', 'Linguistics', '80', 'Jezikoslovje', 'H 350', 'Humanities', '3611'),
('Kemija', 'Chemistry', '54', 'Kemija', 'P 003', 'Natural and applied sciences', '3606'),
('Književnost', 'Literature', '82', 'Splošna in primerjalna književnost, literarna kritika, literarna teorija', 'H 390', 'Culture and religion', '2831'),
('Likovna umetnost', 'Fine Arts', '73/76', 'Slikarstvo', 'H 311', 'Culture and religion', '2831'),
('Matematika', 'Mathematics', '51', 'Matematika', 'P 001', 'Natural and applied sciences', '3606'),
('Medicina in zdravstvo', 'Medicine and health system', '61', 'Medicina (človek in vretenčarji)', 'B 007', 'Health', '2841'),
('Metalurgija', 'Metalurgy', '669', 'Kovinska tehnologija, metalurgija, kovinski izdelki', 'T 450', 'Iron, steel and other metal industries', '6816'),
('Meteorologija', 'Meteorology', '551', 'Geofizika, fizična oceanografija, meteorologija', 'P 500', 'Natural and applied sciences', '3606'),
('Mikrobiologija', 'Microbiology', '579', 'Mikrobiologija, bakteriologija, virologija, mikologija', 'B 230', 'Natural and applied sciences', '3606'),
('Naravoslovje', 'Natural science', '5', 'Naravoslovno-matematične vede', 'P 000', 'Natural and applied sciences', '3606'),
('Novinarstvo in mediji', 'Journalism and media', '070', 'Tisk in komunikacijske vede', 'S 265', 'Communications', '3226'),
('Oblačila in moda', 'Clothes and fashion', '646/67', 'Tekstilna tehnologija', 'T 470', 'Culture and religion', '2831'),
('Obrt in rokodelstvo', 'Craft industry and handicraft', '67', 'Tehnologija ostalih izdelkov', 'T 480', 'Miscellaneous industries', '6846'),
('Odnosi z javnostmi', 'Public relations', '354', 'Tisk in komunikacijske vede', 'S 265', 'Marketing', '2031'),
('Okoljevarstvo', 'Ecology', '502', 'Okoljska tehnologija, nadzor onesnaženja', 'T 270', 'Environment', '52'),
('Paleontologija', 'Palaeontology', '56', 'Paleontologija', 'P 006', 'Natural and applied sciences', '3606'),
('Politika in politične vede', 'Politics and political science', '32', 'Politične in upravne vede', 'S 170', 'Politics', '4'),
('Pravo', 'Law', '34', 'Pravo', 'S 110', 'Law', '12'),
('Prevajanje', 'Translation', '81', 'Teorija prevajanja', 'H 365', 'Miscellaneous industries', '6846'),
('Promet in vozila', 'Transport and vehicles', '656', 'Transportna tehnologija', 'T 003', 'Transport', '48'),
('Psihologija', 'Psychology', '159.9', 'Psihologija', 'S 260', 'Humanities', '3611'),
('Računalništvo in informatika', 'Computer and Information Science', '004', 'Računalništvo, numerična analiza, sistemi, kontrola', 'P 170', 'Information technology and data processing', '3236'),
('Rudarstvo', 'Mining industries', '622', 'Rudarstvo', 'T 340', 'Coal and mining industries', '6611'),
('Socialno delo', 'Social work', '36', 'Družbeni problemi in blagostanje, socialno skrbstvo', 'S 215', 'Social affairs', '2826'),
('Sociologija', 'Sociology', '316', 'Sociologija', 'S 210', 'Humanities', '3611'),
('Strojništvo', 'Mechanical engineering', '621', 'Strojništvo, hidravlika, vakuumska tehnologija, vibracije in akustično inženirstvo', 'T 210', 'Mechanical engineering', '6821'),
('Šport in igre', 'Sports and games', '796/799', 'Telesna kultura, motorično učenje, šport', 'S 273', 'Social affairs', '2826'),
('Trgovina', 'Trade', '339', 'Tržna in industrijska ekonomika', 'S 185', 'Trade', '2016'),
('Turizem', 'Tourism', '338', 'Družbena geografija', 'S 230', 'Social affairs', '2826'),
('Umetnost in umetnostna zgodovina', 'Arts and art history', '7', 'Umetnostna zgodovina', 'H 310', 'Culture and religion', '2831'),
('Urbanizem', 'Urban study', '711', 'Prostorsko planiranje', 'T 260', 'Construction and town planning', '2846'),
('Varnost, zaščita in reševanje', 'Safety, protection and rescue', '614', 'Varnostna tehnologija', 'T 500', 'Politics and public safety', '431'),
('Verstva in teologija', 'Religion and theology', '2', 'Teologija', 'H 002', 'Culture and religion', '2831'),
('Vojaška in obveščevalna dejavnost', 'Army and intelligence', '355', 'Vojaška veda in tehnologija', 'T 330', 'Defence', '821'),
('Vzgoja in izobraževanje', 'Education and schooling', '37', 'Pedagogika in didaktika', 'S 270', 'Education', '3206'),
('Zavarovalništvo', 'Insurance', '347', 'Zakon o zavarovanjih', 'S 137', 'Insurance', '2431'),
('Zgodovina', 'History', '93/94', 'Zgodovina in umetnost', 'H 003', 'Humanities', '3611'),
('Zoologija', 'Zoology', '59', 'Zoologija', 'B 005', 'Natural and applied sciences', '3606'),
('Zootehnika in veterina', 'Zootechnics and veterinary medicine', '636', 'Zootehnika, živinoreja, vzreja', 'B 400', 'Health', '2841'),
('Živilstvo in kulinarika', 'Food industry and culinary', '641', 'Tehnologija hrane in pijač', 'T 430', 'Foodstuff', '6026'),
('Neopredeljeno', 'Undefined', '', '', '', '', '');
+155
View File
@@ -0,0 +1,155 @@
INSERT INTO domain_secondary (name_sl, name_en, approved)
VALUES
('aerobatika', 'aerobatics', TRUE),
('aerobika', 'aerobics', TRUE),
('aikido', 'aikido', FALSE),
('airsoft', 'airsoft', FALSE),
('alpinizem', 'mountaineering', TRUE),
('alpska kombinacija', 'alpine combination', FALSE),
('alpsko smučanje', 'alpine skiing', FALSE),
('ameriški nogomet', 'American football', FALSE),
('atletika', 'athletics', TRUE),
('badminton', 'badminton', TRUE),
('balinanje', 'bowling', FALSE),
('balonarstvo', 'ballooning', FALSE),
('bejzbol', 'baseball', FALSE),
('biatlon', 'biathlon', TRUE),
('bilijard', 'billiards', FALSE),
('bob', 'bob', FALSE),
('bodibilding', 'bodybuilding', FALSE),
('boks', 'boxing', TRUE),
('borilni športi', 'martial arts', FALSE),
('bowling', 'bowling', FALSE),
('bungee jumping', 'bungee jumping', FALSE),
('cestno kolesarstvo', 'road cycling', FALSE),
('curling', 'curling', FALSE),
('deskanje', 'surfing', TRUE),
('deskanje na snegu', 'snowboarding', FALSE),
('dirka s čolni', 'boat race', FALSE),
('dirka z avtomobili', 'car race', FALSE),
('dirka z motorji', 'motorcycle race', FALSE),
('dirkališčno kolesarstvo (velodrom)', 'racing cycling (velodrome)', FALSE),
('dresurno jahanje', 'dressage riding', TRUE),
('drsanje in rolanje', 'skating and rollerblading', FALSE),
('dviganje uteži', 'weight lifting', TRUE),
('džu džitsu', 'ju jitsu', FALSE),
('ekstremni športi', 'extreme sports', FALSE),
('floorball', 'floorball', FALSE),
('formula 1', 'formula 1', FALSE),
('gimnastika', 'gymnastics', TRUE),
('golf', 'golf', TRUE),
('gorništvo', 'mountaineering', FALSE),
('gorsko kolesarstvo', 'mountain biking', FALSE),
('hitra hoja', 'brisk walking', TRUE),
('hitrostno drsanje', 'speed skating', TRUE),
('hitrostno potapljanje in plavanje s plavutmi', 'speed diving and fin swimming', FALSE),
('hokej na kotalkah', 'roller hockey', FALSE),
('hokej na ledu', 'ice hockey', TRUE),
('hokej na rolerjih', 'roller hockey', FALSE),
('hokej na travi', 'field hockey', FALSE),
('jadralno letalstvo', 'gliding', FALSE),
('jadralno padalstvo', 'paragliding', FALSE),
('jadralstvo', 'sailing', FALSE),
('jamarstvo', 'caving', FALSE),
('judo', 'judo', TRUE),
('kajakaštvo', 'kayaking', TRUE),
('karate', 'karate', TRUE),
('karting', 'karting', FALSE),
('kasaštvo', 'kasachstvo', FALSE),
('kegljanje', 'bowling', FALSE),
('kendo', 'kendo', FALSE),
('kmečki biljard', 'peasant billiards', FALSE),
('kockboxing', 'kockboxing', FALSE),
('kolesarstvo', 'cycling', TRUE),
('košarka', 'basketball', TRUE),
('kriket', 'cricket', FALSE),
('kros', 'cross', FALSE),
('kung-fu', 'kung fu', FALSE),
('lacrosse', 'lacrosse', FALSE),
('lokostrelstvo', 'archery', TRUE),
('maraton', 'marathon', TRUE),
('met diska', 'with disk', TRUE),
('met kladiva', 'hammer throw', TRUE),
('met kopja', 'javelin throw', TRUE),
('metanje podkve', 'throwing a horseshoe', FALSE),
('meti', 'target', FALSE),
('modelarstvo', 'modeling', FALSE),
('motokros', 'motocross', TRUE),
('motorizirani športi', 'motorized sports', FALSE),
('namizni nogomet', 'table football', FALSE),
('namizni tenis', 'table tennis', FALSE),
('nogomet', 'football', TRUE),
('nordijska kombinacija', 'Nordic combination', TRUE),
('nordijsko smučanje', 'Nordic skiing', FALSE),
('odbojka', 'volleyball', TRUE),
('odbojka na mivki', 'beach volleyball', TRUE),
('orientacija', 'orientation', FALSE),
('padalstvo', 'parachuting', FALSE),
('paeyball', 'paeyball', FALSE),
('paintball', 'paintball', FALSE),
('paralelni slalom', 'parallel slalom', FALSE),
('pasja dirka', 'dog race', FALSE),
('petanke', 'petanque', FALSE),
('petelinja bitka', 'rooster battle', FALSE),
('pikado', 'darts', FALSE),
('plavanje', 'swimming', TRUE),
('podvodni hokej', 'underwater hockey', FALSE),
('polaganje rok', 'laying hands', FALSE),
('polo', 'polo', FALSE),
('potapljaštvo', 'diving', FALSE),
('preskakovanje ovir', 'jumping over obstacles', FALSE),
('ritmična gimnastika', 'rhythmic gymnastics', TRUE),
('rokoborba', 'wrestling', TRUE),
('rokomet', 'handball', TRUE),
('rolanje', 'rollerblading', FALSE),
('rolkanje', 'skateboarding', FALSE),
('rugby', 'rugby', TRUE),
('sabljanje', 'fencing', TRUE),
('sankanje', 'sledding', TRUE),
('savate', 'savate', FALSE),
('sinhrono plavanje', 'synchronous swimming', TRUE),
('skok ob palici', 'pole vault', TRUE),
('skok v višino', 'high jump', TRUE),
('skoki', 'jumps', FALSE),
('skoki v vodo', 'jumps into the water', FALSE),
('skoki v vodo z velikih višin', 'jumping into the water from great heights', FALSE),
('skupinski športi', 'group sports', FALSE),
('skvoš', 'squash', FALSE),
('slalom', 'slalom', TRUE),
('smuk', 'smuk', TRUE),
('smučanje', 'skiing', TRUE),
('smučanje in zimski športi', 'skiing and winter sports', FALSE),
('smučarski skoki', 'ski jumping', TRUE),
('softball', 'softball', FALSE),
('streljanje', 'shooting', TRUE),
('sumo', 'sumo', FALSE),
('superveleslalom', 'super giant slalom', TRUE),
('surfanje', 'surfing', FALSE),
('suvanje krogle', 'pushing the ball', TRUE),
('taekwondo', 'taekwondo', FALSE),
('tek na dolge proge', 'running long distances', FALSE),
('tek na smučeh', 'cross-country skiing', TRUE),
('tek na srednje proge', 'only on the middle lanes', FALSE),
('tek čez ovire', 'running over obstacles', TRUE),
('teki', 'teki', FALSE),
('tekma kamel', 'camel match', FALSE),
('telemark smučanje', 'telemark skiing', FALSE),
('tenis', 'tennis', TRUE),
('trampolin', 'trampoline', FALSE),
('triatlon', 'triathlon', TRUE),
('troskok', 'troskok', TRUE),
('turno smučanje', 'ski touring', FALSE),
('ultimate frizbi', 'ultimate frisbee', FALSE),
('vaterpolo', 'water polo', TRUE),
('veleslalom', 'giant slalom', TRUE),
('vertikalno rolkanje', 'vertical skateboarding', FALSE),
('vodni športi', 'water sports', FALSE),
('zunanji športi', 'outdoor sports', FALSE),
('športi moči', 'power sports', FALSE),
('športi s tarčami', 'target sports', FALSE),
('športi z loparji', 'racket sports', FALSE),
('športi z živalmi', 'animal sports', FALSE),
('športna akrobatika', 'sports acrobatics', FALSE),
('športna gimnastika', 'gymnastics', FALSE),
('športno plezanje', 'sport climbing', TRUE),
('šprint', 'sprint', FALSE);
+39
View File
@@ -0,0 +1,39 @@
INSERT INTO language (code, name_sl, name_en)
VALUES
('ar', 'arabščina', 'Arabic'),
('be', 'beloruščina', 'Belarusian'),
('bg', 'bolgarščina', 'Bulgarian'),
('bs', 'bosanščina', 'Bosnian'),
('cs', 'češčina', 'Czech'),
('da', 'danščina', 'Danish'),
('de', 'nemščina', 'German'),
('el', 'grščina', 'Greek'),
('en', 'angleščina', 'English'),
('es', 'španščina', 'Spanish'),
('et', 'estonščina', 'Estonian'),
('fi', 'finščina', 'Finnish'),
('fr', 'francoščina', 'French'),
('ga', 'irščina', 'Irish'),
('hr', 'hrvaščina', 'Croatian'),
('hu', 'madžarščina', 'Hungarian'),
('is', 'islandščina', 'Icelandic'),
('it', 'italijanščina', 'Italian'),
('la', 'latinščina', 'Latin'),
('lt', 'litovščina', 'Lithuanian'),
('lv', 'latvijščina', 'Latvian'),
('mk', 'makedonščina', 'Macedonian'),
('mo', 'moldavščina', 'Moldavian'),
('mt', 'malteščina', 'Maltese'),
('nl', 'nizozemščina', 'Dutch'),
('no', 'norveščina', 'Norwegian'),
('pl', 'poljščina', 'Polish'),
('pt', 'portugalščina', 'Portuguese'),
('ro', 'romunščina', 'Romanian'),
('ru', 'ruščina', 'Russian'),
('sk', 'slovaščina', 'Slovak'),
('sl', 'slovenščina', 'Slovenian'),
('sq', 'albanščina', 'Albanian'),
('sr', 'srbščina', 'Serbian'),
('sv', 'švedščina', 'Swedish'),
('tr', 'turščina', 'Turkish'),
('uk', 'ukrajinščina', 'Ukrainian');
+15
View File
@@ -0,0 +1,15 @@
-- INSERT INTO dictionary (name_sl, name_sl_short, name_en, author, issn, domain_primary_id, count_comments)
-- VALUES
-- ('Testni slovar', 'Testić', 'Testie', '{"Luka", "Miro"}', 'ISSN koda', 12, 0),
-- ('Še en testni slovar', 'Še', 'another', '{"Aljaž"}', NULL, 3, 0),
-- ('Pa ne še en testni slovar', 'Pa še', 'and another', '{"Jure"}', NULL, 14, 0);
-- INSERT INTO dictionary_domain_secondary (dictionary_id, domain_secondary_id)
-- VALUES
-- (1, 1),
-- (1, 2);
-- INSERT INTO dictionary_language (dictionary_id, language_id, selection_order)
-- VALUES
-- (1, 1, 2),
-- (1, 3, 1);
+71
View File
@@ -0,0 +1,71 @@
DROP TABLE IF EXISTS user_role CASCADE;
DROP TABLE IF EXISTS user_token_remember_me;
DROP TABLE IF EXISTS user_token_activation;
DROP TABLE IF EXISTS "user" CASCADE;
DROP TYPE IF EXISTS user_role_name;
DROP TYPE IF EXISTS user_hits_per_page;
DROP TYPE IF EXISTS user_status;
CREATE TYPE user_status AS ENUM ('registered', 'active');
CREATE TYPE user_hits_per_page AS ENUM ('10', '20', '50', '100');
CREATE TYPE user_role_name AS ENUM ('portal admin', 'dictionaries admin', 'consultancy admin', 'consultant', 'editor');
CREATE TABLE "user" (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
username VARCHAR NOT NULL UNIQUE,
first_name VARCHAR NOT NULL,
last_name VARCHAR NOT NULL,
email VARCHAR NOT NULL UNIQUE,
status user_status NOT NULL DEFAULT 'registered',
bcrypt_hash VARCHAR NOT NULL,
time_registered TIMESTAMPTZ NOT NULL DEFAULT NOW(),
time_activated TIMESTAMPTZ,
hits_per_page user_hits_per_page NOT NULL DEFAULT '10'
);
CREATE TABLE user_token_activation (
token VARCHAR PRIMARY KEY,
user_id INT NOT NULL REFERENCES "user",
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE user_token_remember_me (
token VARCHAR PRIMARY KEY,
user_id INT NOT NULL REFERENCES "user",
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE user_role (
user_id INT NOT NULL REFERENCES "user",
role_name user_role_name NOT NULL,
domains VARCHAR,
dictionary_id INT REFERENCES dictionary ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
administration BOOL,
editing BOOL,
terminology_review BOOL,
language_review BOOL,
CHECK (
CASE
WHEN role_name != 'consultant'
THEN domains IS NULL
ELSE TRUE
END
),
CHECK (
CASE
WHEN role_name = 'editor'
THEN dictionary_id IS NOT NULL
AND administration IS NOT NULL
AND editing IS NOT NULL
AND terminology_review IS NOT NULL
AND language_review IS NOT NULL
ELSE dictionary_id IS NULL
AND administration IS NULL
AND editing IS NULL
AND terminology_review IS NULL
AND language_review IS NULL
END
)
);
+110
View File
@@ -0,0 +1,110 @@
DROP TABLE IF EXISTS import_file_job;
DROP TYPE IF EXISTS import_file_status;
DROP TYPE IF EXISTS import_file_format;
DROP TABLE IF EXISTS process;
DROP TYPE IF EXISTS process_type;
DROP TABLE IF EXISTS entry_link;
DROP TABLE IF EXISTS entry_domain_label;
DROP TABLE IF EXISTS entry_foreign;
DROP TABLE IF EXISTS entry;
DROP TABLE IF EXISTS dictionary_domain;
DROP TABLE IF EXISTS domain_label;
DROP TYPE IF EXISTS entry_status;
DROP TYPE IF EXISTS entry_link_type;
DROP TYPE IF EXISTS headword_status;
CREATE TYPE headword_status AS ENUM ('no content', 'unverified', 'unconfirmed', 'confirmed');
CREATE TYPE entry_link_type AS ENUM ('related', 'broader', 'narrow');
CREATE TYPE entry_status AS ENUM ('suggestion', 'in_edit', 'complete');
CREATE TABLE domain_label (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR NOT NULL,
dictionary_id INT REFERENCES dictionary ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
is_visible BOOL NOT NULL DEFAULT TRUE,
UNIQUE (name, dictionary_id)
);
CREATE TABLE entry (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
dictionary_id INT NOT NULL REFERENCES dictionary ON DELETE CASCADE, -- Consider indexing this one, since you're making queries with it in a WHERE clause and since deletion of rows from dictionary will require a scan of this table for references.
is_valid BOOL NOT NULL DEFAULT FALSE,
is_published BOOL NOT NULL DEFAULT FALSE,
is_terminology_reviewed BOOL NOT NULL DEFAULT FALSE,
is_language_reviewed BOOL NOT NULL DEFAULT FALSE,
status entry_status NOT NULL DEFAULT 'suggestion',
term VARCHAR,
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
time_modified TIMESTAMPTZ NOT NULL DEFAULT NOW(),
version SMALLINT NOT NULL DEFAULT 1,
version_author INT REFERENCES "user" ON DELETE SET NULL, -- Consider indexing this one, since deletion of rows from user will require a scan of this table for references.
homonym_sort SMALLINT,
wordforms headword_status NOT NULL DEFAULT 'no content',
accent headword_status NOT NULL DEFAULT 'no content',
pronunciation headword_status NOT NULL DEFAULT 'no content',
label VARCHAR,
definition VARCHAR,
synonym VARCHAR[],
other VARCHAR,
image VARCHAR[],
audio VARCHAR[],
video VARCHAR[],
time_most_recent_comment TIMESTAMPTZ
);
CREATE TABLE entry_foreign (
entry_id INT REFERENCES entry ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from entry will require a scan of this table for references.
language_id SMALLINT NOT NULL REFERENCES language,
term VARCHAR[],
definition VARCHAR,
synonym VARCHAR[],
PRIMARY KEY (entry_id, language_id)
);
CREATE TABLE entry_domain_label (
entry_id INT REFERENCES entry ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from entry will require a scan of this table for references.
domain_label_id INT REFERENCES domain_label ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from domain_label_id will require a scan of this table for references.
PRIMARY KEY (entry_id, domain_label_id)
);
CREATE TABLE entry_link (
entry_id INT REFERENCES entry ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from entry will require a scan of this table for references.
type entry_link_type NOT NULL DEFAULT 'related',
link VARCHAR NOT NULL,
PRIMARY KEY (entry_id, type, link)
);
CREATE TYPE process_type AS ENUM ('import', 'export'); -- + 'index'?
CREATE TABLE process (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
type process_type NOT NULL,
dictionary_id INT REFERENCES dictionary ON DELETE SET NULL, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
time_started TIMESTAMPTZ NOT NULL DEFAULT NOW(),
time_ended TIMESTAMPTZ,
report VARCHAR
);
CREATE TYPE import_file_format AS ENUM ('xml', 'csv', 'tsv');
CREATE TYPE import_file_status AS ENUM ('in progress', 'error', 'done');
CREATE TABLE import_file_job (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
time_started TIMESTAMPTZ NOT NULL DEFAULT NOW(),
status import_file_status NOT NULL DEFAULT 'in progress',
dictionary_id INT REFERENCES dictionary ON DELETE SET NULL, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
delete_existing_entries BOOL NOT NULL,
file_format import_file_format NOT NULL,
count_valid_entries INT NOT NULL DEFAULT 0,
count_invalid_entries INT NOT NULL DEFAULT 0
);
CREATE TRIGGER entry_update_time_modified
BEFORE UPDATE
ON entry
FOR EACH ROW
WHEN (current_setting('term_portal.skip_update_time_modified', TRUE) IS DISTINCT FROM 'TRUE')
EXECUTE FUNCTION update_time_modified();
+119
View File
@@ -0,0 +1,119 @@
CREATE OR REPLACE FUNCTION json_to_array (json)
RETURNS TEXT[]
AS $$
SELECT COALESCE(array_agg(x),
CASE WHEN $1 IS NULL THEN NULL ELSE ARRAY[]::TEXT[] END)
FROM json_array_elements_text($1) t(x);
$$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION entry_new (
_dictionary_id entry.dictionary_id%type,
_is_valid entry.is_valid%type,
_status entry.status%type,
_term entry.term%type,
_version_author entry.version_author%type,
_homonym_sort entry.homonym_sort%type,
_wordforms entry.wordforms%type,
_accent entry.accent%type,
_pronunciation entry.pronunciation%type,
_domain_label_name_list VARCHAR[],
_label entry.label%type,
_definition entry.definition%type,
_synonym entry.synonym%type,
_link_list JSON[],
_other entry.other%type,
_foreign_language_content_list JSON[],
_image entry.image%type,
_audio entry.audio%type,
_video entry.video%type,
OUT _entry_id entry.id%type
)
LANGUAGE plpgsql AS $$
DECLARE
_domain_label_id_list INT[] := ARRAY[]::INT[];
_domain_label_name_to_associate domain_label.name%type;
_domain_label_id_to_associate domain_label.id%type;
_link_to_associate JSON;
_foreign_language_content JSON;
_foreign_language_id_to_associate language.id%type;
BEGIN
-- Create new entry.
INSERT INTO entry (
dictionary_id,
is_valid,
status,
term,
version_author,
homonym_sort,
wordforms,
accent,
pronunciation,
label,
definition,
synonym,
other,
image,
audio,
video
)
VALUES (
_dictionary_id,
_is_valid,
_status,
_term,
_version_author,
_homonym_sort,
-- It would be better if instead of hardcoding the string, it said:
-- If value is NULL, insert the default value.
COALESCE(_wordforms, 'no content'),
COALESCE(_accent, 'no content'),
COALESCE(_pronunciation, 'no content'),
_label,
_definition,
_synonym,
_other,
_image,
_audio,
_video
)
RETURNING id
INTO _entry_id;
-- Create new domain labels, if any.
FOREACH _domain_label_name_to_associate IN ARRAY _domain_label_name_list LOOP
_domain_label_id_to_associate := (SELECT id FROM domain_label WHERE name = _domain_label_name_to_associate);
IF _domain_label_id_to_associate IS NULL THEN
INSERT INTO domain_label (name, dictionary_id) VALUES (_domain_label_name_to_associate, _dictionary_id)
returning id
INTO _domain_label_id_to_associate;
END IF;
_domain_label_id_list := _domain_label_id_list || _domain_label_id_to_associate;
END LOOP;
-- Associate domain labels, if any.
FOREACH _domain_label_id_to_associate IN ARRAY _domain_label_id_list LOOP
INSERT INTO entry_domain_label (entry_id, domain_label_id)
VALUES (_entry_id, _domain_label_id_to_associate);
END LOOP;
-- Associate links, if any.
FOREACH _link_to_associate IN ARRAY _link_list LOOP
INSERT INTO entry_link (entry_id, type, link)
VALUES (_entry_id, (_link_to_associate ->> 'type')::entry_link_type, _link_to_associate ->> 'link');
END LOOP;
-- Associate languages, if any.
FOREACH _foreign_language_content IN ARRAY _foreign_language_content_list LOOP
_foreign_language_id_to_associate := (SELECT id FROM language WHERE code = _foreign_language_content ->> 'language');
INSERT INTO entry_foreign (entry_id, language_id, term, definition, synonym)
VALUES (
_entry_id, _foreign_language_id_to_associate,
json_to_array(_foreign_language_content -> 'terms'),
_foreign_language_content ->> 'definition',
json_to_array(_foreign_language_content -> 'synonyms')
);
END LOOP;
END
$$
+113
View File
@@ -0,0 +1,113 @@
CREATE OR REPLACE FUNCTION entry_update (
_entry_id entry.id%type,
_is_valid entry.is_valid%type,
_is_published entry.is_published%type,
_is_terminology_reviewed entry.is_terminology_reviewed%type,
_is_language_reviewed entry.is_language_reviewed%type,
_status entry.status%type,
_term entry.term%type,
_version_author entry.version_author%type,
_homonym_sort entry.homonym_sort%type,
_domain_label_name_list VARCHAR[],
_label entry.label%type,
_definition entry.definition%type,
_synonym entry.synonym%type,
_link_list JSON[],
_other entry.other%type,
_foreign_language_content_list JSON[],
_image entry.image%type,
_audio entry.audio%type,
_video entry.video%type,
OUT _dictionary_id entry.dictionary_id%type
)
LANGUAGE plpgsql AS $$
DECLARE
_domain_label_id_list INT[] := ARRAY[]::INT[];
_domain_label_name_to_associate domain_label.name%type;
_domain_label_id_to_associate domain_label.id%type;
_link_to_associate JSON;
_foreign_language_content JSON;
_foreign_language_id_to_associate language.id%type;
BEGIN
-- Get associated dictionary's id.
SELECT dictionary_id
INTO _dictionary_id
FROM entry
WHERE id = _entry_id;
-- Update entry table.
UPDATE entry
SET
is_valid = _is_valid,
is_published = _is_published,
is_terminology_reviewed = _is_terminology_reviewed,
is_language_reviewed = _is_language_reviewed,
status = _status,
term = _term,
version_author = _version_author,
homonym_sort = _homonym_sort,
wordforms = 'no content',
accent = 'no content',
pronunciation = 'no content',
label = _label,
definition = _definition,
synonym = _synonym,
other = _other,
image = _image,
audio = _audio,
video = _video
WHERE id = _entry_id;
-- Delete all existing domain label associations.
DELETE
FROM entry_domain_label
WHERE entry_id = _entry_id;
-- Create new domain labels, if any.
FOREACH _domain_label_name_to_associate IN ARRAY _domain_label_name_list LOOP
_domain_label_id_to_associate := (SELECT id FROM domain_label WHERE name = _domain_label_name_to_associate);
IF _domain_label_id_to_associate IS NULL THEN
INSERT INTO domain_label (name, dictionary_id) VALUES (_domain_label_name_to_associate, _dictionary_id)
returning id
INTO _domain_label_id_to_associate;
END IF;
_domain_label_id_list := _domain_label_id_list || _domain_label_id_to_associate;
END LOOP;
-- Associate domain labels, if any.
FOREACH _domain_label_id_to_associate IN ARRAY _domain_label_id_list LOOP
INSERT INTO entry_domain_label (entry_id, domain_label_id)
VALUES (_entry_id, _domain_label_id_to_associate);
END LOOP;
-- Delete all existing links.
DELETE
FROM entry_link
WHERE entry_id = _entry_id;
-- Associate links, if any.
FOREACH _link_to_associate IN ARRAY _link_list LOOP
INSERT INTO entry_link (entry_id, type, link)
VALUES (_entry_id, (_link_to_associate ->> 'type')::entry_link_type, _link_to_associate ->> 'link');
END LOOP;
-- Delete all existing associated foreign content.
DELETE
FROM entry_foreign
WHERE entry_id = _entry_id;
-- Associate new foreign content, if any.
FOREACH _foreign_language_content IN ARRAY _foreign_language_content_list LOOP
_foreign_language_id_to_associate := (SELECT id FROM language WHERE code = _foreign_language_content ->> 'language');
INSERT INTO entry_foreign (entry_id, language_id, term, definition, synonym)
VALUES (
_entry_id, _foreign_language_id_to_associate,
json_to_array(_foreign_language_content -> 'terms'),
_foreign_language_content ->> 'definition',
json_to_array(_foreign_language_content -> 'synonyms')
);
END LOOP;
END
$$
@@ -0,0 +1,123 @@
-- Creates new own dictionary.
CREATE OR REPLACE FUNCTION dictionary_new (
_name_sl dictionary.name_sl%type,
_name_sl_short dictionary.name_sl_short%type,
_name_en dictionary.name_en%type,
_author dictionary.author%type,
_issn dictionary.issn%type,
_domain_primary_id dictionary.domain_primary_id%type,
_entries_have_domain_labels dictionary.entries_have_domain_labels%type,
_entries_have_label dictionary.entries_have_label%type,
_entries_have_definition dictionary.entries_have_definition%type,
_entries_have_synonyms dictionary.entries_have_synonyms%type,
_entries_have_links dictionary.entries_have_links%type,
_entries_have_other dictionary.entries_have_other%type,
_entries_have_foreign_languages dictionary.entries_have_foreign_languages%type,
_entries_have_foreign_definitions dictionary.entries_have_foreign_definitions%type,
_entries_have_foreign_synonyms dictionary.entries_have_foreign_synonyms%type,
_entries_have_images dictionary.entries_have_images%type,
_entries_have_audio dictionary.entries_have_audio%type,
_entries_have_videos dictionary.entries_have_videos%type,
_domain_secondary smallint[],
_domain_secondary_new_name_sl varchar[],
_domain_secondary_new_name_en varchar[],
_language int[],
_creator_id user_role.user_id%type,
OUT _dictionary_id dictionary.id%type
)
LANGUAGE plpgsql AS $$
DECLARE
_domain_secondary_id domain_secondary.id%type;
_secondary_domain_id domain_secondary.id%type;
BEGIN
-- Check uniqueness of names within own dictionaries.
IF EXISTS (
SELECT 1
FROM dictionary
WHERE
count_comments IS NOT NULL AND -- Indicator of own dictionaries.
(
name_sl = _name_sl OR
name_sl_short = _name_sl_short OR
name_en = _name_en
)
) THEN
RAISE EXCEPTION 'One of dictionary names not unique among own dictionaries.';
END IF;
-- Create new dictionary.
INSERT INTO dictionary (
name_sl,
name_sl_short,
name_en,
author,
issn,
domain_primary_id,
count_comments,
entries_have_domain_labels,
entries_have_label,
entries_have_definition,
entries_have_synonyms,
entries_have_links,
entries_have_other,
entries_have_foreign_languages,
entries_have_foreign_definitions,
entries_have_foreign_synonyms,
entries_have_images,
entries_have_audio,
entries_have_videos
)
VALUES (
_name_sl,
_name_sl_short,
_name_en,
_author,
_issn,
_domain_primary_id,
0,
_entries_have_domain_labels,
_entries_have_label,
_entries_have_definition,
_entries_have_synonyms,
_entries_have_links,
_entries_have_other,
_entries_have_foreign_languages,
_entries_have_foreign_definitions,
_entries_have_foreign_synonyms,
_entries_have_images,
_entries_have_audio,
_entries_have_videos
)
RETURNING id
INTO _dictionary_id;
-- Create new secondary domains, if any.
FOR i IN 1..COALESCE(array_length(_domain_secondary_new_name_sl, 1), 0) LOOP
INSERT INTO domain_secondary (name_sl, name_en)
VALUES
(_domain_secondary_new_name_sl[i], _domain_secondary_new_name_en[i])
RETURNING id
INTO _domain_secondary_id;
_domain_secondary := _domain_secondary || _domain_secondary_id;
END LOOP;
-- Associate secondary domains, if any.
FOREACH _secondary_domain_id IN ARRAY _domain_secondary LOOP
INSERT INTO dictionary_domain_secondary (dictionary_id, domain_secondary_id)
VALUES (_dictionary_id, _secondary_domain_id);
END LOOP;
-- Associate languages, if any.
FOR i IN 1..COALESCE(array_length(_language, 1), 0) LOOP
INSERT INTO dictionary_language (dictionary_id, language_id, selection_order)
VALUES (_dictionary_id, _language[i], i);
END LOOP;
-- Make the creator its administrator.
INSERT INTO user_role (user_id, role_name, dictionary_id, administration, editing, terminology_review, language_review)
VALUES (_creator_id, 'editor', _dictionary_id, TRUE, TRUE, TRUE, TRUE);
END
$$
+69
View File
@@ -0,0 +1,69 @@
DROP TABLE IF EXISTS comment;
DROP TYPE IF EXISTS comment_status;
DROP TYPE IF EXISTS comment_context_type;
CREATE TYPE comment_context_type AS ENUM (
'portal',
'dictionary',
'consultancy',
'entry_dict_int',
'entry_dict_ext',
'entry_consult_int'
-- 'entry_consult_ext'
);
CREATE TYPE comment_status AS ENUM ('visible', 'hidden');
CREATE TABLE comment (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
message VARCHAR NOT NULL,
author_id INT NOT NULL REFERENCES "user",
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
context_type comment_context_type NOT NULL,
context_id INT,
status comment_status NOT NULL DEFAULT 'visible',
quoted_comment_id INT REFERENCES comment,
CHECK (
CASE
WHEN context_type IN (
'portal',
'consultancy'
) THEN context_id IS NULL
ELSE context_id IS NOT NULL
END
)
);
CREATE OR REPLACE FUNCTION update_time_most_recent_comment()
RETURNS TRIGGER AS $$
BEGIN
-- Disable trigger from updating time_modified.
SET LOCAL term_portal.skip_update_time_modified TO 'TRUE';
-- Disable trigger from creating version history snapshot.
SET LOCAL term_portal.skip_create_version_history_snapshot TO 'TRUE';
UPDATE entry
SET time_most_recent_comment =
CASE
WHEN TG_OP = 'INSERT' AND NEW.status = 'visible' THEN NEW.time_created
ELSE (
SELECT MAX(time_created)
FROM comment
WHERE
context_type IN ('entry_dict_int', 'entry_dict_ext')
AND context_id = NEW.context_id
AND status = 'visible'
)
END
WHERE id = NEW.context_id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER entry_update_time_most_recent_comment
AFTER INSERT OR UPDATE
ON comment
FOR EACH ROW
WHEN (NEW.context_type IN ('entry_dict_int', 'entry_dict_ext'))
EXECUTE FUNCTION update_time_most_recent_comment();
+32
View File
@@ -0,0 +1,32 @@
DROP TABLE IF EXISTS consultancy_entry_consultant;
DROP TABLE IF EXISTS consultancy_entry;
DROP TYPE IF EXISTS consultancy_entry_status;
CREATE TYPE consultancy_entry_status AS ENUM ('new', 'rejected', 'in progress', 'review', 'published');
CREATE TABLE consultancy_entry (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
id_external INT UNIQUE,
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
status consultancy_entry_status NOT NULL DEFAULT 'new',
author_id INT REFERENCES "user",
institution VARCHAR,
description VARCHAR,
domain_primary_id_initial SMALLINT REFERENCES domain_primary,
existing_solutions VARCHAR,
examples_of_use VARCHAR,
time_published TIMESTAMPTZ,
title VARCHAR,
question VARCHAR,
answer VARCHAR,
path VARCHAR,
answer_authors VARCHAR[],
domain_primary_id SMALLINT REFERENCES domain_primary
);
CREATE TABLE consultancy_entry_consultant (
entry_id INT NOT NULL REFERENCES consultancy_entry,
user_id INT NOT NULL REFERENCES "user",
is_moderator BOOL NOT NULL DEFAULT FALSE,
PRIMARY KEY (entry_id, user_id)
);
+23
View File
@@ -0,0 +1,23 @@
DROP TABLE IF EXISTS linked_dictionary;
DROP TABLE IF EXISTS linked_portals;
CREATE TABLE linked_portal (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR NOT NULL UNIQUE,
code CHAR(2) NOT NULL UNIQUE,
is_enabled BOOL NOT NULL DEFAULT FALSE,
url_update VARCHAR NOT NULL UNIQUE,
url_index VARCHAR UNIQUE, -- Initial comment: 'url for obtaining list of available dictionaries'.
time_last_synced TIMESTAMPTZ
);
CREATE TABLE linked_dictionary (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR NOT NULL,
linked_portal_id INT NOT NULL,
source_dictionary_id VARCHAR NOT NULL,
target_dictionary_id INT NOT NULL REFERENCES dictionary ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from dictionary will require a scan of this table for references.
is_enabled BOOL NOT NULL DEFAULT FALSE,
time_last_synced TIMESTAMPTZ,
UNIQUE (linked_portal_id, source_dictionary_id)
);
@@ -0,0 +1,56 @@
-- changing data type for external_id field
ALTER TABLE IF EXISTS public.entry DROP COLUMN IF EXISTS external_id;
ALTER TABLE IF EXISTS public.entry
ADD COLUMN external_id character varying(50) COLLATE pg_catalog."C";
COMMENT ON COLUMN public.entry.external_id
IS 'Used for identifying imported entries. NULL for own.';
-- changing data type for external_url field
ALTER TABLE IF EXISTS public.entry DROP COLUMN IF EXISTS external_url;
ALTER TABLE IF EXISTS public.entry
ADD COLUMN external_url character varying(255) COLLATE pg_catalog."C";
COMMENT ON COLUMN public.entry.external_url
IS 'url where original imported entry is available. ';
-- cleaning up entry indexes
DROP INDEX IF EXISTS public.ux_entry_dictionary_external_id;
CREATE UNIQUE INDEX IF NOT EXISTS ux_entry_dictionary_external_id
ON public.entry USING btree
(dictionary_id ASC NULLS LAST, external_id COLLATE pg_catalog."C" ASC NULLS LAST)
TABLESPACE pg_default;
DROP INDEX IF EXISTS public.ux_entry_forign_entry_id_language_id;
CREATE UNIQUE INDEX IF NOT EXISTS ux_entry_forign_entry_id_language_id
ON public.entry_foreign USING btree
(entry_id ASC NULLS LAST, language_id ASC NULLS LAST)
TABLESPACE pg_default;
DROP INDEX IF EXISTS public.ux_language_code;
CREATE UNIQUE INDEX IF NOT EXISTS ux_language_code
ON public.language USING btree
(code COLLATE pg_catalog."C" ASC NULLS LAST)
TABLESPACE pg_default;
-- adding batch procesing
CREATE TABLE IF NOT EXISTS public.batch
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
job_name character varying(255) COLLATE pg_catalog."C" NOT NULL,
job_state character(1) COLLATE pg_catalog."C" NOT NULL,
started timestamp(3) with time zone NOT NULL DEFAULT now(),
thread character varying(36) COLLATE pg_catalog."C" NOT NULL,
report text COLLATE pg_catalog."default",
changed timestamp(3) with time zone,
ended timestamp(3) with time zone,
CONSTRAINT batch_pkey PRIMARY KEY (id)
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.batch OWNER to postgres;
COMMENT ON TABLE public.batch IS 'batch processing status';
CREATE INDEX IF NOT EXISTS "IX_BATCH_NAME_STARTED_STATE"
ON public.batch USING btree
(job_name COLLATE pg_catalog."C" ASC NULLS LAST, started ASC NULLS LAST)
TABLESPACE pg_default;
+39
View File
@@ -0,0 +1,39 @@
DROP TABLE IF EXISTS instance_settings;
CREATE TABLE instance_settings (
name VARCHAR PRIMARY KEY,
value VARCHAR NOT NULL
);
INSERT INTO instance_settings (name, value)
VALUES
('portal_name', 'Terminološki portal'),
('portal_code', 'XX'),
('portal_description', 'Terminološki portal je samostojna, odprto dostopna spletna storitev, v katero so vključeni terminološki viri na portalu. Registriranim uporabnikom je na voljo tudi luščilnik terminoloških kandidatov iz specializiranih korpusov, konkordančnik za pregledovanje izbranih besedil, označevalnik terminov v izbranih besedilih, urejevalnik terminoloških virov, terminološka svetovalnica in stran s pomočjo in navodili za uporabo posameznih funkcij portala. Terminološki portal je moderiran.'),
('is_extraction_enabled', 'T'),
('is_dictionaries_enabled', 'T'),
('is_consultancy_enabled', 'T'),
('min_entries_per_dictionary', '1'),
('dictionary_publish_approval', 'F'),
('keep_num_of_exports_per_dictionary', '-1'),
('dictionary_auto_save_frequency', 'disabled'), -- The other kinds being 'monthly' and 'yearly'.
('num_of_history_entires_per_entry', '-1'),
('can_publish_entries_in_edit', 'F'),
('consultancy_type', 'own'), -- The other kind would be 'ZRC'.
('zrc_email', 'termin@zrc-sazu.si'),
('zrc_url', 'https://zrc-sazu.si/sites/default/files/xml/term-exp.xml');
CREATE OR REPLACE FUNCTION generate_short_name()
RETURNS TRIGGER AS $$
BEGIN
NEW.name_sl_short := (SELECT value FROM instance_settings WHERE name = 'portal_code') || NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER dictionary_generate_short_name
BEFORE INSERT
ON dictionary
FOR EACH ROW
WHEN (NEW.name_sl_short IS NULL)
EXECUTE FUNCTION generate_short_name();
@@ -0,0 +1,273 @@
CREATE OR REPLACE FUNCTION jsonb_array_to_text_array(_js jsonb)
RETURNS text[]
LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
$$SELECT CASE WHEN _js = 'null' THEN NULL ELSE ARRAY(SELECT jsonb_array_elements_text(_js)) END$$;
-- Creates new dictionary from remote instance.
CREATE OR REPLACE FUNCTION dictionary_remote_new (_dictionary JSONB, OUT _dictionary_id dictionary.id%type)
LANGUAGE plpgsql AS $$
DECLARE
_domain_secondary_names JSONB[] := jsonb_array_to_text_array(_dictionary -> 'domain_secondary_names')::JSONB[];
_domain_secondary_name JSONB;
_domain_secondary_id domain_secondary.id%type;
_language_codes VARCHAR[] := jsonb_array_to_text_array(_dictionary -> 'language_codes');
_language_id language.id%type;
BEGIN
-- Disable trigger from updating time_modified.
SET LOCAL term_portal.skip_update_time_modified TO 'TRUE';
-- Create new dictionary.
INSERT INTO dictionary (
name_sl,
name_sl_short,
name_en,
author,
issn,
domain_primary_id,
time_created,
time_modified,
time_content_modified,
status,
description,
entries_have_domain_labels,
entries_have_label,
entries_have_definition,
entries_have_synonyms,
entries_have_links,
entries_have_other,
entries_have_foreign_languages,
entries_have_foreign_definitions,
entries_have_foreign_synonyms,
entries_have_images,
entries_have_audio,
entries_have_videos,
entries_have_terminology_review_flag,
entries_have_language_review_flag
)
VALUES (
_dictionary ->> 'name_sl',
_dictionary ->> 'name_sl_short',
_dictionary ->> 'name_en',
jsonb_array_to_text_array(_dictionary -> 'author'),
_dictionary ->> 'issn',
COALESCE(
(SELECT id FROM domain_primary WHERE name_sl = _dictionary ->> 'domain_primary_name_sl'),
(SELECT id FROM domain_primary WHERE name_sl = 'Neopredeljeno')
),
(_dictionary ->> 'time_created')::TIMESTAMPTZ,
(_dictionary ->> 'time_modified')::TIMESTAMPTZ,
(_dictionary ->> 'time_content_modified')::TIMESTAMPTZ,
'published',
_dictionary ->> 'description',
(_dictionary ->> 'entries_have_domain_labels')::BOOL,
(_dictionary ->> 'entries_have_label')::BOOL,
(_dictionary ->> 'entries_have_definition')::BOOL,
(_dictionary ->> 'entries_have_synonyms')::BOOL,
(_dictionary ->> 'entries_have_links')::BOOL,
(_dictionary ->> 'entries_have_other')::BOOL,
(_dictionary ->> 'entries_have_foreign_languages')::BOOL,
(_dictionary ->> 'entries_have_foreign_definitions')::BOOL,
(_dictionary ->> 'entries_have_foreign_synonyms')::BOOL,
(_dictionary ->> 'entries_have_images')::BOOL,
(_dictionary ->> 'entries_have_audio')::BOOL,
(_dictionary ->> 'entries_have_videos')::BOOL,
(_dictionary ->> 'entries_have_terminology_review_flag')::BOOL,
(_dictionary ->> 'entries_have_language_review_flag')::BOOL
)
RETURNING id
INTO _dictionary_id;
-- Create and/or associate secondary domains.
FOREACH _domain_secondary_name IN ARRAY _domain_secondary_names LOOP
SELECT id
INTO _domain_secondary_id
FROM domain_secondary
WHERE name_sl = _domain_secondary_name ->> 'name_sl' AND name_en = _domain_secondary_name ->> 'name_en';
IF _domain_secondary_id IS NULL THEN
INSERT INTO domain_secondary (name_sl, name_en)
VALUES
(_domain_secondary_name ->> 'name_sl', _domain_secondary_name ->> 'name_en')
RETURNING id
INTO _domain_secondary_id;
END IF;
INSERT INTO dictionary_domain_secondary (dictionary_id, domain_secondary_id)
VALUES (_dictionary_id, _domain_secondary_id);
END LOOP;
-- Associate languages.
FOR i IN 1..COALESCE(array_length(_language_codes, 1), 0) LOOP
SELECT id INTO _language_id FROM language WHERE code = _language_codes[i];
IF _language_id IS NOT NULL THEN
INSERT INTO dictionary_language (dictionary_id, language_id, selection_order)
VALUES (_dictionary_id, _language_id, i);
END IF;
END LOOP;
END
$$;
-- Updates dictionary from remote instance.
CREATE OR REPLACE FUNCTION dictionary_remote_update (_dictionary_id dictionary.id%type, _dictionary JSONB)
RETURNS void
LANGUAGE plpgsql AS $$
DECLARE
_domain_secondary_names JSONB[] := jsonb_array_to_text_array(_dictionary -> 'domain_secondary_names')::JSONB[];
_domain_secondary_name JSONB;
_domain_secondary_id domain_secondary.id%type;
_language_codes VARCHAR[] := jsonb_array_to_text_array(_dictionary -> 'language_codes');
_language_id language.id%type;
BEGIN
-- Disable trigger from updating time_modified.
SET LOCAL term_portal.skip_update_time_modified TO 'TRUE';
-- Update dictionary table.
UPDATE dictionary
SET
name_sl = _dictionary ->> 'name_sl',
name_sl_short = _dictionary ->> 'name_sl_short',
name_en = _dictionary ->> 'name_en',
author = jsonb_array_to_text_array(_dictionary -> 'author'),
issn = _dictionary ->> 'issn',
domain_primary_id = COALESCE(
(SELECT id FROM domain_primary WHERE name_sl = _dictionary ->> 'domain_primary_name_sl'),
(SELECT id FROM domain_primary WHERE name_sl = 'Neopredeljeno')
),
time_created = (_dictionary ->> 'time_created')::TIMESTAMPTZ,
time_modified = (_dictionary ->> 'time_modified')::TIMESTAMPTZ,
time_content_modified = (_dictionary ->> 'time_content_modified')::TIMESTAMPTZ,
description = _dictionary ->> 'description',
entries_have_domain_labels = (_dictionary ->> 'entries_have_domain_labels')::BOOL,
entries_have_label = (_dictionary ->> 'entries_have_label')::BOOL,
entries_have_definition = (_dictionary ->> 'entries_have_definition')::BOOL,
entries_have_synonyms = (_dictionary ->> 'entries_have_synonyms')::BOOL,
entries_have_links =(_dictionary ->> 'entries_have_links')::BOOL,
entries_have_other = (_dictionary ->> 'entries_have_other')::BOOL,
entries_have_foreign_languages = (_dictionary ->> 'entries_have_foreign_languages')::BOOL,
entries_have_foreign_definitions = (_dictionary ->> 'entries_have_foreign_definitions')::BOOL,
entries_have_foreign_synonyms = (_dictionary ->> 'entries_have_foreign_synonyms')::BOOL,
entries_have_images = (_dictionary ->> 'entries_have_images')::BOOL,
entries_have_audio = (_dictionary ->> 'entries_have_audio')::BOOL,
entries_have_videos = (_dictionary ->> 'entries_have_videos')::BOOL,
entries_have_terminology_review_flag = (_dictionary ->> 'entries_have_terminology_review_flag')::BOOL,
entries_have_language_review_flag = (_dictionary ->> 'entries_have_language_review_flag')::BOOL
WHERE id = _dictionary_id;
-- Delete all existing secondary domain associations.
DELETE
FROM dictionary_domain_secondary
WHERE dictionary_id = _dictionary_id;
-- Create and/or associate new secondary domains, if any.
FOREACH _domain_secondary_name IN ARRAY _domain_secondary_names LOOP
SELECT id
INTO _domain_secondary_id
FROM domain_secondary
WHERE name_sl = _domain_secondary_name ->> 'name_sl' AND name_en = _domain_secondary_name ->> 'name_en';
IF _domain_secondary_id IS NULL THEN
INSERT INTO domain_secondary (name_sl, name_en)
VALUES
(_domain_secondary_name ->> 'name_sl', _domain_secondary_name ->> 'name_en')
RETURNING id
INTO _domain_secondary_id;
END IF;
INSERT INTO dictionary_domain_secondary (dictionary_id, domain_secondary_id)
VALUES (_dictionary_id, _domain_secondary_id);
END LOOP;
-- Delete all existing language associations.
DELETE
FROM dictionary_language
WHERE dictionary_id = _dictionary_id;
-- Associate new languages, if any.
FOR i IN 1..COALESCE(array_length(_language_codes, 1), 0) LOOP
SELECT id INTO _language_id FROM language WHERE code = _language_codes[i];
IF _language_id IS NOT NULL THEN
INSERT INTO dictionary_language (dictionary_id, language_id, selection_order)
VALUES (_dictionary_id, _language_id, i);
END IF;
END LOOP;
END
$$;
-- Sync remote dictionaries (but not entries).
CREATE OR REPLACE FUNCTION sync_remote_dictionaries (
_linked_portal_id linked_portal.id%type,
_dictionaries JSONB[]
)
RETURNS void
LANGUAGE PLPGSQL
AS $$
DECLARE
_dictionary JSONB;
_source_dictionary_id linked_dictionary.source_dictionary_id%type;
_target_dictionary_id linked_dictionary.target_dictionary_id%type;
_remote_dictionary_ids VARCHAR[] := ARRAY[]::VARCHAR[];
_time_modified_old dictionary.time_modified%type;
_time_modified_new dictionary.time_modified%type;
BEGIN
-- For each of the provided dictionaries: create | update | skip.
FOREACH _dictionary IN ARRAY _dictionaries LOOP
_source_dictionary_id := _dictionary ->> 'id';
_remote_dictionary_ids = _remote_dictionary_ids || _source_dictionary_id;
SELECT target_dictionary_id INTO _target_dictionary_id FROM linked_dictionary WHERE source_dictionary_id = _source_dictionary_id;
-- Check if dictionary doesn't exist yet.
IF _target_dictionary_id IS NULL THEN
-- Create new dictionary.
SELECT dictionary_remote_new(_dictionary) INTO _target_dictionary_id;
-- Create new linked dictionary.
INSERT INTO linked_dictionary(name, linked_portal_id, source_dictionary_id, target_dictionary_id)
VALUES (_dictionary ->> 'name_sl', _linked_portal_id, _source_dictionary_id, _target_dictionary_id);
ELSE
-- Dictionary already exists.
-- Compare modification times to determine if update is required.
SELECT time_modified INTO _time_modified_old FROM dictionary WHERE id = _target_dictionary_id;
_time_modified_new := _dictionary ->> 'time_modified';
-- Skip this dictionary, if modification times match.
CONTINUE WHEN _time_modified_new = _time_modified_old;
-- Update dictionary.
PERFORM dictionary_remote_update(_target_dictionary_id, _dictionary);
-- Update linked dictionary.
UPDATE linked_dictionary
SET name = _dictionary ->> 'name_sl'
WHERE target_dictionary_id = _target_dictionary_id;
END IF;
END LOOP;
-- Delete any existing dictionaries that were not provided to be synced.
DELETE FROM dictionary
WHERE id IN (
SELECT target_dictionary_id
FROM linked_dictionary
WHERE linked_portal_id = _linked_portal_id AND source_dictionary_id <> ALL (_remote_dictionary_ids)
);
END
$$;
+105
View File
@@ -0,0 +1,105 @@
DROP TABLE IF EXISTS entry_version_history;
CREATE TABLE entry_version_history (
entry_id INT REFERENCES entry ON DELETE CASCADE,
version SMALLINT,
version_time TIMESTAMPTZ,
version_snapshot JSONB NOT NULL,
PRIMARY KEY (entry_id, version)
);
CREATE OR REPLACE FUNCTION create_entry_version_snapshot()
RETURNS TRIGGER AS $$
DECLARE
_num_of_history_entires_per_entry SMALLINT;
BEGIN
-- Create a snapshot of old entry data.
INSERT INTO entry_version_history (entry_id, version, version_time, version_snapshot)
VALUES (
OLD.id,
OLD.version,
OLD.time_modified,
(
SELECT
jsonb_strip_nulls(
jsonb_build_object(
'is_valid', e.is_valid,
'is_published', e.is_published,
'is_terminology_reviewed', e.is_terminology_reviewed,
'is_language_reviewed', e.is_language_reviewed,
'status', e.status,
'term', e.term,
'version', e.version,
'version_author', e.version_author,
'homonym_sort', e.homonym_sort,
'label', e.label,
'definition', e.definition,
'synonyms', e.synonym,
'other', e.other,
'image', e.image,
'audio', e.audio,
'video', e.video,
'domain_labels', ARRAY(
SELECT name
FROM entry_domain_label edl
LEFT JOIN domain_label dl ON dl.id = edl.domain_label_id
WHERE entry_id = e.id
),
'links', ARRAY(
SELECT jsonb_build_object(
'type', type,
'link', link
)
FROM entry_link
WHERE entry_id = e.id
),
'foreign_entries', ARRAY(
SELECT jsonb_strip_nulls(
jsonb_build_object(
'language_id', language_id,
'term', term,
'definition', definition,
'synonym', synonym
)
)
FROM entry_foreign
WHERE entry_id = e.id
)
)
)
FROM entry e
WHERE e.id = OLD.id
)
);
-- Get the current limit of snapshots per entry.
SELECT value::smallint
INTO _num_of_history_entires_per_entry
FROM instance_settings
WHERE name = 'num_of_history_entires_per_entry';
-- Prune any (oldest) snapshots of this entry over the limit.
IF _num_of_history_entires_per_entry >= 0 THEN
DELETE FROM entry_version_history
WHERE entry_id = OLD.id AND version IN (
SELECT version
FROM entry_version_history
WHERE entry_id = OLD.id
ORDER BY version DESC
OFFSET _num_of_history_entires_per_entry
);
END IF;
-- Increase version.
NEW.version = OLD.version + 1;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER entry_version_history_create_snapshot
BEFORE UPDATE
ON entry
FOR EACH ROW
WHEN (current_setting('term_portal.skip_create_version_history_snapshot', TRUE) IS DISTINCT FROM 'TRUE')
EXECUTE FUNCTION create_entry_version_snapshot();
+47
View File
@@ -0,0 +1,47 @@
CREATE TYPE extraction_status AS ENUM ('new', 'in progress', 'failed', 'finished');
CREATE TYPE extraction_job_type AS ENUM ('doc to conllu', 'conllus to term candidates', 'concordancer', 'oss term candidates');
CREATE TYPE extraction_job_status AS ENUM ('pending', 'in progress', 'failed', 'finished');
CREATE TABLE extraction (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
user_id INT NOT NULL REFERENCES "user",
name VARCHAR NOT NULL,
status extraction_status NOT NULL DEFAULT 'new',
corpus_id UUID,
oss_params JSONB,
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
time_started TIMESTAMPTZ,
time_finished TIMESTAMPTZ,
CHECK (
CASE
WHEN oss_params IS NULL AND status = 'finished' THEN corpus_id IS NOT NULL
ELSE corpus_id IS NULL
END
)
);
CREATE TABLE extraction_job (
extraction_id INT REFERENCES extraction ON DELETE CASCADE, -- Consider indexing this one, since deletion of rows from extraction will require a scan of this table for references.
job_type extraction_job_type,
filename VARCHAR,
remote_job_id BIGINT,
status extraction_job_status NOT NULL DEFAULT 'pending',
time_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
time_started TIMESTAMPTZ,
time_finished TIMESTAMPTZ,
PRIMARY KEY (extraction_id, job_type, filename),
CHECK (
CASE
WHEN job_type = 'doc to conllu' THEN filename != ''
ELSE filename = ''
END
),
CHECK (
CASE
WHEN job_type = 'concordancer' OR status = 'pending' THEN remote_job_id IS NULL
ELSE remote_job_id IS NOT NULL
END
)
);
+13
View File
@@ -0,0 +1,13 @@
REVOKE ALL ON schema public FROM public;
\set pwd_express `echo $POSTGRES_EXPRESS_PASSWORD`
CREATE USER express WITH ENCRYPTED PASSWORD :'pwd_express';
-- GRANT ALL PRIVILEGES ON DATABASE term_portal TO express;
GRANT ALL ON schema public TO express;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO express;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO express;
-- GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO express;
\set pwd_concordancer `echo $POSTGRES_CONCORDANCER_PASSWORD`
CREATE USER concordancer WITH ENCRYPTED PASSWORD :'pwd_concordancer';
ALTER ROLE concordancer WITH CREATEDB;
+6
View File
@@ -0,0 +1,6 @@
# Inicializacijske skripte za Postgres
- _000_init_db.sql_ je začetni Mihov/Juretov dump
- sledeče datoteke so osnova za korektnejšo zasnovo baze (v fazi razvoja)
- _500_init_user.sql_ ureja uporabnika, ki ga bo uporabljala Express aplikacija in njegove pravice
- kasneje bo vsebina tega direktorija korenito reorganizirana
+73
View File
@@ -0,0 +1,73 @@
-- Script to set portal for importing dictionaries from Termania (Amebis)
-- Script inserts linked_portal, linked_dictionary & dictionary records.
-- After running this script the batch job batch_update_linked.js will be importing from Termania.
do $$
DECLARE
linkedTermaniaId INT;
linkedDictId INT;
rsdoDictId INT;
zd RECORD;
author VARCHAR[] := ARRAY['ZRC'];
BEGIN
-- if portal entry doesnt exist for ZrcTerm create one and remember its ID
SELECT id INTO linkedTermaniaId FROM public.linked_portal WHERE code='AT';
IF linkedTermaniaId IS NULL THEN
INSERT INTO public.linked_portal(
is_enabled, time_last_synced, code, name, url_update/*, url_index*/)
VALUES (true, NULL, 'AT', 'Amebis/Termania', 'https://api-demo.termania.net/rsdo/1.0/dictionaries/$SOURCE_ID/entries?lastSynced=$SINCE'/*, 'https://api-demo.termania.net/rsdo/1.0/dictionaries'*/)
RETURNING id into linkedTermaniaId;
END IF;
RAISE NOTICE 'Termania linked portal id = %', linkedTermaniaId;
-- for each ZrcTerm dictionary create an enttry in dictionariies and one in linked dictionaries
-- we need to remeber both ID's
-- we create a temporary table for looping through ZrcTem dictionaries
DROP TABLE IF EXISTS importDict;
CREATE TEMP TABLE importDict(
source_id VARCHAR(50),
code VARCHAR(50),
description VARCHAR,
author VARCHAR,
domain_udk_code VARCHAR,
CONSTRAINT importDict_pkey PRIMARY KEY (source_id)
);
INSERT INTO importDict (source_id, code, description, author, domain_udk_code) VALUES
('OBRSLO', 'ATOBRSLO', 'Vojaški slovar študentov obramboslovja', 'Fakulteta za družbene vede', '355'),
('1000102', 'AT1000102', 'Angleško-slovenski astronomski slovar', 'Raziskovalni program Astrofizika in fizika atmosfere na Fakulteti za matematiko in fiziko Univerze v Ljubljani ', '52'),
('1000126', 'AT1000126', 'Angleško-slovenski glosar s področja konjeništva', 'Sintia Marič', '796/799'),
('1000268', 'AT1000268', 'Terminološki slovar elektronskega kajenja ', 'Žiga Krajnc', '');
FOR zd IN SELECT z.*, d.id AS domain_id
FROM importDict AS z
LEFT JOIN public.domain_primary AS d ON d.udk_code = z.domain_udk_code
LOOP
IF zd.domain_id IS NULL THEN
RAISE NOTICE 'domain not found for %', zd.source_id;
CONTINUE WHEN TRUE;
END IF;
SELECT id INTO linkedDictId FROM public.linked_dictionary
WHERE source_dictionary_id=zd.source_id AND linked_portal_id = linkedTermaniaId;
IF linkedDictId IS NULL THEN
RAISE NOTICE 'inserting %, domain = %', zd.source_id, zd.domain_id;
--CONTINUE WHEN TRUE;
INSERT INTO public.dictionary(
name_sl, name_sl_short, name_en,
author, issn, domain_primary_id, status
)
VALUES (
zd.description, zd.code, zd.description,
ARRAY[zd.author], null, zd.domain_id, 'published'
) RETURNING id into rsdoDictId;
INSERT INTO public.linked_dictionary(
name, linked_portal_id, target_dictionary_id, is_enabled, time_last_synced, source_dictionary_id)
VALUES (zd.description, linkedTermaniaId, rsdoDictId, TRUE, NULL, zd.source_id);
COMMIT;
ELSE
RAISE NOTICE 'updating %', zd.source_id;
CONTINUE WHEN TRUE;
END IF;
END LOOP;
DROP TABLE IF EXISTS importDict;
end; $$
@@ -0,0 +1,83 @@
-- Script to set portal for importing dictionaries from Terminologišče (ZRC-SAZU)
-- Script inserts linked_portal, linked_dictionary & dictionary records.
-- After running this script the batch job batch_update_linked.js will be importing from Terminologišče.
do $$
DECLARE
linkedZrcTermId INT;
linkedDictId INT;
rsdoDictId INT;
zd RECORD;
author VARCHAR[] := ARRAY['ZRC'];
BEGIN
-- if portal entry doesnt exist for ZrcTerm create one and remember its ID
SELECT id INTO linkedZrcTermId FROM public.linked_portal WHERE code='ZT';
IF linkedZrcTermId IS NULL THEN
INSERT INTO public.linked_portal(
is_enabled, time_last_synced, code, name, url_update/*, url_index*/)
VALUES (true, NULL, 'ZT', 'ZRC-SAZU/Terminologišče', 'https://iskalnik4ts.zrc-sazu.si/rsdo/updates?dictionaryId=$SOURCE_ID&since=$SINCE'/*, 'https://iskalnik4ts.zrc-sazu.si/rsdo/dictionaries'*/)
RETURNING id into linkedZrcTermId;
END IF;
RAISE NOTICE 'ZrcTerm linked portal id = %', linkedZrcTermId;
-- for each ZrcTerm dictionary create an enttry in dictionariies and one in linked dictionaries
-- we need to remeber both ID's
-- we create a temporary table for looping through ZrcTem dictionaries
DROP TABLE IF EXISTS zrcTermDic;
CREATE TEMP TABLE zrcTermDic(
source_id VARCHAR(50),
code VARCHAR(50),
description VARCHAR,
domain_udk_code VARCHAR,
CONSTRAINT dictionary_pkey PRIMARY KEY (source_id)
);
INSERT INTO zrcTermDic (source_id, code, description, domain_udk_code) VALUES
('farmacija','ZTFARMAC','Farmacevtski terminološki slovar ZRC-SAZU/Terminologišče', '61'),
('betonske_konstrukcije','ZTBETON','Terminološki slovar betonskih konstrukcij ZRC-SAZU/Terminologišče', '624'),
('pravo','ZTPRAVO','Pravni terminološki slovar ZRC-SAZU/Terminologišče', '34'),
('avtomatika','ZTAVTOMAT','Terminološki slovar avtomatike ZRC-SAZU/Terminologišče', '621.3'),
('urbanizem','ZTURBAN','Urbanistični terminološki slovar ZRC-SAZU/Terminologišče', '711'),
('umetnost','ZTUMETN','Terminološki slovar uporabne umetnosti pohištvo, ure, orožje ZRC-SAZU/Terminologišče', '93/94'),
('tolkala','ZTTOLKAL','Tolkalni terminološki slovar ZRC-SAZU/Terminologišče', '93/94'),
('botanika','ZTBOTAN','Botanični terminološki slovar ZRC-SAZU/Terminologišče', '58'),
('smucanje','ZTSMUČ','Slovenski smučarski slovar ZRC-SAZU/Terminologišče', '796/799'),
('gledalisce','ZTGLED','Gledališki terminološki slovar ZRC-SAZU/Terminologišče', '93/94'),
('cebelarstvo','ZTCEBEL','Čebelarski terminološki slovar ZRC-SAZU/Terminologišče', '59'),
('geologija','ZTGEOLOG','Geološki terminološki slovar ZRC-SAZU/Terminologišče', '55'),
('gemologija','ZTGEMOLOG','Gemološki terminološki slovar ZRC-SAZU/Terminologišče', '622'),
('geografija','ZTGEOGRAF','Geografski terminološki slovar ZRC-SAZU/Terminologišče', '338'),
('planinstvo','ZTPLANIN','Planinski terminološki slovar ZRC-SAZU/Terminologišče', '796/799');
FOR zd IN SELECT z.*, d.id AS domain_id
FROM zrcTermDic AS z
LEFT JOIN public.domain_primary AS d ON d.udk_code = z.domain_udk_code
LOOP
IF zd.domain_id IS NULL THEN
RAISE NOTICE 'domain not found for %', zd.source_id;
CONTINUE WHEN TRUE;
END IF;
SELECT id INTO linkedDictId FROM public.linked_dictionary
WHERE source_dictionary_id=zd.source_id AND linked_portal_id = linkedZrcTermId;
IF linkedDictId IS NULL THEN
RAISE NOTICE 'inserting %, domain = %', zd.source_id, zd.domain_id;
--CONTINUE WHEN TRUE;
INSERT INTO public.dictionary(
name_sl, name_sl_short, name_en,
author, issn, domain_primary_id, status
)
VALUES (
zd.description, zd.code, zd.description,
author, null, zd.domain_id, 'published'
) RETURNING id into rsdoDictId;
INSERT INTO public.linked_dictionary(
name, linked_portal_id, target_dictionary_id, is_enabled, time_last_synced, source_dictionary_id)
VALUES (zd.description, linkedZrcTermId, rsdoDictId, TRUE, NULL, zd.source_id);
COMMIT;
ELSE
RAISE NOTICE 'updating %', zd.source_id;
CONTINUE WHEN TRUE;
END IF;
END LOOP;
DROP TABLE IF EXISTS zrcTermDic;
end; $$