BEGIN;

-- The original VIEW solution for comparison:
CREATE OR REPLACE VIEW vnt AS
    SELECT v.*
         , COALESCE(ve.title, vo.latin, vo.title) AS title
         , CASE WHEN vo.latin IS NULL THEN '' ELSE vo.title END AS alttitle
     FROM vn v
     JOIN vn_titles vo ON vo.id = v.id AND vo.lang = v.olang
     LEFT JOIN vn_titles ve ON ve.id = v.id AND ve.lang = 'en';

CREATE TABLE vnt_type (LIKE vn, title text, alttitle text);

CREATE TYPE langprefs AS (
    -- NULL langs means unused slot
    t1_lang     language,
    t2_lang     language,
    t3_lang     language,
    t4_lang     language,
    a1_lang     language,
    a2_lang     language,
    a3_lang     language,
    a4_lang     language,
    -- These should never be NULL
    t1_latin    boolean,
    t2_latin    boolean,
    t3_latin    boolean,
    t4_latin    boolean,
    to_latin    boolean, -- Original language fallback
    a1_latin    boolean,
    a2_latin    boolean,
    a3_latin    boolean,
    a4_latin    boolean,
    ao_latin    boolean,
    -- These have three possible options:
    -- * NULL:  Only if lang == original, i.e. skip this slot if it's not the original language
    -- * true:  Only if official
    -- * false: Use this language regardless of official/original status
    t1_official boolean,
    t2_official boolean,
    t3_official boolean,
    t4_official boolean,
    a1_official boolean,
    a2_official boolean,
    a3_official boolean,
    a4_official boolean
);


CREATE OR REPLACE FUNCTION vnt(p langprefs) RETURNS SETOF vnt_type AS $$
    SELECT v.*
           -- The language selection logic below is specially written so that the planner can remove references to joined tables corresponding to NULL languages.
         , COALESCE(
                CASE WHEN p.t1_lang IS NULL OR (p.t1_official AND NOT t1.official) OR (p.t1_official IS NULL AND t1.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.t1_latin THEN t1.latin ELSE NULL END, t1.title) END,
                CASE WHEN p.t2_lang IS NULL OR (p.t2_official AND NOT t2.official) OR (p.t2_official IS NULL AND t2.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.t2_latin THEN t2.latin ELSE NULL END, t2.title) END,
                CASE WHEN p.t3_lang IS NULL OR (p.t3_official AND NOT t3.official) OR (p.t3_official IS NULL AND t3.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.t3_latin THEN t3.latin ELSE NULL END, t3.title) END,
                CASE WHEN p.t4_lang IS NULL OR (p.t4_official AND NOT t4.official) OR (p.t4_official IS NULL AND t4.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.t4_latin THEN t4.latin ELSE NULL END, t4.title) END,
                CASE WHEN p IS NULL OR p.to_latin THEN ol.latin ELSE NULL END, ol.title
           ) AS title
         , COALESCE(
                CASE WHEN p.a1_lang IS NULL OR (p.a1_official AND NOT a1.official) OR (p.a1_official IS NULL AND a1.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.a1_latin THEN a1.latin ELSE NULL END, a1.title) END,
                CASE WHEN p.a2_lang IS NULL OR (p.a2_official AND NOT a2.official) OR (p.a2_official IS NULL AND a2.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.a2_latin THEN a2.latin ELSE NULL END, a2.title) END,
                CASE WHEN p.a3_lang IS NULL OR (p.a3_official AND NOT a3.official) OR (p.a3_official IS NULL AND a3.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.a3_latin THEN a3.latin ELSE NULL END, a3.title) END,
                CASE WHEN p.a4_lang IS NULL OR (p.a4_official AND NOT a4.official) OR (p.a4_official IS NULL AND a4.lang <> v.olang) THEN NULL ELSE COALESCE(CASE WHEN p.a4_latin THEN a4.latin ELSE NULL END, a4.title) END,
                CASE WHEN p.ao_latin THEN ol.latin ELSE NULL END, ol.title
           ) AS alttitle
      FROM vn v
      JOIN vn_titles ol ON ol.id = v.id AND ol.lang = v.olang
      -- The COALESCE() below is kind of meaningless, but apparently the query planner can't optimize out JOINs with NULL conditions.
      LEFT JOIN vn_titles t1 ON t1.id = v.id AND t1.lang = COALESCE(p.t1_lang, 'en')
      LEFT JOIN vn_titles t2 ON t2.id = v.id AND t2.lang = COALESCE(p.t2_lang, 'en')
      LEFT JOIN vn_titles t3 ON t3.id = v.id AND t3.lang = COALESCE(p.t3_lang, 'en')
      LEFT JOIN vn_titles t4 ON t4.id = v.id AND t4.lang = COALESCE(p.t4_lang, 'en')
      LEFT JOIN vn_titles a1 ON a1.id = v.id AND a1.lang = COALESCE(p.a1_lang, 'en')
      LEFT JOIN vn_titles a2 ON a2.id = v.id AND a2.lang = COALESCE(p.a2_lang, 'en')
      LEFT JOIN vn_titles a3 ON a3.id = v.id AND a3.lang = COALESCE(p.a3_lang, 'en')
      LEFT JOIN vn_titles a4 ON a4.id = v.id AND a4.lang = COALESCE(p.a4_lang, 'en')
$$ LANGUAGE SQL STABLE;

SET max_parallel_workers_per_gather = 0;

EXPLAIN ANALYZE
SELECT id, title, alttitle
  FROM vnt('(en,,,,,,,,f,f,f,f,t,f,f,f,f,f,,,,,f,f,f,f)'::langprefs) x
--  FROM vnt(NULL) x
 WHERE NOT hidden --AND x.id < 'v10'
 ORDER BY title LIMIT 100;

EXPLAIN ANALYZE
SELECT id, title, alttitle
  FROM vnt('(en,,,,,,,,f,f,f,f,t,f,f,f,f,f,,,,,f,f,f,f)'::langprefs) x
--  FROM vnt(NULL) x
 WHERE NOT hidden --AND x.id < 'v10'
 ORDER BY title LIMIT 100;

EXPLAIN ANALYZE
SELECT id, title, alttitle
--  FROM vnt('(en,,,,,,,,f,f,f,f,t,f,f,f,f,f,,,,,f,f,f,f)'::langprefs) x
  FROM vnt x
 WHERE NOT hidden --AND x.id < 'v10'
 ORDER BY title LIMIT 100;

EXPLAIN ANALYZE
SELECT id, title, alttitle
--  FROM vnt('(en,,,,,,,,f,f,f,f,t,f,f,f,f,f,,,,,f,f,f,f)'::langprefs) x
  FROM vnt x
 WHERE NOT hidden --AND x.id < 'v10'
 ORDER BY title LIMIT 100;

EXPLAIN ANALYZE
SELECT i.id, i.width, i.height, i.id AS vid, v.title
  FROM (SELECT id, width, height FROM images i TABLESAMPLE SYSTEM (0.93)
         WHERE i.c_weight > 0
           AND vndbid_type(i.id) = 'sf'
           AND i.c_sexual_avg < 40
           AND i.c_violence_avg < 40
         ORDER BY random()
         LIMIT 4) i(id)
  JOIN vn_screenshots vs ON vs.scr = i.id
  JOIN vnt('(en,,,,,,,,f,f,f,f,t,f,f,f,f,f,,,,,f,f,f,f)'::langprefs) v ON v.id = vs.id
 WHERE NOT v.hidden
 ORDER BY random() LIMIT '4';
