[ Index ] |
|
Code source de SPIP Agora 1.4 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2004 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: Tomas V.V.Cox <cox@idecnet.com> | 17 // | Maintainer: Daniel Convissor <danielc@php.net> | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: ifx.php,v 1.47 2004/03/05 01:46:53 danielc Exp $ 21 22 23 // Legend: 24 // For more info on Informix errors see: 25 // http://www.informix.com/answers/english/ierrors.htm 26 // 27 // TODO: 28 // - set needed env Informix vars on connect 29 // - implement native prepare/execute 30 31 32 require_once 'DB/common.php'; 33 34 /** 35 * Database independent query interface definition for PHP's Informix 36 * extension. 37 * 38 * @package DB 39 * @version $Id: ifx.php,v 1.47 2004/03/05 01:46:53 danielc Exp $ 40 * @category Database 41 * @author Tomas V.V.Cox <cox@idecnet.com> 42 */ 43 class DB_ifx extends DB_common 44 { 45 // {{{ properties 46 47 var $connection; 48 var $affected = 0; 49 var $dsn = array(); 50 var $transaction_opcount = 0; 51 var $autocommit = true; 52 var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */ 53 54 // }}} 55 // {{{ constructor 56 57 function DB_ifx() 58 { 59 $this->phptype = 'ifx'; 60 $this->dbsyntax = 'ifx'; 61 $this->features = array( 62 'prepare' => false, 63 'pconnect' => true, 64 'transactions' => true, 65 'limit' => 'emulate' 66 ); 67 $this->errorcode_map = array( 68 '-201' => DB_ERROR_SYNTAX, 69 '-206' => DB_ERROR_NOSUCHTABLE, 70 '-217' => DB_ERROR_NOSUCHFIELD, 71 '-239' => DB_ERROR_CONSTRAINT, 72 '-253' => DB_ERROR_SYNTAX, 73 '-292' => DB_ERROR_CONSTRAINT_NOT_NULL, 74 '-310' => DB_ERROR_ALREADY_EXISTS, 75 '-329' => DB_ERROR_NODBSELECTED, 76 '-346' => DB_ERROR_CONSTRAINT, 77 '-386' => DB_ERROR_CONSTRAINT_NOT_NULL, 78 '-391' => DB_ERROR_CONSTRAINT_NOT_NULL, 79 '-554' => DB_ERROR_SYNTAX, 80 '-691' => DB_ERROR_CONSTRAINT, 81 '-703' => DB_ERROR_CONSTRAINT_NOT_NULL, 82 '-1204' => DB_ERROR_INVALID_DATE, 83 '-1205' => DB_ERROR_INVALID_DATE, 84 '-1206' => DB_ERROR_INVALID_DATE, 85 '-1209' => DB_ERROR_INVALID_DATE, 86 '-1210' => DB_ERROR_INVALID_DATE, 87 '-1212' => DB_ERROR_INVALID_DATE, 88 '-1213' => DB_ERROR_INVALID_NUMBER, 89 ); 90 } 91 92 // }}} 93 // {{{ connect() 94 95 /** 96 * Connect to a database and log in as the specified user. 97 * 98 * @param $dsn the data source name (see DB::parseDSN for syntax) 99 * @param $persistent (optional) whether the connection should 100 * be persistent 101 * 102 * @return int DB_OK on success, a DB error code on failure 103 */ 104 function connect($dsninfo, $persistent = false) 105 { 106 if (!DB::assertExtension('informix') && 107 !DB::assertExtension('Informix')) 108 { 109 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 110 } 111 $this->dsn = $dsninfo; 112 $dbhost = $dsninfo['hostspec'] ? '@' . $dsninfo['hostspec'] : ''; 113 $dbname = $dsninfo['database'] ? $dsninfo['database'] . $dbhost : ''; 114 $user = $dsninfo['username'] ? $dsninfo['username'] : ''; 115 $pw = $dsninfo['password'] ? $dsninfo['password'] : ''; 116 117 $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; 118 119 $this->connection = @$connect_function($dbname, $user, $pw); 120 if (!is_resource($this->connection)) { 121 return $this->ifxraiseError(DB_ERROR_CONNECT_FAILED); 122 } 123 return DB_OK; 124 } 125 126 // }}} 127 // {{{ disconnect() 128 129 /** 130 * Log out and disconnect from the database. 131 * 132 * @return bool true on success, false if not connected. 133 */ 134 function disconnect() 135 { 136 $ret = @ifx_close($this->connection); 137 $this->connection = null; 138 return $ret; 139 } 140 141 // }}} 142 // {{{ simpleQuery() 143 144 /** 145 * Send a query to Informix and return the results as a 146 * Informix resource identifier. 147 * 148 * @param $query the SQL query 149 * 150 * @return int returns a valid Informix result for successful SELECT 151 * queries, DB_OK for other successful queries. A DB error code 152 * is returned on failure. 153 */ 154 function simpleQuery($query) 155 { 156 $ismanip = DB::isManip($query); 157 $this->last_query = $query; 158 $this->affected = null; 159 if (preg_match('/(SELECT)/i', $query)) { //TESTME: Use !DB::isManip()? 160 // the scroll is needed for fetching absolute row numbers 161 // in a select query result 162 $result = @ifx_query($query, $this->connection, IFX_SCROLL); 163 } else { 164 if (!$this->autocommit && $ismanip) { 165 if ($this->transaction_opcount == 0) { 166 $result = @ifx_query('BEGIN WORK', $this->connection); 167 if (!$result) { 168 return $this->ifxraiseError(); 169 } 170 } 171 $this->transaction_opcount++; 172 } 173 $result = @ifx_query($query, $this->connection); 174 } 175 if (!$result) { 176 return $this->ifxraiseError(); 177 } 178 $this->affected = @ifx_affected_rows($result); 179 // Determine which queries should return data, and which 180 // should return an error code only. 181 if (preg_match('/(SELECT)/i', $query)) { 182 return $result; 183 } 184 // XXX Testme: free results inside a transaction 185 // may cause to stop it and commit the work? 186 187 // Result has to be freed even with a insert or update 188 @ifx_free_result($result); 189 190 return DB_OK; 191 } 192 193 // }}} 194 // {{{ nextResult() 195 196 /** 197 * Move the internal ifx result pointer to the next available result 198 * 199 * @param a valid fbsql result resource 200 * 201 * @access public 202 * 203 * @return true if a result is available otherwise return false 204 */ 205 function nextResult($result) 206 { 207 return false; 208 } 209 210 // }}} 211 // {{{ affectedRows() 212 213 /** 214 * Gets the number of rows affected by the last query. 215 * if the last query was a select, returns 0. 216 * 217 * @return number of rows affected by the last query 218 */ 219 function affectedRows() 220 { 221 if (DB::isManip($this->last_query)) { 222 return $this->affected; 223 } else { 224 return 0; 225 } 226 227 } 228 229 // }}} 230 // {{{ fetchInto() 231 232 /** 233 * Fetch a row and insert the data into an existing array. 234 * 235 * Formating of the array and the data therein are configurable. 236 * See DB_result::fetchInto() for more information. 237 * 238 * @param resource $result query result identifier 239 * @param array $arr (reference) array where data from the row 240 * should be placed 241 * @param int $fetchmode how the resulting array should be indexed 242 * @param int $rownum the row number to fetch 243 * 244 * @return mixed DB_OK on success, null when end of result set is 245 * reached or on failure 246 * 247 * @see DB_result::fetchInto() 248 * @access private 249 */ 250 function fetchInto($result, &$arr, $fetchmode, $rownum=null) 251 { 252 if (($rownum !== null) && ($rownum < 0)) { 253 return null; 254 } 255 if ($rownum === null) { 256 /* 257 * Even though fetch_row() should return the next row if 258 * $rownum is null, it doesn't in all cases. Bug 598. 259 */ 260 $rownum = 'NEXT'; 261 } else { 262 // Index starts at row 1, unlike most DBMS's starting at 0. 263 $rownum++; 264 } 265 if (!$arr = @ifx_fetch_row($result, $rownum)) { 266 return null; 267 } 268 if ($fetchmode !== DB_FETCHMODE_ASSOC) { 269 $i=0; 270 $order = array(); 271 foreach ($arr as $val) { 272 $order[$i++] = $val; 273 } 274 $arr = $order; 275 } elseif ($fetchmode == DB_FETCHMODE_ASSOC && 276 $this->options['portability'] & DB_PORTABILITY_LOWERCASE) 277 { 278 $arr = array_change_key_case($arr, CASE_LOWER); 279 } 280 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 281 $this->_rtrimArrayValues($arr); 282 } 283 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 284 $this->_convertNullArrayValuesToEmpty($arr); 285 } 286 return DB_OK; 287 } 288 289 // }}} 290 // {{{ numRows() 291 292 function numRows($result) 293 { 294 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 295 } 296 297 // }}} 298 // {{{ numCols() 299 300 /** 301 * Get the number of columns in a result set. 302 * 303 * @param $result Informix result identifier 304 * 305 * @return int the number of columns per row in $result 306 */ 307 function numCols($result) 308 { 309 if (!$cols = @ifx_num_fields($result)) { 310 return $this->ifxraiseError(); 311 } 312 return $cols; 313 } 314 315 // }}} 316 // {{{ freeResult() 317 318 /** 319 * Free the internal resources associated with $result. 320 * 321 * @param $result Informix result identifier 322 * 323 * @return bool true on success, false if $result is invalid 324 */ 325 function freeResult($result) 326 { 327 return @ifx_free_result($result); 328 } 329 330 // }}} 331 // {{{ autoCommit() 332 333 /** 334 * Enable/disable automatic commits 335 */ 336 function autoCommit($onoff = true) 337 { 338 // XXX if $this->transaction_opcount > 0, we should probably 339 // issue a warning here. 340 $this->autocommit = $onoff ? true : false; 341 return DB_OK; 342 } 343 344 // }}} 345 // {{{ commit() 346 347 /** 348 * Commit the current transaction. 349 */ 350 function commit() 351 { 352 if ($this->transaction_opcount > 0) { 353 $result = @ifx_query('COMMIT WORK', $this->connection); 354 $this->transaction_opcount = 0; 355 if (!$result) { 356 return $this->ifxRaiseError(); 357 } 358 } 359 return DB_OK; 360 } 361 362 // }}} 363 // {{{ rollback() 364 365 /** 366 * Roll back (undo) the current transaction. 367 */ 368 function rollback() 369 { 370 if ($this->transaction_opcount > 0) { 371 $result = @ifx_query('ROLLBACK WORK', $this->connection); 372 $this->transaction_opcount = 0; 373 if (!$result) { 374 return $this->ifxRaiseError(); 375 } 376 } 377 return DB_OK; 378 } 379 380 // }}} 381 // {{{ ifxraiseError() 382 383 /** 384 * Gather information about an error, then use that info to create a 385 * DB error object and finally return that object. 386 * 387 * @param integer $errno PEAR error number (usually a DB constant) if 388 * manually raising an error 389 * @return object DB error object 390 * @see errorNative() 391 * @see errorCode() 392 * @see DB_common::raiseError() 393 */ 394 function ifxraiseError($errno = null) 395 { 396 if ($errno === null) { 397 $errno = $this->errorCode(ifx_error()); 398 } 399 400 return $this->raiseError($errno, null, null, null, 401 $this->errorNative()); 402 } 403 404 // }}} 405 // {{{ errorCode() 406 407 /** 408 * Map native error codes to DB's portable ones. 409 * 410 * Requires that the DB implementation's constructor fills 411 * in the <var>$errorcode_map</var> property. 412 * 413 * @param string $nativecode error code returned by the database 414 * @return int a portable DB error code, or DB_ERROR if this DB 415 * implementation has no mapping for the given error code. 416 */ 417 function errorCode($nativecode) 418 { 419 if (ereg('SQLCODE=(.*)]', $nativecode, $match)) { 420 $code = $match[1]; 421 if (isset($this->errorcode_map[$code])) { 422 return $this->errorcode_map[$code]; 423 } 424 } 425 return DB_ERROR; 426 } 427 428 // }}} 429 // {{{ errorNative() 430 431 /** 432 * Get the native error message of the last error (if any) that 433 * occured on the current connection. 434 * 435 * @return int native Informix error code 436 */ 437 function errorNative() 438 { 439 return @ifx_error() . ' ' . @ifx_errormsg(); 440 } 441 442 // }}} 443 // {{{ getSpecialQuery() 444 445 /** 446 * Returns the query needed to get some backend info 447 * @param string $type What kind of info you want to retrieve 448 * @return string The SQL query string 449 */ 450 function getSpecialQuery($type) 451 { 452 switch ($type) { 453 case 'tables': 454 return 'select tabname from systables where tabid >= 100'; 455 default: 456 return null; 457 } 458 } 459 460 // }}} 461 // {{{ tableInfo() 462 463 /** 464 * Returns information about a table or a result set. 465 * 466 * NOTE: only supports 'table' if <var>$result</var> is a table name. 467 * 468 * If analyzing a query result and the result has duplicate field names, 469 * an error will be raised saying 470 * <samp>can't distinguish duplicate field names</samp>. 471 * 472 * @param object|string $result DB_result object from a query or a 473 * string containing the name of a table 474 * @param int $mode a valid tableInfo mode 475 * @return array an associative array with the information requested 476 * or an error object if something is wrong 477 * @access public 478 * @internal 479 * @since 1.6.0 480 * @see DB_common::tableInfo() 481 */ 482 function tableInfo($result, $mode = null) 483 { 484 if (isset($result->result)) { 485 /* 486 * Probably received a result object. 487 * Extract the result resource identifier. 488 */ 489 $id = $result->result; 490 $got_string = false; 491 } elseif (is_string($result)) { 492 /* 493 * Probably received a table name. 494 * Create a result resource identifier. 495 */ 496 $id = @ifx_query("SELECT * FROM $result WHERE 1=0", 497 $this->connection); 498 $got_string = true; 499 } else { 500 /* 501 * Probably received a result resource identifier. 502 * Copy it. 503 */ 504 $id = $result; 505 $got_string = false; 506 } 507 508 if (!is_resource($id)) { 509 return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); 510 } 511 512 $flds = @ifx_fieldproperties($id); 513 $count = @ifx_num_fields($id); 514 515 if (count($flds) != $count) { 516 return $this->raiseError("can't distinguish duplicate field names"); 517 } 518 519 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 520 $case_func = 'strtolower'; 521 } else { 522 $case_func = 'strval'; 523 } 524 525 $i = 0; 526 // made this IF due to performance (one if is faster than $count if's) 527 if (!$mode) { 528 foreach ($flds as $key => $value) { 529 $props = explode(';', $value); 530 531 $res[$i]['table'] = $got_string ? $case_func($result) : ''; 532 $res[$i]['name'] = $case_func($key); 533 $res[$i]['type'] = $props[0]; 534 $res[$i]['len'] = $props[1]; 535 $res[$i]['flags'] = $props[4] == 'N' ? 'not_null' : ''; 536 $i++; 537 } 538 539 } else { // full 540 $res['num_fields'] = $count; 541 542 foreach ($flds as $key => $value) { 543 $props = explode(';', $value); 544 545 $res[$i]['table'] = $got_string ? $case_func($result) : ''; 546 $res[$i]['name'] = $case_func($key); 547 $res[$i]['type'] = $props[0]; 548 $res[$i]['len'] = $props[1]; 549 $res[$i]['flags'] = $props[4] == 'N' ? 'not_null' : ''; 550 551 if ($mode & DB_TABLEINFO_ORDER) { 552 $res['order'][$res[$i]['name']] = $i; 553 } 554 if ($mode & DB_TABLEINFO_ORDERTABLE) { 555 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 556 } 557 $i++; 558 } 559 } 560 561 // free the result only if we were called on a table 562 if ($got_string) { 563 @ifx_free_result($id); 564 } 565 return $res; 566 } 567 568 // }}} 569 570 } 571 572 /* 573 * Local variables: 574 * tab-width: 4 575 * c-basic-offset: 4 576 * End: 577 */ 578 579 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 14:40:03 2007 | par Balluche grâce à PHPXref 0.7 |