[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5 /** 6 * The PEAR DB driver for PHP's ifx extension 7 * for interacting with Informix databases 8 * 9 * PHP versions 4 and 5 10 * 11 * LICENSE: This source file is subject to version 3.0 of the PHP license 12 * that is available through the world-wide-web at the following URI: 13 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 14 * the PHP License and are unable to obtain it through the web, please 15 * send a note to license@php.net so we can mail you a copy immediately. 16 * 17 * @category Database 18 * @package DB 19 * @author Tomas V.V.Cox <cox@idecnet.com> 20 * @author Daniel Convissor <danielc@php.net> 21 * @copyright 1997-2005 The PHP Group 22 * @license http://www.php.net/license/3_0.txt PHP License 3.0 23 * @version CVS: $Id: ifx.php,v 1.74 2007/01/12 03:11:17 aharvey Exp $ 24 * @link http://pear.php.net/package/DB 25 */ 26 27 /** 28 * Obtain the DB_common class so it can be extended from 29 */ 30 require_once 'DB/common.php'; 31 32 /** 33 * The methods PEAR DB uses to interact with PHP's ifx extension 34 * for interacting with Informix databases 35 * 36 * These methods overload the ones declared in DB_common. 37 * 38 * More info on Informix errors can be found at: 39 * http://www.informix.com/answers/english/ierrors.htm 40 * 41 * TODO: 42 * - set needed env Informix vars on connect 43 * - implement native prepare/execute 44 * 45 * @category Database 46 * @package DB 47 * @author Tomas V.V.Cox <cox@idecnet.com> 48 * @author Daniel Convissor <danielc@php.net> 49 * @copyright 1997-2005 The PHP Group 50 * @license http://www.php.net/license/3_0.txt PHP License 3.0 51 * @version Release: 1.7.9 52 * @link http://pear.php.net/package/DB 53 */ 54 class DB_ifx extends DB_common 55 { 56 // {{{ properties 57 58 /** 59 * The DB driver type (mysql, oci8, odbc, etc.) 60 * @var string 61 */ 62 var $phptype = 'ifx'; 63 64 /** 65 * The database syntax variant to be used (db2, access, etc.), if any 66 * @var string 67 */ 68 var $dbsyntax = 'ifx'; 69 70 /** 71 * The capabilities of this DB implementation 72 * 73 * The 'new_link' element contains the PHP version that first provided 74 * new_link support for this DBMS. Contains false if it's unsupported. 75 * 76 * Meaning of the 'limit' element: 77 * + 'emulate' = emulate with fetch row by number 78 * + 'alter' = alter the query 79 * + false = skip rows 80 * 81 * @var array 82 */ 83 var $features = array( 84 'limit' => 'emulate', 85 'new_link' => false, 86 'numrows' => 'emulate', 87 'pconnect' => true, 88 'prepare' => false, 89 'ssl' => false, 90 'transactions' => true, 91 ); 92 93 /** 94 * A mapping of native error codes to DB error codes 95 * @var array 96 */ 97 var $errorcode_map = array( 98 '-201' => DB_ERROR_SYNTAX, 99 '-206' => DB_ERROR_NOSUCHTABLE, 100 '-217' => DB_ERROR_NOSUCHFIELD, 101 '-236' => DB_ERROR_VALUE_COUNT_ON_ROW, 102 '-239' => DB_ERROR_CONSTRAINT, 103 '-253' => DB_ERROR_SYNTAX, 104 '-268' => DB_ERROR_CONSTRAINT, 105 '-292' => DB_ERROR_CONSTRAINT_NOT_NULL, 106 '-310' => DB_ERROR_ALREADY_EXISTS, 107 '-316' => DB_ERROR_ALREADY_EXISTS, 108 '-319' => DB_ERROR_NOT_FOUND, 109 '-329' => DB_ERROR_NODBSELECTED, 110 '-346' => DB_ERROR_CONSTRAINT, 111 '-386' => DB_ERROR_CONSTRAINT_NOT_NULL, 112 '-391' => DB_ERROR_CONSTRAINT_NOT_NULL, 113 '-554' => DB_ERROR_SYNTAX, 114 '-691' => DB_ERROR_CONSTRAINT, 115 '-692' => DB_ERROR_CONSTRAINT, 116 '-703' => DB_ERROR_CONSTRAINT_NOT_NULL, 117 '-1202' => DB_ERROR_DIVZERO, 118 '-1204' => DB_ERROR_INVALID_DATE, 119 '-1205' => DB_ERROR_INVALID_DATE, 120 '-1206' => DB_ERROR_INVALID_DATE, 121 '-1209' => DB_ERROR_INVALID_DATE, 122 '-1210' => DB_ERROR_INVALID_DATE, 123 '-1212' => DB_ERROR_INVALID_DATE, 124 '-1213' => DB_ERROR_INVALID_NUMBER, 125 ); 126 127 /** 128 * The raw database connection created by PHP 129 * @var resource 130 */ 131 var $connection; 132 133 /** 134 * The DSN information for connecting to a database 135 * @var array 136 */ 137 var $dsn = array(); 138 139 140 /** 141 * Should data manipulation queries be committed automatically? 142 * @var bool 143 * @access private 144 */ 145 var $autocommit = true; 146 147 /** 148 * The quantity of transactions begun 149 * 150 * {@internal While this is private, it can't actually be designated 151 * private in PHP 5 because it is directly accessed in the test suite.}} 152 * 153 * @var integer 154 * @access private 155 */ 156 var $transaction_opcount = 0; 157 158 /** 159 * The number of rows affected by a data manipulation query 160 * @var integer 161 * @access private 162 */ 163 var $affected = 0; 164 165 166 // }}} 167 // {{{ constructor 168 169 /** 170 * This constructor calls <kbd>$this->DB_common()</kbd> 171 * 172 * @return void 173 */ 174 function DB_ifx() 175 { 176 $this->DB_common(); 177 } 178 179 // }}} 180 // {{{ connect() 181 182 /** 183 * Connect to the database server, log in and open the database 184 * 185 * Don't call this method directly. Use DB::connect() instead. 186 * 187 * @param array $dsn the data source name 188 * @param bool $persistent should the connection be persistent? 189 * 190 * @return int DB_OK on success. A DB_Error object on failure. 191 */ 192 function connect($dsn, $persistent = false) 193 { 194 if (!PEAR::loadExtension('informix') && 195 !PEAR::loadExtension('Informix')) 196 { 197 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 198 } 199 200 $this->dsn = $dsn; 201 if ($dsn['dbsyntax']) { 202 $this->dbsyntax = $dsn['dbsyntax']; 203 } 204 205 $dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : ''; 206 $dbname = $dsn['database'] ? $dsn['database'] . $dbhost : ''; 207 $user = $dsn['username'] ? $dsn['username'] : ''; 208 $pw = $dsn['password'] ? $dsn['password'] : ''; 209 210 $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; 211 212 $this->connection = @$connect_function($dbname, $user, $pw); 213 if (!is_resource($this->connection)) { 214 return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED); 215 } 216 return DB_OK; 217 } 218 219 // }}} 220 // {{{ disconnect() 221 222 /** 223 * Disconnects from the database server 224 * 225 * @return bool TRUE on success, FALSE on failure 226 */ 227 function disconnect() 228 { 229 $ret = @ifx_close($this->connection); 230 $this->connection = null; 231 return $ret; 232 } 233 234 // }}} 235 // {{{ simpleQuery() 236 237 /** 238 * Sends a query to the database server 239 * 240 * @param string the SQL query string 241 * 242 * @return mixed + a PHP result resrouce for successful SELECT queries 243 * + the DB_OK constant for other successful queries 244 * + a DB_Error object on failure 245 */ 246 function simpleQuery($query) 247 { 248 $ismanip = $this->_checkManip($query); 249 $this->last_query = $query; 250 $this->affected = null; 251 if (preg_match('/(SELECT|EXECUTE)/i', $query)) { //TESTME: Use !DB::isManip()? 252 // the scroll is needed for fetching absolute row numbers 253 // in a select query result 254 $result = @ifx_query($query, $this->connection, IFX_SCROLL); 255 } else { 256 if (!$this->autocommit && $ismanip) { 257 if ($this->transaction_opcount == 0) { 258 $result = @ifx_query('BEGIN WORK', $this->connection); 259 if (!$result) { 260 return $this->ifxRaiseError(); 261 } 262 } 263 $this->transaction_opcount++; 264 } 265 $result = @ifx_query($query, $this->connection); 266 } 267 if (!$result) { 268 return $this->ifxRaiseError(); 269 } 270 $this->affected = @ifx_affected_rows($result); 271 // Determine which queries should return data, and which 272 // should return an error code only. 273 if (preg_match('/(SELECT|EXECUTE)/i', $query)) { 274 return $result; 275 } 276 // XXX Testme: free results inside a transaction 277 // may cause to stop it and commit the work? 278 279 // Result has to be freed even with a insert or update 280 @ifx_free_result($result); 281 282 return DB_OK; 283 } 284 285 // }}} 286 // {{{ nextResult() 287 288 /** 289 * Move the internal ifx result pointer to the next available result 290 * 291 * @param a valid fbsql result resource 292 * 293 * @access public 294 * 295 * @return true if a result is available otherwise return false 296 */ 297 function nextResult($result) 298 { 299 return false; 300 } 301 302 // }}} 303 // {{{ affectedRows() 304 305 /** 306 * Determines the number of rows affected by a data maniuplation query 307 * 308 * 0 is returned for queries that don't manipulate data. 309 * 310 * @return int the number of rows. A DB_Error object on failure. 311 */ 312 function affectedRows() 313 { 314 if ($this->_last_query_manip) { 315 return $this->affected; 316 } else { 317 return 0; 318 } 319 } 320 321 // }}} 322 // {{{ fetchInto() 323 324 /** 325 * Places a row from the result set into the given array 326 * 327 * Formating of the array and the data therein are configurable. 328 * See DB_result::fetchInto() for more information. 329 * 330 * This method is not meant to be called directly. Use 331 * DB_result::fetchInto() instead. It can't be declared "protected" 332 * because DB_result is a separate object. 333 * 334 * @param resource $result the query result resource 335 * @param array $arr the referenced array to put the data in 336 * @param int $fetchmode how the resulting array should be indexed 337 * @param int $rownum the row number to fetch (0 = first row) 338 * 339 * @return mixed DB_OK on success, NULL when the end of a result set is 340 * reached or on failure 341 * 342 * @see DB_result::fetchInto() 343 */ 344 function fetchInto($result, &$arr, $fetchmode, $rownum = null) 345 { 346 if (($rownum !== null) && ($rownum < 0)) { 347 return null; 348 } 349 if ($rownum === null) { 350 /* 351 * Even though fetch_row() should return the next row if 352 * $rownum is null, it doesn't in all cases. Bug 598. 353 */ 354 $rownum = 'NEXT'; 355 } else { 356 // Index starts at row 1, unlike most DBMS's starting at 0. 357 $rownum++; 358 } 359 if (!$arr = @ifx_fetch_row($result, $rownum)) { 360 return null; 361 } 362 if ($fetchmode !== DB_FETCHMODE_ASSOC) { 363 $i=0; 364 $order = array(); 365 foreach ($arr as $val) { 366 $order[$i++] = $val; 367 } 368 $arr = $order; 369 } elseif ($fetchmode == DB_FETCHMODE_ASSOC && 370 $this->options['portability'] & DB_PORTABILITY_LOWERCASE) 371 { 372 $arr = array_change_key_case($arr, CASE_LOWER); 373 } 374 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 375 $this->_rtrimArrayValues($arr); 376 } 377 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 378 $this->_convertNullArrayValuesToEmpty($arr); 379 } 380 return DB_OK; 381 } 382 383 // }}} 384 // {{{ numCols() 385 386 /** 387 * Gets the number of columns in a result set 388 * 389 * This method is not meant to be called directly. Use 390 * DB_result::numCols() instead. It can't be declared "protected" 391 * because DB_result is a separate object. 392 * 393 * @param resource $result PHP's query result resource 394 * 395 * @return int the number of columns. A DB_Error object on failure. 396 * 397 * @see DB_result::numCols() 398 */ 399 function numCols($result) 400 { 401 if (!$cols = @ifx_num_fields($result)) { 402 return $this->ifxRaiseError(); 403 } 404 return $cols; 405 } 406 407 // }}} 408 // {{{ freeResult() 409 410 /** 411 * Deletes the result set and frees the memory occupied by the result set 412 * 413 * This method is not meant to be called directly. Use 414 * DB_result::free() instead. It can't be declared "protected" 415 * because DB_result is a separate object. 416 * 417 * @param resource $result PHP's query result resource 418 * 419 * @return bool TRUE on success, FALSE if $result is invalid 420 * 421 * @see DB_result::free() 422 */ 423 function freeResult($result) 424 { 425 return is_resource($result) ? ifx_free_result($result) : false; 426 } 427 428 // }}} 429 // {{{ autoCommit() 430 431 /** 432 * Enables or disables automatic commits 433 * 434 * @param bool $onoff true turns it on, false turns it off 435 * 436 * @return int DB_OK on success. A DB_Error object if the driver 437 * doesn't support auto-committing transactions. 438 */ 439 function autoCommit($onoff = true) 440 { 441 // XXX if $this->transaction_opcount > 0, we should probably 442 // issue a warning here. 443 $this->autocommit = $onoff ? true : false; 444 return DB_OK; 445 } 446 447 // }}} 448 // {{{ commit() 449 450 /** 451 * Commits the current transaction 452 * 453 * @return int DB_OK on success. A DB_Error object on failure. 454 */ 455 function commit() 456 { 457 if ($this->transaction_opcount > 0) { 458 $result = @ifx_query('COMMIT WORK', $this->connection); 459 $this->transaction_opcount = 0; 460 if (!$result) { 461 return $this->ifxRaiseError(); 462 } 463 } 464 return DB_OK; 465 } 466 467 // }}} 468 // {{{ rollback() 469 470 /** 471 * Reverts the current transaction 472 * 473 * @return int DB_OK on success. A DB_Error object on failure. 474 */ 475 function rollback() 476 { 477 if ($this->transaction_opcount > 0) { 478 $result = @ifx_query('ROLLBACK WORK', $this->connection); 479 $this->transaction_opcount = 0; 480 if (!$result) { 481 return $this->ifxRaiseError(); 482 } 483 } 484 return DB_OK; 485 } 486 487 // }}} 488 // {{{ ifxRaiseError() 489 490 /** 491 * Produces a DB_Error object regarding the current problem 492 * 493 * @param int $errno if the error is being manually raised pass a 494 * DB_ERROR* constant here. If this isn't passed 495 * the error information gathered from the DBMS. 496 * 497 * @return object the DB_Error object 498 * 499 * @see DB_common::raiseError(), 500 * DB_ifx::errorNative(), DB_ifx::errorCode() 501 */ 502 function ifxRaiseError($errno = null) 503 { 504 if ($errno === null) { 505 $errno = $this->errorCode(ifx_error()); 506 } 507 return $this->raiseError($errno, null, null, null, 508 $this->errorNative()); 509 } 510 511 // }}} 512 // {{{ errorNative() 513 514 /** 515 * Gets the DBMS' native error code and message produced by the last query 516 * 517 * @return string the DBMS' error code and message 518 */ 519 function errorNative() 520 { 521 return @ifx_error() . ' ' . @ifx_errormsg(); 522 } 523 524 // }}} 525 // {{{ errorCode() 526 527 /** 528 * Maps native error codes to DB's portable ones. 529 * 530 * Requires that the DB implementation's constructor fills 531 * in the <var>$errorcode_map</var> property. 532 * 533 * @param string $nativecode error code returned by the database 534 * @return int a portable DB error code, or DB_ERROR if this DB 535 * implementation has no mapping for the given error code. 536 */ 537 function errorCode($nativecode) 538 { 539 if (ereg('SQLCODE=(.*)]', $nativecode, $match)) { 540 $code = $match[1]; 541 if (isset($this->errorcode_map[$code])) { 542 return $this->errorcode_map[$code]; 543 } 544 } 545 return DB_ERROR; 546 } 547 548 // }}} 549 // {{{ tableInfo() 550 551 /** 552 * Returns information about a table or a result set 553 * 554 * NOTE: only supports 'table' if <var>$result</var> is a table name. 555 * 556 * If analyzing a query result and the result has duplicate field names, 557 * an error will be raised saying 558 * <samp>can't distinguish duplicate field names</samp>. 559 * 560 * @param object|string $result DB_result object from a query or a 561 * string containing the name of a table. 562 * While this also accepts a query result 563 * resource identifier, this behavior is 564 * deprecated. 565 * @param int $mode a valid tableInfo mode 566 * 567 * @return array an associative array with the information requested. 568 * A DB_Error object on failure. 569 * 570 * @see DB_common::tableInfo() 571 * @since Method available since Release 1.6.0 572 */ 573 function tableInfo($result, $mode = null) 574 { 575 if (is_string($result)) { 576 /* 577 * Probably received a table name. 578 * Create a result resource identifier. 579 */ 580 $id = @ifx_query("SELECT * FROM $result WHERE 1=0", 581 $this->connection); 582 $got_string = true; 583 } elseif (isset($result->result)) { 584 /* 585 * Probably received a result object. 586 * Extract the result resource identifier. 587 */ 588 $id = $result->result; 589 $got_string = false; 590 } else { 591 /* 592 * Probably received a result resource identifier. 593 * Copy it. 594 */ 595 $id = $result; 596 $got_string = false; 597 } 598 599 if (!is_resource($id)) { 600 return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); 601 } 602 603 $flds = @ifx_fieldproperties($id); 604 $count = @ifx_num_fields($id); 605 606 if (count($flds) != $count) { 607 return $this->raiseError("can't distinguish duplicate field names"); 608 } 609 610 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 611 $case_func = 'strtolower'; 612 } else { 613 $case_func = 'strval'; 614 } 615 616 $i = 0; 617 $res = array(); 618 619 if ($mode) { 620 $res['num_fields'] = $count; 621 } 622 623 foreach ($flds as $key => $value) { 624 $props = explode(';', $value); 625 $res[$i] = array( 626 'table' => $got_string ? $case_func($result) : '', 627 'name' => $case_func($key), 628 'type' => $props[0], 629 'len' => $props[1], 630 'flags' => $props[4] == 'N' ? 'not_null' : '', 631 ); 632 if ($mode & DB_TABLEINFO_ORDER) { 633 $res['order'][$res[$i]['name']] = $i; 634 } 635 if ($mode & DB_TABLEINFO_ORDERTABLE) { 636 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 637 } 638 $i++; 639 } 640 641 // free the result only if we were called on a table 642 if ($got_string) { 643 @ifx_free_result($id); 644 } 645 return $res; 646 } 647 648 // }}} 649 // {{{ getSpecialQuery() 650 651 /** 652 * Obtains the query string needed for listing a given type of objects 653 * 654 * @param string $type the kind of objects you want to retrieve 655 * 656 * @return string the SQL query string or null if the driver doesn't 657 * support the object type requested 658 * 659 * @access protected 660 * @see DB_common::getListOf() 661 */ 662 function getSpecialQuery($type) 663 { 664 switch ($type) { 665 case 'tables': 666 return 'SELECT tabname FROM systables WHERE tabid >= 100'; 667 default: 668 return null; 669 } 670 } 671 672 // }}} 673 674 } 675 676 /* 677 * Local variables: 678 * tab-width: 4 679 * c-basic-offset: 4 680 * End: 681 */ 682 683 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |