2017-12-04 243 views
8

Próbuję wykonać proste zapytanie jako gotowe oświadczenie, ale nie powiodło się. Oto kod:Perl DBI (MySQL) umieszcza pojedynczy cytat zamiast rzeczywistego parametru w przygotowanym oświadczeniu

package sqltest; 
use DBI; 

DBI->trace(2); 

my $dbh = DBI->connect('dbi:mysql:database=test;host=***;port=3306','the_username', '****'); 
my $prep = 'SELECT me.id, me.session_data, me.expires FROM sys_session me WHERE me.id = ?'; 
$dbh->{RaiseError} = 1; 
my $sth = $dbh->prepare($prep); 
$sth->bind_param(1, 'session:06b6d2138df949524092eefc066ee5ab3598bf96'); 
$sth->execute; 
DBI::dump_results($sth); 

Serwer MySQL odpowiada błąd składni near '''.

Wyjście DBI-Trace pokazuje

-> bind_param for DBD::mysql::st (DBI::st=HASH(0x21e35cc)~0x21e34f4 1 'session:06b6d2138df949524092eefc066ee5ab3598bf96') thr#3ccdb4 
Called: dbd_bind_ph 
    <- bind_param= (1) [1 items] at perl_test_dbi_params.pl line 10 
[...] 
>parse_params statement SELECT me.id, me.session_data, me.expires FROM sys_session me WHERE me.id = ? 
Binding parameters: SELECT me.id, me.session_data, me.expires FROM sys_session me WHERE me.id = ' 
[...] 
DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1 

Więc dla mnie, wygląda na to oświadczenie nie zostanie przygotowane jak należy. Po wysłaniu zapytania bez parametru działa zgodnie z oczekiwaniami.

Czego tu brakuje?

wersja DBI jest DBI 1.637-ithread, wersja MySQL jest 5.5.57-0+deb8u1

Testowane z Windows perl 5, version 26, subversion 1 (v5.26.1) built for MSWin32-x86-multi-thread-64int
i Ubuntu perl 5, version 22, subversion 1 (v5.22.1) built for x86_64-linux-gnu-thread-multi

Edit1:
dla kontekstu: Zauważyłem ten problem podczas korzystania z Catalyst::Plugin::Session::Store::DBIC Catalyst. Tutaj kolumna id jest typem Varchar (72), który przechowuje identyfikator sesji.

Edit2:

  • DBD :: mysql wersja jest 4.043
  • Oprawa poprzez $sth->execute('session:foo'); wyników w tym samym problemem
  • Binding poprzez $sth->bind_param('session:foo', SQL_VARCHAR); wyników w tym samym problemem
  • wiązania Pole numeryczne działa, ale tylko z jawną definicją typu $sth->bind_param(1, 1512407082, SQL_INTEGER);

Edit3:
znalazłem czasu, aby zrobić trochę więcej badań, ale nie bez satysfakcjonujących wyników:

  • udało mi się przetestować ze starszym serwerze i to działało. Wersje DBI i DBD :: mysql są takie same, ale uważam, że serwer MySQL 5.5 klienta, poinformował w DBI-Trace jako MYSQL_VERSION_ID 50557, podczas obu moich oryginalnych serwerach testowych przy użyciu MySQL 5.7 MYSQL_VERSION_ID 50720 i MYSQL_VERSION_ID 50716
  • z $dbh->{mysql_server_prepare} = 1;to działa! Może to pomoże ktoś, kto znajdzie ten q., Ale wolałbym teraz prawdziwą przyczyną problemu
+2

który wygląda poprawne. Co się stanie, jeśli zastąpisz wywołania 'bind_param' i' execute' za pomocą '$ sth-> execute ('session: 06b6d2138df949524092eefc066ee5ab3598bf96')'? – Borodin

+0

@Borodin to ten sam problem z '$ sth-> execute (...)' –

+0

Jakiego rodzaju danych jest kolumna 'id'? Jesteś pewien, że nie jest to numeryczny? – Borodin

Odpowiedz

3

Po kilku testach, doszedłem do wniosku, że to wydaje się być problem kompatybilności pomiędzy DBD :: mysql i Klient MySQL 5.7 (i/lub serwer MySQL 5.5).

przynajmniej I znalazł rozwiązanie dla Ubuntu xenial (16), a więc dla innych, które mogą działać w tym samym numerze:

  • możliwość zmiany na MySQL 5.6, jak to opisano here. Dla mnie, instalowanie libmysqlclient-dev bez serwera/klienta była wystarczająca
  • ponowna DBD :: MySQL sudo cpanm --reinstall DBD::mysql, tak że robi się zbudować z zainstalowany MySQL 5,6

będę złożyć kwestię na DBD::mysql GitHub i zaktualizuje ta odpowiedź, jeśli są jakieś wiadomości dotyczące tego problemu.


Alternatywnym rozwiązaniem, który również pracował dla mnie:
niech serwer przygotować swoje oświadczenie $dbh->{mysql_server_prepare} = 1;