Funcionalidade de Timeout com DataServer SQL – parte III

Escrito por Marcos Kirchner em 24 de junho de 2009, 13:46h

No post anterior desta série verificamos como implementar uma forma de restringir o acesso a apenas uma sessão de cada produto por usuário.

Nossa implementação anterior utilizou uma trigger de Logon diretamente no banco de dados. A maior desvantagem desta implementação são as mensagens de erro que não apresentam informações úteis.

Nossa nova implementação enviará um comando SQL ao servidor para verificar se já existem sessões ativas para o mesmo usuário e produto. Os requisitos anteriores continuam os mesmos (autenticação integrada, informar o nome da aplicação nas conexões, arquitetura DataServer local).

O código deve estar no primeiro programa executado na sessão (parâmetro –p do prowin32.exe ou _progres.exe). Caso não seja possível alterar este programa, pode-se criar um programa novo e alterar o parâmetro –p da sessão.

 

ATENÇÃO: este código é uma ilustração dos conceitos abordados neste Post. Não há suporte para este código. Só utilize este código se entender exatamente o que ele faz e estiver satisfeito com o resultado.

DEFINE TEMP-TABLE ttResult NO-UNDO
    FIELD Resultado AS INTEGER
    FIELD Usuario AS CHARACTER.

DEF VAR ttH AS HANDLE NO-UNDO.
ASSIGN ttH = TEMP-TABLE ttResult:HANDLE.
RUN STORED-PROCEDURE mgadt.send-sql-statement
    LOAD-RESULT-INTO ttH
    ("IF EXISTS
        (SELECT *
        FROM sys.dm_exec_sessions s1 INNER JOIN sys.dm_exec_sessions s2
            ON s1.program_name = s2.program_name AND
            s1.original_login_name = s2.original_login_name AND
            (s1.host_name <> s2.host_name OR
            s1.host_process_id <> s2.host_process_id)
        WHERE s1.is_user_process = 1
            AND s2.is_user_process = 1
            AND s1.client_interface_name = 'ODBC'
            AND s2.client_interface_name = 'ODBC'
            AND s1.program_name LIKE 'Datasul%'
            AND s1.session_id = @@SPID
            AND s1.original_login_name = ORIGINAL_LOGIN())
    BEGIN
        SELECT 1, CAST(ORIGINAL_LOGIN() AS VARCHAR(128));
    END;
    ELSE
    BEGIN
        SELECT 0, '';
    END;").

FIND FIRST ttResult NO-ERROR.
IF AVAIL(ttResult) THEN DO:
    IF ttResult.Resultado = 0 THEN DO:
        RUN men/men902za.P.
    END.
    ELSE DO:
        MESSAGE 'Já existe uma sessão ativa deste produto para o usuário ' +
            ttResult.Usuario VIEW-AS ALERT-BOX ERROR.
    END.
END.

QUIT.

 

A parte SQL deste código é muito semelhante ao código do post anterior. No entanto, como não estamos mais executando uma trigger de login, a função EVENTDATA() não está mais disponível. Para obter o número da conexão e o login do usuário utilizamos as funções @@SPID e ORIGINAL_LOGIN(). Para execução correta deste código, os usuários devem possuir a permissão VIEW SERVER STATE.

O código SQL retorna 1 caso já exista uma sessão ativa para este usuário, e 0 caso contrário. O próximo passo é validar o retorno e continuar com a execução do programa ou apresentar uma mensagem de erro.

Todos os exemplos apresentados nesta série podem ser aprimorados ou adaptados para diferentes ambientes. Duas sugestões que podem ser úteis são a geração de logs das ações executadas pelas rotinas e criação de controles para que determinados usuários não sejam afetados por estas rotinas.

Categorias: Banco de dados | DataServer | SQL Server

Tags:

Comentar




biuquote
  • Comentário
  • Pré-visualização
Loading