BEGIN; CREATE OR REPLACE FUNCTION public.reorder_custom_instruction( instruction_id uuid, direction text ) RETURNS SETOF public.custom_instructions LANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$ DECLARE current_user_id uuid := auth.uid(); ordered_ids uuid[]; current_index integer; target_index integer; swapped_id uuid; BEGIN IF current_user_id IS NULL THEN RAISE EXCEPTION 'authentication_required' USING ERRCODE = '42501'; END IF; IF direction NOT IN ('up', 'down') THEN RAISE EXCEPTION 'invalid_direction' USING ERRCODE = '22023'; END IF; PERFORM pg_advisory_xact_lock(hashtextextended(current_user_id::text, 73036)); SELECT array_agg(instruction.id ORDER BY instruction.sort_order, instruction.created_at, instruction.id) INTO ordered_ids FROM public.custom_instructions AS instruction WHERE instruction.user_id = current_user_id AND instruction.builtin_key IS NULL; current_index := array_position(ordered_ids, instruction_id); IF current_index IS NULL THEN RAISE EXCEPTION 'instruction_not_found' USING ERRCODE = 'P0002'; END IF; target_index := current_index + CASE direction WHEN 'up' THEN -1 ELSE 1 END; IF target_index < 1 OR target_index > coalesce(array_length(ordered_ids, 1), 0) THEN RETURN QUERY SELECT instruction.* FROM public.custom_instructions AS instruction WHERE instruction.user_id = current_user_id ORDER BY instruction.sort_order, instruction.created_at, instruction.id; RETURN; END IF; swapped_id := ordered_ids[target_index]; ordered_ids[target_index] := ordered_ids[current_index]; ordered_ids[current_index] := swapped_id; UPDATE public.custom_instructions AS instruction SET sort_order = (ordering.ordinality * 10 + 1000)::integer FROM unnest(ordered_ids) WITH ORDINALITY AS ordering(id, ordinality) WHERE instruction.id = ordering.id AND instruction.user_id = current_user_id AND instruction.builtin_key IS NULL; RETURN QUERY SELECT instruction.* FROM public.custom_instructions AS instruction WHERE instruction.user_id = current_user_id ORDER BY instruction.sort_order, instruction.created_at, instruction.id; END; $$; REVOKE ALL ON FUNCTION public.reorder_custom_instruction(uuid, text) FROM PUBLIC; GRANT EXECUTE ON FUNCTION public.reorder_custom_instruction(uuid, text) TO authenticated; COMMIT;