e4f99255bd
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
132 lines
5.1 KiB
PL/PgSQL
132 lines
5.1 KiB
PL/PgSQL
-- nightly — Fix migration: align DB with iOS app + add missing features
|
|
-- Run after 001_schema.sql
|
|
|
|
-- ── 1. Fix mood enum: replace old values with iOS app values ─────────────────
|
|
|
|
-- Drop dependent objects first
|
|
DROP VIEW IF EXISTS public.feed_posts;
|
|
|
|
ALTER TABLE public.posts ALTER COLUMN mood TYPE text USING mood::text;
|
|
DROP TYPE IF EXISTS public.post_mood;
|
|
|
|
CREATE TYPE public.post_mood AS ENUM ('still', 'unruhig', 'schwer', 'geladen', 'zart', 'dunkel');
|
|
ALTER TABLE public.posts ALTER COLUMN mood TYPE public.post_mood USING mood::public.post_mood;
|
|
|
|
-- ── 2. Increase content length from 280 to 420 ───────────────────────────────
|
|
|
|
ALTER TABLE public.posts DROP CONSTRAINT posts_content_check;
|
|
ALTER TABLE public.posts ADD CONSTRAINT posts_content_check
|
|
CHECK (LENGTH(TRIM(content)) BETWEEN 1 AND 420);
|
|
|
|
-- ── 3. Add content warning columns to posts ─────────────────────────────────
|
|
|
|
ALTER TABLE public.posts ADD COLUMN IF NOT EXISTS has_content_warning BOOLEAN DEFAULT FALSE NOT NULL;
|
|
ALTER TABLE public.posts ADD COLUMN IF NOT EXISTS content_warning_type TEXT;
|
|
|
|
-- ── 4. Recreate feed_posts view with content_warning fields ──────────────────
|
|
|
|
CREATE OR REPLACE VIEW public.feed_posts AS
|
|
SELECT
|
|
p.id,
|
|
p.content,
|
|
p.mood,
|
|
p.is_anonymous,
|
|
p.created_at,
|
|
p.has_content_warning,
|
|
p.content_warning_type,
|
|
CASE WHEN p.is_anonymous THEN NULL ELSE p.user_id END AS author_id,
|
|
CASE WHEN p.is_anonymous THEN NULL ELSE pr.username END AS author_username,
|
|
CASE WHEN p.is_anonymous THEN NULL ELSE pr.display_name END AS author_display_name,
|
|
CASE WHEN p.is_anonymous THEN NULL ELSE pr.avatar_url END AS author_avatar_url,
|
|
COALESCE((
|
|
SELECT COUNT(*) FROM public.resonances r WHERE r.post_id = p.id
|
|
), 0)::int AS resonance_count
|
|
FROM public.posts p
|
|
JOIN public.profiles pr ON pr.id = p.user_id
|
|
WHERE p.deleted_at IS NULL
|
|
AND p.review_status IN ('ok', 'approved')
|
|
AND p.created_at > NOW() - INTERVAL '14 hours';
|
|
|
|
-- ── 5. Add get_streak RPC ────────────────────────────────────────────────────
|
|
|
|
CREATE OR REPLACE FUNCTION public.get_streak(p_user_id UUID)
|
|
RETURNS TABLE(streak INT) LANGUAGE plpgsql STABLE AS $$
|
|
DECLARE
|
|
v_streak INT := 0;
|
|
v_check_date DATE := CURRENT_DATE;
|
|
v_has_post BOOLEAN;
|
|
BEGIN
|
|
LOOP
|
|
SELECT EXISTS(
|
|
SELECT 1 FROM public.posts
|
|
WHERE user_id = p_user_id
|
|
AND deleted_at IS NULL
|
|
AND (created_at AT TIME ZONE 'Europe/Berlin')::DATE = v_check_date
|
|
) INTO v_has_post;
|
|
|
|
IF v_has_post THEN
|
|
v_streak := v_streak + 1;
|
|
v_check_date := v_check_date - 1;
|
|
ELSE
|
|
EXIT;
|
|
END IF;
|
|
END LOOP;
|
|
|
|
-- Check if user posted today; if not, streak is 0
|
|
IF v_streak = 0 THEN
|
|
RETURN NEXT;
|
|
ELSE
|
|
RETURN QUERY SELECT v_streak;
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
-- ── 6. Add get_resonance_count RPC ───────────────────────────────────────────
|
|
|
|
CREATE OR REPLACE FUNCTION public.get_resonance_count(p_user_id UUID)
|
|
RETURNS TABLE(count INT) LANGUAGE plpgsql STABLE AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT COUNT(*)::int AS count
|
|
FROM public.resonances r
|
|
JOIN public.posts p ON p.id = r.post_id
|
|
WHERE p.user_id = p_user_id
|
|
AND p.deleted_at IS NULL;
|
|
END;
|
|
$$;
|
|
|
|
-- ── 7. Add public_profile view for other-user profile lookups ────────────────
|
|
|
|
CREATE OR REPLACE VIEW public.public_profile AS
|
|
SELECT
|
|
p.id,
|
|
p.username,
|
|
p.display_name,
|
|
p.bio,
|
|
p.avatar_url,
|
|
p.is_pro,
|
|
p.is_admin,
|
|
p.created_at,
|
|
(SELECT COUNT(*) FROM public.posts WHERE user_id = p.id AND deleted_at IS NULL)::int AS post_count,
|
|
(SELECT COUNT(*) FROM public.resonances r JOIN public.posts p2 ON p2.id = r.post_id WHERE p2.user_id = p.id AND p2.deleted_at IS NULL)::int AS resonance_count,
|
|
(SELECT COUNT(*) FROM public.follows WHERE following_id = p.id)::int AS follower_count,
|
|
(SELECT COUNT(*) FROM public.follows WHERE follower_id = p.id)::int AS following_count
|
|
FROM public.profiles p;
|
|
|
|
-- ── 8. Add profile view RLS (public_profile is a view, inherits from profiles) ─
|
|
|
|
-- Allow updates to profiles row
|
|
-- (already handled by existing policy, no change needed)
|
|
|
|
-- ── 9. Enable Realtime for posts table ────────────────────────────────────────
|
|
|
|
ALTER PUBLICATION supabase_realtime ADD TABLE public.posts;
|
|
|
|
-- ── 10. Fix RLS for posts: allow reading all non-deleted approved posts ───────
|
|
|
|
DROP POLICY IF EXISTS posts_select ON public.posts;
|
|
CREATE POLICY "posts_select" ON public.posts FOR SELECT
|
|
USING (
|
|
deleted_at IS NULL
|
|
AND review_status IN ('ok', 'approved')
|
|
); |