Rust AppView - highly experimental!
at experiments 4.9 kB view raw
1-- Insert post with direct actor_id and parent/root/embedded post natural keys 2-- Self-contained schema: No records table, metadata embedded directly in posts 3-- Parameters: $1=actor_id(INT4), $2=cid, $3=content(BYTEA, compressed), 4-- $4=languages(text[], up to 3), $5=tags, 5-- $6=parent_post_actor_id, $7=parent_post_rkey, 6-- $8=root_post_actor_id, $9=root_post_rkey, 7-- $10=embed, $11=embed_subtype, $12=violates_threadgate, $13=rkey(INT8), 8-- $14=tokens(text[], for search) 9-- $15=ext_embed(post_ext_embed), $16=video_embed(post_video_embed), 10-- $17=embedded_post_actor_id, $18=embedded_post_rkey, 11-- $19=record_detached(BOOL), 12-- $20-$23=image_1, image_2, image_3, image_4 (post_image_embed), 13-- $24-$31=facet_1 through facet_8 (post_facet_embed), 14-- $32=mentions(int[]) 15-- Note: created_at is derived from TID rkey 16-- Actor must already exist before calling this function 17-- Parent and root posts must exist before calling this function (use ensure_post_exists first) 18WITH embed_types AS ( 19 SELECT 20 CASE WHEN $10::text IS NOT NULL THEN $10::text::embed_type ELSE NULL::embed_type END as embed_type, 21 CASE WHEN $11::text IS NOT NULL THEN $11::text::embed_type ELSE NULL::embed_type END as embed_subtype 22) 23INSERT INTO posts ( 24 actor_id, rkey, cid, content, langs, tags, 25 parent_post_actor_id, parent_post_rkey, 26 root_post_actor_id, root_post_rkey, 27 embed_type, embed_subtype, 28 violates_threadgate, status, tokens, 29 ext_embed, video_embed, 30 embedded_post_actor_id, embedded_post_rkey, 31 record_detached, 32 image_1, image_2, image_3, image_4, 33 facet_1, facet_2, facet_3, facet_4, facet_5, facet_6, facet_7, facet_8, 34 mentions 35) 36SELECT 37 $1, -- actor_id (passed directly as INT4) 38 $13, -- rkey (INT8) 39 $2::bytea, -- cid (embedded) 40 $3, -- content (compressed BYTEA) 41 -- Convert text array to language_code array (supports up to 3 languages per AT Protocol spec) 42 -- Only include valid language codes that can be cast to the enum 43 COALESCE( 44 (SELECT array_agg(lang::language_code ORDER BY ordinality) 45 FROM unnest($4::text[]) WITH ORDINALITY AS t(lang, ordinality) 46 WHERE lang IS NOT NULL 47 AND lang::text IN (SELECT enumlabel FROM pg_enum WHERE enumtypid = 'language_code'::regtype) 48 LIMIT 3), 49 ARRAY[]::language_code[] 50 ), -- langs (array of up to 3 language codes) 51 $5, -- tags 52 $6, -- parent_post_actor_id 53 $7, -- parent_post_rkey 54 $8, -- root_post_actor_id 55 $9, -- root_post_rkey 56 (SELECT embed_type FROM embed_types), -- embed_type 57 (SELECT embed_subtype FROM embed_types), -- embed_subtype 58 $12, -- violates_threadgate 59 'complete'::post_status, -- status (this is a complete post with full content) 60 $14, -- tokens (text array, pre-tokenized in Rust) 61 $15, -- ext_embed 62 $16, -- video_embed 63 $17, -- embedded_post_actor_id 64 $18, -- embedded_post_rkey 65 $19, -- record_detached 66 $20, $21, $22, $23, -- image_1, image_2, image_3, image_4 67 $24, $25, $26, $27, $28, $29, $30, $31, -- facet_1 through facet_8 68 $32 -- mentions 69-- Posts are immutable - cannot be edited in AT Protocol 70-- However, if a stub/missing post already exists, upgrade it to complete 71-- (missing posts can become complete if we later receive the actual data) 72ON CONFLICT (actor_id, rkey) DO UPDATE 73SET cid = EXCLUDED.cid, -- Ensure CID is correct (stubs may have placeholder) 74 content = EXCLUDED.content, 75 langs = EXCLUDED.langs, 76 tags = EXCLUDED.tags, 77 parent_post_actor_id = EXCLUDED.parent_post_actor_id, 78 parent_post_rkey = EXCLUDED.parent_post_rkey, 79 root_post_actor_id = EXCLUDED.root_post_actor_id, 80 root_post_rkey = EXCLUDED.root_post_rkey, 81 embed_type = EXCLUDED.embed_type, 82 embed_subtype = EXCLUDED.embed_subtype, 83 violates_threadgate = EXCLUDED.violates_threadgate, 84 status = 'complete'::post_status, 85 tokens = EXCLUDED.tokens, -- Update tokens when upgrading from stub/missing 86 ext_embed = EXCLUDED.ext_embed, 87 video_embed = EXCLUDED.video_embed, 88 embedded_post_actor_id = EXCLUDED.embedded_post_actor_id, 89 embedded_post_rkey = EXCLUDED.embedded_post_rkey, 90 record_detached = EXCLUDED.record_detached, 91 image_1 = EXCLUDED.image_1, 92 image_2 = EXCLUDED.image_2, 93 image_3 = EXCLUDED.image_3, 94 image_4 = EXCLUDED.image_4, 95 facet_1 = EXCLUDED.facet_1, 96 facet_2 = EXCLUDED.facet_2, 97 facet_3 = EXCLUDED.facet_3, 98 facet_4 = EXCLUDED.facet_4, 99 facet_5 = EXCLUDED.facet_5, 100 facet_6 = EXCLUDED.facet_6, 101 facet_7 = EXCLUDED.facet_7, 102 facet_8 = EXCLUDED.facet_8, 103 mentions = EXCLUDED.mentions 104WHERE posts.status IN ('stub'::post_status, 'missing'::post_status) 105RETURNING actor_id, rkey