| [ PHPXref.com ] | [ Generated: Sun Jul 20 20:47:21 2008 ] | [ TPLN 2.6 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
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.70 2005/02/20 00:44:48 danielc 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: @package_version@ 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 '-292' => DB_ERROR_CONSTRAINT_NOT_NULL, 105 '-310' => DB_ERROR_ALREADY_EXISTS, 106 '-316' => DB_ERROR_ALREADY_EXISTS, 107 '-319' => DB_ERROR_NOT_FOUND, 108 '-329' => DB_ERROR_NODBSELECTED, 109 '-346' => DB_ERROR_CONSTRAINT, 110 '-386' => DB_ERROR_CONSTRAINT_NOT_NULL, 111 '-391' => DB_ERROR_CONSTRAINT_NOT_NULL, 112 '-554' => DB_ERROR_SYNTAX, 113 '-691' => DB_ERROR_CONSTRAINT, 114 '-692' => DB_ERROR_CONSTRAINT, 115 '-703' => DB_ERROR_CONSTRAINT_NOT_NULL, 116 '-1204' => DB_ERROR_INVALID_DATE, 117 '-1205' => DB_ERROR_INVALID_DATE, 118 '-1206' => DB_ERROR_INVALID_DATE, 119 '-1209' => DB_ERROR_INVALID_DATE, 120 '-1210' => DB_ERROR_INVALID_DATE, 121 '-1212' => DB_ERROR_INVALID_DATE, 122 '-1213' => DB_ERROR_INVALID_NUMBER, 123 ); 124 125 /** 126 * The raw database connection created by PHP 127 * @var resource 128 */ 129 var $connection; 130 131 /** 132 * The DSN information for connecting to a database 133 * @var array 134 */ 135 var $dsn = array(); 136 137 138 /** 139 * Should data manipulation queries be committed automatically? 140 * @var bool 141 * @access private 142 */ 143 var $autocommit = true; 144 145 /** 146 * The quantity of transactions begun 147 * 148 * {@internal While this is private, it can't actually be designated 149 * private in PHP 5 because it is directly accessed in the test suite.}} 150 * 151 * @var integer 152 * @access private 153 */ 154 var $transaction_opcount = 0; 155 156 /** 157 * The number of rows affected by a data manipulation query 158 * @var integer 159 * @access private 160 */ 161 var $affected = 0; 162 163 164 // }}} 165 // {{{ constructor 166 167 /** 168 * This constructor calls <kbd>$this->DB_common()</kbd> 169 * 170 * @return void 171 */ 172 function DB_ifx() 173 { 174 $this->DB_common(); 175 } 176 177 // }}} 178 // {{{ connect() 179 180 /** 181 * Connect to the database server, log in and open the database 182 * 183 * Don't call this method directly. Use DB::connect() instead. 184 * 185 * @param array $dsn the data source name 186 * @param bool $persistent should the connection be persistent? 187 * 188 * @return int DB_OK on success. A DB_Error object on failure. 189 */ 190 function connect($dsn, $persistent = false) 191 { 192 if (!PEAR::loadExtension('informix') && 193 !PEAR::loadExtension('Informix')) 194 { 195 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 196 } 197 198 $this->dsn = $dsn; 199 if ($dsn['dbsyntax']) { 200 $this->dbsyntax = $dsn['dbsyntax']; 201 } 202 203 $dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : ''; 204 $dbname = $dsn['database'] ? $dsn['database'] . $dbhost : ''; 205 $user = $dsn['username'] ? $dsn['username'] : ''; 206 $pw = $dsn['password'] ? $dsn['password'] : ''; 207 208 $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; 209 210 $this->connection = @$connect_function($dbname, $user, $pw); 211 if (!is_resource($this->connection)) { 212 return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED); 213 } 214 return DB_OK; 215 } 216 217 // }}} 218 // {{{ disconnect() 219 220 /** 221 * Disconnects from the database server 222 * 223 * @return bool TRUE on success, FALSE on failure 224 */ 225 function disconnect() 226 { 227 $ret = @ifx_close($this->connection); 228 $this->connection = null; 229 return $ret; 230 } 231 232 // }}} 233 // {{{ simpleQuery() 234 235 /** 236 * Sends a query to the database server 237 * 238 * @param string the SQL query string 239 * 240 * @return mixed + a PHP result resrouce for successful SELECT queries 241 * + the DB_OK constant for other successful queries 242 * + a DB_Error object on failure 243 */ 244 function simpleQuery($query) 245 { 246 $ismanip = DB::isManip($query); 247 $this->last_query = $query; 248 $this->affected = null; 249 if (preg_match('/(SELECT)/i', $query)) { //TESTME: Use !DB::isManip()? 250 // the scroll is needed for fetching absolute row numbers 251 // in a select query result 252 $result = @ifx_query($query, $this->connection, IFX_SCROLL); 253 } else { 254 if (!$this->autocommit && $ismanip) { 255 if ($this->transaction_opcount == 0) { 256 $result = @ifx_query('BEGIN WORK', $this->connection); 257 if (!$result) { 258 return $this->ifxRaiseError(); 259 } 260 } 261 $this->transaction_opcount++; 262 } 263 $result = @ifx_query($query, $this->connection); 264 } 265 if (!$result) { 266 return $this->ifxRaiseError(); 267 } 268 $this->affected = @ifx_affected_rows($result); 269 // Determine which queries should return data, and which 270 // should return an error code only. 271 if (preg_match('/(SELECT)/i', $query)) { 272 return $result; 273 } 274 // XXX Testme: free results inside a transaction 275 // may cause to stop it and commit the work? 276 277 // Result has to be freed even with a insert or update 278 @ifx_free_result($result); 279 280 return DB_OK; 281 } 282 283 // }}} 284 // {{{ nextResult() 285 286 /** 287 * Move the internal ifx result pointer to the next available result 288 * 289 * @param a valid fbsql result resource 290 * 291 * @access public 292 * 293 * @return true if a result is available otherwise return false 294 */ 295 function nextResult($result) 296 { 297 return false; 298 } 299 300 // }}} 301 // {{{ affectedRows() 302 303 /** 304 * Determines the number of rows affected by a data maniuplation query 305 * 306 * 0 is returned for queries that don't manipulate data. 307 * 308 * @return int the number of rows. A DB_Error object on failure. 309 */ 310 function affectedRows() 311 { 312 if (DB::isManip($this->last_query)) { 313 return $this->affected; 314 } else { 315 return 0; 316 } 317 } 318 319 // }}} 320 // {{{ fetchInto() 321 322 /** 323 * Places a row from the result set into the given array 324 * 325 * Formating of the array and the data therein are configurable. 326 * See DB_result::fetchInto() for more information. 327 * 328 * This method is not meant to be called directly. Use 329 * DB_result::fetchInto() instead. It can't be declared "protected" 330 * because DB_result is a separate object. 331 * 332 * @param resource $result the query result resource 333 * @param array $arr the referenced array to put the data in 334 * @param int $fetchmode how the resulting array should be indexed 335 * @param int $rownum the row number to fetch (0 = first row) 336 * 337 * @return mixed DB_OK on success, NULL when the end of a result set is 338 * reached or on failure 339 * 340 * @see DB_result::fetchInto() 341 */ 342 function fetchInto($result, &$arr, $fetchmode, $rownum = null) 343 { 344 if (($rownum !== null) && ($rownum < 0)) { 345 return null; 346 } 347 if ($rownum === null) { 348 /* 349 * Even though fetch_row() should return the next row if 350 * $rownum is null, it doesn't in all cases. Bug 598. 351 */ 352 $rownum = 'NEXT'; 353 } else { 354 // Index starts at row 1, unlike most DBMS's starting at 0. 355 $rownum++; 356 } 357 if (!$arr = @ifx_fetch_row($result, $rownum)) { 358 return null; 359 } 360 if ($fetchmode !== DB_FETCHMODE_ASSOC) { 361 $i=0; 362 $order = array(); 363 foreach ($arr as $val) { 364 $order[$i++] = $val; 365 } 366 $arr = $order; 367 } elseif ($fetchmode == DB_FETCHMODE_ASSOC && 368 $this->options['portability'] & DB_PORTABILITY_LOWERCASE) 369 { 370 $arr = array_change_key_case($arr, CASE_LOWER); 371 } 372 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 373 $this->_rtrimArrayValues($arr); 374 } 375 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 376 $this->_convertNullArrayValuesToEmpty($arr); 377 } 378 return DB_OK; 379 } 380 381 // }}} 382 // {{{ numCols() 383 384 /** 385 * Gets the number of columns in a result set 386 * 387 * This method is not meant to be called directly. Use 388 * DB_result::numCols() instead. It can't be declared "protected" 389 * because DB_result is a separate object. 390 * 391 * @param resource $result PHP's query result resource 392 * 393 * @return int the number of columns. A DB_Error object on failure. 394 * 395 * @see DB_result::numCols() 396 */ 397 function numCols($result) 398 { 399 if (!$cols = @ifx_num_fields($result)) { 400 return $this->ifxRaiseError(); 401 } 402 return $cols; 403 } 404 405 // }}} 406 // {{{ freeResult() 407 408 /** 409 * Deletes the result set and frees the memory occupied by the result set 410 * 411 * This method is not meant to be called directly. Use 412 * DB_result::free() instead. It can't be declared "protected" 413 * because DB_result is a separate object. 414 * 415 * @param resource $result PHP's query result resource 416 * 417 * @return bool TRUE on success, FALSE if $result is invalid 418 * 419 * @see DB_result::free() 420 */ 421 function freeResult($result) 422 { 423 return @ifx_free_result($result); 424 } 425 426 // }}} 427 // {{{ autoCommit() 428 429 /** 430 * Enables or disables automatic commits 431 * 432 * @param bool $onoff true turns it on, false turns it off 433 * 434 * @return int DB_OK on success. A DB_Error object if the driver 435 * doesn't support auto-committing transactions. 436 */ 437 function autoCommit($onoff = true) 438 { 439 // XXX if $this->transaction_opcount > 0, we should probably 440 // issue a warning here. 441 $this->autocommit = $onoff ? true : false; 442 return DB_OK; 443 } 444 445 // }}} 446 // {{{ commit() 447 448 /** 449 * Commits the current transaction 450 * 451 * @return int DB_OK on success. A DB_Error object on failure. 452 */ 453 function commit() 454 { 455 if ($this->transaction_opcount > 0) { 456 $result = @ifx_query('COMMIT WORK', $this->connection); 457 $this->transaction_opcount = 0; 458 if (!$result) { 459 return $this->ifxRaiseError(); 460 } 461 } 462 return DB_OK; 463 } 464 465 // }}} 466 // {{{ rollback() 467 468 /** 469 * Reverts the current transaction 470 * 471 * @return int DB_OK on success. A DB_Error object on failure. 472 */ 473 function rollback() 474 { 475 if ($this->transaction_opcount > 0) { 476 $result = @ifx_query('ROLLBACK WORK', $this->connection); 477 $this->transaction_opcount = 0; 478 if (!$result) { 479 return $this->ifxRaiseError(); 480 } 481 } 482 return DB_OK; 483 } 484 485 // }}} 486 // {{{ ifxRaiseError() 487 488 /** 489 * Produces a DB_Error object regarding the current problem 490 * 491 * @param int $errno if the error is being manually raised pass a 492 * DB_ERROR* constant here. If this isn't passed 493 * the error information gathered from the DBMS. 494 * 495 * @return object the DB_Error object 496 * 497 * @see DB_common::raiseError(), 498 * DB_ifx::errorNative(), DB_ifx::errorCode() 499 */ 500 function ifxRaiseError($errno = null) 501 { 502 if ($errno === null) { 503 $errno = $this->errorCode(ifx_error()); 504 } 505 return $this->raiseError($errno, null, null, null, 506 $this->errorNative()); 507 } 508 509 // }}} 510 // {{{ errorNative() 511 512 /** 513 * Gets the DBMS' native error code and message produced by the last query 514 * 515 * @return string the DBMS' error code and message 516 */ 517 function errorNative() 518 { 519 return @ifx_error() . ' ' . @ifx_errormsg(); 520 } 521 522 // }}} 523 // {{{ errorCode() 524 525 /** 526 * Maps native error codes to DB's portable ones. 527 * 528 * Requires that the DB implementation's constructor fills 529 * in the <var>$errorcode_map</var> property. 530 * 531 * @param string $nativecode error code returned by the database 532 * @return int a portable DB error code, or DB_ERROR if this DB 533 * implementation has no mapping for the given error code. 534 */ 535 function errorCode($nativecode) 536 { 537 if (ereg('SQLCODE=(.*)]', $nativecode, $match)) { 538 $code = $match[1]; 539 if (isset($this->errorcode_map[$code])) { 540 return $this->errorcode_map[$code]; 541 } 542 } 543 return DB_ERROR; 544 } 545 546 // }}} 547 // {{{ tableInfo() 548 549 /** 550 * Returns information about a table or a result set 551 * 552 * NOTE: only supports 'table' if <var>$result</var> is a table name. 553 * 554 * If analyzing a query result and the result has duplicate field names, 555 * an error will be raised saying 556 * <samp>can't distinguish duplicate field names</samp>. 557 * 558 * @param object|string $result DB_result object from a query or a 559 * string containing the name of a table. 560 * While this also accepts a query result 561 * resource identifier, this behavior is 562 * deprecated. 563 * @param int $mode a valid tableInfo mode 564 * 565 * @return array an associative array with the information requested. 566 * A DB_Error object on failure. 567 * 568 * @see DB_common::tableInfo() 569 * @since Method available since Release 1.6.0 570 */ 571 function tableInfo($result, $mode = null) 572 { 573 if (is_string($result)) { 574 /* 575 * Probably received a table name. 576 * Create a result resource identifier. 577 */ 578 $id = @ifx_query("SELECT * FROM $result WHERE 1=0", 579 $this->connection); 580 $got_string = true; 581 } elseif (isset($result->result)) { 582 /* 583 * Probably received a result object. 584 * Extract the result resource identifier. 585 */ 586 $id = $result->result; 587 $got_string = false; 588 } else { 589 /* 590 * Probably received a result resource identifier. 591 * Copy it. 592 */ 593 $id = $result; 594 $got_string = false; 595 } 596 597 if (!is_resource($id)) { 598 return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); 599 } 600 601 $flds = @ifx_fieldproperties($id); 602 $count = @ifx_num_fields($id); 603 604 if (count($flds) != $count) { 605 return $this->raiseError("can't distinguish duplicate field names"); 606 } 607 608 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 609 $case_func = 'strtolower'; 610 } else { 611 $case_func = 'strval'; 612 } 613 614 $i = 0; 615 $res = array(); 616 617 if ($mode) { 618 $res['num_fields'] = $count; 619 } 620 621 foreach ($flds as $key => $value) { 622 $props = explode(';', $value); 623 $res[$i] = array( 624 'table' => $got_string ? $case_func($result) : '', 625 'name' => $case_func($key), 626 'type' => $props[0], 627 'len' => $props[1], 628 'flags' => $props[4] == 'N' ? 'not_null' : '', 629 ); 630 if ($mode & DB_TABLEINFO_ORDER) { 631 $res['order'][$res[$i]['name']] = $i; 632 } 633 if ($mode & DB_TABLEINFO_ORDERTABLE) { 634 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 635 } 636 $i++; 637 } 638 639 // free the result only if we were called on a table 640 if ($got_string) { 641 @ifx_free_result($id); 642 } 643 return $res; 644 } 645 646 // }}} 647 // {{{ getSpecialQuery() 648 649 /** 650 * Obtains the query string needed for listing a given type of objects 651 * 652 * @param string $type the kind of objects you want to retrieve 653 * 654 * @return string the SQL query string or null if the driver doesn't 655 * support the object type requested 656 * 657 * @access protected 658 * @see DB_common::getListOf() 659 */ 660 function getSpecialQuery($type) 661 { 662 switch ($type) { 663 case 'tables': 664 return 'SELECT tabname FROM systables WHERE tabid >= 100'; 665 default: 666 return null; 667 } 668 } 669 670 // }}} 671 672 } 673 674 /* 675 * Local variables: 676 * tab-width: 4 677 * c-basic-offset: 4 678 * End: 679 */ 680 681 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| [ Powered by PHPXref - Served by Debian GNU/Linux ] |