• Publicidad

Problema al hacer consulta en Database

Todo acerca de las bases de datos que existen: SQL, MySQL, Oracle, Postgres, CSV, etc.

Problema al hacer consulta en Database

Notapor Leibvitz » 2005-08-14 11:28 @519

Hola! Tengo un problema muy curioso. Cuando ejecuto este script, me funciona bien y hace lo que tiene que hacer.
Código: Seleccionar todo
require "config.conf";
use DBI;
my $nick = "leibvitz";
my $dbh = DBI->connect("DBI:mysql:$db:localhost",$user_db,$pass_db)
or die "No puedo conectarme\n";

my $sth = $dbh->prepare("SELECT COUNT(*) FROM service_admin WHERE admin='$nick';");
$sth->execute();
($num) = $sth->fetchrow_array();
$sth->finish();
$dbh->disconnect;

print "$num\n";


Pero cuando meto esta consulta en un subrutina y la ejecuto des de otro lugar, me dice:
DBD::mysql::st execute warning: at sql.pl line 14, <GEN0> line 36.
DBD::mysql::st fetchrow_array failed: fetch() without execute() at sql.pl line 15, <GEN0> line 36.


Y es que es exactamente lo mismo, solo que no hace execute por lo que veo. Qué puede ser?
Nam nunc tempus est.
Avatar de Usuario
Leibvitz
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2004-11-07 13:19 @596
Ubicación: Reus, Catalunya

Publicidad

Re: Problema curioso

Notapor Perl user » 2005-08-14 13:25 @600

Leibvitz escribiste:Hola! Tengo un problema muy curioso. Cuando ejecuto este script, me funciona bien y hace lo que tiene que hacer.
Código: Seleccionar todo
require "config.conf";
use DBI;
my $nick = "leibvitz";
my $dbh = DBI->connect("DBI:mysql:$db:localhost",$user_db,$pass_db)
or die "No puedo conectarme\n";

my $sth = $dbh->prepare("SELECT COUNT(*) FROM service_admin WHERE admin='$nick';");
$sth->execute();
($num) = $sth->fetchrow_array();
$sth->finish();
$dbh->disconnect;

print "$num\n";


Pero cuando meto esta consulta en un subrutina y la ejecuto des de otro lugar, me dice:
DBD::mysql::st execute warning: at sql.pl line 14, <GEN0> line 36.
DBD::mysql::st fetchrow_array failed: fetch() without execute() at sql.pl line 15, <GEN0> line 36.


Y es que es exactamente lo mismo, solo que no hace execute por lo que veo. Qué puede ser?


Bueno el problema es que se te pudo pasar el execute, pero además, no se si realmente solo pusiste ese código como ejemplo, o es ya el código terminal de tu aplicación, pero tienes algunos detalles importantes que se te pasaron:

1) No encuentro por qué tu archivo en el require no pudo llamarse config.pl, pero además, si estás importando variables que posiblemente luego tengas que cambiar, sería mejor que importaras constantes. Pero aún mejor, genera un archivo en YAML o simplemente en CSV o algo en texto plano, y luego escribe un programa (config.pl) que lo interprete, y te importe un %config con todo lo que necesitas de configuraciones, esto mas sencillo de manejar, y cualquier cambio en los valores de configuración, no hará que tengas que modificar todo el código o los códigos.
2) Jamás estás usando strict ni warnings, y eso está de alguna manera penalizado, el no usarlos en una aplicación en producción es de muy mal estilo, y puedes tener problemas al mantener y depurar tu código.
3) Haz que DBI cargue RaiseError al inicio, así, cada que algo falle, automáticamente lanzará una excepción con die incluyendo el mensaje de error que provocó dicho fallo, y de esa manera no tienes que andar checando $dbi->errstr ( que no lo haces de todos modos ) para ver que es lo que ocurrió. O si tu prefieres hacer el manejo de errores, mete las sentencias que ejecutará DBI en bloque de eval y verifica $@ al final para ver que fué lo que sucedió.
4) Estás pasando directamente los parámetros al query sin cuidar que puede haber SQL injection, es decir, sin usar placeholders que puedan escapar tus parámetros apropiadamente.

