···11+drop trigger t_profile_state_ins on follows;
22+drop trigger t_profile_state_del on follows;
33+drop trigger t_profile_state_ins on blocks;
44+drop trigger t_profile_state_del on blocks;
55+drop trigger t_profile_state_ins on mutes;
66+drop trigger t_profile_state_del on mutes;
77+88+drop function f_profile_state_ins_follow;
99+drop function f_profile_state_del_follow;
1010+drop function f_profile_state_ins_block;
1111+drop function f_profile_state_del_block;
1212+drop function f_profile_state_ins_mute;
1313+drop function f_profile_state_del_mute;
1414+1515+drop view v_list_mutes_exp;
1616+drop view v_list_block_exp;
1717+drop table profile_states;
···11+create table profile_states
22+(
33+ did text not null,
44+ subject text not null,
55+ muting bool not null default false, -- subj muted by did
66+ blocked bool not null default false, -- did blocked by subj
77+ blocking text, -- subj blocked by did
88+ following text, -- rkey of follow record (did->subj)
99+ followed text, -- rkey of follow record (subj->did)
1010+1111+ primary key (did, subject)
1212+);
1313+1414+create index profilestates_did_index on profile_states using hash (did);
1515+create index profilestates_sub_index on profile_states using hash (subject);
1616+1717+create view v_list_block_exp as
1818+(
1919+select lb.list_uri, did, li.subject
2020+from list_blocks lb
2121+ inner join list_items li on lb.list_uri = li.list_uri
2222+ );
2323+2424+create view v_list_mutes_exp as
2525+(
2626+select lm.list_uri, did, li.subject
2727+from list_mutes lm
2828+ inner join list_items li on lm.list_uri = li.list_uri
2929+ );
3030+3131+-- profile_states follow triggers
3232+create function f_profile_state_ins_follow() returns trigger
3333+ language plpgsql as
3434+$$
3535+begin
3636+ insert into profile_states (did, subject, following)
3737+ VALUES (NEW.did, NEW.subject, NEW.rkey)
3838+ ON CONFLICT (did, subject) DO UPDATE SET following=excluded.following;
3939+4040+ insert into profile_states (did, subject, followed)
4141+ VALUES (NEW.subject, NEW.did, NEW.rkey)
4242+ ON CONFLICT (did, subject) DO UPDATE SET followed=excluded.followed;
4343+4444+ return NEW;
4545+end;
4646+$$;
4747+4848+create trigger t_profile_state_ins
4949+ before insert
5050+ on follows
5151+ for each row
5252+execute procedure f_profile_state_ins_follow();
5353+5454+create function f_profile_state_del_follow() returns trigger
5555+ language plpgsql as
5656+$$
5757+begin
5858+ update profile_states set following = null where did = OLD.did and subject = OLD.subject;
5959+ update profile_states set followed = null where did = OLD.subject and subject = OLD.did;
6060+6161+ return OLD;
6262+end;
6363+$$;
6464+6565+create trigger t_profile_state_del
6666+ before delete
6767+ on follows
6868+ for each row
6969+execute procedure f_profile_state_del_follow();
7070+7171+-- profile_states block triggers
7272+7373+create function f_profile_state_ins_block() returns trigger
7474+ language plpgsql as
7575+$$
7676+begin
7777+ insert into profile_states (did, subject, blocking)
7878+ VALUES (NEW.did, NEW.subject, NEW.rkey)
7979+ ON CONFLICT (did, subject) DO UPDATE SET blocking=excluded.blocking;
8080+8181+ insert into profile_states (did, subject, blocked)
8282+ VALUES (NEW.subject, NEW.did, TRUE)
8383+ ON CONFLICT (did, subject) DO UPDATE SET blocked=excluded.blocked;
8484+8585+ return NEW;
8686+end;
8787+$$;
8888+8989+create trigger t_profile_state_ins
9090+ before insert
9191+ on blocks
9292+ for each row
9393+execute procedure f_profile_state_ins_block();
9494+9595+create function f_profile_state_del_block() returns trigger
9696+ language plpgsql as
9797+$$
9898+begin
9999+ update profile_states set blocking = null where did = OLD.did and subject = OLD.subject;
100100+ update profile_states set blocked = FALSE where did = OLD.subject and subject = OLD.did;
101101+102102+ return OLD;
103103+end;
104104+$$;
105105+106106+create trigger t_profile_state_del
107107+ before delete
108108+ on blocks
109109+ for each row
110110+execute procedure f_profile_state_del_block();
111111+112112+-- profile_states mutes triggers
113113+114114+create function f_profile_state_ins_mute() returns trigger
115115+ language plpgsql as
116116+$$
117117+begin
118118+ insert into profile_states (did, subject, muting)
119119+ VALUES (NEW.did, NEW.subject, TRUE)
120120+ ON CONFLICT (did, subject) DO UPDATE SET muting=excluded.muting;
121121+122122+ return NEW;
123123+end;
124124+$$;
125125+126126+create trigger t_profile_state_ins
127127+ before insert
128128+ on mutes
129129+ for each row
130130+execute procedure f_profile_state_ins_mute();
131131+132132+create function f_profile_state_del_mute() returns trigger
133133+ language plpgsql as
134134+$$
135135+begin
136136+ update profile_states set muting = false where did = OLD.did and subject = OLD.subject;
137137+138138+ return OLD;
139139+end;
140140+$$;
141141+142142+create trigger t_profile_state_del
143143+ before delete
144144+ on mutes
145145+ for each row
146146+execute procedure f_profile_state_del_mute();
···11+select l.at_uri, lb.at_uri as block, lm.did is not null as muted
22+from lists l
33+ left join list_blocks lb on l.at_uri = lb.list_uri and lb.did = $1
44+ left join list_mutes lm on l.at_uri = lm.list_uri and lm.did = $1
55+where l.at_uri = any ($2) and (lm.did is not null or lb.at_uri is not null)
+16
parakeet/src/sql/post_state.sql
···11+select bq.*, coalesce(bq.at_uri = pinned_uri, false) as pinned
22+from (select p.at_uri,
33+ p.did,
44+ p.cid,
55+ l.rkey as like_rkey,
66+ r.rkey as repost_rkey,
77+ b.did is not null as bookmarked,
88+ coalesce(pg.rules && ARRAY ['app.bsky.feed.postgate#disableRule'], false) as embed_disabled
99+ from posts p
1010+ left join likes l on l.subject = p.at_uri and l.did = $1
1111+ left join reposts r on r.post = p.at_uri and r.did = $1
1212+ left join bookmarks b on b.subject = p.at_uri and b.did = $1
1313+ left join postgates pg on pg.post_uri = p.at_uri
1414+ where p.at_uri = any ($2)
1515+ and (l.rkey is not null or r.rkey is not null or b.did is not null or pg.rules is not null)) bq,
1616+ (select pinned_uri, pinned_cid from profiles where did = $1) pp;
+20
parakeet/src/sql/profile_state.sql
···11+with vlb as (select * from v_list_block_exp where did = $1 and subject = any ($2)),
22+ vlm as (select * from v_list_mutes_exp where did = $1 and subject = any ($2)),
33+ ps as (select * from profile_states where did = $1 and subject = any ($2)),
44+ vlb2 as (select subject as did, did as subject, list_uri is not null as blocked
55+ from v_list_block_exp
66+ where did = any ($2)
77+ and subject = $1)
88+select distinct on (did, subject) did,
99+ subject,
1010+ muting,
1111+ ps.blocked or vlb2.blocked as blocked,
1212+ blocking,
1313+ following,
1414+ followed,
1515+ vlb.list_uri as list_block,
1616+ vlm.list_uri as list_mute
1717+from ps
1818+ full join vlb using (did, subject)
1919+ full join vlm using (did, subject)
2020+ full join vlb2 using (did, subject);