poniedziałek, 22 sierpnia 2011

Konkatenacja w zapytaniach SQL a bindowanie przez "?"

Ostatnio w kodzie pewnego programisty znalazłem dosyć ciekawy błąd. Wynikał on z różnego sposobu podpinania parametrów do zapytania UPDATE (SQL). Wartości pól po "SET" były bowiem konkatenowane, natomiast część po słowie kluczowym "WHERE" bindowana przez znaki zapytania. Mniej więcej wyglądało to tak (pół-pseudokod):
 
<?php
$set = ' user_id ='.escape($user_id).' '; (...) if(isset($_POST['comment'])) { $set .= ', comment="'.escape($_POST['comment']).'"'; } query('UPDATE `tabela` SET '. $set . ' WHERE id=? ' , $id);
?>
Cały szkopuł polegał na tym, że w momencie, kiedy w którejkolwiek wartości podpiętej w zmiennej $set pojawił się znak zapytania (bo użytkownik np. chciał zadać pytanie), to do tego znaku zapytania została zbindowana zmienna $id i finalne zapytanie wyglądało np. tak :
UPDATE `tabela`
SET `user_id`=5, `comment`="Co slychac345"
WHERE id=? ;
Gdzie "345" to np. klucz główny tabeli z komentarzami do czegokolwiek. Jak wiadomo, taka składnia jest błędna i zapytanie się nie wykona. Celem naprawienia błędu wystarczy zmienić linijkę odpowiedzialną za wykonanie zapytania na taką:
<?php
query('UPDATE `tabela` SET '. $set . ' WHERE id= '.escape($id));
?>
Na pierwszy rzut oka błąd jest praktycznie niewidoczny i wykryłem go dopiero po użyciu debuggera. Taka lekcja uczy, by nie mieszać konkatenacji stringów do zapytania z bindowaniem poprzez znaki zapytania :-).

Artykuł udostępniany na licencji CC-BY-SA-3.0

Brak komentarzy:

Prześlij komentarz