-- Create function to calculate and update stats in the cache table -- This function runs the expensive queries and stores the results CREATE OR REPLACE FUNCTION update_and_get_stats() RETURNS TABLE ( pokemon_caught BIGINT, total_users BIGINT, completed_pokedexes BIGINT, updated_at TIMESTAMPTZ ) SECURITY DEFINER SET search_path = public, pg_temp LANGUAGE plpgsql AS $$ DECLARE v_pokemon_caught BIGINT; v_total_users BIGINT; v_completed_pokedexes BIGINT; v_updated_at TIMESTAMPTZ := NOW(); BEGIN -- Calculate current stats: count of caught Pokémon SELECT COUNT(*) INTO v_pokemon_caught FROM catch_records WHERE caught = true; -- Calculate current stats: count of total users SELECT COUNT(*) INTO v_total_users FROM auth.users; -- Calculate current stats: count of completed pokedexes -- A pokedex is completed when all its entries have caught = true SELECT COUNT(*) INTO v_completed_pokedexes FROM ( SELECT "pokedexId" FROM catch_records GROUP BY "pokedexId" HAVING COUNT(*) = COUNT(*) FILTER (WHERE caught = true) ) completed; -- Update cache using UPSERT pattern INSERT INTO stats_cache (id, pokemon_caught, total_users, completed_pokedexes, updated_at) VALUES (1, v_pokemon_caught, v_total_users, v_completed_pokedexes, v_updated_at) ON CONFLICT (id) DO UPDATE SET pokemon_caught = EXCLUDED.pokemon_caught, total_users = EXCLUDED.total_users, completed_pokedexes = EXCLUDED.completed_pokedexes, updated_at = v_updated_at; -- Return the stats RETURN QUERY SELECT v_pokemon_caught, v_total_users, v_completed_pokedexes, v_updated_at AS updated_at; END; $$;