Un intento "sano" de tu aplicación podría ser:
Código: Seleccionar todo
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
require 'config.pl'; #importará %config

my $nick = 'leibvitz';
my $dbh = DBI->connect( "dbi:mysql:$config{db_name}", $config{user}, $config{pass},
          { RaiseError => 1 } ) or die "No se pudo conectar: $DBI::errstr\n";
my $sth = $dbh->prepare( 'SELECT COUNT(*) FROM service_admin WHERE admin=?' );
$sth->execute( $nick );
my ( $num ) = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect;

print $num, "\n",


Saludos,
Última edición por Perl user el 2005-08-14 17:57 @790, editado 1 vez en total
Marco A. Manzo
[email protected]
http://www.unixmonkeys.com/amnesiac/
Perl Programming Language
Perl user
Maestro honorario
Maestro honorario
 
Mensajes: 271
Registrado: 2004-11-03 21:11 @924

Notapor Invitado » 2005-08-14 13:52 @619

No sé qué es ni YAML ni CSV. Y lo que no entiendo es pq suelto hace lo que debe hacer y incluido en un función no.
Código: Seleccionar todo
sub verify {
   if ($root eq lc($nick{$tok})) {
      return 1;
   }
   else {
      my $sth = $dbh->prepare( 'SELECT COUNT(*) FROM service_admin WHERE admin=?' );
      $sth->execute( $nick{$tok} );
      my ( $num ) = $sth->fetchrow_array;
      $sth->finish;
      $dbh->disconnect;
      return $num;
   }
}

$nick{$tok} devuelve el nick del numerico $tok
Invitado
 

Notapor Leibvitz » 2005-08-14 13:55 @622

Luego el resultado de &verify lo uso para saber si tiene acceso o no al comando.
Código: Seleccionar todo
sub srv_msg {
   $permet = &verify;
   if ($permet) {
      print $socket "@param\n";
   }
   else {
      &access_denied;
   }
}
Nam nunc tempus est.
Avatar de Usuario
Leibvitz
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2004-11-07 13:19 @596
Ubicación: Reus, Catalunya

Notapor Perl user » 2005-08-14 14:42 @654

Creo que eres de los que tampoco ha leído del por qué no usar &funcion, pero bueno..

Por lo visto tienes a $dbh accesible globalmente, entonces para que generas una función como la de verify? No te sirve de nada si realmente tienes cosas no encapsuladas, la programación estructurada no es solo escribir funciones al azar, sino estructurar tu programa de tal manera que mantengas encapsulados tus datos de manera segura.

Sobre YAML y CSV, ok, entiendo que no los conoces, pero si estas en el foro supongo que tienes conexión a internet, lo cual, te abre una GRAN puerta al conocimiento desde muchos puntos de vista. Es decir, basta con ponerle en google YAML o CSV ( comma separated value ) y con eso podrás saber lo que cada cosa significa y como se usa.

También te recomiendo leer este post:
viewtopic.php?p=2162#2162

NOTA: Decir "no hace lo que tiene que hacer" no ayuda de mucho.

Saludos,
Marco A. Manzo
[email protected]
http://www.unixmonkeys.com/amnesiac/
Perl Programming Language
Perl user
Maestro honorario
Maestro honorario
 
Mensajes: 271
Registrado: 2004-11-03 21:11 @924

Notapor Leibvitz » 2005-08-14 16:12 @716

Creo que eres de los que tampoco ha leído del por qué no usar &funcion, pero bueno..


Pégame el post por favor.

Ah, es necesario serializar los datos de configuración? para luego generar un %? Como se definen constantes en perl?
Nam nunc tempus est.
Avatar de Usuario
Leibvitz
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2004-11-07 13:19 @596
Ubicación: Reus, Catalunya

Notapor Invitado » 2005-08-14 17:32 @772

Leibvitz escribiste:
Creo que eres de los que tampoco ha leído del por qué no usar &funcion, pero bueno..


Pégame el post por favor.

Ah, es necesario serializar los datos de configuración? para luego generar un %? Como se definen constantes en perl?


Que tal, en mi mensaje anterior allí te puse la liga hacia el otro thread que comentaba sobre la problemática de usar &sub.

