venerdì 21 gennaio 2011

Record Counting ^ 2

Mi sono trovato a dover mettere la mani sui sorgenti di una applicazione PHP che accede ad un database PostgreSQL mediante ADODB, scovando un errore a prima vista di difficile individuazione anche se molto banale. Questo errore oltretutto non e' strettamente correlato ne' a PostgreSQL ne' a PHP, ma e' un semplice esempio di "cattiva programmazione" (o meglio di programmazione "distratta").
Il codice in questione doveva inserire un record in una tabella, senza sapere a priori se il record fosse da modificare o da inserire from-scratch; per discriminare le possibilita' il codice effettuava prima una ricerca fra i dati della tabella per vedere quante righe associate ai dati in esame esistevano. Da notare che la selezione implicitamente faceva un conteggio del numero di righe esistenti. Il risultato veniva poi passato ad un metodo di ADODB per il conteggio delle tuple ritornate, quindi qualcosa del tipo:

$query = "SELECT count(id) FROM myTable";
$resultSet = $driver->execute( $query );
$rowCount = $resultset->RecordCount();


Notato l'errore? Ebbene inizialmente io non me ne sono accorto, ma il problema del pezzo di codice qui sopra e' che la query che viene richiesta al database e' una "count", e su questa si fa il record count nuovamente. Ora il count di count non ritorna un count al quadrato (eh eh) ma sempre 1: la "SELECT count(id)" ritorna una sola tupla monodimensionale con il numero di record, e quindi il record count di una sola tupla ritorna sempre 1, anche se il valore della tupla (e quindi il conteggio effettivo del count) e' 0! Il codice va quindi corretto con qualcosa del tipo:

$query = "SELECT id FROM myTable";
$resultSet = $driver->execute( $query );
$rowCount = $resultset->RecordCount();


oppure con qualcosa del tipo:

$query = "SELECT count(id) AS conteggio FROM myTable";
$resultSet = $driver->execute( $query );
$tuple = $resultset->GetArray();
$rowCount = $tuple[0][0];



L'errore e' subdolo poiche' anche leggendo il codice e' chiaro quali siano le intenzioni del programmatore: contare i record presenti. Tuttavia e' il "doppio conteggio" a mascherare l'errore di esecuzione!

Nessun commento: