paramétre dans un fichier de conf

paramétre dans un fichier de conf - Perl - Programmation

Marsh Posté le 12-10-2018 à 08:41:09    

Bonjour,
 
Je crée un page html générée par un script perl en cgi.
Dans ce script j'utilise un fichier de configuration pour initialiser toutes mes variables.
Une des variables est un requête SQL qui contient un paramètre ($param) passé depuis la page précédente.
 
voici mon fichier de conf :
 

Code :
  1. data_source=dbi:ODBC:localhost
  2. user=userdb
  3. password=1234567
  4. Server=server1\SQLEXPRESS
  5. sql=SELECT * FROM Mytable where name='$param'


 
Voici le début de mon script :

Code :
  1. use strict;
  2. use warnings;
  3. use LWP::UserAgent;
  4. use CGI;
  5. use DBI;
  6. use Config::File qw(read_config_file);
  7. use Cwd;
  8. #récupération de $param
  9. my $cgi = new CGI;
  10. my $param = $cgi->param('param');
  11. #récupération de l'environnement
  12. my $env=$ENV{"m_Envir"};
  13. #récupération du répertoire de travail
  14. my $rep = cwd();
  15. #lecture du fichier de conf
  16. my $config=read_config_file($rep.'/conf/db.conf');
  17. #assignation des variables
  18. my $data_source=$config->{data_source};
  19. my $user=$config->{user};
  20. my $password=$config->{password};
  21. my $Server=$config->{Server};
  22. my $sql=$config->{sql};
  23. # Connect to the data source and get a handle for that connection.
  24. my $dbh = DBI->connect("dbi:ODBC:Driver={SQL Server};Server=$Server;UID=$user;PWD=$password" ) or die "Can't connect to $data_source: $DBI::errstr";
  25. $dbh->{LongReadLen} = 25000;
  26. # Select to get all variables
  27. my $sth= $dbh->prepare($sql);
  28. $sth->execute();
  29. my @tabs;
  30. while (my @row = $sth->fetchrow_array())
  31. {
  32. push (@tabs,@row)
  33. }
  34. my $nb_var=$sth->rows;
  35. $sth->finish();
  36. $dbh->disconnect;
  37. ...


 
Mon problème c'est que $param n'est pas interprété et ne prend pas la valeur de la variable $param et $sql=SELECT * FROM Mytable where name='$param' au lieu de $sql=SELECT * FROM Mytable where name='toto' si $param=toto.
Je ne vois pas comment faire pour que $param puisse être évalué avec sa valeur.
 
Quelqu'un à une idée, une piste ?
 
Par avance merci pour votre aide :jap:
 
 

Reply

Marsh Posté le 12-10-2018 à 08:41:09   

Reply

Marsh Posté le 12-10-2018 à 09:32:08    

Salut,
 
Comme le souligne la doc DBI, "execute" peut recevoir des paramètres (ici $params) en utilisant des "?" dans la requête préparé par "prepare".
 
Exemple de la doc:  

Code :
  1. $sth = $dbh->prepare("SELECT foo, bar FROM table WHERE baz=?" );
  2. $sth->execute( $baz );


 
Source: https://metacpan.org/pod/DBI
 
Application à ton cas:  

Code :
  1. my $sql = "SELECT * FROM Mytable where name='?'";
  2. my $sth= $dbh->prepare($sql);
  3. $sth->execute($param);


 
dd


Message édité par dede_sav le 12-10-2018 à 09:32:40
Reply

Marsh Posté le 12-10-2018 à 09:37:51    

Salut Dede,
 
