[SP-pm] Ajuda com módulo DBI::mysql e funcoes.

Otávio Fernandes otaviof at gmail.com
Sat Mar 13 06:56:35 PST 2010


2010/3/13 jefferson alexandre <jefferson.alexandre em gmail.com>:
> Bom dia a todos.
> Primeiramente, gostaria de parabenizar aos membros da lista pela educação e
> respeito com os usuários, independente do nível de conhecimento.  É legal
> ver que ainda existem listas nacionais que vale a pena frequentar, e esta é
> uma delas. :D
> Recentemente, consegui introduzir o perl no meu ambiente de trabalho,
> criando algumas ferramentas para manutenção e administração de servidores
> Asterisk. (PABX IP Open Source.)
> Eu tenho pouca ou quase nenhuma experiência com programação. No máximo,
> alguns scripts shell que estão sendo devidamente portados/reescritos em
> Perl.
> Eu criei uma rotina para o Asterisk para que, quando um usuário disparar uma
> ligação, meu script ira consultar o numero digitado pelo usuário com uma
> base de dados mysql, e então, mediante resultado, ira passar o controle de
> volta para o asterisk, para que ele complete ou não a ligação. Essa solução
> será instalada em Callcenters de São Paulo para cumprir esta
> lei: http://www.procon.sp.gov.br/noticia.asp?id=934
>
> O meu problema é, que independente do numero passado pelo asterisk, meu
> script sempre retorna 0 para a função &consulta_banco, e acaba bloqueando a
> ligação.
> Eu acredito que poderia resolver isso comparando o valor de $var em um if,
> mas eu gostaria de entender como resolver isso apenas usando o retorno da
> função, se este for o modo correto de fazer isso.
> Abaixo, o código:
> ++ Begin Code ++
> #!/usr/bin/perl -w
> use DBI();
> use Asterisk::AGI;
> $AGI = new Asterisk::AGI;
> ($database, $host, $user, $pw) = qw( procon 127.0.0.1 usuario senha );
> #Obter numero discado  via AGI. Deve retornar algo como (01112345678) ;
> $EXTEN = $AGI->get_variable('EXTEN') ;
>
> if ( &consulta_banco($EXTEN) )  {
> #Colocando o valor "1" na variavel FORBIDEN, que será tratada pelo asterisk,
> e imprimindo na tela.
>         $AGI->set_variable("FORBIDEN", "1");
> $AGI->verbose("Numero consta na lista do Procon-SP") ;
> }
> else {
> $AGI->set_variable("FORBIDEN", "0") ;
> $AGI->verbose("Executando ligacao para $EXTEN") ;
> }
> #Consultando banco de dados.
> sub consulta_banco {
> $dbh = DBI->connect("DBI:mysql:database=$database;host=$host", $user, $pw )
>  || die print $DBI::errstr;
>          $dbh->{RaiseError} = 1;
> $sth = $dbh->prepare(" SELECT numero FROM numeros WHERE numero LIKE
> \"%$_[0]%\" ");
>          $sth->execute() ;
> }
> ++ End Code ++
> Obrigado,
> _______________________________________________
> SaoPaulo-pm mailing list
> SaoPaulo-pm em pm.org
> http://mail.pm.org/mailman/listinfo/saopaulo-pm

Jefferson,

Em nome da lista eu lhe agradeço pelo elogio, é muito importante para
nós termos este tipo de feedback. Muito obrigado!

Pelo seu código, fica evidente que você te pouca experiência me
desenvolvimento, mas este é um problema que nós podemos resolver aqui
na lista, é apenas uma questão de tempo.

Alguns pontos são bastante falhos no seu código, dentre eles:
    * "use scrict";
    * Uso do DBI diretamente;
    * Cuidados com a indentação;
    * Não ter testes automatizados (estou supondo isso);

Segue um exemplo de como ele pode ser melhorado (acredito que ele já
deve até funcionar corretamente agora):

#!/usr/bin/env perl

use strict;
use warnings;

use DBI();
use Asterisk::AGI;

# ---------------------------------------------------------------------------
#                                Subroutines
# ---------------------------------------------------------------------------

sub consulta_banco {
    my ($number) = @_;

    my $dbh
        = DBI->connect( "DBI:mysql:database=" . $database . ";host=" . $host,
        $user, $pw )
        or die $!;
    $dbh->{RaiseError} = 1;

    my $sth;
    eval {
        $sth
            = $dbh->prepare( "
        SELECT
            numero
        FROM
            numeros
        WHERE
            numero LIKE \"%$number%\"
        " );

    };
    die $@ if $@;

    return 0 if ( !$sth );
    return 0 if ( !$sth->execute() );

    my $numeros = $sth->fetchrow_hashref;

    $sth->finish();

    return 1 if ( $numeros->{numero} );
    return 0;
}

# ---------------------------------------------------------------------------
#                                -- Main --
# ---------------------------------------------------------------------------

my $agi = new Asterisk::AGI;

my ( $database, $host, $user, $pw ) = qw( procon 127.0.0.1 usuario senha );

# obter numero discado  via AGI, deve retornar algo como (01112345678)
my $exten = $agi->get_variable('EXTEN');

if ( consulta_banco($exten) ) {
    # colocando o valor "4" na variavel FORBIDEN, que será tratada pelo
    # asterisk, e imprimindo na  tela.
    $agi->set_variable( "FORBIDEN", "1" );
    $agi->verbose("Numero consta na lista do Procon-SP");
} else {
    $agi->set_variable( "FORBIDEN", "0" );
    $agi->verbose("Executando ligacao para $exten");
}

__END__

O único problema que impedira do seu script funcionar corretamente,
independente da qualidade, é o uso incorreto da DBI, na função
"consulta_banco" eu coloquei a forma correta de como lidar com ele.
Apenas um exemplo.

Para melhorar os pontos citados acima, recomendo fortemente as leituras:

http://perldoc.perl.org/strict.html
http://perldoc.perl.org/warnings.html
http://sao-paulo.pm.org/equinocio/2010/mar/11
http://sao-paulo.pm.org/equinocio/2010/mar/12
http://en.wikipedia.org/wiki/Test-driven_development
http://www.agiledata.org/essays/tdd.html
http://search.cpan.org/~mschwern/Test-Simple-0.94/lib/Test/More.pm

Aproveitando o ensejo, segue dentre os links um artigo do Eden
publicado no Equinócio de Março, o qual é muito completo e vai lhe
ajudar muito.

um abraço,

-- 
Otávio Fernandes <otaviof at gmail.com>
http://blog.emresumo.com


More information about the SaoPaulo-pm mailing list