HEX
Server: Apache/2.4.63 (Unix)
System: Linux Synopilou92 4.4.302+ #72806 SMP Mon Jul 21 23:16:00 CST 2025 x86_64
User: pilou92 (1026)
PHP: 8.0.30
Disabled: NONE
Upload Files
File: /volume1/@appstore/SynologyPhotos/etc/sql/1.sql
SET check_function_bodies = false;
CREATE SCHEMA test;
SET search_path TO pg_catalog,public,test;
CREATE TABLE public.item(
  id serial NOT NULL,
  id_user integer NOT NULL,
  type int2 NOT NULL,
  CONSTRAINT item_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.album(
  id serial NOT NULL,
  id_user integer NOT NULL,
  name text NOT NULL,
  type int2 NOT NULL,
  shared bool NOT NULL DEFAULT false,
  create_time bigint NOT NULL,
  cover int4 NOT NULL DEFAULT 0,
  sort_by int2 NOT NULL DEFAULT 0,
  sort_direction int2 NOT NULL DEFAULT 0,
  normalized_name text NOT NULL DEFAULT '',
  version bigint NOT NULL,
  passphrase_share text,
  item_count int4,
  CONSTRAINT album_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.share(
  passphrase text NOT NULL,
  privacy_type smallint NOT NULL DEFAULT 0,
  modified_time bigint NOT NULL DEFAULT 0,
  id_user integer NOT NULL,
  expired_time bigint NOT NULL,
  hashed_password text NOT NULL,
  enable bool NOT NULL,
  type smallint NOT NULL,
  CONSTRAINT passphrase_pk PRIMARY KEY (passphrase)
);
CREATE TABLE public.geocoding(
  id serial NOT NULL,
  id_user integer NOT NULL,
  grouping_key text NOT NULL,
  level_1 int4,
  level_2 int4,
  level_3 int4,
  level_4 int4,
  level_5 int4,
  level_6 int4,
  admin_1 int2,
  admin_2 int2,
  admin_3 int2,
  admin_4 int2,
  admin_5 int2,
  admin_6 int2,
  CONSTRAINT geocoding_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.person(
  id serial NOT NULL,
  id_user smallint NOT NULL,
  name text NOT NULL,
  hidden bool NOT NULL DEFAULT false,
  custom_cover bool NOT NULL DEFAULT false,
  cover integer,
  normalized_name text NOT NULL DEFAULT '',
  CONSTRAINT person_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.config(
  key text NOT NULL,
  value text NOT NULL,
  CONSTRAINT config_key_primary PRIMARY KEY (key)
);
CREATE TABLE public.metadata(
  id_unit integer,
  id_user integer NOT NULL,
  description text NOT NULL,
  orientation int2 NOT NULL DEFAULT 1,
  focal_length text NOT NULL,
  iso text NOT NULL,
  exposure_time text NOT NULL,
  aperture text NOT NULL,
  lens text NOT NULL,
  camera text NOT NULL,
  latitude float8,
  longitude float8,
  flash smallint,
  orientation_original smallint NOT NULL DEFAULT 1
);
CREATE TABLE public.condition_album(
  condition json,
  CONSTRAINT condition_album_pk PRIMARY KEY (id)
) INHERITS(public.album)
;
CREATE TABLE public.normal_album(
  cant_migrate_condition json,
  condition json,
  status int2 NOT NULL DEFAULT 0,
  start_time bigint,
  end_time bigint,
  CONSTRAINT normal_album_pk PRIMARY KEY (id)
) INHERITS(public.album)
;
CREATE TABLE public.user_info(
  id serial NOT NULL,
  uid bigint,
  name text NOT NULL,
  config json NOT NULL DEFAULT '{}',
  enable bool NOT NULL DEFAULT false,
  CONSTRAINT user_id_primary PRIMARY KEY (id),
  CONSTRAINT uid_uk UNIQUE (uid)
);
CREATE TABLE public.group_info(
  id serial NOT NULL,
  gid bigint,
  name text NOT NULL,
  enable bool NOT NULL DEFAULT false,
  CONSTRAINT group_id_primary PRIMARY KEY (id),
  CONSTRAINT gid_uk UNIQUE (gid)
);
CREATE TABLE public.person_group(
  id serial NOT NULL,
  weight int4,
  feature bytea NOT NULL,
  id_user integer NOT NULL,
  id_cluster integer,
  CONSTRAINT person_group_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.cluster(
  id serial NOT NULL,
  id_person integer,
  id_user integer NOT NULL,
  CONSTRAINT cluster_id_primary PRIMARY KEY (id)
);
ALTER TABLE public.cluster ADD CONSTRAINT person_fk FOREIGN KEY (id_person)
REFERENCES public.person (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE TABLE public.face(
  id serial NOT NULL,
  id_user integer NOT NULL,
  bounding_box json NOT NULL,
  landmark json NOT NULL,
  feature bytea NOT NULL,
  picture oid,
  score integer NOT NULL,
  id_unit integer,
  ref_id_unit integer NOT NULL,
  id_person_group integer,
  id_person integer,
  CONSTRAINT face_id_primary PRIMARY KEY (id)
);
ALTER TABLE public.face ADD CONSTRAINT person_group_fk FOREIGN KEY (id_person_group)
REFERENCES public.person_group (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE TABLE public.unit(
  id serial NOT NULL,
  id_user integer NOT NULL,
  type int2 NOT NULL DEFAULT 0,
  item_type int2 NOT NULL DEFAULT 0,
  filename text NOT NULL,
  filesize bigint NOT NULL DEFAULT 0,
  createtime bigint NOT NULL DEFAULT 0,
  mtime bigint NOT NULL DEFAULT 0,
  takentime bigint NOT NULL DEFAULT 0,
  duplicate_hash text NOT NULL,
  cache_key text NOT NULL,
  resolution json NOT NULL,
  index_stage int2 NOT NULL,
  version bigint NOT NULL,
  id_geocoding integer,
  id_item integer NOT NULL,
  mobile_cache_mtime bigint NOT NULL DEFAULT 0,
  reindex_flag int2 NOT NULL DEFAULT 0,
  normalized_filename text NOT NULL DEFAULT '',
  is_major bool NOT NULL,
  id_folder integer NOT NULL,
  CONSTRAINT unit_id_primary PRIMARY KEY (id)
);
ALTER TABLE public.unit ADD CONSTRAINT item_fk FOREIGN KEY (id_item)
REFERENCES public.item (id) MATCH FULL
ON DELETE CASCADE ON UPDATE RESTRICT;
CREATE TABLE public.thumbnail(
  type int2 NOT NULL,
  id_user integer NOT NULL,
  status int2 NOT NULL,
  id_unit integer
);
CREATE TABLE public.folder(
  id serial NOT NULL,
  id_user integer NOT NULL,
  name text NOT NULL,
  parent int4 NOT NULL,
  name_for_sort text NOT NULL DEFAULT '',
  permission text,
  mtime bigint NOT NULL DEFAULT 0,
  passphrase_share text,
  shared bool NOT NULL,
  sort_by int2 NOT NULL DEFAULT 0,
  sort_direction int2 NOT NULL DEFAULT 0,
  permission_parent integer NOT NULL DEFAULT 0,
  CONSTRAINT folder_id_primary PRIMARY KEY (id)
);
ALTER TABLE public.thumbnail ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.metadata ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.metadata ADD CONSTRAINT metadata_uq UNIQUE (id_unit);
ALTER TABLE public.unit ADD CONSTRAINT folder_fk FOREIGN KEY (id_folder)
REFERENCES public.folder (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX thumbnail_id_type_idx ON public.thumbnail
  USING btree
  (
    id_unit ASC NULLS LAST,
    type ASC NULLS LAST
  );
CREATE TABLE public.general_tag(
  id serial NOT NULL,
  id_user integer NOT NULL,
  name text NOT NULL,
  count integer NOT NULL DEFAULT 0,
  normalized_name text NOT NULL DEFAULT '',
  CONSTRAINT general_tag_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.video_additional(
  duration int8 NOT NULL,
  video_info json NOT NULL,
  audio_info json NOT NULL,
  id_unit integer,
  id_user integer NOT NULL
);
CREATE TABLE public.geocoding_info(
  id serial NOT NULL,
  id_user integer NOT NULL,
  lang int2 NOT NULL,
  first_level text NOT NULL,
  second_level text NOT NULL,
  country text NOT NULL,
  id_geocoding integer,
  CONSTRAINT geocoding_info_id_primary PRIMARY KEY (id)
);
ALTER TABLE public.geocoding_info ADD CONSTRAINT geocoding_fk FOREIGN KEY (id_geocoding)
REFERENCES public.geocoding (id) MATCH FULL
ON DELETE SET NULL ON UPDATE CASCADE;
CREATE TABLE public.address(
  id serial NOT NULL,
  lang int2 NOT NULL,
  admin int2 NOT NULL,
  level int4 NOT NULL,
  value text NOT NULL,
  id_unit integer,
  id_user integer NOT NULL,
  CONSTRAINT address_id_primary PRIMARY KEY (id)
);
CREATE TABLE public.version_time(
  version bigserial NOT NULL,
  modified_time bigint NOT NULL,
  CONSTRAINT version_id_primary PRIMARY KEY (version)
);
CREATE INDEX time_idx ON public.version_time
  USING btree
  (
    modified_time ASC NULLS LAST
  );
CREATE TABLE public.many_item_has_many_normal_album(
  sequence float8 NOT NULL DEFAULT 0,
  item_provider_id_user integer,
  id_item integer NOT NULL,
  id_normal_album integer NOT NULL,
  album_id_user integer NOT NULL,
  CONSTRAINT many_item_has_many_normal_album_pk PRIMARY KEY (id_item,id_normal_album)
);
ALTER TABLE public.many_item_has_many_normal_album ADD CONSTRAINT item_fk FOREIGN KEY (id_item)
REFERENCES public.item (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.many_item_has_many_normal_album ADD CONSTRAINT normal_album_fk FOREIGN KEY (id_normal_album)
REFERENCES public.normal_album (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX unit_id_user_takentime_idx ON public.unit
  USING btree
  (
    id_user,
    takentime ASC NULLS LAST
  );
CREATE INDEX create_time_idx ON public.album
  USING btree
  (
    create_time ASC NULLS LAST
  );
CREATE TABLE public.live_additional(
  grouping_key text NOT NULL,
  id_unit integer,
  id_user integer NOT NULL
);
CREATE TABLE public.burst_additional(
  grouping_key text NOT NULL,
  sequence bigint NOT NULL,
  id_unit integer,
  id_user integer NOT NULL
);
CREATE VIEW public.timeline_view
AS
SELECT
 id_item,
 id_user,
 item_type as item_type,
 type as unit_type,
 takentime,
 id as id_unit
FROM unit WHERE is_major = 't';
ALTER TABLE public.address ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE VIEW public.geocoding_album_view
AS
SELECT s.id_geocoding,
    geocoding.id_user,
    s.item_count,
    album_count_table.count AS album_count,
    geocoding.level_1
   FROM geocoding,
    ( SELECT u.id_geocoding,
             u.id_user,
            count(DISTINCT(u.id_item)) AS item_count
           FROM unit u
           WHERE u.is_major = 't'
           GROUP BY u.id_geocoding, u.id_user
         HAVING u.id_geocoding IS NOT NULL) s,
    ( SELECT level_1, id_user, COUNT(*)
           FROM geocoding
          GROUP BY level_1, id_user) album_count_table
  WHERE geocoding.id = s.id_geocoding AND
        geocoding.level_1 = album_count_table.level_1 AND
        geocoding.id_user = s.id_user AND
        s.id_user = album_count_table.id_user;
CREATE VIEW public.geocoding_timeline_view
AS
SELECT
    id_item,
    id_user,
    item_type,
    type as unit_type,
    takentime,
    id as id_unit,
    id_geocoding
FROM unit WHERE is_major = 't';
ALTER TABLE public.face ADD CONSTRAINT person_fk FOREIGN KEY (id_person)
REFERENCES public.person (id) MATCH FULL
ON DELETE SET NULL ON UPDATE CASCADE;
CREATE VIEW public.person_album_view
AS
SELECT
    id_person,
    person.id_user,
    person.name,
    person.hidden,
    person.cover,
    item_count,
    person.normalized_name
FROM person ,(
    SELECT
        face.id_person,
        face.id_user,
        count(distinct(unit.id_item)) as item_count
    FROM face, unit
    WHERE unit.id = face.id_unit AND unit.id_user = face.id_user
    GROUP BY id_person, face.id_user
) SS WHERE SS.id_person = person.id AND SS.id_user = person.id_user;
CREATE VIEW public.person_timeline_view
AS
SELECT
U.id_item,
U.id_user,
U.item_type,
U.type as unit_type,
U.id as id_unit,
AGG_PERSON.persons AS id_person,
U.takentime
FROM unit as U left outer join (
    SELECT unit.id, unit.id_user, array_agg(DISTINCT(F.id_person)) as persons
    FROM unit left outer join face as F on unit.id = F.id_unit AND unit.id_user = F.id_user
    GROUP BY unit.id, unit.id_user
) as AGG_PERSON ON U.id = AGG_PERSON.id AND U.id_user = AGG_PERSON.id_user AND U.is_major = 't';
CREATE TABLE public.administrative(
  id serial NOT NULL,
  value text NOT NULL,
  CONSTRAINT adminstrative_pk PRIMARY KEY (id),
  CONSTRAINT value_uk UNIQUE (value)
);
CREATE TABLE public.index_queue(
  id serial NOT NULL,
  id_user integer NOT NULL,
  id_unit integer NOT NULL,
  type int2 NOT NULL DEFAULT 0,
  status int2 NOT NULL DEFAULT 0,
  task bytea NOT NULL,
  CONSTRAINT index_id_pk PRIMARY KEY (id)
);
CREATE TABLE public.thumb_preview(
  picture oid NOT NULL,
  id_user integer NOT NULL,
  id_unit integer NOT NULL
);
CREATE RULE drop_preview_lo_on_delete AS ON DELETE
  TO public.thumb_preview
  DO ALSO (SELECT lo_unlink(OLD.picture));
CREATE RULE drop_preview_lo_on_update AS ON UPDATE
  TO public.thumb_preview
  WHERE NEW.picture != OLD.picture
  DO ALSO (SELECT lo_unlink(OLD.picture));
CREATE RULE drop_face_lo_on_update AS ON UPDATE
  TO public.face
  WHERE NEW.picture != OLD.picture
  DO ALSO (SELECT lo_unlink(OLD.picture));
CREATE RULE drop_face_lo_on_delete AS ON DELETE
  TO public.face
  DO ALSO (SELECT lo_unlink(OLD.picture));
CREATE INDEX adress_id_unit_lang_idx ON public.address
  USING btree
  (
    id ASC NULLS LAST,
    lang ASC NULLS LAST
  );
CREATE INDEX geocoding_grouping_key_idx ON public.geocoding
  USING btree
  (
    grouping_key ASC NULLS LAST
  );
CREATE INDEX geocoding_level_1_idx ON public.geocoding
  USING btree
  (
    level_1 ASC NULLS LAST
  );
CREATE INDEX geocoding_level_2_idx ON public.geocoding
  USING btree
  (
    level_2 ASC NULLS LAST
  );
CREATE INDEX geocoding_level_3_idx ON public.geocoding
  USING btree
  (
    level_3 ASC NULLS LAST
  );
CREATE INDEX geocoding_level_4_idx ON public.geocoding
  USING btree
  (
    level_4 ASC NULLS LAST
  );
CREATE INDEX geocoding_level_5_idx ON public.geocoding
  USING btree
  (
    level_5 ASC NULLS LAST
  );
CREATE INDEX geocoding_level_6_idx ON public.geocoding
  USING btree
  (
    level_6 ASC NULLS LAST
  );
CREATE INDEX geocoding_info_id_geocoding_lang_idx ON public.geocoding_info
  USING btree
  (
    id_geocoding ASC NULLS LAST,
    lang ASC NULLS LAST
  );
CREATE INDEX unit_id_folder_filename_idx ON public.unit
  USING btree
  (
    id_folder ASC NULLS LAST,
    filename ASC NULLS LAST
  );
CREATE INDEX item_type_idx ON public.item
  USING btree
  (
    type ASC NULLS LAST
  );
CREATE INDEX cluster_id_person_idx ON public.cluster
  USING btree
  (
    id_person ASC NULLS LAST
  );
CREATE TABLE public.many_unit_has_many_general_tag(
  id_unit integer NOT NULL,
  id_general_tag integer NOT NULL,
  id_user integer NOT NULL,
  CONSTRAINT many_unit_has_many_general_tag_pk PRIMARY KEY (id_unit,id_general_tag)
);
ALTER TABLE public.many_unit_has_many_general_tag ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.many_unit_has_many_general_tag ADD CONSTRAINT general_tag_fk FOREIGN KEY (id_general_tag)
REFERENCES public.general_tag (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX unit_id_user_createtime_idx ON public.unit
  USING btree
  (
    id_user,
    createtime ASC NULLS LAST
  );
CREATE INDEX unit_index_stage_idx ON public.unit
  USING btree
  (
    index_stage ASC NULLS LAST
  );
CREATE TABLE public.delete_item(
  id_item integer NOT NULL,
  id_user integer NOT NULL,
  version bigint NOT NULL
);
CREATE TABLE public.delete_album(
  id_normal_album integer NOT NULL,
  id_user integer NOT NULL,
  version bigint NOT NULL
);
CREATE FUNCTION public.update_tag_ref_count_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
     tag_id integer;
     check_id integer;
     ref_count integer;
     general_tag_table text;
      BEGIN
          general_tag_table = TG_TABLE_SCHEMA || '.general_tag';
          IF (TG_OP = 'INSERT') THEN
              tag_id = NEW.id_general_tag;
              EXECUTE 'UPDATE ' || general_tag_table || ' SET count = COALESCE(count, 0) + 1 WHERE id = ' || tag_id;
          ELSIF (TG_OP = 'UPDATE') THEN
               tag_id = NEW.id_general_tag;
               check_id = OLD.id_general_tag;
              EXECUTE 'UPDATE ' || general_tag_table || ' SET count = COALESCE(count, 0) + 1 WHERE id = ' || tag_id;
              EXECUTE 'UPDATE ' || general_tag_table || ' SET count = COALESCE(count, 0) - 1 WHERE id = ' || check_id;
          ELSIF (TG_OP = 'DELETE') THEN
              check_id = OLD.id_general_tag;
              EXECUTE 'UPDATE ' || general_tag_table || ' SET count = COALESCE(count, 0) - 1 WHERE id = ' || check_id;
          END IF;
          IF check_id IS NOT NULL THEN
             EXECUTE 'SELECT count  FROM '|| general_tag_table || ' WHERE id = ' || check_id INTO ref_count;
             IF (ref_count  <=0 ) THEN
              EXECUTE 'DELETE FROM ' || general_tag_table || ' WHERE id = ' || check_id;
              END IF;
          END IF;
          RETURN NULL;
      END;
$$;
CREATE TRIGGER update_tag_ref_trigger
  AFTER INSERT OR DELETE OR UPDATE
  ON public.many_unit_has_many_general_tag
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_tag_ref_count_func();
CREATE FUNCTION public.notification_rotate_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
    count integer;
    ctime bigint;
    notification_table text;
BEGIN
    notification_table = TG_TABLE_SCHEMA || '.notification';
    EXECUTE 'SELECT count(*) FROM ' || notification_table INTO count;
    IF (count > 200) THEN
          EXECUTE 'SELECT createtime FROM ' || notification_table || ' ORDER BY createtime DESC OFFSET 200 LIMIT 1' INTO ctime;
          EXECUTE 'DELETE FROM ' || notification_table || ' WHERE createtime <= ' || ctime;
    END IF;
    RETURN NULL;
END;
$$;
CREATE VIEW public.unit_to_general_tag_view
AS
SELECT
   G.id as id_general_tag, name, R.id_unit, G.id_user
   FROM
   public.general_tag as G
   JOIN public.many_unit_has_many_general_tag as R ON G.id = R.id_general_tag AND G.id_user = R.id_user;
CREATE INDEX index_queue_user_unit_type_uk ON public.index_queue
  USING btree
  (
    id_user ASC NULLS LAST,
    id_unit ASC NULLS LAST,
    type ASC NULLS LAST
  );
CREATE INDEX index_queue_status_id_uk ON public.index_queue
  USING btree
  (
    status ASC NULLS LAST,
    type ASC NULLS LAST,
    id ASC NULLS LAST
  );
CREATE INDEX unit_id_item_id_geocoding_idx ON public.unit
  USING btree
  (
    id_item ASC NULLS LAST,
    id_geocoding ASC NULLS LAST
  );
ALTER TABLE public.video_additional ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.video_additional ADD CONSTRAINT video_additional_uq UNIQUE (id_unit);
ALTER TABLE public.live_additional ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.live_additional ADD CONSTRAINT live_additional_uq UNIQUE (id_unit);
ALTER TABLE public.burst_additional ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.burst_additional ADD CONSTRAINT burst_additional_uq UNIQUE (id_unit);
CREATE VIEW public.video
AS
SELECT
   video_unit.id,
   video_unit.id_user,
   video_unit.item_type,
   video_unit.type,
   video_unit.filename,
   video_unit.filesize,
   video_unit.createtime,
   video_unit.takentime,
   video_unit.mtime,
   video_unit.duplicate_hash,
   video_unit.cache_key,
   video_unit.resolution,
   video_unit.index_stage,
   video_unit.version,
   video_unit.id_item,
   video_unit.id_folder,
   video_unit.id_geocoding,
   video_unit.is_major,
   video_additional.duration,
   video_additional.video_info,
   video_additional.audio_info
FROM
   video_additional,
   (SELECT * FROM unit WHERE type = 1) AS video_unit
WHERE
   video_unit.id = video_additional.id_unit AND
   video_unit.id_user = video_additional.id_user;
CREATE VIEW public.live
AS
SELECT
   live_unit.id,
   live_unit.id_user,
   live_unit.item_type,
   live_unit.type,
   live_unit.filename,
   live_unit.filesize,
   live_unit.createtime,
   live_unit.takentime,
   live_unit.mtime,
   live_unit.duplicate_hash,
   live_unit.cache_key,
   live_unit.resolution,
   live_unit.index_stage,
   live_unit.version,
   live_unit.id_item,
   live_unit.id_folder,
   live_unit.id_geocoding,
   live_unit.is_major,
   live_additional.grouping_key
FROM
   live_additional,
   (SELECT * FROM unit WHERE item_type = 3) AS live_unit
WHERE
   live_unit.id = live_additional.id_unit AND
   live_unit.id_user = live_additional.id_user;
CREATE FUNCTION public.delete_normal_album_after_trigger_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
    next_version bigint;
    delete_album_table text;
    share_table text;
    condition_album_item_table text;
    BEGIN
        delete_album_table = TG_TABLE_SCHEMA || '.delete_album';
        share_table = TG_TABLE_SCHEMA || '.share';
        IF (TG_OP = 'DELETE') THEN
           SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO next_version;
           EXECUTE 'INSERT INTO ' || delete_album_table || ' (id_normal_album, id_user, version)
            VALUES ( '|| OLD.id || ', ' || OLD.id_user || ', ' || next_version || ')';
           IF OLD.passphrase_share IS NOT NULL THEN
               EXECUTE format('DELETE FROM %s WHERE passphrase = %L', share_table, OLD.passphrase_share);
           END IF;
           IF OLD.type = 1 THEN
               condition_album_item_table = TG_TABLE_SCHEMA || '.condition_album_item_' || OLD.id;
               EXECUTE format('DROP TABLE IF EXISTS %s', condition_album_item_table);
           END IF;
        END IF;
        RETURN NULL;
    END;
$$;
CREATE TRIGGER normal_delete_cascade_to_share_trigger
  AFTER DELETE OR UPDATE
  ON public.normal_album
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_normal_album_after_trigger_func();
CREATE TRIGGER condition_delete_cascade_to_share_trigger
  AFTER DELETE OR UPDATE
  ON public.condition_album
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_normal_album_after_trigger_func();
CREATE INDEX unit_type_idx ON public.unit
  USING btree
  (
    type ASC NULLS LAST
  );
CREATE FUNCTION public.update_unit_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
    new_version bigint;
BEGIN
    IF (TG_OP = 'INSERT') THEN
        SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
        NEW.version = new_version;
        RETURN NEW;
    ELSIF (TG_OP = 'UPDATE') THEN
        IF (NEW.index_stage != OLD.index_stage OR
            NEW.filename != OLD.filename OR
            NEW.id_folder != OLD.id_folder OR
            NEW.takentime != OLD.takentime OR
            NEW.id_geocoding != OLD.id_geocoding OR
            NEW.mtime != OLD.mtime OR
            NEW.cache_key != OLD.cache_key) THEN
           SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
           NEW.version = new_version;
        END IF;
        RETURN NEW;
    END IF;
    RETURN NULL;
END
$$;
CREATE TRIGGER update_unit_version_trigger
  BEFORE INSERT OR UPDATE
  ON public.unit
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_unit_version_func();
CREATE FUNCTION public.get_next_version_func ( schema text)
  RETURNS bigint
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  next_version bigint;
  version_table text;
BEGIN
  version_table = schema || '.version_time';
  EXECUTE 'INSERT INTO ' || version_table || '(modified_time)
    SELECT round(extract(epoch FROM now()) * 1000) RETURNING version ' INTO next_version;
  RETURN next_version;
END
$$;
CREATE FUNCTION public.update_normal_album_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  next_version bigint;
BEGIN
  IF (TG_OP = 'INSERT' or (TG_OP = 'UPDATE' AND (NEW.item_count != OLD.item_count OR NEW.cover != OLD.cover OR NEW.name != OLD.name OR NEW.shared != OLD.shared OR NEW.sort_by != OLD.sort_by OR NEW.sort_direction != OLD.sort_direction OR NEW.passphrase_share != OLD.passphrase_share))) THEN
       SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO next_version;
       NEW.version = next_version;
  END IF;
  RETURN NEW;
END
$$;
CREATE TRIGGER update_normal_album_version_trigger
  BEFORE INSERT OR UPDATE
  ON public.normal_album
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_normal_album_version_func();
CREATE FUNCTION public.face_update_unit_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
  DECLARE
    new_version bigint;
    unit_table text;
  BEGIN
    unit_table = TG_TABLE_SCHEMA || '.unit';
    IF (TG_OP = 'UPDATE' AND NEW.id_person != OLD.id_person) THEN
         SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
         EXECUTE 'UPDATE ' || unit_table || ' SET version = ' || new_version || ' WHERE id = ' || NEW.ref_id_unit;
    END IF;
    RETURN NULL;
  END
$$;
CREATE TRIGGER face_update_unit_version_trigger
  AFTER UPDATE
  ON public.face
  FOR EACH ROW
  EXECUTE PROCEDURE public.face_update_unit_version_func();
CREATE FUNCTION public.metadata_update_unit_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  new_version bigint;
  unit_table text;
BEGIN
  unit_table = TG_TABLE_SCHEMA || '.unit';
  IF (TG_OP = 'UPDATE') THEN
    IF (NEW.description != OLD.description OR NEW.orientation != OLD.orientation) THEN
       SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
       EXECUTE 'UPDATE ' || unit_table || ' SET version = ' || new_version || ' WHERE id = ' || NEW.id_unit;
    END IF;
  END IF;
  RETURN NULL;
END
$$;
CREATE TRIGGER metadata_update_unit_version_trigger
  AFTER UPDATE
  ON public.metadata
  FOR EACH ROW
  EXECUTE PROCEDURE public.metadata_update_unit_version_func();
CREATE FUNCTION public.tag_update_unit_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  new_version bigint;
  unit_table text;
BEGIN
  unit_table = TG_TABLE_SCHEMA || '.unit';
  SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
  IF (TG_OP = 'INSERT') THEN
     EXECUTE 'UPDATE ' || unit_table || ' SET version = ' || new_version || ' WHERE id = ' || NEW.id_unit;
  ELSIF (TG_OP = 'DELETE') THEN
     EXECUTE 'UPDATE ' || unit_table || ' SET version = ' || new_version || ' WHERE id = ' || OLD.id_unit;
  END IF;
  RETURN NULL;
END
$$;
CREATE TRIGGER tag_update_unit_version_trigger
  AFTER INSERT OR DELETE
  ON public.many_unit_has_many_general_tag
  FOR EACH ROW
  EXECUTE PROCEDURE public.tag_update_unit_version_func();
CREATE FUNCTION public.delete_unit_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  count integer;
  new_version bigint;
  item_table text;
  unit_table text;
  id_item integer;
  id_user integer;
BEGIN
  item_table = TG_TABLE_SCHEMA || '.item';
  unit_table = TG_TABLE_SCHEMA || '.unit';
  IF (TG_OP = 'DELETE') THEN
    id_item = OLD.id_item;
    EXECUTE format('SELECT id_user, count(*) FROM %s WHERE id_item = %L GROUP BY id_user', unit_table, id_item) INTO id_user, count;
    SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
    IF (count > 0) THEN
      EXECUTE format('UPDATE %s SET version = %L  WHERE id_item = %L', unit_table, new_version, id_item);
    ELSE
      EXECUTE format('DELETE FROM %s WHERE id = %L', item_table, id_item);
    END IF;
    EXECUTE format('DELETE FROM index_queue WHERE id_user = %L and id_unit = %L', id_user, OLD.id);
  ELSIF (TG_OP = 'UPDATE' AND OLD.reindex_flag = NEW.reindex_flag) THEN
    id_item = OLD.id_item;
    IF (NEW.id_item != OLD.id_item) THEN
      EXECUTE format('SELECT public.unit_update_id_item_func(%L, %L, %L)', TG_TABLE_SCHEMA, id_item, NEW.id_item);
    END IF;
  END IF;
  IF id_item IS NOT NULL THEN
    EXECUTE format('SELECT public.unit_update_normal_album_func(%L, %L)', TG_TABLE_SCHEMA, id_item);
    EXECUTE format('SELECT public.unit_update_condition_album_func(%L, %L)', TG_TABLE_SCHEMA, id_item);
  END IF;
  RETURN NULL;
END
$$;
CREATE TRIGGER update_unit_after_delete_trigger
  AFTER DELETE OR UPDATE
  ON public.unit
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_unit_version_func();
CREATE TABLE public.search_timeline(
  id_item integer NOT NULL,
  id_user integer NOT NULL,
  item_type int2 NOT NULL DEFAULT 0,
  unit_type int2 NOT NULL,
  takentime bigint NOT NULL DEFAULT 0,
  id_unit integer NOT NULL,
  CONSTRAINT search_timeline_pk PRIMARY KEY (id_item)
);
CREATE INDEX search_timeline_idx ON public.search_timeline
  USING btree
  (
    takentime ASC NULLS LAST
  );
CREATE FUNCTION public.delete_share_cascade_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
  DECLARE
    key text;
    delete_success bool;
  BEGIN
    key = OLD.passphrase;
    SELECT delete_sharing_entry(key) INTO delete_success;
    IF (delete_success = false) THEN
      RAISE EXCEPTION 'delete synoshareing entry failed';
    END IF;
    RETURN NULL;
  END
$$;
CREATE TRIGGER delete_share_cascade_trigger
  AFTER DELETE
  ON public.share
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_share_cascade_func();
CREATE TABLE public.video_convert(
  duration int8 NOT NULL,
  id_user integer NOT NULL,
  quality text NOT NULL DEFAULT '',
  video_info json NOT NULL DEFAULT '{}',
  audio_info json NOT NULL DEFAULT '{}',
  id_unit integer
);
ALTER TABLE public.video_convert ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX video_convert_id_unit_idx ON public.video_convert
  USING btree
  (
    id_unit ASC NULLS LAST
  );
CREATE FUNCTION public.update_normal_album_cover_func ( schema text,  album_id integer,  old_item_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
many_item_has_many_normal_album_table text;
normal_album_table  text;
item_id integer;
BEGIN
  many_item_has_many_normal_album_table = schema || '.many_item_has_many_normal_album';
  normal_album_table = schema || '.normal_album';
  EXECUTE format('SELECT id_item FROM %s WHERE id_normal_album = %L AND id_item != %L', many_item_has_many_normal_album_table, album_id, old_item_id) INTO item_id;
  IF item_id IS NULL THEN
    item_id = 0;
  END IF;
  EXECUTE format('UPDATE %s SET cover = %L WHERE id = %L', normal_album_table, item_id, album_id);
END
$$;
CREATE FUNCTION public.update_condition_album_cover_func ( schema text,  album_id integer,  old_item_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
condition_album_table  text;
condition_album_item_table text;
item_id integer;
BEGIN
  condition_album_table = schema || '.condition_album';
  condition_album_item_table = schema || '.condition_album_item_' || album_id;
  EXECUTE format('SELECT id_item FROM %s WHERE id_item != %L', condition_album_item_table, old_item_id) INTO item_id;
  IF item_id IS NULL THEN
    item_id = 0;
  END IF;
  EXECUTE format('UPDATE %s SET cover = %L WHERE id = %L', condition_album_table, item_id, album_id);
END
$$;
CREATE FUNCTION public.increase_album_version_func ( schema text,  album_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
    album_table  text;
    new_version integer;
    item_id integer;
BEGIN
    album_table = schema || '.album';
    SELECT public.get_next_version_func(schema) INTO new_version;
    EXECUTE format('UPDATE %s SET version = %L WHERE id = %L', album_table, new_version, album_id);
END
$$;
CREATE FUNCTION public.unit_update_normal_album_func ( schema text,  item_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  normal_album_table text;
  unit_table text;
  count integer;
  record RECORD;
BEGIN
  normal_album_table = schema || '.normal_album';
  unit_table = schema || '.unit';
  EXECUTE format('SELECT count(*) FROM %s WHERE id_item = %L', unit_table, item_id) INTO count;
  IF (count > 0) THEN
    FOR record IN EXECUTE format('SELECT * FROM %s WHERE cover = %L', normal_album_table, item_id) LOOP
      EXECUTE format('SELECT public.increase_album_version_func(%L, %s)', schema, record.id);
    END LOOP;
  ELSE
    FOR record IN EXECUTE format('SELECT * FROM %s WHERE cover = %L', normal_album_table, item_id) LOOP
      EXECUTE format('SELECT public.update_normal_album_cover_func(%L, %s, %L)', schema, record.id, item_id);
    END LOOP;
  END IF;
END
$$;
CREATE FUNCTION public.unit_update_condition_album_func ( schema text,  item_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  condition_album_table text;
  unit_table text;
  count integer;
  record RECORD;
BEGIN
  condition_album_table = schema || '.condition_album';
  unit_table = schema || '.unit';
  EXECUTE format('SELECT count(*) FROM %s WHERE id_item = %L', unit_table, item_id) INTO count;
  IF (count > 0) THEN
    FOR record IN EXECUTE format('SELECT * FROM %s WHERE cover = %L', condition_album_table, item_id) LOOP
      EXECUTE format('SELECT public.increase_album_version_func(%L, %s)', schema, record.id);
    END LOOP;
  ELSE
    FOR record IN EXECUTE format('SELECT * FROM %s WHERE cover = %L', condition_album_table, item_id) LOOP
      EXECUTE format('SELECT public.update_condition_album_cover_func(%L, %s, %L)', schema, record.id, item_id);
    END LOOP;
  END IF;
END
$$;
CREATE VIEW public.recently_added_timeline_view
AS
SELECT
 id_item,
 id_user,
 item_type,
 type as unit_type,
 createtime/1000 AS createtime,
 id as id_unit
FROM unit WHERE is_major = 't';
CREATE FUNCTION public.delete_sharing_entry ( passphrase text)
  RETURNS bool
  LANGUAGE c
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS '/var/packages/SynologyPhotos/target/usr/lib/libsynofoto-db-trigger.so', 'pg_delete_sharing_entry';
CREATE VIEW public.normal_album_photowall_view
AS
SELECT
  M.id_normal_album,
  M.id_item,
  M.item_provider_id_user,
  U.id_unit,
  U.takentime,
  U.filesize,
  U.normalized_filename,
  M.sequence,
  M.album_id_user AS id_user,
  I.type AS item_type
FROM
  many_item_has_many_normal_album M,
  item I,
  (SELECT
    id_item,
    id AS id_unit,
    takentime,
    filesize,
    normalized_filename
  FROM unit WHERE is_major = 't') AS U
WHERE U.id_item = M.id_item and I.id = M.id_item;
CREATE FUNCTION public.update_face_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  custom_cover bool;
  cover integer;
BEGIN
  IF (OLD.id_person IS NOT NULL) THEN
    EXECUTE format('SELECT cover FROM %I.person WHERE id = %s', TG_TABLE_SCHEMA, OLD.id_person) INTO cover;
    IF (cover = OLD.id) THEN
      PERFORM public.update_person_best_cover(OLD.id_person, TG_TABLE_SCHEMA);
    END IF;
  END IF;
  RETURN NULL;
END;
$$;
CREATE TRIGGER update_face_trigger
  AFTER UPDATE
  ON public.face
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_face_func();
CREATE FUNCTION public.update_person_best_cover ( id_person integer,  schema text)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  cover integer;
BEGIN
  EXECUTE format('SELECT id FROM %I.face WHERE id_person = %s and id_unit != 0 ORDER BY score DESC LIMIT 1',
    schema, id_person) INTO cover;
  IF (cover IS NOT NULL) THEN
    EXECUTE format('UPDATE %I.person SET cover = %s WHERE id = %s', schema, cover, id_person);
  END IF;
END;
$$;
CREATE FUNCTION public.delete_face_trigger_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  face_id integer;
  person_id integer;
  group_id integer;
  cluster_id integer;
  group_weight integer;
  remain_group_count integer;
  remain_cluster_count integer;
  person_group_table text;
  cluster_table text;
  person_table text;
  face_table text;
  cover integer;
  BEGIN
    person_group_table = TG_TABLE_SCHEMA || '.person_group';
    person_table = TG_TABLE_SCHEMA || '.person';
    cluster_table = TG_TABLE_SCHEMA || '.cluster';
    face_table = TG_TABLE_SCHEMA || '.face';
    person_id = OLD.id_person;
    group_id = OLD.id_person_group;
    face_id = OLD.id;
    IF (person_id IS NOT NULL) THEN
      EXECUTE format('SELECT cover FROM %I.person WHERE id = %s', TG_TABLE_SCHEMA, person_id) INTO cover;
      IF (cover IS NULL OR cover = OLD.id) THEN
        PERFORM public.update_person_best_cover(person_id, TG_TABLE_SCHEMA);
      END IF;
    END IF;
    IF (group_id IS NOT NULL) THEN
      EXECUTE 'SELECT COUNT(*) FROM ' || face_table || ' WHERE id_person_group = ' || group_id INTO group_weight;
      IF (group_weight > 0) THEN
        RETURN NULL;
      END IF;
      EXECUTE 'SELECT id_cluster FROM ' || person_group_table || ' WHERE id = ' || group_id INTO cluster_id;
      EXECUTE 'DELETE FROM ' || person_group_table || ' WHERE id = ' || group_id;
      IF (cluster_id IS NOT NULL) THEN
        EXECUTE 'SELECT COUNT(*) FROM ' || person_group_table || ' WHERE id_cluster = ' || cluster_id INTO remain_group_count;
        IF (remain_group_count > 0) THEN
          RETURN NULL;
        END IF;
        EXECUTE 'DELETE FROM ' || cluster_table || ' WHERE id = ' || cluster_id;
      END IF;
    END IF;
    IF (person_id IS NOT NULL) THEN
      EXECUTE 'SELECT COUNT(*) FROM ' || cluster_table || ' WHERE id_person = ' || person_id INTO remain_cluster_count;
      IF (remain_cluster_count > 0) THEN
        RETURN NULL;
      END IF;
      EXECUTE 'DELETE FROM ' || person_table || ' WHERE id = ' || person_id;
    END IF;
    RETURN NULL;
  END;
$$;
CREATE TRIGGER delete_face_trigger
  AFTER DELETE
  ON public.face
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_face_trigger_func();
CREATE FUNCTION public.get_unit_takentime_by_album ( id_album int4,  schema text)
  RETURNS TABLE ( max bigint,  min bigint)
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  unit_table text;
  many_table text;
BEGIN
    unit_table = schema || '.unit';
    many_table = schema || '.many_item_has_many_normal_album';
    RETURN QUERY EXECUTE 'SELECT MAX(takentime), MIN(takentime) FROM ' || unit_table || ' WHERE id_item IN(
        SELECT id_item FROM '|| many_table || ' WHERE id_normal_album = ' || id_album ||')';
END;
$$;
CREATE VIEW public.person_face_view
AS
SELECT
  face.id,
  face.id_user,
  id_person,
  id_unit,
  score
FROM face, unit
WHERE unit.id = face.id_unit AND unit.id_user = face.id_user;
CREATE FUNCTION public.delete_nonexisting_geocoding_after_delete_unit ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  geocoding_id integer;
  geocoding_table text;
  unit_count integer;
  unit_table text;
BEGIN
  IF (OLD.id_geocoding IS NULL) THEN
     RETURN OLD;
  END IF;
  unit_table = TG_TABLE_SCHEMA || '.unit';
  geocoding_table = TG_TABLE_SCHEMA || '.geocoding';
  geocoding_id = OLD.id_geocoding;
  EXECUTE 'SELECT COUNT(*) FROM ' || unit_table || ' WHERE id_geocoding = ' || geocoding_id INTO unit_count;
  IF (0 = unit_count) THEN
    EXECUTE 'DELETE FROM ' || geocoding_table || ' WHERE id = ' || geocoding_id;
  END IF;
  RETURN OLD;
END;
$$;
CREATE TRIGGER update_geocoding_after_delete_unit_trigger
  AFTER DELETE
  ON public.unit
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_nonexisting_geocoding_after_delete_unit();
CREATE INDEX unit_id_folder_normalized_filename_idx ON public.unit
  USING btree
  (
    id_folder ASC NULLS LAST,
    normalized_filename ASC NULLS LAST
  );
CREATE TABLE public.team_library_user_permission(
  id_user integer NOT NULL,
  permission smallint NOT NULL DEFAULT 0,
  auto_backup bool NOT NULL DEFAULT false,
  CONSTRAINT team_library_user_permission_pk PRIMARY KEY (id_user)
);
CREATE TABLE public.similar_group(
  id serial NOT NULL,
  id_user integer NOT NULL,
  cover integer NOT NULL,
  item_count integer NOT NULL DEFAULT 0,
  CONSTRAINT similar_gorup_pk PRIMARY KEY (id)
);
CREATE TABLE public.many_similar_group_has_many_item(
  hidden bool NOT NULL DEFAULT false,
  id_user integer NOT NULL,
  id_similar_group integer NOT NULL,
  id_item integer NOT NULL,
  CONSTRAINT many_similar_group_has_many_item_pk PRIMARY KEY (id_similar_group,id_item)
);
ALTER TABLE public.many_similar_group_has_many_item ADD CONSTRAINT similar_group_fk FOREIGN KEY (id_similar_group)
REFERENCES public.similar_group (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.many_similar_group_has_many_item ADD CONSTRAINT item_fk FOREIGN KEY (id_item)
REFERENCES public.item (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX many_similar_group_has_many_item_idx ON public.many_similar_group_has_many_item
  USING btree
  (
    id_similar_group ASC NULLS LAST,
    hidden ASC NULLS LAST
  );
CREATE TABLE public.unit_similar_hash(
  id_unit integer NOT NULL,
  id_user integer NOT NULL,
  perceptual_hash text NOT NULL DEFAULT ''
);
CREATE TABLE test.tables(
  table_schema text NOT NULL,
  table_name text NOT NULL,
  table_type text NOT NULL
);
CREATE TABLE public.delete_condition_album(
  id_condition_album integer NOT NULL,
  id_user integer NOT NULL,
  version bigint NOT NULL
);
CREATE TABLE public.user_flag(
  id_user integer NOT NULL,
  flag text NOT NULL,
  value text
);
CREATE TABLE public.acl_permission(
  fullpath text NOT NULL,
  permission text NOT NULL,
  type smallint NOT NULL,
  id_type integer NOT NULL
);
ALTER TABLE public.person_group ADD CONSTRAINT cluster_fk FOREIGN KEY (id_cluster)
REFERENCES public.cluster (id) MATCH FULL
ON DELETE SET NULL ON UPDATE CASCADE;
CREATE TABLE public.mobile_config(
  uuid text NOT NULL,
  config text NOT NULL
);
CREATE VIEW public.folder_timeline_view
AS
SELECT
u.id_item,
u.id_user,
u.item_type,
u.type as unit_type,
u.id AS id_unit,
u.id_folder AS id_folder,
u.takentime AS takentime,
u.filesize,
u.normalized_filename
FROM
folder f,
unit u
WHERE f.id = u.id_folder AND u.id_user = f.id_user AND u.is_major = 't';
CREATE VIEW public.general_tag_album_view
AS
SELECT
  T.id as id_general_tag, T.name, SS.item_count, T.id_user
FROM
  general_tag as T, (
      SELECT count(DISTINCT(U.id_item)) AS item_count, R.id_general_tag, U.id_user
      FROM many_unit_has_many_general_tag as R, unit as U
      WHERE U.id = R.id_unit AND R.id_user = U.id_user
      GROUP BY R.id_general_tag, U.id_user
    ) SS WHERE T.id = SS.id_general_tag AND T.id_user = SS.id_user;
CREATE VIEW public.general_tag_timeline_view
AS
SELECT
U.id_item,
U.id_user,
U.item_type,
U.type as unit_type,
U.id as id_unit,
AGG_TAG.tags AS id_general_tag,
U.takentime
FROM unit as U left outer join (
    SELECT unit.id, unit.id_user, array_agg(distinct(R.id_general_tag)) as tags
    FROM unit left outer join many_unit_has_many_general_tag as R on unit.id = R.id_unit AND unit.id_user = R.id_user
    GROUP BY unit.id, unit.id_user
) as AGG_TAG ON U.id = AGG_TAG.id AND U.id_user = AGG_TAG.id_user AND U.is_major = 't';
CREATE FUNCTION public.init_user_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  root_id integer;
BEGIN
  SELECT nextval('folder_id_seq') INTO root_id;
  INSERT INTO folder (id, id_user, name, parent, name_for_sort, shared, permission_parent) VALUES (root_id, NEW.id, '/', root_id, '/', false, root_id);
  RETURN NULL;
END
$$;
CREATE FUNCTION public.update_normal_album_time_trigger_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  id_item integer;
  many_table text;
  normal_album_table text;
  max_time bigint;
  min_time bigint;
  record RECORD;
BEGIN
  id_item  = OLD.id_item;
  normal_album_table = TG_TABLE_SCHEMA || '.normal_album';
  many_table = TG_TABLE_SCHEMA || '.many_item_has_many_normal_album';
  FOR record IN EXECUTE format('SELECT * FROM %s WHERE id_item = %L', many_table, id_item) LOOP
    EXECUTE format('SELECT COALESCE(max, 0), COALESCE(min, 0) FROM public.get_unit_takentime_by_album(%L, %L)', record.id_normal_album, TG_TABLE_SCHEMA) INTO max_time, min_time;
    EXECUTE 'UPDATE ' || normal_album_table || ' SET start_time = ' || min_time || ', end_time = ' || max_time || ' WHERE id = ' || record.id_normal_album;
  END LOOP;
  RETURN NULL;
END;
$$;
CREATE TRIGGER init_user_trigger
  AFTER INSERT
  ON public.user_info
  FOR EACH ROW
  EXECUTE PROCEDURE public.init_user_func();
CREATE TRIGGER unit_update_takentime_cascade_to_noraml_album_trigger
  AFTER UPDATE OF takentime
  ON public.unit
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_normal_album_time_trigger_func();
CREATE VIEW public.level_1_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_1 AS level,
    geocoding.admin_1 AS admin
   FROM unit
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_2_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_2 AS level,
    geocoding.admin_2 AS admin
   FROM unit
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_3_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_3 AS level,
    geocoding.admin_3 AS admin
   FROM unit
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_4_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_4 AS level,
    geocoding.admin_4 AS admin
   FROM unit
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_5_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_5 AS level,
    geocoding.admin_5 AS admin
   FROM unit
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_6_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_6 AS level,
    geocoding.admin_6 AS admin
   FROM unit
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_1_person_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_1 AS level,
    geocoding.admin_1 AS admin,
    person.id_person
   FROM (
     SELECT face.id_unit, array_agg(DISTINCT face.id_person) AS id_person
     FROM face
     GROUP BY face.id_unit ) person
  LEFT JOIN unit ON person.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_2_person_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_2 AS level,
    geocoding.admin_2 AS admin,
    person.id_person
   FROM (
     SELECT face.id_unit, array_agg(DISTINCT face.id_person) AS id_person
     FROM face
     GROUP BY face.id_unit ) person
  LEFT JOIN unit ON person.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_3_person_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_3 AS level,
    geocoding.admin_3 AS admin,
    person.id_person
   FROM (
     SELECT face.id_unit, array_agg(DISTINCT face.id_person) AS id_person
     FROM face
     GROUP BY face.id_unit ) person
  LEFT JOIN unit ON person.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_4_person_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_4 AS level,
    geocoding.admin_4 AS admin,
    person.id_person
   FROM (
     SELECT face.id_unit, array_agg(DISTINCT face.id_person) AS id_person
     FROM face
     GROUP BY face.id_unit ) person
  LEFT JOIN unit ON person.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_5_person_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_5 AS level,
    geocoding.admin_5 AS admin,
    person.id_person
   FROM (
     SELECT face.id_unit, array_agg(DISTINCT face.id_person) AS id_person
     FROM face
     GROUP BY face.id_unit ) person
  LEFT JOIN unit ON person.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_6_person_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_6 AS level,
    geocoding.admin_6 AS admin,
    person.id_person
   FROM (
     SELECT face.id_unit, array_agg(DISTINCT face.id_person) AS id_person
     FROM face
     GROUP BY face.id_unit ) person
  LEFT JOIN unit ON person.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_1_general_tag_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_1 AS level,
    geocoding.admin_1 AS admin,
    tag.id_general_tag
   FROM (
     SELECT many_unit_has_many_general_tag.id_unit, array_agg(DISTINCT many_unit_has_many_general_tag.id_general_tag) AS id_general_tag
     FROM many_unit_has_many_general_tag
     GROUP BY many_unit_has_many_general_tag.id_unit ) tag
  LEFT JOIN unit ON tag.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_2_general_tag_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_2 AS level,
    geocoding.admin_2 AS admin,
    tag.id_general_tag
   FROM (
     SELECT many_unit_has_many_general_tag.id_unit, array_agg(DISTINCT many_unit_has_many_general_tag.id_general_tag) AS id_general_tag
     FROM many_unit_has_many_general_tag
     GROUP BY many_unit_has_many_general_tag.id_unit ) tag
  LEFT JOIN unit ON tag.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_3_general_tag_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_3 AS level,
    geocoding.admin_3 AS admin,
    tag.id_general_tag
   FROM (
     SELECT many_unit_has_many_general_tag.id_unit, array_agg(DISTINCT many_unit_has_many_general_tag.id_general_tag) AS id_general_tag
     FROM many_unit_has_many_general_tag
     GROUP BY many_unit_has_many_general_tag.id_unit ) tag
  LEFT JOIN unit ON tag.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_4_general_tag_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_4 AS level,
    geocoding.admin_4 AS admin,
    tag.id_general_tag
   FROM (
     SELECT many_unit_has_many_general_tag.id_unit, array_agg(DISTINCT many_unit_has_many_general_tag.id_general_tag) AS id_general_tag
     FROM many_unit_has_many_general_tag
     GROUP BY many_unit_has_many_general_tag.id_unit ) tag
  LEFT JOIN unit ON tag.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_5_general_tag_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_5 AS level,
    geocoding.admin_5 AS admin,
    tag.id_general_tag
   FROM (
     SELECT many_unit_has_many_general_tag.id_unit, array_agg(DISTINCT many_unit_has_many_general_tag.id_general_tag) AS id_general_tag
     FROM many_unit_has_many_general_tag
     GROUP BY many_unit_has_many_general_tag.id_unit ) tag
  LEFT JOIN unit ON tag.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_6_general_tag_timeline_view
AS
SELECT unit.id_item,
    unit.id_user,
    unit.item_type,
    unit.type AS unit_type,
    unit.takentime,
    unit.id AS id_unit,
    geocoding.level_6 AS level,
    geocoding.admin_6 AS admin,
    tag.id_general_tag
   FROM (
     SELECT many_unit_has_many_general_tag.id_unit, array_agg(DISTINCT many_unit_has_many_general_tag.id_general_tag) AS id_general_tag
     FROM many_unit_has_many_general_tag
     GROUP BY many_unit_has_many_general_tag.id_unit ) tag
  LEFT JOIN unit ON tag.id_unit = unit.id
  LEFT JOIN geocoding ON unit.id_geocoding = geocoding.id AND unit.id_user = geocoding.id_user
  WHERE unit.is_major = true AND unit.id_geocoding IS NOT NULL;
CREATE VIEW public.level_1_search_timeline_view
AS
SELECT U.id_item,
    U.id_user,
    U.item_type,
    U.type AS unit_type,
    U.takentime,
    U.id_unit,
    geocoding.level_1 AS level,
    geocoding.admin_1 AS admin
   FROM (
      SELECT
        unit.id_user,
        unit.id_geocoding,
        unit.id_item,
        unit.item_type,
        unit.type,
        unit.takentime,
        unit.id AS id_unit,
        unit.is_major
      FROM search_timeline s, unit
      WHERE s.id_unit = unit.id ) U
  LEFT JOIN geocoding ON U.id_geocoding = geocoding.id AND U.id_user = geocoding.id_user
  WHERE U.is_major = true AND U.id_geocoding IS NOT NULL;
CREATE VIEW public.level_2_search_timeline_view
AS
SELECT U.id_item,
    U.id_user,
    U.item_type,
    U.type AS unit_type,
    U.takentime,
    U.id_unit,
    geocoding.level_2 AS level,
    geocoding.admin_2 AS admin
   FROM (
      SELECT
        unit.id_user,
        unit.id_geocoding,
        unit.id_item,
        unit.item_type,
        unit.type,
        unit.takentime,
        unit.id AS id_unit,
        unit.is_major
      FROM search_timeline s, unit
      WHERE s.id_unit = unit.id ) U
  LEFT JOIN geocoding ON U.id_geocoding = geocoding.id AND U.id_user = geocoding.id_user
  WHERE U.is_major = true AND U.id_geocoding IS NOT NULL;
CREATE VIEW public.level_3_search_timeline_view
AS
SELECT U.id_item,
    U.id_user,
    U.item_type,
    U.type AS unit_type,
    U.takentime,
    U.id_unit,
    geocoding.level_3 AS level,
    geocoding.admin_3 AS admin
   FROM (
      SELECT
        unit.id_user,
        unit.id_geocoding,
        unit.id_item,
        unit.item_type,
        unit.type,
        unit.takentime,
        unit.id AS id_unit,
        unit.is_major
      FROM search_timeline s, unit
      WHERE s.id_unit = unit.id ) U
  LEFT JOIN geocoding ON U.id_geocoding = geocoding.id AND U.id_user = geocoding.id_user
  WHERE U.is_major = true AND U.id_geocoding IS NOT NULL;
CREATE VIEW public.level_4_search_timeline_view
AS
SELECT U.id_item,
    U.id_user,
    U.item_type,
    U.type AS unit_type,
    U.takentime,
    U.id_unit,
    geocoding.level_4 AS level,
    geocoding.admin_4 AS admin
   FROM (
      SELECT
        unit.id_user,
        unit.id_geocoding,
        unit.id_item,
        unit.item_type,
        unit.type,
        unit.takentime,
        unit.id AS id_unit,
        unit.is_major
      FROM search_timeline s, unit
      WHERE s.id_unit = unit.id ) U
  LEFT JOIN geocoding ON U.id_geocoding = geocoding.id AND U.id_user = geocoding.id_user
  WHERE U.is_major = true AND U.id_geocoding IS NOT NULL;
CREATE VIEW public.level_5_search_timeline_view
AS
SELECT U.id_item,
    U.id_user,
    U.item_type,
    U.type AS unit_type,
    U.takentime,
    U.id_unit,
    geocoding.level_5 AS level,
    geocoding.admin_5 AS admin
   FROM (
      SELECT
        unit.id_user,
        unit.id_geocoding,
        unit.id_item,
        unit.item_type,
        unit.type,
        unit.takentime,
        unit.id AS id_unit,
        unit.is_major
      FROM search_timeline s, unit
      WHERE s.id_unit = unit.id ) U
  LEFT JOIN geocoding ON U.id_geocoding = geocoding.id AND U.id_user = geocoding.id_user
  WHERE U.is_major = true AND U.id_geocoding IS NOT NULL;
CREATE VIEW public.level_6_search_timeline_view
AS
SELECT U.id_item,
    U.id_user,
    U.item_type,
    U.type AS unit_type,
    U.takentime,
    U.id_unit,
    geocoding.level_6 AS level,
    geocoding.admin_6 AS admin
   FROM (
      SELECT
        unit.id_user,
        unit.id_geocoding,
        unit.id_item,
        unit.item_type,
        unit.type,
        unit.takentime,
        unit.id AS id_unit,
        unit.is_major
      FROM search_timeline s, unit
      WHERE s.id_unit = unit.id ) U
  LEFT JOIN geocoding ON U.id_geocoding = geocoding.id AND U.id_user = geocoding.id_user
  WHERE U.is_major = true AND U.id_geocoding IS NOT NULL;
CREATE VIEW public.share_album_view
AS
SELECT album.id,
    album.id_user,
    album.name,
    album.type,
    album.shared,
    album.create_time,
    album.cover,
    album.sort_by,
    album.sort_direction,
    album.passphrase_share,
    album.version,
    album.item_count,
    share.modified_time,
    album.normalized_name
   FROM album, share
  WHERE album.passphrase_share = share.passphrase;
CREATE FUNCTION public.item_type_update_unit_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  new_version bigint;
  unit_table text;
BEGIN
  unit_table = TG_TABLE_SCHEMA || '.unit';
  IF (TG_OP = 'UPDATE') THEN
    SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
    EXECUTE 'UPDATE ' || unit_table || ' SET version = ' || new_version || ' WHERE id_item = ' || NEW.id;
  END IF;
  RETURN NULL;
END
$$;
CREATE FUNCTION public.insert_item_to_update_normal_album_func ( id_album int4)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  many_table text;
  normal_album_table text;
  max_time bigint;
  min_time bigint;
  count integer;
BEGIN
  normal_album_table = 'public.normal_album';
  many_table = 'public.many_item_has_many_normal_album';
  EXECUTE 'SELECT count(*) FROM ' || many_table || ' WHERE id_normal_album = ' || id_album INTO count;
  EXECUTE format('SELECT COALESCE(max, 0), COALESCE(min, 0) FROM public.get_unit_takentime_by_album(%L, %L)', id_album, 'public') INTO max_time, min_time;
  EXECUTE 'UPDATE ' || normal_album_table || ' SET start_time = ' || min_time || ', end_time = ' || max_time || ', item_count = ' || count || ' WHERE id = ' || id_album;
END;
$$;
CREATE FUNCTION public.delete_expired_version_time_data_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  count bigint;
  version_time text;
BEGIN
  version_time = TG_TABLE_SCHEMA || '.version_time';
  EXECUTE format('SELECT count(*) FROM %s', version_time) INTO count;
  IF (count > 110000) THEN
        EXECUTE format('DELETE FROM %s WHERE version IN (SELECT version FROM %s order by version limit %L)', version_time, version_time, 10000);
  END IF;
    RETURN NEW;
END
$$;
CREATE FUNCTION public.unit_update_id_item_func ( schema text,  item_id integer,  new_item_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  many_item_has_many_normal_album_table text;
  many_similar_group_has_many_item_table text;
  album_array bigint[];
  album_id bigint;
  similar_group_array bigint[];
  similar_group bigint;
  record RECORD;
BEGIN
  many_item_has_many_normal_album_table = schema || '.many_item_has_many_normal_album';
  many_similar_group_has_many_item_table = schema || '.many_similar_group_has_many_item';
  EXECUTE format('SELECT array_agg(id_normal_album) FROM %s WHERE id_item = %L', many_item_has_many_normal_album_table, item_id) INTO album_array;
  IF (album_array IS NOT NULL) THEN
    FOREACH album_id IN ARRAY album_array LOOP
      EXECUTE format('SELECT * FROM %s WHERE id_normal_album = %L AND id_item = %L', many_item_has_many_normal_album_table, album_id, new_item_id) INTO record;
      IF (record IS NULL) THEN
        EXECUTE format('UPDATE %s SET id_item = %L WHERE id_normal_album = %L AND id_item = %L', many_item_has_many_normal_album_table, new_item_id, album_id, item_id);
      END IF;
    END LOOP;
  END IF;
  EXECUTE format('SELECT array_agg(id_similar_group) FROM %s WHERE id_item = %L', many_similar_group_has_many_item_table, item_id) INTO similar_group_array;
  IF (similar_group_array IS NOT NULL) THEN
    FOREACH similar_group IN ARRAY similar_group_array LOOP
      EXECUTE format('SELECT * FROM %s WHERE id_similar_group = %L AND id_item = %L', many_similar_group_has_many_item_table, similar_group, new_item_id) INTO record;
      IF (record IS NULL) THEN
        EXECUTE format('UPDATE %s SET id_item = %L WHERE id_similar_group = %L AND id_item = %L', many_similar_group_has_many_item_table, new_item_id, similar_group, item_id);
      END IF;
    END LOOP;
  END IF;
END
$$;
CREATE FUNCTION public.delete_item_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  delete_item_table text;
  new_version bigint;
  id_user integer;
BEGIN
  delete_item_table = TG_TABLE_SCHEMA || '.delete_item';
  SELECT id from user_info where id = OLD.id_user INTO id_user;
  if (id_user IS NOT NULL) THEN
    SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
    EXECUTE format('INSERT INTO %s (id_item, id_user, version) VALUES (%L, %L, %L)', delete_item_table, OLD.id, OLD.id_user, new_version);
  END IF;
  RETURN NULL;
END
$$;
CREATE FUNCTION public.update_similar_info_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  similar_group_table text;
  many_similar_group_has_many_item_table text;
  cover text;
  current_cover bigint;
  item_count bigint;
  similar_group_id bigint;
  need_update_cover bool;
BEGIN
  similar_group_table = TG_TABLE_SCHEMA || '.similar_group';
  many_similar_group_has_many_item_table = TG_TABLE_SCHEMA || '.many_similar_group_has_many_item';
  need_update_cover = false;
  IF (TG_OP = 'DELETE') THEN
    similar_group_id = OLD.id_similar_group;
  ELSE
    similar_group_id = NEW.id_similar_group;
  END IF;
  EXECUTE format('SELECT count(*) FROM %s WHERE id_similar_group = %L', many_similar_group_has_many_item_table, similar_group_id) INTO item_count;
  EXECUTE format('SELECT cover FROM %s WHERE id = %L', similar_group_table, similar_group_id) INTO current_cover;
  IF (TG_OP = 'INSERT' AND current_cover IS NULL) THEN
    need_update_cover = true;
  ELSIF (TG_OP = 'UPDATE' AND current_cover = NEW.id_item AND NEW.hidden = 't') THEN
    need_update_cover = true;
  ELSIF (TG_OP = 'DELETE' AND current_cover = OLD.id_item) THEN
    need_update_cover = true;
  END IF;
  IF (item_count IS NULL) THEN
    EXECUTE format('DELETE FROM %s WHERE id = %L', similar_group_table, similar_group_id);
    RETURN NULL;
  END IF;
  IF (need_update_cover OR current_cover = 0) THEN
    EXECUTE format('SELECT public.update_similar_group_cover(%L, %s)', TG_TABLE_SCHEMA, similar_group_id);
  END IF;
  EXECUTE format('SELECT public.update_similar_group_count(%L, %s)', TG_TABLE_SCHEMA, similar_group_id);
  RETURN NULL;
END
$$;
CREATE FUNCTION public.delete_item_to_update_normal_album_trigger_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
    album_id integer;
    item_id integer;
    album_start_time bigint;
    album_end_time bigint;
    unit_time bigint;
    unit_table text;
    normal_album_table text;
    album_takentime_max bigint;
    album_takentime_min bigint;
BEGIN
  unit_table = TG_TABLE_SCHEMA || '.unit';
  normal_album_table = TG_TABLE_SCHEMA || '.normal_album';
  album_id = OLD.id_normal_album;
  item_id  = OLD.id_item;
  EXECUTE 'UPDATE ' || normal_album_table || ' SET item_count = COALESCE(item_count, 0) - 1 WHERE id =' || album_id;
  EXECUTE 'SELECT takentime FROM ' || unit_table || ' WHERE id_item = ' || item_id INTO unit_time;
  EXECUTE 'SELECT COALESCE(start_time, 0), COALESCE(end_time, 0) FROM ' || normal_album_table ||
          ' WHERE id =' || album_id INTO album_start_time, album_end_time;
  IF (unit_time IS NULL OR unit_time = album_start_time OR unit_time = album_end_time) THEN
    EXECUTE format('SELECT COALESCE(max, 0), COALESCE(min, 0) FROM public.get_unit_takentime_by_album(%L, %L)', album_id, TG_TABLE_SCHEMA) INTO album_takentime_max, album_takentime_min;
    EXECUTE 'UPDATE ' || normal_album_table || ' SET start_time = ' || album_takentime_min || ', end_time = ' || album_takentime_max || ' WHERE id = ' || album_id;
  END IF;
  RETURN NULL;
END
$$;
CREATE TRIGGER delete_item_trigger
  AFTER DELETE
  ON public.item
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_item_func();
CREATE TRIGGER delete_item_to_update_normal_album_trigger_func
  AFTER DELETE
  ON public.many_item_has_many_normal_album
  FOR EACH ROW
  EXECUTE PROCEDURE public.delete_item_to_update_normal_album_trigger_func();
CREATE FUNCTION public.update_similar_group_count ( schema text,  similar_group_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  similar_group_table text;
  many_similar_group_has_many_item_table text;
  unit_table text;
  visable_count bigint;
BEGIN
  similar_group_table = schema || '.similar_group';
  many_similar_group_has_many_item_table = schema || '.many_similar_group_has_many_item';
  unit_table = schema || '.unit';
  EXECUTE format('SELECT COUNT(DISTINCT(id_item)) from %s WHERE id_item in (SELECT id_item FROM %s WHERE id_similar_group = %L AND hidden = false ORDER BY id_item)', unit_table, many_similar_group_has_many_item_table, similar_group_id) INTO visable_count;
  IF (visable_count IS NULL) THEN
    visable_count = 0;
  END IF;
  EXECUTE format('UPDATE %s SET item_count = %L WHERE id = %L', similar_group_table, visable_count, similar_group_id);
END
$$;
CREATE FUNCTION public.update_similar_group_cover ( schema text,  similar_group_id integer)
  RETURNS void
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  similar_group_table text;
  many_similar_group_has_many_item_table text;
  cover text;
BEGIN
  similar_group_table = schema || '.similar_group';
  many_similar_group_has_many_item_table = schema || '.many_similar_group_has_many_item';
  EXECUTE format('SELECT id_item from unit WHERE id_item in (SELECT id_item FROM %s WHERE id_similar_group = %L AND hidden = false ORDER BY id_item) limit 1', many_similar_group_has_many_item_table, similar_group_id) INTO cover;
  IF (cover IS NULL) THEN
    cover = 0;
  END IF;
  EXECUTE format('UPDATE %s SET cover = %L WHERE id = %L', similar_group_table, cover, similar_group_id);
END
$$;
CREATE TRIGGER update_similar_group_trigger
  AFTER INSERT OR DELETE OR UPDATE
  ON public.many_similar_group_has_many_item
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_similar_info_func();
CREATE TABLE public.aperture(
  id serial NOT NULL,
  name text NOT NULL,
  normalized_name text NOT NULL,
  CONSTRAINT aperture_pk PRIMARY KEY (id),
  CONSTRAINT aperture_uq UNIQUE (name)
);
CREATE TABLE public.camera(
  id serial NOT NULL,
  name text NOT NULL,
  normalized_name text NOT NULL,
  CONSTRAINT camera_pk PRIMARY KEY (id),
  CONSTRAINT camera_uq UNIQUE (name)
);
CREATE TABLE public.exposure_time(
  id serial NOT NULL,
  name text NOT NULL,
  normalized_name text NOT NULL,
  CONSTRAINT exposure_time_pk PRIMARY KEY (id),
  CONSTRAINT exposure_time_uq UNIQUE (name)
);
CREATE TABLE public.focal_length(
  id serial NOT NULL,
  name text NOT NULL,
  normalized_name text NOT NULL,
  CONSTRAINT focal_length_pk PRIMARY KEY (id),
  CONSTRAINT focal_length_uq UNIQUE (name)
);
CREATE TABLE public.iso(
  id serial NOT NULL,
  name text NOT NULL,
  normalized_name text NOT NULL,
  CONSTRAINT iso_pk PRIMARY KEY (id),
  CONSTRAINT iso_uq UNIQUE (name)
);
CREATE TABLE public.lens(
  id serial NOT NULL,
  name text NOT NULL,
  normalized_name text NOT NULL,
  CONSTRAINT lens_pk PRIMARY KEY (id),
  CONSTRAINT lens_qu UNIQUE (name)
);
CREATE TABLE public.filter(
  id_unit integer NOT NULL,
  id_filter integer NOT NULL,
  filter_type text NOT NULL,
  id_user integer NOT NULL,
  CONSTRAINT filter_uq UNIQUE (id_unit,id_filter,filter_type,id_user)
);
CREATE INDEX filter_idx ON public.filter
  USING btree
  (
    id_user,
    filter_type,
    id_filter
  );
CREATE TABLE public.share_permission(
  id serial NOT NULL,
  id_user integer NOT NULL,
  permission int2 NOT NULL,
  target_type smallint NOT NULL,
  target_id int4 NOT NULL,
  passphrase_share text NOT NULL,
  CONSTRAINT share_permission_pk PRIMARY KEY (id)
);
CREATE VIEW public.share_with_member_view
AS
SELECT share_permission.id,
    share_permission.permission,
    share_permission.target_type,
    share_permission.target_id,
    share.id_user,
    share.passphrase,
    share.type,
    share.expired_time,
    share.modified_time
   FROM share_permission, share
  WHERE share_permission.passphrase_share = share.passphrase AND share.enable = true AND (share.id_user IN (SELECT user_info.id FROM user_info WHERE user_info.enable = 't'));
ALTER TABLE public.share_permission ADD CONSTRAINT share_fk FOREIGN KEY (passphrase_share)
REFERENCES public.share (passphrase) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE INDEX id_user_idx ON public.share_permission
  USING btree
  (
    id_user
  );
CREATE INDEX id_user_target_type_target_id_idx ON public.share_permission
  USING btree
  (
    id_user,
    target_type ASC NULLS LAST,
    target_id ASC NULLS LAST
  );
ALTER TABLE public.share_permission ADD CONSTRAINT passpharase_target_type_target_id_unique UNIQUE (passphrase_share,target_type,target_id);
ALTER TABLE public.album ADD CONSTRAINT share_fk FOREIGN KEY (passphrase_share)
REFERENCES public.share (passphrase) MATCH FULL
ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE public.album ADD CONSTRAINT album_uq UNIQUE (passphrase_share);
ALTER TABLE public.folder ADD CONSTRAINT share_fk FOREIGN KEY (passphrase_share)
REFERENCES public.share (passphrase) MATCH FULL
ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE public.folder ADD CONSTRAINT folder_uq UNIQUE (passphrase_share);
CREATE TABLE public.team_library_group_permission(
  id_group integer NOT NULL,
  permission smallint NOT NULL DEFAULT 0,
  auto_backup bool NOT NULL DEFAULT false,
  CONSTRAINT team_library_group_permission_pk PRIMARY KEY (id_group)
);
CREATE INDEX metadata_id_unit_idx ON public.metadata
  USING btree
  (
    id_unit
  );
CREATE INDEX address_id_unit_idx ON public.address
  USING btree
  (
    id_unit ASC NULLS LAST
  );
CREATE INDEX many_similar_group_has_many_item_id_item_idx ON public.many_similar_group_has_many_item
  USING btree
  (
    id_item
  );
CREATE INDEX delete_album_version_idx ON public.delete_album
  USING btree
  (
    version
  );
CREATE INDEX delete_item_version_idx ON public.delete_item
  USING btree
  (
    version
  );
CREATE INDEX unit_id_user_idx ON public.unit
  USING btree
  (
    id_user
  );
CREATE INDEX face_id_user_idx ON public.face
  USING btree
  (
    id_user
  );
CREATE INDEX address_id_user_lang_id_unit_idx ON public.address
  USING btree
  (
    id_user,
    lang ASC NULLS LAST,
    id_unit ASC NULLS LAST
  );
CREATE TABLE public.takentime(
  id serial NOT NULL,
  takentime_day text NOT NULL,
  takentime_month text NOT NULL,
  takentime bigint NOT NULL DEFAULT 0,
  CONSTRAINT takentime_pk PRIMARY KEY (id),
  CONSTRAINT takentime_uq UNIQUE (takentime_day)
);
CREATE INDEX takentime_day_idx ON public.takentime
  USING btree
  (
    takentime_day
  );
CREATE INDEX takentime_month_idx ON public.takentime
  USING btree
  (
    id
  );
CREATE INDEX takentime_takentime_idx ON public.takentime
  USING btree
  (
    takentime ASC NULLS LAST
  );
CREATE FUNCTION public.share_permission_update_album_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  new_version bigint;
  album_table text;
  passphrase text;
BEGIN
  album_table = TG_TABLE_SCHEMA || '.album';
  IF (TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND (NEW.permission != OLD.permission))) THEN
    passphrase = NEW.passphrase_share;
  ELSEIF (TG_OP = 'DELETE') THEN
    passphrase = OLD.passphrase_share;
  END IF;
  if passphrase IS NOT NULL THEN
    SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
    EXECUTE format('UPDATE %s SET version = %L WHERE passphrase_share = %L', album_table, new_version, passphrase);
  END IF;
  RETURN NULL;
END
$$;
CREATE FUNCTION public.share_update_album_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  new_version bigint;
  album_table text;
BEGIN
  album_table = TG_TABLE_SCHEMA || '.album';
  IF (TG_OP = 'UPDATE') THEN
    IF (NEW.privacy_type != OLD.privacy_type OR NEW.modified_time != OLD.modified_time OR NEW.expired_time != OLD.expired_time OR NEW.hashed_password != OLD.hashed_password OR NEW.enable != OLD.enable) THEN
      SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
      EXECUTE format('UPDATE %s SET version = %L WHERE passphrase_share = %L', album_table, new_version, NEW.passphrase);
    END IF;
  END IF;
  RETURN NULL;
END
$$;
CREATE TRIGGER share_update_album_version_trigger
  AFTER UPDATE
  ON public.share
  FOR EACH ROW
  EXECUTE PROCEDURE public.share_update_album_version_func();
CREATE TRIGGER share_permission_update_album_version_trigger
  AFTER INSERT OR DELETE OR UPDATE
  ON public.share_permission
  FOR EACH ROW
  EXECUTE PROCEDURE public.share_permission_update_album_version_func();
CREATE FUNCTION public.update_condition_album_version_func ()
  RETURNS trigger
  LANGUAGE plpgsql
  VOLATILE
  CALLED ON NULL INPUT
  SECURITY INVOKER
  COST 1
  AS $$
DECLARE
  new_version bigint;
BEGIN
  IF (TG_OP = 'INSERT' or
      (TG_OP = 'UPDATE' AND
        (
          NEW.condition::text != OLD.condition::text
          OR NEW.item_count != OLD.item_count
          OR NEW.cover != OLD.cover
          OR NEW.name != OLD.name
          OR NEW.shared != OLD.shared
          OR NEW.sort_by != OLD.sort_by
          OR NEW.sort_direction != OLD.sort_direction
          OR NEW.passphrase_share != OLD.passphrase_share
        )
      )
     ) THEN
    SELECT public.get_next_version_func(TG_TABLE_SCHEMA) INTO new_version;
    NEW.version = new_version;
  END IF;
  RETURN NEW;
END
$$;
CREATE TRIGGER update_condition_album_version_func
  BEFORE INSERT OR UPDATE
  ON public.condition_album
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_condition_album_version_func();
CREATE INDEX album_id_user_idx ON public.album
  USING btree
  (
    id_user ASC NULLS LAST
  );
CREATE INDEX normal_album_id_user_idx ON public.normal_album
  USING btree
  (
    id_user ASC NULLS LAST
  );
CREATE INDEX normal_album_id_user_status_idx ON public.normal_album
  USING btree
  (
    id_user ASC NULLS LAST,
    status ASC NULLS LAST
  );
CREATE INDEX condition_album_id_user_idx ON public.condition_album
  USING btree
  (
    id_user ASC NULLS LAST
  );
CREATE TABLE public.background_task(
  id serial NOT NULL,
  uid bigint NOT NULL,
  id_dsm_task text NOT NULL,
  operation int2 NOT NULL,
  status int2 NOT NULL,
  created_time bigint NOT NULL,
  modified_time bigint NOT NULL,
  total int8 NOT NULL,
  completion int8 NOT NULL,
  CONSTRAINT id PRIMARY KEY (id),
  CONSTRAINT id_dsm_task_unique UNIQUE (id_dsm_task)
);
CREATE TABLE public.file_operation_task(
  id_task integer NOT NULL,
  id integer[],
  team_prefix text,
  remove_src bool,
  target_folder_id integer,
  policy int2,
  CONSTRAINT pk_id_task PRIMARY KEY (id_task)
);
CREATE INDEX id_person_id_unit_score_idx ON public.face
  USING btree
  (
    id_person ASC NULLS LAST,
    id_unit ASC NULLS LAST,
    score ASC NULLS LAST
  );
CREATE TABLE public.check_album_task(
  id serial NOT NULL,
  id_user integer NOT NULL DEFAULT 0,
  id_group integer NOT NULL DEFAULT 0,
  id_folder integer NOT NULL DEFAULT 0,
  status smallint NOT NULL DEFAULT 0,
  CONSTRAINT check_album_task_pk PRIMARY KEY (id)
);
CREATE INDEX check_album_task_status_user_group_folder_idx ON public.check_album_task
  USING btree
  (
    status,
    id_user ASC NULLS LAST,
    id_group ASC NULLS LAST,
    id_folder ASC NULLS LAST
  );
ALTER TABLE public.item ADD CONSTRAINT user_id_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.album ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.share ADD CONSTRAINT share_id_user_info_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.geocoding ADD CONSTRAINT level_1_fk FOREIGN KEY (level_1)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT;
ALTER TABLE public.geocoding ADD CONSTRAINT level_2_fk FOREIGN KEY (level_2)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT;
ALTER TABLE public.geocoding ADD CONSTRAINT level_3_fk FOREIGN KEY (level_3)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT;
ALTER TABLE public.geocoding ADD CONSTRAINT level_4_fk FOREIGN KEY (level_4)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT;
ALTER TABLE public.geocoding ADD CONSTRAINT level_5_fk FOREIGN KEY (level_5)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT;
ALTER TABLE public.geocoding ADD CONSTRAINT level_6_fk FOREIGN KEY (level_6)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT;
ALTER TABLE public.geocoding ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.person ADD CONSTRAINT cover_id_face FOREIGN KEY (cover)
REFERENCES public.face (id) MATCH FULL
ON DELETE SET NULL ON UPDATE RESTRICT DEFERRABLE INITIALLY IMMEDIATE;
ALTER TABLE public.person ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.metadata ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.condition_album ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.normal_album ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.person_group ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.cluster ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.face ADD CONSTRAINT person_ref_id_unit_fk FOREIGN KEY (ref_id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.face ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.unit ADD CONSTRAINT unit_id_geocoding_fk FOREIGN KEY (id_geocoding)
REFERENCES public.geocoding (id) MATCH FULL
ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE public.unit ADD CONSTRAINT user_id_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.thumbnail ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.folder ADD CONSTRAINT folder_parent_fk FOREIGN KEY (parent)
REFERENCES public.folder (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.folder ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.video_additional ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.geocoding_info ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.address ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.address ADD CONSTRAINT level_fk FOREIGN KEY (level)
REFERENCES public.administrative (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.many_item_has_many_normal_album ADD CONSTRAINT item_provider_id_user_fk FOREIGN KEY (item_provider_id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.many_item_has_many_normal_album ADD CONSTRAINT album_id_user_fk FOREIGN KEY (album_id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.live_additional ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.burst_additional ADD CONSTRAINT user_id_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE public.thumb_preview ADD CONSTRAINT id_unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH SIMPLE
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.thumb_preview ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.delete_item ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.delete_album ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.video_convert ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.team_library_user_permission ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.similar_group ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.many_similar_group_has_many_item ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.unit_similar_hash ADD CONSTRAINT unit_similar_hash_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.unit_similar_hash ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.delete_condition_album ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.user_flag ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.filter ADD CONSTRAINT unit_fk FOREIGN KEY (id_unit)
REFERENCES public.unit (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.filter ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.share_permission ADD CONSTRAINT id_user_fk FOREIGN KEY (id_user)
REFERENCES public.user_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.team_library_group_permission ADD CONSTRAINT id_group_fk FOREIGN KEY (id_group)
REFERENCES public.group_info (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.file_operation_task ADD CONSTRAINT id_task_fk FOREIGN KEY (id_task)
REFERENCES public.background_task (id) MATCH FULL
ON DELETE CASCADE ON UPDATE CASCADE;