Merci beaucoup pour ton aide.
Dans mon cas ma requête doit absolument se trouver dans le fichier de conf (la requête est différente en fonction de l'environnement).
Au début je faisais à peu prés comme ça, mais maintenant je ne peu plus :(
 
 :hello:

Reply

Marsh Posté le 12-10-2018 à 09:57:30    

Je ne comprends pas, la requête sql n'est qu'une chaine de caractère.  
Dans mon exemple "SELECT * FROM Mytable where name='?'" peut se trouver dans ton fichier de conf comme actuellement.
 

Reply

Marsh Posté le 12-10-2018 à 10:01:46    

Ah je n'avais pas compris  :pt1cable:  
 
Je test ça tout de suite :)

Reply

Marsh Posté le 12-10-2018 à 10:19:32    

Pareil :(
le name='?' n'est pas interprété lors du $sth->execute($param);
 
 :??:

Reply

Marsh Posté le 12-10-2018 à 10:38:16    

Tu vérifies comment ? Tu regardes au niveau de la bdd ?
Tu as vérifiés le contenu de $param ? C'est bien une chaine de caractère ?
 
dd

Reply

Marsh Posté le 12-10-2018 à 10:51:08    

J'affiche la valeur de $sql et le résultat de la requête qui est vide.
$param est bien valorisé, c'est une chaîne de caractère.

Reply

Marsh Posté le 12-10-2018 à 11:23:11    

Ok, normal que tu ne vois pas de changement à "name='?'" car cela se passe lors de l'envoie de ta requête SQL vers la base de donnée.
Si tu veux voir si la requête est vraiment interprété =>  
https://stackoverflow.com/questions [...] laceholder
 
Donc je te propose de rajouter dans ton code  

Code :
  1. $dbh->trace($dbh->parse_trace_flags('SQL|1|test'));


puis de regarder les logs.
 
Sinon, il faut vérifier si la requête une fois construire renvoie vraiment quelque chose depuis le serveur, si ça se trouve c'est un soucis de cast dans la condition where ... un oubli bête quoi ^^'

Reply

Marsh Posté le 12-10-2018 à 11:28:26    

Je vais tester la trace, mais si je fais directement

Code :
  1. $sql="SELECT * FROM Mytable where name='$param'"

sans passer par le fichier de conf, ça fonctionne très bien.
Il n'y a pas de problème dans mon where :(


Message édité par web_olivier le 12-10-2018 à 11:28:48
Reply

Marsh Posté le 12-10-2018 à 11:28:26   

Reply

Marsh Posté le 12-10-2018 à 11:41:22    

J'ai testé la trace et le résultat envoyé dans la requête est est

Code :
  1. SELECT * FROM Mytable where name='?'


:(

Reply

Marsh Posté le 12-10-2018 à 12:24:16    

Enlève peut être les simple quote autour du ?.
 
C'est normal que la solution ou tu mets la variable directement fonctionne.  
Mais c'est parce qu'il existe dans ton fichier .pl un my $param et que tu définis l'ensemble de la requête dans ce même fichier.

Reply

Marsh Posté le 12-10-2018 à 12:33:28    

Pourquoi faire dans le compliqué alors qu'il y a simple.
my $sql=$config->{sql};
$sql =~ s/$param/$param/;
et basta
 
Bon, si il y avait plusieurs exécutions avec des valeurs différentes dans une même session avec la BDD, on pourrait partir dans la voie que vous explorez, mais au vu de son exemple d'utilisation, cela n'a pas l'air d'être le cas.
 
A+,

Message cité 1 fois
Message édité par gilou le 12-10-2018 à 12:37:34

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 12-10-2018 à 12:37:01    

pour le plaisir de comprendre :)
 
mais sinon, oui c'est l'autre solution.

Reply

Marsh Posté le 12-10-2018 à 13:04:51    

gilou a écrit :

Pourquoi faire dans le compliqué alors qu'il y a simple.
my $sql=$config->{sql};
$sql =~ s/$param/$param/;
et basta
 
Bon, si il y avait plusieurs exécutions avec des valeurs différentes dans une même session avec la BDD, on pourrait partir dans la voie que vous explorez, mais au vu de son exemple d'utilisation, cela n'a pas l'air d'être le cas.
 
A+,


 
Merci Gilou, mais c'est pareil :(
J'ai toujours le $param dans la requête à la place de sa valeur !

Reply

Marsh Posté le 12-10-2018 à 13:11:50    

J'ai trouvé, il fallait faire  
$sql =~ s/\$param/$param/;
 
Merciiiiiii Gilou et dd :)


Message édité par web_olivier le 12-10-2018 à 13:19:30
Reply

Marsh Posté le 12-10-2018 à 13:34:50    

web_olivier a écrit :

J'ai toujours le $param dans la requête à la place de sa valeur !
J'ai trouvé, il fallait faire  
$sql =~ s/\$param/$param/;


Oui, tu as tout a fait raison. J'avais testé sur un exemple, mais qui marchait pour de mauvaises raisons.
 
Pour en revenir a la question initiale, il suffit de lire la doc de perl DBI poyr avoir la réponse:
sql=SELECT * FROM Mytable where name=?
..............................
my $sth= $dbh->prepare( $sql );
$sth->bind_param( 1, $param );
$sth->execute(  );
 
 
Et probablement aussi  
my $sth= $dbh->prepare( $sql );
$sth->execute( $param );
 
S'il y a des quotes autour de la valeur dans la query standard, elles ne sont pas présentes en cas de remplacement par un ?
cf cette page de Programming the Perl DBI: https://docstore.mik.ua/orelly/linux/dbi/ch05_03.htm
ou on voit que
$sth = $dbh->prepare( "SELECT name, location FROM megaliths WHERE name = " . $dbh->quote( $siteName ) . "" );
passe a  
$sth = $dbh->prepare( "SELECT name, location FROM megaliths WHERE name = ?" );
$sth->bind_param( 1, $siteName );
et ou c'est dit en toutes lettres modulo la remarque ça marche sauf quand ça marche pas.

Citation :

You may have noticed that we haven't called the quote( ) method on the values. Bind values are passed to the database separately from the SQL statement,[50] so there's no need to "wrap up" the value in SQL quoting rules.
 
    [50]This is not strictly true, since some drivers emulate placeholders by doing a textual replacement of the placeholders with bind values before passing the SQL to the database. Such drivers use Perl's internal information to guess whether each value needs quoting or not. Refer to the driver documentation for more information.


 
A+,


Message édité par gilou le 12-10-2018 à 13:48:11

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 12-10-2018 à 14:07:34    

Merci Gilou pour cette explication très enrichissante, je vais lire ça et essayer d'améliorer mon code.
 
A+

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed