Eu tenho um daemon de jogo não-bifurcado escrito em Perl , que usa consultas acync para gravar estatísticas de jogador em um banco de dados PostgreSQL 9.3. Mas quando preciso ler algo do banco de dados (como se um jogador é banido ou se o jogador tem um status VIP), então uso consultas síncronas.
Isso faz o jogo parar por um breve momento, até que o valor seja lido no banco de dados.
Não consigo reescrever meu daemon de jogo para usar consultas assíncronas para ler valores (tentei, mas exigiu muitas alterações); portanto, minha pergunta é : faria sentido combinar várias consultas não relacionadas (que eu preciso fazer quando um novo jogador conecta) a 1 procedimento e como eu poderia retornar vários valores ao mesmo tempo ao meu programa Perl?
Todas as minhas consultas atuais usam um ID de jogador como parâmetro e retornam 1 valor:
-- Has the player been banned?
select true from pref_ban where id=?
-- What is the reputation of this player?
select
count(nullif(nice, false)) -
count(nullif(nice, true)) as rep
from pref_rep where id=?
-- Is he or she a special VIP player?
select vip > now() as vip from pref_users where id=?
-- How many games has the player played to the end?
select completed from pref_match where id=?
Para combinar as consultas acima, provavelmente preciso de um procedimento como este:
create or replace function get_user_info(_id varchar) returns XXX as $BODY$
declare
is_banned boolean;
reputation integer;
is_vip boolean;
completed_games integer;
begin
select 1 into is_banned from pref_ban where id=_id;
select
count(nullif(nice, false)) -
count(nullif(nice, true))
into reputation
from pref_rep where id=_id;
select vip > now() into is_vip from pref_users where id=_id;
select completed into completed_games from pref_match where id=_id;
return XXX; /* How to return 4 values here? */
end;
$BODY$ language plpgsql;
Por favor, ajude-me a declarar o procedimento acima corretamente.
fonte
NULL
ouTRUE
na minhais_banned
variável com a seguinte declaração:select true into is_banned from pref_ban where id=_id
. Existe uma maneira de mudar paraFALSE
ouTRUE
?is_banned := exists(select 1 from pref_ban where id=_id)
deve funcionar, mas essa é uma pergunta diferente.Você deve definir um tipo composto. Você pode usá-lo como tipo de retorno de função e para registrar variáveis dentro de uma função.
Exemplo:
Na minha opinião, o uso de funções como essa é bastante razoável em termos de desempenho e lógica de aplicação.
Tipos compostos definidos pelo usuário são muito úteis se você deseja retornar um conjunto de linhas de sua função. Em seguida, defina o tipo de retorno da função como
setof composite-type
e usereturn next
oureturn query.
Exemplo:
fonte
OUT
parâmetros alcançar basicamente a mesma coisa, mas sem criar tipos definidos pelo usuário: postgresql.org/docs/current/static/...OUT
parâmetros - mas comoSELECT
eles no meu caso de 4 consultas não relacionadas?drop type if exists user_type cascade; create type user_type as(...);
porque meu script Perl chama as instruções SQL toda vez no momento da inicialização.