| 1 | <?php |
|---|
| 2 | /********************************************************************\ |
|---|
| 3 | * This program is free software; you can redistribute it and/or * |
|---|
| 4 | * modify it under the terms of the GNU General Public License as * |
|---|
| 5 | * published by the Free Software Foundation; either version 2 of * |
|---|
| 6 | * the License, or (at your option) any later version. * |
|---|
| 7 | * * |
|---|
| 8 | * This program is distributed in the hope that it will be useful, * |
|---|
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|---|
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|---|
| 11 | * GNU General Public License for more details. * |
|---|
| 12 | * * |
|---|
| 13 | * You should have received a copy of the GNU General Public License* |
|---|
| 14 | * along with this program; if not, contact: * |
|---|
| 15 | * * |
|---|
| 16 | * Free Software Foundation Voice: +1-617-542-5942 * |
|---|
| 17 | * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * |
|---|
| 18 | * Boston, MA 02111-1307, USA gnu@gnu.org * |
|---|
| 19 | * * |
|---|
| 20 | \********************************************************************/ |
|---|
| 21 | /**@file AbstractBd.php |
|---|
| 22 | * @author Copyright (C) 2004 Technologies Coeus inc. |
|---|
| 23 | */ |
|---|
| 24 | error_reporting(E_ALL); |
|---|
| 25 | /** Classe statique, permet d'abstraire la connexion à la base de donnée |
|---|
| 26 | */ |
|---|
| 27 | class AbstractDb |
|---|
| 28 | { |
|---|
| 29 | function connexionDb($db_name) |
|---|
| 30 | { |
|---|
| 31 | if ($db_name == NULL) |
|---|
| 32 | { |
|---|
| 33 | $db_name = CONF_DATABASE_NAME; |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | $conn_string = "host=".CONF_DATABASE_HOST." dbname=$db_name user=".CONF_DATABASE_USER." password=".CONF_DATABASE_PASSWORD.""; |
|---|
| 37 | $ptr_connexion = pg_connect($conn_string); |
|---|
| 38 | |
|---|
| 39 | if ($ptr_connexion == FALSE) |
|---|
| 40 | { |
|---|
| 41 | echo sprintf(_("Unable to connect to database on %s"),CONF_DATABASE_HOST); |
|---|
| 42 | throw new Exception(sprintf(_("Unable to connect to database on %s"),CONF_DATABASE_HOST)); |
|---|
| 43 | } |
|---|
| 44 | |
|---|
| 45 | return $ptr_connexion; |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | /**Exécute la requête, et retourne le résultat. Affiche l'erreur s'il y a lieu. |
|---|
| 49 | @param $sql requête SELECT à exécuter |
|---|
| 50 | @param $returnResults un array à deux dimensions des rangées de résultats, NULL si aucun résultats. |
|---|
| 51 | @param $debug Si TRUE, affiche les résultats bruts de la requête |
|---|
| 52 | @return TRUE si la requete a été effectuée avec succés, FALSE autrement. |
|---|
| 53 | */ |
|---|
| 54 | function ExecSql($sql, & $returnResults, $debug=false) |
|---|
| 55 | { |
|---|
| 56 | $connection = $this -> connexionDb(NULL); |
|---|
| 57 | if ($debug == TRUE) |
|---|
| 58 | { |
|---|
| 59 | echo "<hr /><p>ExecSql() : SQL Query<br>\n<pre>$sql</pre></p>\n<p>Query plan:<br />\n"; |
|---|
| 60 | $result = pg_query($connection, "EXPLAIN ".$sql); |
|---|
| 61 | |
|---|
| 62 | $plan_array = pg_fetch_all($result); |
|---|
| 63 | foreach ($plan_array as $plan_line) |
|---|
| 64 | { |
|---|
| 65 | echo $plan_line['QUERY PLAN']."<br />\n"; |
|---|
| 66 | } |
|---|
| 67 | echo "</p>\n"; |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | $sql_starttime = microtime(); |
|---|
| 71 | $result = pg_query($connection, $sql); |
|---|
| 72 | $sql_endtime = microtime(); |
|---|
| 73 | |
|---|
| 74 | global $sql_total_time; |
|---|
| 75 | global $sql_num_select_querys; |
|---|
| 76 | $sql_num_select_querys ++; |
|---|
| 77 | $parts_of_starttime = explode(' ', $sql_starttime); |
|---|
| 78 | $sql_starttime = $parts_of_starttime[0] + $parts_of_starttime[1]; |
|---|
| 79 | //echo "sql_starttime: $sql_starttime <br />\n"; |
|---|
| 80 | |
|---|
| 81 | $parts_of_endtime = explode(' ', $sql_endtime); |
|---|
| 82 | $sql_endtime = $parts_of_endtime[0] + $parts_of_endtime[1]; |
|---|
| 83 | //echo "sql_endtime: $sql_endtime <br />\n"; |
|---|
| 84 | $sql_timetaken = $sql_endtime - $sql_starttime; |
|---|
| 85 | //echo "sql_timetaken: $sql_timetaken <br />\n"; |
|---|
| 86 | |
|---|
| 87 | $sql_total_time = $sql_total_time + $sql_timetaken; |
|---|
| 88 | |
|---|
| 89 | if ($debug == TRUE) |
|---|
| 90 | { |
|---|
| 91 | echo "<P>Elapsed time for query execution : $sql_timetaken second(s)</P>\n"; |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | if ($result == FALSE) |
|---|
| 95 | { |
|---|
| 96 | echo "<p>ExecSql() : An error occured while executing the following SQL query :<br>$sql</p>"; |
|---|
| 97 | echo "<p>Error message :<br>".pg_last_error($connection)."</p>"; |
|---|
| 98 | $returnResults = NULL; |
|---|
| 99 | $return_value = FALSE; |
|---|
| 100 | } |
|---|
| 101 | else |
|---|
| 102 | if (pg_num_rows($result) == 0) |
|---|
| 103 | { |
|---|
| 104 | $returnResults = NULL; |
|---|
| 105 | $return_value = TRUE; |
|---|
| 106 | } |
|---|
| 107 | else |
|---|
| 108 | { |
|---|
| 109 | $returnResults = pg_fetch_all($result); |
|---|
| 110 | $return_value = TRUE; |
|---|
| 111 | if ($debug) |
|---|
| 112 | { |
|---|
| 113 | $num_rows = pg_num_rows($result); |
|---|
| 114 | echo "<p>ExecSql() : The query returned $num_rows results :<br><TABLE>"; |
|---|
| 115 | if ($returnResults != NULL) |
|---|
| 116 | { |
|---|
| 117 | //On affiche l'en-téte des colonnes une seule fois*/ |
|---|
| 118 | echo "<TR>"; |
|---|
| 119 | while (list ($col_name, $col_content) = each($returnResults[0])) |
|---|
| 120 | { |
|---|
| 121 | echo "<TH>$col_name</TH>"; |
|---|
| 122 | } |
|---|
| 123 | echo "</TR>\n"; |
|---|
| 124 | } |
|---|
| 125 | while ($returnResults != NULL && list ($key, $value) = each($returnResults)) |
|---|
| 126 | { |
|---|
| 127 | echo "<TR>"; |
|---|
| 128 | while ($value != NULL && list ($col_name, $col_content) = each($value)) |
|---|
| 129 | { |
|---|
| 130 | echo "<TD>$col_content</TD>"; |
|---|
| 131 | } |
|---|
| 132 | echo "</TR>\n"; |
|---|
| 133 | } |
|---|
| 134 | reset($returnResults); |
|---|
| 135 | echo "</TABLE></p><hr />\n"; |
|---|
| 136 | } |
|---|
| 137 | } |
|---|
| 138 | return $return_value; |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | /**Retourne une chaine de caractère dans un format compatible pour stockage dans la bd |
|---|
| 142 | @param $chaine La chaéne de caractère à nettoyer |
|---|
| 143 | @return La chaéne nettoyée |
|---|
| 144 | */ |
|---|
| 145 | function EscapeString($chaine) |
|---|
| 146 | { |
|---|
| 147 | if (true) //if (!get_magic_quotes_gpc()) |
|---|
| 148 | { |
|---|
| 149 | return pg_escape_string($chaine); |
|---|
| 150 | } |
|---|
| 151 | else |
|---|
| 152 | { |
|---|
| 153 | return ($chaine); |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | /** Nettoye une chaine de caractère dans un format compatible bytea. |
|---|
| 158 | @param $chaine La chaéne de caractère à nettoyer |
|---|
| 159 | @return La chaéne nettoyée (escaped string) |
|---|
| 160 | */ |
|---|
| 161 | |
|---|
| 162 | function EscapeBinaryString($chaine) |
|---|
| 163 | { |
|---|
| 164 | return pg_escape_bytea($chaine); |
|---|
| 165 | |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | /** Reconverti une chaine de caractère en format bytea pur. |
|---|
| 169 | @param $chaine La chaéne de caractère |
|---|
| 170 | @return La chaéne reconvertie en format original (unescaped string) |
|---|
| 171 | */ |
|---|
| 172 | |
|---|
| 173 | function UnescapeBinaryString($chaine) |
|---|
| 174 | { |
|---|
| 175 | return pg_unescape_bytea($chaine); |
|---|
| 176 | |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | /**Exécute une requête pour laquelle on prévoit un résultat UNIQUE. Si le résultat n'est pas unique, un avertissement est affiché |
|---|
| 180 | @param $sql requête SELECT à exécuter |
|---|
| 181 | @param $retVal un array des colonnes de la rangée retournée, NULL si aucun résultats. |
|---|
| 182 | @param $debug Si TRUE, affiche les résultats bruts de la requête |
|---|
| 183 | @return TRUE si la requete a été effectuée avec succés, FALSE autrement. |
|---|
| 184 | */ |
|---|
| 185 | function ExecSqlUniqueRes($sql, & $retVal, $debug=false) |
|---|
| 186 | { |
|---|
| 187 | $retval = TRUE; |
|---|
| 188 | if ($debug == TRUE) |
|---|
| 189 | { |
|---|
| 190 | echo "<hr /><p>SQL Query : <br><pre>$sql</pre></p>"; |
|---|
| 191 | } |
|---|
| 192 | $connection = $this -> connexionDb(NULL); |
|---|
| 193 | |
|---|
| 194 | $sql_starttime = microtime(); |
|---|
| 195 | $result = @pg_query($connection, $sql); |
|---|
| 196 | $sql_endtime = microtime(); |
|---|
| 197 | |
|---|
| 198 | global $sql_total_time; |
|---|
| 199 | global $sql_num_select_unique_querys; |
|---|
| 200 | $sql_num_select_unique_querys ++; |
|---|
| 201 | |
|---|
| 202 | $parts_of_starttime = explode(' ', $sql_starttime); |
|---|
| 203 | $sql_starttime = $parts_of_starttime[0] + $parts_of_starttime[1]; |
|---|
| 204 | //echo "sql_starttime: $sql_starttime <br />\n"; |
|---|
| 205 | |
|---|
| 206 | $parts_of_endtime = explode(' ', $sql_endtime); |
|---|
| 207 | $sql_endtime = $parts_of_endtime[0] + $parts_of_endtime[1]; |
|---|
| 208 | //echo "sql_endtime: $sql_endtime <br />\n"; |
|---|
| 209 | $sql_timetaken = $sql_endtime - $sql_starttime; |
|---|
| 210 | //echo "sql_timetaken: $sql_timetaken <br />\n"; |
|---|
| 211 | |
|---|
| 212 | $sql_total_time = $sql_total_time + $sql_timetaken; |
|---|
| 213 | |
|---|
| 214 | if ($debug == TRUE) |
|---|
| 215 | { |
|---|
| 216 | echo "<P>Elapsed time for query execution : $sql_timetaken second(s)</P>\n"; |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | if ($result == FALSE) |
|---|
| 220 | { |
|---|
| 221 | echo "<p>ExecSqlUniqueRes() : An error occured while executing the following SQL query :<br>$sql</p>"; |
|---|
| 222 | echo "<p>Error message : <br>".pg_last_error($connection)."</p>"; |
|---|
| 223 | $retval = FALSE; |
|---|
| 224 | } |
|---|
| 225 | else |
|---|
| 226 | { |
|---|
| 227 | $returnResults = pg_fetch_all($result); |
|---|
| 228 | $retVal = $returnResults[0]; |
|---|
| 229 | if (pg_num_rows($result) > 1) |
|---|
| 230 | { |
|---|
| 231 | echo "<p>ExecSqlUniqueRes() : An error occured while executing the following SQL query :<br>$sql</p>"; |
|---|
| 232 | echo "<p>The query returned ".pg_num_rows($result)." results, although there should have been only one.</p>"; |
|---|
| 233 | $retval = FALSE; |
|---|
| 234 | $debug = true; |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | |
|---|
| 238 | if ($debug) |
|---|
| 239 | { |
|---|
| 240 | $num_rows = pg_num_rows($result); |
|---|
| 241 | echo "<p>ExecSqlUniqueRes(): The query returned $num_rows result(s) :<br><TABLE>"; |
|---|
| 242 | if ($returnResults != NULL) |
|---|
| 243 | { |
|---|
| 244 | //On affiche l'en-téte des colonnes une seule fois*/ |
|---|
| 245 | echo "<TR>"; |
|---|
| 246 | while (list ($col_name, $col_content) = each($returnResults[0])) |
|---|
| 247 | { |
|---|
| 248 | echo "<TH>$col_name</TH>"; |
|---|
| 249 | } |
|---|
| 250 | echo "</TR>\n"; |
|---|
| 251 | |
|---|
| 252 | while ($returnResults != NULL && list ($key, $value) = each($returnResults)) |
|---|
| 253 | { |
|---|
| 254 | echo "<TR>"; |
|---|
| 255 | while ($value != NULL && list ($col_name, $col_content) = each($value)) |
|---|
| 256 | { |
|---|
| 257 | echo "<TD>$col_content</TD>"; |
|---|
| 258 | } |
|---|
| 259 | echo "</TR>\n"; |
|---|
| 260 | } |
|---|
| 261 | reset($returnResults); |
|---|
| 262 | } |
|---|
| 263 | echo "</TABLE></p><hr />\n"; |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | } |
|---|
| 267 | return $retval; |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | /**Exécute une requête visant à modifier la base de donnée, et donc ne retournant aucun résultat. |
|---|
| 271 | @param $sql requête SELECT à exécuter |
|---|
| 272 | @param $debug Si TRUE, affiche la requête brute |
|---|
| 273 | @return false on failure, true otherwise |
|---|
| 274 | */ |
|---|
| 275 | function ExecSqlUpdate($sql, $debug=false) |
|---|
| 276 | { |
|---|
| 277 | $connection = $this -> connexionDb(NULL); |
|---|
| 278 | if ($debug == TRUE) |
|---|
| 279 | { |
|---|
| 280 | echo "<hr /><p>ExecSqlUpdate(): SQL Query :<br>\n<pre>$sql</pre></p>\n"; |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | global $sql_num_update_querys; |
|---|
| 284 | $sql_num_update_querys ++; |
|---|
| 285 | |
|---|
| 286 | $sql_starttime = microtime(); |
|---|
| 287 | $result = pg_query($connection, $sql); |
|---|
| 288 | $sql_endtime = microtime(); |
|---|
| 289 | |
|---|
| 290 | global $sql_total_time; |
|---|
| 291 | $parts_of_starttime = explode(' ', $sql_starttime); |
|---|
| 292 | $sql_starttime = $parts_of_starttime[0] + $parts_of_starttime[1]; |
|---|
| 293 | //echo "sql_starttime: $sql_starttime <br />\n"; |
|---|
| 294 | |
|---|
| 295 | $parts_of_endtime = explode(' ', $sql_endtime); |
|---|
| 296 | $sql_endtime = $parts_of_endtime[0] + $parts_of_endtime[1]; |
|---|
| 297 | //echo "sql_endtime: $sql_endtime <br />\n"; |
|---|
| 298 | $sql_timetaken = $sql_endtime - $sql_starttime; |
|---|
| 299 | //echo "sql_timetaken: $sql_timetaken <br />\n"; |
|---|
| 300 | |
|---|
| 301 | $sql_total_time = $sql_total_time + $sql_timetaken; |
|---|
| 302 | |
|---|
| 303 | if ($debug == TRUE) |
|---|
| 304 | { |
|---|
| 305 | echo "<P>".pg_affected_rows($result)." rangées affectées par la requête SQL<br>\n"; |
|---|
| 306 | echo "Temps écoulé: $sql_timetaken seconde(s)</P>\n"; |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | if ($result == FALSE) |
|---|
| 310 | { |
|---|
| 311 | echo "<p>ExecuterSqlResUnique(): ERREUR: Lors de l'exécution de la requête SQL:<br><pre>$sql</pre></p>"; |
|---|
| 312 | echo "<p>L'erreur est:<br>".pg_last_error()."<br>".pg_result_error($result)."</p>"; |
|---|
| 313 | } |
|---|
| 314 | else |
|---|
| 315 | { |
|---|
| 316 | if ($debug == TRUE) |
|---|
| 317 | { |
|---|
| 318 | echo "<p>ExecuterSqlUpdate(): DEBUG: ".pg_affected_rows($result)." rangée(s) affectée(s)</p><hr />\n"; |
|---|
| 319 | } |
|---|
| 320 | } |
|---|
| 321 | return $result; |
|---|
| 322 | } |
|---|
| 323 | |
|---|
| 324 | /** |
|---|
| 325 | * Read entire large object and send it to the browser |
|---|
| 326 | */ |
|---|
| 327 | function ReadAndFlushLargeObject($lo_oid) |
|---|
| 328 | { |
|---|
| 329 | $connection = $this->connexionDb(NULL); |
|---|
| 330 | // Large objects calls MUST be enclosed in transaction block |
|---|
| 331 | // remember, large objects must be obtained from within a transaction |
|---|
| 332 | pg_query ($connection, "begin"); |
|---|
| 333 | $handle_lo = pg_lo_open($connection, $lo_oid, "r") or die("<h1>Error.. can't get handle</h1>"); |
|---|
| 334 | |
|---|
| 335 | pg_lo_read_all($handle_lo) or die("<h1>Error, can't read large object.</h1>"); |
|---|
| 336 | |
|---|
| 337 | // committing the data transaction |
|---|
| 338 | pg_query ($connection, "commit"); |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| 341 | function ImportLargeObject($path) |
|---|
| 342 | { |
|---|
| 343 | $connection = $this->connexionDb(NULL); |
|---|
| 344 | // Large objects calls MUST be enclosed in transaction block |
|---|
| 345 | // remember, large objects must be obtained from within a transaction |
|---|
| 346 | pg_query ($connection, "begin"); |
|---|
| 347 | |
|---|
| 348 | $new_oid = pg_lo_import($connection, $path); |
|---|
| 349 | |
|---|
| 350 | // committing the data transaction |
|---|
| 351 | pg_query ($connection, "commit"); |
|---|
| 352 | |
|---|
| 353 | return $new_oid; |
|---|
| 354 | } |
|---|
| 355 | |
|---|
| 356 | function UnlinkLargeObject($oid) |
|---|
| 357 | { |
|---|
| 358 | return $this->ExecSqlUpdate("BEGIN; SELECT lo_unlink($oid); COMMIT;", false); |
|---|
| 359 | } |
|---|
| 360 | |
|---|
| 361 | |
|---|
| 362 | /** Builds a string suitable for the databases interval datatype and returns it. |
|---|
| 363 | @param $duration The source Duration object |
|---|
| 364 | @return a string suitable for storage in the database's interval datatype |
|---|
| 365 | */ |
|---|
| 366 | function GetIntervalStrFromDuration($duration) |
|---|
| 367 | { |
|---|
| 368 | $str = ''; |
|---|
| 369 | if ($duration -> GetYears() != 0) |
|---|
| 370 | $str.= $duration -> GetYears().' years '; |
|---|
| 371 | if ($duration -> GetMonths() != 0) |
|---|
| 372 | $str.= $duration -> GetMonths().' months '; |
|---|
| 373 | if ($duration -> GetDays() != 0) |
|---|
| 374 | $str.= $duration -> GetDays().' days '; |
|---|
| 375 | |
|---|
| 376 | if ($duration -> GetHours() != 0 || $duration -> GetMinutes() != 0 || $duration -> GetSeconds() != 0) |
|---|
| 377 | { |
|---|
| 378 | $str.= $duration -> GetHours().':'.$duration -> GetMinutes().':'.$duration -> GetSeconds(); |
|---|
| 379 | } |
|---|
| 380 | return $str; |
|---|
| 381 | } |
|---|
| 382 | |
|---|
| 383 | /** Builds the internal duration Array from a databases interval datatype and returns it. |
|---|
| 384 | @param $intervalstr A string in the database's interval datatype format |
|---|
| 385 | @return the internal representration on the Duration object |
|---|
| 386 | */ |
|---|
| 387 | function GetDurationArrayFromIntervalStr($intervalstr) |
|---|
| 388 | { |
|---|
| 389 | if (empty($intervalstr)) |
|---|
| 390 | { |
|---|
| 391 | $retval['years'] = 0; |
|---|
| 392 | $retval['months'] = 0; |
|---|
| 393 | $retval['days'] = 0; |
|---|
| 394 | $retval['hours'] = 0; |
|---|
| 395 | $retval['minutes'] = 0; |
|---|
| 396 | $retval['seconds'] = 0; |
|---|
| 397 | } |
|---|
| 398 | else |
|---|
| 399 | { |
|---|
| 400 | $sql = "SELECT EXTRACT (year FROM INTERVAL '$intervalstr') AS years, EXTRACT (month FROM INTERVAL '$intervalstr') AS months, EXTRACT (day FROM INTERVAL '$intervalstr') AS days, EXTRACT (hour FROM INTERVAL '$intervalstr') AS hours, EXTRACT (minutes FROM INTERVAL '$intervalstr') AS minutes, EXTRACT (seconds FROM INTERVAL '$intervalstr') AS seconds"; |
|---|
| 401 | $this -> ExecSqlUniqueRes($sql, $retval, false); |
|---|
| 402 | } |
|---|
| 403 | return $retval; |
|---|
| 404 | } |
|---|
| 405 | |
|---|
| 406 | } /* end class AbstractDb */ |
|---|
| 407 | ?> |
|---|