OVH Cloud OVH Cloud

[mystere] dbi + anti_slash + apostrophe + deux_points = erreur

5 réponses
Avatar
Edwin Vancleef
[mystere] dbi + anti_slash + apostrophe + deux_points =3D erreur

J'aimerais comprendre ce myst=E8re :

---

my $query =3D "CREATE TEMPORARY TABLE test( a TEXT, b TEXT )";
print "$query\n";
my $sth =3D $cnx->prepare($query) or die("boom");
$sth->execute or die("boom ($DBI::errstr)");

$query =3D "INSERT INTO test(a,b) VALUES('foo',':bar')";
print "$query\n";
$sth =3D $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works

$query =3D "INSERT INTO test(a,b) VALUES('fo\\'o',':bar')";
print "$query\n";
$sth =3D $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works

$query =3D "INSERT INTO test(a,b) VALUES('foo\\'','bar')";
print "$query\n";
$sth =3D $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works

$query =3D "INSERT INTO test(a,b) VALUES('foo\\'',':bar')";
print "$query\n";
$sth =3D $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # boom ! unbound placeholder

---

Ne me parlez pas de la fonction "quote", ni de la technique des doubles-apo=
strophes. Je ne cherche pas =E0 corriger l'erreur. Je cherche =E0 comprendr=
e le myst=E8re.

5 réponses

Avatar
Paul Gaborit
À (at) Wed, 5 Apr 2006 16:33:00 +0200,
Edwin Vancleef écrivait (wrote):
J'aimerais comprendre ce mystère :


Vous précisez pas le SGBD que vous utilisez. J'ai donc fait les mêmes
tests que vous avec SQLite.

my $query = "CREATE TEMPORARY TABLE test( a TEXT, b TEXT )";
print "$queryn";
my $sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom ($DBI::errstr)");


Ok.

$query = "INSERT INTO test(a,b) VALUES('foo',':bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works


Ok.

$query = "INSERT INTO test(a,b) VALUES('fo'o',':bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works


Échoue avec le message : near "o": syntax error...

Normal puisque :

INSERT INTO test(a,b) VALUES('foo'o','bar')

n'est pas du SQL valide. 'foo' est correct. C'est le o tout seule qui
est problèmatique.

$query = "INSERT INTO test(a,b) VALUES('foo'','bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works


Échoue avec le message : near "bar": syntax error...

Normal puisque :

INSERT INTO test(a,b) VALUES('foo'','bar')

n'est pas du SQL valide. 'foo'',' est correct (c'est la valeur "foo',").
C'est le bar tout seul qui est problèmatique...

$query = "INSERT INTO test(a,b) VALUES('foo'',':bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # boom ! unbound placeholder


Échoue avec le message : near ":bar": syntax error...

Mêmes explications que ci-dessus.

Ne me parlez pas de la fonction "quote", ni de la technique des
doubles-apostrophes. Je ne cherche pas à corriger l'erreur. Je
cherche à comprendre le mystère.


Pour mieux comprendre, essayez l'exemple suivant (et regardez donc ce
qui est insérer dans votre base de données) :

$query = "INSERT INTO test(a,b) VALUES('foo''bar', 'bar')";
...

PS pour ceux qui n'ont pas envie de chercher : en SQL le caractère
n'a pas de signification particulière... sauf pour certains SGBD
(comme mysql par exemple). D'où l'utilité d'utiliser 'quote' qui
connaît les spécificités du SGBD.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Edwin Vancleef
Le Wed, 05 Apr 2006 18:48:18 +0200,

$query = "INSERT INTO test(a,b) VALUES('fo'o',':bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works


Échoue avec le message : near "o": syntax error...


Ca marche chez moi...

$query = "INSERT INTO test(a,b) VALUES('foo'','bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works


Échoue avec le message : near "bar": syntax error...


Ca marche chez moi...

Ne me parlez pas de la fonction "quote", ni de la technique des
doubles-apostrophes. Je ne cherche pas à corriger l'erreur. Je
cherche à comprendre le mystère.


Pour mieux comprendre, essayez l'exemple suivant (et regardez donc ce
qui est insérer dans votre base de données) :


Je connais déjà les doubles-apostrophes, mais comme je l'ai déjà di t, je ne cherche pas à éviter l'erreur. Je cherche à la comprendre.

$query = "INSERT INTO test(a,b) VALUES('foo''bar', 'bar')";
...

PS pour ceux qui n'ont pas envie de chercher : en SQL le caractère
n'a pas de signification particulière... sauf pour certains SGBD
(comme mysql par exemple). D'où l'utilité d'utiliser 'quote' qui
connaît les spécificités du SGBD.


Je connais déjà la fonction "quote", mais comme je l'ai déjà dit, j e ne cherche pas à éviter l'erreur. Je cherche à la comprendre.


Avatar
Paul Gaborit
À (at) Thu, 6 Apr 2006 12:17:34 +0200,
Edwin Vancleef écrivait (wrote):
Le Wed, 05 Apr 2006 18:48:18 +0200,

$query = "INSERT INTO test(a,b) VALUES('fo'o',':bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # works


Échoue avec le message : near "o": syntax error...


Ca marche chez moi...


Oui. Vos commentaires (# works) l'indiquaient déjà.

[...]
Je connais déjà la fonction "quote", mais comme je l'ai déjà dit, je
ne cherche pas à éviter l'erreur. Je cherche à la comprendre.


Ma réponse visait aussi à vous montrer que le code fourni n'avait pas
un comportement indépendant de l'environnement. Or vous ne nous
décrivez toujours pas votre environnement. Alors comment voulez-vous
que nous vous expliquions les messages d'erreur obtenus ?

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>



Avatar
Paul Gaborit
À (at) Thu, 06 Apr 2006 13:31:19 +0200,
Paul Gaborit écrivait (wrote):
Ma réponse visait aussi à vous montrer que le code fourni n'avait pas
un comportement indépendant de l'environnement. Or vous ne nous
décrivez toujours pas votre environnement. Alors comment voulez-vous
que nous vous expliquions les messages d'erreur obtenus ?


Juste par curiosité, je viens d'exécuter votre code en utilisant non
plus SQLite mais mysql et là tout passe comme une lettre à la poste.

Donc pour l'instant :

- avec SQLite, il y a des tests qui ne passent pas mais pas les
mêmes que ceux que vous constatez...

- avec mysql, tout se passe bien...

- avec *votre* SGBD *inconnu* le dernier test ne passe pas.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Jacques Caron
Salut,

On Wed, 05 Apr 2006 16:33:00 +0200, Edwin Vancleef
wrote:

$query = "INSERT INTO test(a,b) VALUES('foo'',':bar')";
print "$queryn";
$sth = $cnx->prepare($query) or die("boom");
$sth->execute or die("boom($DBI::errstr)"); # boom ! unbound placeholder


Sur certains SGBD et/ou drivers DBD (comme DBD::Pg avec PostgreSQL), il
existe une notation :nom pour les placeholders (en parallèle de ? ou de
$numéro). Là, comme vous ne voulez pas utiliser quote, ou, mieux, des
placeholders qui utiliseront quote tout seuls, le driver se débrouille
comme il peut (mal), probablement parce qu'il voit ça comme "foo'," suivi
du placeholder :bar (et une chaîne non terminée ")"), ou un truc du genre
(sans savoir le driver utilisé et ses règles de quoting, difficile de dire
exactement). Ca doit planter au niveau du driver, avant même que ça ne
soit envoyé au SGBD.

La bonne solution c'est bien entendu:

$sth = $cnx->prepare("INSERT INTO test (a,b) VALUES (?,?)");
$sth->execute("foo'",":bar");

Evidemment, vous allez me dire, mais pourquoi:

$query = "INSERT INTO test(a,b) VALUES('foo',':bar')";
$query = "INSERT INTO test(a,b) VALUES('fo'o',':bar')";

ne font pas d'erreur? Probablement parce que dans le premier cas, le
driver voit bien deux chaînes "foo" et ":bar" (il n'interpole pas les :nom
à l'intérieur d'une chaîne), et dans le deuxième je n'en sais trop rien,
tiens, j'aurais tendance à penser que ça devrait aussi planter, mais bon...

Donc:
1. Dites nous quel SGBD (y compris la version exacte) et quel driver DBD
(y compris la version exacte, il y a eu beaucoup de changements - et de
bugs - au fil de l'évolution de DBD::Pg, par exemple).
2. Utilisez des placeholders, ils sont là pour ça. Au passage, comme il en
existe plusieurs types, celui qui est le plus portable et le plus
recommandé est "?". Sinon vous vous aventurez en contrée spécifique au
SGBD et au driver utilisé.

Jacques.
--
Oxado http://www.oxado.com/