Sobre serializar, bueno, la serialización o también conocida como data marshaling no es mas que la conversión de valores arbitrarios a cadenas. La idea que te planteaba sobre usar YAML, o algun otro formato, el que gustes, era para que tengas un archivo de configuración ( config.conf o como quieras llamarle ), en el cual puedas cambiar tus datos o valores cada que lo necesites, y bastaría con escribir un pequeño programa que lea ese archivo de configuración, y lo acomode en un hash correspondiente con su llave-valor el cual puedas importar mediante la invocación de dicho módulo.

Por ejemplo, un archivo podría .conf podría ser:

#config.conf
db_name=leibnitz
username=leibnitz
password=foobarbaz
hostname=192.168.0.2

y el código que lo analice podría ser:
Código: Seleccionar todo
package Conf;

use strict;
use warnings;

our ( @ISA, @EXPORT );
@ISA = qw ( Exporter );
@EXPORT = qw( %config );

open my $file, 'config.conf' or die $!;
our %config = map { split/=/ } <$file>;

1;

Y lo usarías de la siguiente manera:
Código: Seleccionar todo
#!/usr/bin/perl
#test.pl

use strict;
use warnings;
use Conf; #importará %config a tu espacio de nombres actual
use DBI;

my $dbh = DBI->connect( "dbi:mysql:$config{db_name}", $config{username}, $config{password} );
...
...


Este ejemplo importa el hash %config, pero bien podría ser una funcion que te lo retorne, como gustes.

Sobre como definir constantes en Perl, lo puedes hacer sencillamente con el módulo pragmático constant:
Código: Seleccionar todo
use constant USER => 'leibnitz';
use constant PASSWORD => 'foo';
#o bien...
sub USER () { 'leibnitz' }
sub PASSWORD () { 'foo' }


Para mas información consultar: perlsub, perlmod, perlmodlib.

Saludos,
Invitado
 

Notapor Leibvitz » 2005-08-14 17:42 @779

Ok! haré lo del conf. He seguido provando y no entindo por qué no se ejecuta el $sth->execute. No lo entiendo.
Nam nunc tempus est.
Avatar de Usuario
Leibvitz
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2004-11-07 13:19 @596
Ubicación: Reus, Catalunya

Notapor Perl user » 2005-08-14 17:55 @788

Leibvitz escribiste:Ok! haré lo del conf. He seguido provando y no entindo por qué no se ejecuta el $sth->execute. No lo entiendo.


Sería bueno que postearas buena parte de tu código tal cual como lo estás usando.

Y sobre el correo que me enviaste, normalmente me encuentras en #perl en irc.freenode.net por IRC obviamente, con el nickname de Amnesiac.

Saludos,
Marco A. Manzo
[email protected]
http://www.unixmonkeys.com/amnesiac/
Perl Programming Language
Perl user
Maestro honorario
Maestro honorario
 
Mensajes: 271
Registrado: 2004-11-03 21:11 @924

Notapor kidd » 2005-08-15 09:51 @452

Anonymous escribiste:
Código: Seleccionar todo
sub verify {
   if ($root eq lc($nick{$tok})) {
      return 1;
   }
   else {
      my $sth = $dbh->prepare( 'SELECT COUNT(*) FROM service_admin WHERE admin=?' );
      $sth->execute( $nick{$tok} );
      my ( $num ) = $sth->fetchrow_array;
      $sth->finish;
      $dbh->disconnect;
      return $num;
   }
}



Al inicio de tu función tienes una condicional if. Lo que puede estar pasando es que tus valores $root y $nick{$tok} en las pruebas que estás haciendo son los mismos por ello nunca pasas al else.

Te recomiendo que cheques los valores de las dos variables, por lo menos eso es lo primero que checaría.

También así como dice Marco, si realmente quieres encapsular tu código, el $dbh que usas en tu función, no debería ser el global, más bien lo deberías de mandar como un argumento.


SALUDOS
Uriel Lizama Perl programmer fundador de Perl en Español
Perl Programming Language
Avatar de Usuario
kidd
Creador de Perl en Español
Creador de Perl en Español
 
Mensajes: 1166
Registrado: 2003-10-15 16:52 @744
Ubicación: México


Volver a Bases de datos

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 6 invitados

cron