Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,24 @@ returns json as $$
select
(p_filters->>'event_id')::uuid as event_id,
(p_filters->>'limit')::int as limit_value,
(p_filters->>'offset')::int as offset_value
(p_filters->>'offset')::int as offset_value,
nullif(btrim(p_filters->>'ts_query'), '') as ts_query_value
),
-- Prepare text search with prefix matching
search_filter as (
select
ts_rewrite(
websearch_to_tsquery('simple', ts_query_value),
format('
select
to_tsquery(''simple'', lexeme),
to_tsquery(''simple'', lexeme || '':*'')
from unnest(tsvector_to_array(to_tsvector(''simple'', %L))) as lexeme
', ts_query_value
)
) as ts_query
from filters
where ts_query_value is not null
),
-- Select visible attendee and invitation rows
base_attendees as (
Expand All @@ -31,6 +48,7 @@ returns json as $$
u.name,
u.photo_url,
err.status as refund_request_status,
u.tsdoc,
u.title,

(
Expand Down Expand Up @@ -82,6 +100,19 @@ returns json as $$
'registration-questions-pending'
)
),
-- Apply table filters while retaining internal search data
filtered_attendees as (
select *
from base_attendees
where (
not exists (select 1 from search_filter)
or exists (
select 1
from search_filter
where search_filter.ts_query @@ base_attendees.tsdoc
)
)
),
-- Apply pagination and project public attendee fields
attendees as (
select
Expand All @@ -107,18 +138,21 @@ returns json as $$
title,

can_receive_attendee_email
from base_attendees
from filtered_attendees
order by coalesce(lower(name), lower(username)) asc, user_id asc
offset (select offset_value from filters)
limit (select limit_value from filters)
),
-- Count visible rows and eligible notification recipients
-- Count filtered rows and event-wide eligible notification recipients
totals as (
select
count(*) filter (where can_receive_attendee_email = true)::int
as all_attendees_email_recipient_total,
(
select count(*)::int
from base_attendees
where can_receive_attendee_email = true
) as all_attendees_email_recipient_total,
count(*)::int as total
from base_attendees
from filtered_attendees
),
-- Render attendees as JSON
attendees_json as (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,30 @@ returns json as $$
select
(p_filters->>'event_id')::uuid as event_id,
(p_filters->>'limit')::int as limit_value,
(p_filters->>'offset')::int as offset_value
(p_filters->>'offset')::int as offset_value,
nullif(btrim(p_filters->>'ts_query'), '') as ts_query_value
),
-- Select the paginated invitation requests
invitation_requests as (
-- Prepare text search with prefix matching
search_filter as (
select
ts_rewrite(
websearch_to_tsquery('simple', ts_query_value),
format('
select
to_tsquery(''simple'', lexeme),
to_tsquery(''simple'', lexeme || '':*'')
from unnest(tsvector_to_array(to_tsvector(''simple'', %L))) as lexeme
', ts_query_value
)
) as ts_query
from filters
where ts_query_value is not null
),
-- Select invitation requests with internal search data
base_invitation_requests as (
select
extract(epoch from eir.created_at)::bigint as created_at,
eir.created_at as created_at_sort,
eir.status as invitation_request_status,
u.user_id,
u.username,
Expand All @@ -21,30 +39,56 @@ returns json as $$
u.name,
u.photo_url,
extract(epoch from eir.reviewed_at)::bigint as reviewed_at,
u.tsdoc,
u.title
from event_invitation_request eir
join event e on e.event_id = eir.event_id
join "user" u on u.user_id = eir.user_id
where e.group_id = p_group_id
and eir.event_id = (select event_id from filters)
),
-- Apply table filters while retaining internal search data
filtered_invitation_requests as (
select *
from base_invitation_requests
where (
not exists (select 1 from search_filter)
or exists (
select 1
from search_filter
where search_filter.ts_query @@ base_invitation_requests.tsdoc
)
)
),
-- Apply pagination and project public invitation request fields
invitation_requests as (
select
created_at,
invitation_request_status,
user_id,
username,

company,
name,
photo_url,
reviewed_at,
title
from filtered_invitation_requests
order by
case eir.status
case invitation_request_status
when 'pending' then 0
when 'accepted' then 1
else 2
end asc,
eir.created_at asc,
eir.user_id asc
created_at_sort asc,
user_id asc
offset (select offset_value from filters)
limit (select limit_value from filters)
),
-- Count total invitation requests before pagination
-- Count filtered invitation requests before pagination
totals as (
select count(*)::int as total
from event_invitation_request eir
join event e on e.event_id = eir.event_id
where e.group_id = p_group_id
and eir.event_id = (select event_id from filters)
from filtered_invitation_requests
),
-- Render invitation requests as JSON
invitation_requests_json as (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,79 @@ returns json as $$
select
(p_filters->>'event_id')::uuid as event_id,
(p_filters->>'limit')::int as limit_value,
(p_filters->>'offset')::int as offset_value
(p_filters->>'offset')::int as offset_value,
nullif(btrim(p_filters->>'ts_query'), '') as ts_query_value
),
-- Select the paginated waitlist entries
waitlist as (
-- Prepare text search with prefix matching
search_filter as (
select
ts_rewrite(
websearch_to_tsquery('simple', ts_query_value),
format('
select
to_tsquery(''simple'', lexeme),
to_tsquery(''simple'', lexeme || '':*'')
from unnest(tsvector_to_array(to_tsvector(''simple'', %L))) as lexeme
', ts_query_value
)
) as ts_query
from filters
where ts_query_value is not null
),
-- Select waitlist entries with internal search data
base_waitlist as (
select
extract(epoch from ew.created_at)::bigint as created_at,
ew.created_at as created_at_sort,
u.user_id,
u.username,
row_number() over (order by ew.created_at asc, ew.user_id asc)::int as waitlist_position,

u.company,
u.name,
u.photo_url,
u.tsdoc,
u.title
from event_waitlist ew
join event e on e.event_id = ew.event_id
join "user" u on u.user_id = ew.user_id
where e.group_id = p_group_id
and ew.event_id = (select event_id from filters)
order by ew.created_at asc, ew.user_id asc
),
-- Apply table filters while retaining internal search data
filtered_waitlist as (
select *
from base_waitlist
where (
not exists (select 1 from search_filter)
or exists (
select 1
from search_filter
where search_filter.ts_query @@ base_waitlist.tsdoc
)
)
),
-- Apply pagination and project public waitlist fields
waitlist as (
select
created_at,
user_id,
username,
waitlist_position,

company,
name,
photo_url,
title
from filtered_waitlist
order by created_at_sort asc, user_id asc
offset (select offset_value from filters)
limit (select limit_value from filters)
),
-- Count total waitlist entries before pagination
-- Count filtered waitlist entries before pagination
totals as (
select count(*)::int as total
from event_waitlist ew
join event e on e.event_id = ew.event_id
where e.group_id = p_group_id
and ew.event_id = (select event_id from filters)
from filtered_waitlist
),
-- Render waitlist entries as JSON
waitlist_json as (
Expand Down
12 changes: 12 additions & 0 deletions database/migrations/schema/0057_add_user_tsdoc.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Adds an indexed search document for user profile lookup.

alter table "user" add column tsdoc tsvector not null
generated always as (
setweight(to_tsvector('simple', coalesce(name, '')), 'A') ||
setweight(to_tsvector('simple', username), 'A') ||
setweight(to_tsvector('simple', email), 'B') ||
setweight(to_tsvector('simple', coalesce(company, '')), 'C') ||
setweight(to_tsvector('simple', coalesce(title, '')), 'C')
) stored;

create index user_tsdoc_idx on "user" using gin (tsdoc);
Loading
Loading