| [ 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 * Contains the DB_common base class 7 * 8 * PHP versions 4 and 5 9 * 10 * LICENSE: This source file is subject to version 3.0 of the PHP license 11 * that is available through the world-wide-web at the following URI: 12 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 13 * the PHP License and are unable to obtain it through the web, please 14 * send a note to license@php.net so we can mail you a copy immediately. 15 * 16 * @category Database 17 * @package DB 18 * @author Stig Bakken <ssb@php.net> 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: common.php,v 1.140 2007/01/12 02:41:07 aharvey Exp $ 24 * @link http://pear.php.net/package/DB 25 */ 26 27 /** 28 * Obtain the PEAR class so it can be extended from 29 */ 30 require_once 'PEAR.php'; 31 32 /** 33 * DB_common is the base class from which each database driver class extends 34 * 35 * All common methods are declared here. If a given DBMS driver contains 36 * a particular method, that method will overload the one here. 37 * 38 * @category Database 39 * @package DB 40 * @author Stig Bakken <ssb@php.net> 41 * @author Tomas V.V. Cox <cox@idecnet.com> 42 * @author Daniel Convissor <danielc@php.net> 43 * @copyright 1997-2005 The PHP Group 44 * @license http://www.php.net/license/3_0.txt PHP License 3.0 45 * @version Release: 1.7.9 46 * @link http://pear.php.net/package/DB 47 */ 48 class DB_common extends PEAR 49 { 50 // {{{ properties 51 52 /** 53 * The current default fetch mode 54 * @var integer 55 */ 56 var $fetchmode = DB_FETCHMODE_ORDERED; 57 58 /** 59 * The name of the class into which results should be fetched when 60 * DB_FETCHMODE_OBJECT is in effect 61 * 62 * @var string 63 */ 64 var $fetchmode_object_class = 'stdClass'; 65 66 /** 67 * Was a connection present when the object was serialized()? 68 * @var bool 69 * @see DB_common::__sleep(), DB_common::__wake() 70 */ 71 var $was_connected = null; 72 73 /** 74 * The most recently executed query 75 * @var string 76 */ 77 var $last_query = ''; 78 79 /** 80 * Run-time configuration options 81 * 82 * The 'optimize' option has been deprecated. Use the 'portability' 83 * option instead. 84 * 85 * @var array 86 * @see DB_common::setOption() 87 */ 88 var $options = array( 89 'result_buffering' => 500, 90 'persistent' => false, 91 'ssl' => false, 92 'debug' => 0, 93 'seqname_format' => '%s_seq', 94 'autofree' => false, 95 'portability' => DB_PORTABILITY_NONE, 96 'optimize' => 'performance', // Deprecated. Use 'portability'. 97 ); 98 99 /** 100 * The parameters from the most recently executed query 101 * @var array 102 * @since Property available since Release 1.7.0 103 */ 104 var $last_parameters = array(); 105 106 /** 107 * The elements from each prepared statement 108 * @var array 109 */ 110 var $prepare_tokens = array(); 111 112 /** 113 * The data types of the various elements in each prepared statement 114 * @var array 115 */ 116 var $prepare_types = array(); 117 118 /** 119 * The prepared queries 120 * @var array 121 */ 122 var $prepared_queries = array(); 123 124 /** 125 * Flag indicating that the last query was a manipulation query. 126 * @access protected 127 * @var boolean 128 */ 129 var $_last_query_manip = false; 130 131 /** 132 * Flag indicating that the next query <em>must</em> be a manipulation 133 * query. 134 * @access protected 135 * @var boolean 136 */ 137 var $_next_query_manip = false; 138 139 140 // }}} 141 // {{{ DB_common 142 143 /** 144 * This constructor calls <kbd>$this->PEAR('DB_Error')</kbd> 145 * 146 * @return void 147 */ 148 function DB_common() 149 { 150 $this->PEAR('DB_Error'); 151 } 152 153 // }}} 154 // {{{ __sleep() 155 156 /** 157 * Automatically indicates which properties should be saved 158 * when PHP's serialize() function is called 159 * 160 * @return array the array of properties names that should be saved 161 */ 162 function __sleep() 163 { 164 if ($this->connection) { 165 // Don't disconnect(), people use serialize() for many reasons 166 $this->was_connected = true; 167 } else { 168 $this->was_connected = false; 169 } 170 if (isset($this->autocommit)) { 171 return array('autocommit', 172 'dbsyntax', 173 'dsn', 174 'features', 175 'fetchmode', 176 'fetchmode_object_class', 177 'options', 178 'was_connected', 179 ); 180 } else { 181 return array('dbsyntax', 182 'dsn', 183 'features', 184 'fetchmode', 185 'fetchmode_object_class', 186 'options', 187 'was_connected', 188 ); 189 } 190 } 191 192 // }}} 193 // {{{ __wakeup() 194 195 /** 196 * Automatically reconnects to the database when PHP's unserialize() 197 * function is called 198 * 199 * The reconnection attempt is only performed if the object was connected 200 * at the time PHP's serialize() function was run. 201 * 202 * @return void 203 */ 204 function __wakeup() 205 { 206 if ($this->was_connected) { 207 $this->connect($this->dsn, $this->options); 208 } 209 } 210 211 // }}} 212 // {{{ __toString() 213 214 /** 215 * Automatic string conversion for PHP 5 216 * 217 * @return string a string describing the current PEAR DB object 218 * 219 * @since Method available since Release 1.7.0 220 */ 221 function __toString() 222 { 223 $info = strtolower(get_class($this)); 224 $info .= ': (phptype=' . $this->phptype . 225 ', dbsyntax=' . $this->dbsyntax . 226 ')'; 227 if ($this->connection) { 228 $info .= ' [connected]'; 229 } 230 return $info; 231 } 232 233 // }}} 234 // {{{ toString() 235 236 /** 237 * DEPRECATED: String conversion method 238 * 239 * @return string a string describing the current PEAR DB object 240 * 241 * @deprecated Method deprecated in Release 1.7.0 242 */ 243 function toString() 244 { 245 return $this->__toString(); 246 } 247 248 // }}} 249 // {{{ quoteString() 250 251 /** 252 * DEPRECATED: Quotes a string so it can be safely used within string 253 * delimiters in a query 254 * 255 * @param string $string the string to be quoted 256 * 257 * @return string the quoted string 258 * 259 * @see DB_common::quoteSmart(), DB_common::escapeSimple() 260 * @deprecated Method deprecated some time before Release 1.2 261 */ 262 function quoteString($string) 263 { 264 $string = $this->quote($string); 265 if ($string{0} == "'") { 266 return substr($string, 1, -1); 267 } 268 return $string; 269 } 270 271 // }}} 272 // {{{ quote() 273 274 /** 275 * DEPRECATED: Quotes a string so it can be safely used in a query 276 * 277 * @param string $string the string to quote 278 * 279 * @return string the quoted string or the string <samp>NULL</samp> 280 * if the value submitted is <kbd>null</kbd>. 281 * 282 * @see DB_common::quoteSmart(), DB_common::escapeSimple() 283 * @deprecated Deprecated in release 1.6.0 284 */ 285 function quote($string = null) 286 { 287 return ($string === null) ? 'NULL' 288 : "'" . str_replace("'", "''", $string) . "'"; 289 } 290 291 // }}} 292 // {{{ quoteIdentifier() 293 294 /** 295 * Quotes a string so it can be safely used as a table or column name 296 * 297 * Delimiting style depends on which database driver is being used. 298 * 299 * NOTE: just because you CAN use delimited identifiers doesn't mean 300 * you SHOULD use them. In general, they end up causing way more 301 * problems than they solve. 302 * 303 * Portability is broken by using the following characters inside 304 * delimited identifiers: 305 * + backtick (<kbd>`</kbd>) -- due to MySQL 306 * + double quote (<kbd>"</kbd>) -- due to Oracle 307 * + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access 308 * 309 * Delimited identifiers are known to generally work correctly under 310 * the following drivers: 311 * + mssql 312 * + mysql 313 * + mysqli 314 * + oci8 315 * + odbc(access) 316 * + odbc(db2) 317 * + pgsql 318 * + sqlite 319 * + sybase (must execute <kbd>set quoted_identifier on</kbd> sometime 320 * prior to use) 321 * 322 * InterBase doesn't seem to be able to use delimited identifiers 323 * via PHP 4. They work fine under PHP 5. 324 * 325 * @param string $str the identifier name to be quoted 326 * 327 * @return string the quoted identifier 328 * 329 * @since Method available since Release 1.6.0 330 */ 331 function quoteIdentifier($str) 332 { 333 return '"' . str_replace('"', '""', $str) . '"'; 334 } 335 336 // }}} 337 // {{{ quoteSmart() 338 339 /** 340 * Formats input so it can be safely used in a query 341 * 342 * The output depends on the PHP data type of input and the database 343 * type being used. 344 * 345 * @param mixed $in the data to be formatted 346 * 347 * @return mixed the formatted data. The format depends on the input's 348 * PHP type: 349 * <ul> 350 * <li> 351 * <kbd>input</kbd> -> <samp>returns</samp> 352 * </li> 353 * <li> 354 * <kbd>null</kbd> -> the string <samp>NULL</samp> 355 * </li> 356 * <li> 357 * <kbd>integer</kbd> or <kbd>double</kbd> -> the unquoted number 358 * </li> 359 * <li> 360 * <kbd>bool</kbd> -> output depends on the driver in use 361 * Most drivers return integers: <samp>1</samp> if 362 * <kbd>true</kbd> or <samp>0</samp> if 363 * <kbd>false</kbd>. 364 * Some return strings: <samp>TRUE</samp> if 365 * <kbd>true</kbd> or <samp>FALSE</samp> if 366 * <kbd>false</kbd>. 367 * Finally one returns strings: <samp>T</samp> if 368 * <kbd>true</kbd> or <samp>F</samp> if 369 * <kbd>false</kbd>. Here is a list of each DBMS, 370 * the values returned and the suggested column type: 371 * <ul> 372 * <li> 373 * <kbd>dbase</kbd> -> <samp>T/F</samp> 374 * (<kbd>Logical</kbd>) 375 * </li> 376 * <li> 377 * <kbd>fbase</kbd> -> <samp>TRUE/FALSE</samp> 378 * (<kbd>BOOLEAN</kbd>) 379 * </li> 380 * <li> 381 * <kbd>ibase</kbd> -> <samp>1/0</samp> 382 * (<kbd>SMALLINT</kbd>) [1] 383 * </li> 384 * <li> 385 * <kbd>ifx</kbd> -> <samp>1/0</samp> 386 * (<kbd>SMALLINT</kbd>) [1] 387 * </li> 388 * <li> 389 * <kbd>msql</kbd> -> <samp>1/0</samp> 390 * (<kbd>INTEGER</kbd>) 391 * </li> 392 * <li> 393 * <kbd>mssql</kbd> -> <samp>1/0</samp> 394 * (<kbd>BIT</kbd>) 395 * </li> 396 * <li> 397 * <kbd>mysql</kbd> -> <samp>1/0</samp> 398 * (<kbd>TINYINT(1)</kbd>) 399 * </li> 400 * <li> 401 * <kbd>mysqli</kbd> -> <samp>1/0</samp> 402 * (<kbd>TINYINT(1)</kbd>) 403 * </li> 404 * <li> 405 * <kbd>oci8</kbd> -> <samp>1/0</samp> 406 * (<kbd>NUMBER(1)</kbd>) 407 * </li> 408 * <li> 409 * <kbd>odbc</kbd> -> <samp>1/0</samp> 410 * (<kbd>SMALLINT</kbd>) [1] 411 * </li> 412 * <li> 413 * <kbd>pgsql</kbd> -> <samp>TRUE/FALSE</samp> 414 * (<kbd>BOOLEAN</kbd>) 415 * </li> 416 * <li> 417 * <kbd>sqlite</kbd> -> <samp>1/0</samp> 418 * (<kbd>INTEGER</kbd>) 419 * </li> 420 * <li> 421 * <kbd>sybase</kbd> -> <samp>1/0</samp> 422 * (<kbd>TINYINT(1)</kbd>) 423 * </li> 424 * </ul> 425 * [1] Accommodate the lowest common denominator because not all 426 * versions of have <kbd>BOOLEAN</kbd>. 427 * </li> 428 * <li> 429 * other (including strings and numeric strings) -> 430 * the data with single quotes escaped by preceeding 431 * single quotes, backslashes are escaped by preceeding 432 * backslashes, then the whole string is encapsulated 433 * between single quotes 434 * </li> 435 * </ul> 436 * 437 * @see DB_common::escapeSimple() 438 * @since Method available since Release 1.6.0 439 */ 440 function quoteSmart($in) 441 { 442 if (is_int($in)) { 443 return $in; 444 } elseif (is_float($in)) { 445 return $this->quoteFloat($in); 446 } elseif (is_bool($in)) { 447 return $this->quoteBoolean($in); 448 } elseif (is_null($in)) { 449 return 'NULL'; 450 } else { 451 if ($this->dbsyntax == 'access' 452 && preg_match('/^#.+#$/', $in)) 453 { 454 return $this->escapeSimple($in); 455 } 456 return "'" . $this->escapeSimple($in) . "'"; 457 } 458 } 459 460 // }}} 461 // {{{ quoteBoolean() 462 463 /** 464 * Formats a boolean value for use within a query in a locale-independent 465 * manner. 466 * 467 * @param boolean the boolean value to be quoted. 468 * @return string the quoted string. 469 * @see DB_common::quoteSmart() 470 * @since Method available since release 1.7.8. 471 */ 472 function quoteBoolean($boolean) { 473 return $boolean ? '1' : '0'; 474 } 475 476 // }}} 477 // {{{ quoteFloat() 478 479 /** 480 * Formats a float value for use within a query in a locale-independent 481 * manner. 482 * 483 * @param float the float value to be quoted. 484 * @return string the quoted string. 485 * @see DB_common::quoteSmart() 486 * @since Method available since release 1.7.8. 487 */ 488 function quoteFloat($float) { 489 return "'".$this->escapeSimple(str_replace(',', '.', strval(floatval($float))))."'"; 490 } 491 492 // }}} 493 // {{{ escapeSimple() 494 495 /** 496 * Escapes a string according to the current DBMS's standards 497 * 498 * In SQLite, this makes things safe for inserts/updates, but may 499 * cause problems when performing text comparisons against columns 500 * containing binary data. See the 501 * {@link http://php.net/sqlite_escape_string PHP manual} for more info. 502 * 503 * @param string $str the string to be escaped 504 * 505 * @return string the escaped string 506 * 507 * @see DB_common::quoteSmart() 508 * @since Method available since Release 1.6.0 509 */ 510 function escapeSimple($str) 511 { 512 return str_replace("'", "''", $str); 513 } 514 515 // }}} 516 // {{{ provides() 517 518 /** 519 * Tells whether the present driver supports a given feature 520 * 521 * @param string $feature the feature you're curious about 522 * 523 * @return bool whether this driver supports $feature 524 */ 525 function provides($feature) 526 { 527 return $this->features[$feature]; 528 } 529 530 // }}} 531 // {{{ setFetchMode() 532 533 /** 534 * Sets the fetch mode that should be used by default for query results 535 * 536 * @param integer $fetchmode DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC 537 * or DB_FETCHMODE_OBJECT 538 * @param string $object_class the class name of the object to be returned 539 * by the fetch methods when the 540 * DB_FETCHMODE_OBJECT mode is selected. 541 * If no class is specified by default a cast 542 * to object from the assoc array row will be 543 * done. There is also the posibility to use 544 * and extend the 'DB_row' class. 545 * 546 * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT 547 */ 548 function setFetchMode($fetchmode, $object_class = 'stdClass') 549 { 550 switch ($fetchmode) { 551 case DB_FETCHMODE_OBJECT: 552 $this->fetchmode_object_class = $object_class; 553 case DB_FETCHMODE_ORDERED: 554 case DB_FETCHMODE_ASSOC: 555 $this->fetchmode = $fetchmode; 556 break; 557 default: 558 return $this->raiseError('invalid fetchmode mode'); 559 } 560 } 561 562 // }}} 563 // {{{ setOption() 564 565 /** 566 * Sets run-time configuration options for PEAR DB 567 * 568 * Options, their data types, default values and description: 569 * <ul> 570 * <li> 571 * <var>autofree</var> <kbd>boolean</kbd> = <samp>false</samp> 572 * <br />should results be freed automatically when there are no 573 * more rows? 574 * </li><li> 575 * <var>result_buffering</var> <kbd>integer</kbd> = <samp>500</samp> 576 * <br />how many rows of the result set should be buffered? 577 * <br />In mysql: mysql_unbuffered_query() is used instead of 578 * mysql_query() if this value is 0. (Release 1.7.0) 579 * <br />In oci8: this value is passed to ocisetprefetch(). 580 * (Release 1.7.0) 581 * </li><li> 582 * <var>debug</var> <kbd>integer</kbd> = <samp>0</samp> 583 * <br />debug level 584 * </li><li> 585 * <var>persistent</var> <kbd>boolean</kbd> = <samp>false</samp> 586 * <br />should the connection be persistent? 587 * </li><li> 588 * <var>portability</var> <kbd>integer</kbd> = <samp>DB_PORTABILITY_NONE</samp> 589 * <br />portability mode constant (see below) 590 * </li><li> 591 * <var>seqname_format</var> <kbd>string</kbd> = <samp>%s_seq</samp> 592 * <br />the sprintf() format string used on sequence names. This 593 * format is applied to sequence names passed to 594 * createSequence(), nextID() and dropSequence(). 595 * </li><li> 596 * <var>ssl</var> <kbd>boolean</kbd> = <samp>false</samp> 597 * <br />use ssl to connect? 598 * </li> 599 * </ul> 600 * 601 * ----------------------------------------- 602 * 603 * PORTABILITY MODES 604 * 605 * These modes are bitwised, so they can be combined using <kbd>|</kbd> 606 * and removed using <kbd>^</kbd>. See the examples section below on how 607 * to do this. 608 * 609 * <samp>DB_PORTABILITY_NONE</samp> 610 * turn off all portability features 611 * 612 * This mode gets automatically turned on if the deprecated 613 * <var>optimize</var> option gets set to <samp>performance</samp>. 614 * 615 * 616 * <samp>DB_PORTABILITY_LOWERCASE</samp> 617 * convert names of tables and fields to lower case when using 618 * <kbd>get*()</kbd>, <kbd>fetch*()</kbd> and <kbd>tableInfo()</kbd> 619 * 620 * This mode gets automatically turned on in the following databases 621 * if the deprecated option <var>optimize</var> gets set to 622 * <samp>portability</samp>: 623 * + oci8 624 * 625 * 626 * <samp>DB_PORTABILITY_RTRIM</samp> 627 * right trim the data output by <kbd>get*()</kbd> <kbd>fetch*()</kbd> 628 * 629 * 630 * <samp>DB_PORTABILITY_DELETE_COUNT</samp> 631 * force reporting the number of rows deleted 632 * 633 * Some DBMS's don't count the number of rows deleted when performing 634 * simple <kbd>DELETE FROM tablename</kbd> queries. This portability 635 * mode tricks such DBMS's into telling the count by adding 636 * <samp>WHERE 1=1</samp> to the end of <kbd>DELETE</kbd> queries. 637 * 638 * This mode gets automatically turned on in the following databases 639 * if the deprecated option <var>optimize</var> gets set to 640 * <samp>portability</samp>: 641 * + fbsql 642 * + mysql 643 * + mysqli 644 * + sqlite 645 * 646 * 647 * <samp>DB_PORTABILITY_NUMROWS</samp> 648 * enable hack that makes <kbd>numRows()</kbd> work in Oracle 649 * 650 * This mode gets automatically turned on in the following databases 651 * if the deprecated option <var>optimize</var> gets set to 652 * <samp>portability</samp>: 653 * + oci8 654 * 655 * 656 * <samp>DB_PORTABILITY_ERRORS</samp> 657 * makes certain error messages in certain drivers compatible 658 * with those from other DBMS's 659 * 660 * + mysql, mysqli: change unique/primary key constraints 661 * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT 662 * 663 * + odbc(access): MS's ODBC driver reports 'no such field' as code 664 * 07001, which means 'too few parameters.' When this option is on 665 * that code gets mapped to DB_ERROR_NOSUCHFIELD. 666 * DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD 667 * 668 * <samp>DB_PORTABILITY_NULL_TO_EMPTY</samp> 669 * convert null values to empty strings in data output by get*() and 670 * fetch*(). Needed because Oracle considers empty strings to be null, 671 * while most other DBMS's know the difference between empty and null. 672 * 673 * 674 * <samp>DB_PORTABILITY_ALL</samp> 675 * turn on all portability features 676 * 677 * ----------------------------------------- 678 * 679 * Example 1. Simple setOption() example 680 * <code> 681 * $db->setOption('autofree', true); 682 * </code> 683 * 684 * Example 2. Portability for lowercasing and trimming 685 * <code> 686 * $db->setOption('portability', 687 * DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM); 688 * </code> 689 * 690 * Example 3. All portability options except trimming 691 * <code> 692 * $db->setOption('portability', 693 * DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM); 694 * </code> 695 * 696 * @param string $option option name 697 * @param mixed $value value for the option 698 * 699 * @return int DB_OK on success. A DB_Error object on failure. 700 * 701 * @see DB_common::$options 702 */ 703 function setOption($option, $value) 704 { 705 if (isset($this->options[$option])) { 706 $this->options[$option] = $value; 707 708 /* 709 * Backwards compatibility check for the deprecated 'optimize' 710 * option. Done here in case settings change after connecting. 711 */ 712 if ($option == 'optimize') { 713 if ($value == 'portability') { 714 switch ($this->phptype) { 715 case 'oci8': 716 $this->options['portability'] = 717 DB_PORTABILITY_LOWERCASE | 718 DB_PORTABILITY_NUMROWS; 719 break; 720 case 'fbsql': 721 case 'mysql': 722 case 'mysqli': 723 case 'sqlite': 724 $this->options['portability'] = 725 DB_PORTABILITY_DELETE_COUNT; 726 break; 727 } 728 } else { 729 $this->options['portability'] = DB_PORTABILITY_NONE; 730 } 731 } 732 733 return DB_OK; 734 } 735 return $this->raiseError("unknown option $option"); 736 } 737 738 // }}} 739 // {{{ getOption() 740 741 /** 742 * Returns the value of an option 743 * 744 * @param string $option the option name you're curious about 745 * 746 * @return mixed the option's value 747 */ 748 function getOption($option) 749 { 750 if (isset($this->options[$option])) { 751 return $this->options[$option]; 752 } 753 return $this->raiseError("unknown option $option"); 754 } 755 756 // }}} 757 // {{{ prepare() 758 759 /** 760 * Prepares a query for multiple execution with execute() 761 * 762 * Creates a query that can be run multiple times. Each time it is run, 763 * the placeholders, if any, will be replaced by the contents of 764 * execute()'s $data argument. 765 * 766 * Three types of placeholders can be used: 767 * + <kbd>?</kbd> scalar value (i.e. strings, integers). The system 768 * will automatically quote and escape the data. 769 * + <kbd>!</kbd> value is inserted 'as is' 770 * + <kbd>&</kbd> requires a file name. The file's contents get 771 * inserted into the query (i.e. saving binary 772 * data in a db) 773 * 774 * Example 1. 775 * <code> 776 * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); 777 * $data = array( 778 * "John's text", 779 * "'it''s good'", 780 * 'filename.txt' 781 * ); 782 * $res = $db->execute($sth, $data); 783 * </code> 784 * 785 * Use backslashes to escape placeholder characters if you don't want 786 * them to be interpreted as placeholders: 787 * <pre> 788 * "UPDATE foo SET col=? WHERE col='over \& under'" 789 * </pre> 790 * 791 * With some database backends, this is emulated. 792 * 793 * {@internal ibase and oci8 have their own prepare() methods.}} 794 * 795 * @param string $query the query to be prepared 796 * 797 * @return mixed DB statement resource on success. A DB_Error object 798 * on failure. 799 * 800 * @see DB_common::execute() 801 */ 802 function prepare($query) 803 { 804 $tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1, 805 PREG_SPLIT_DELIM_CAPTURE); 806 $token = 0; 807 $types = array(); 808 $newtokens = array(); 809 810 foreach ($tokens as $val) { 811 switch ($val) { 812 case '?': 813 $types[$token++] = DB_PARAM_SCALAR; 814 break; 815 case '&': 816 $types[$token++] = DB_PARAM_OPAQUE; 817 break; 818 case '!': 819 $types[$token++] = DB_PARAM_MISC; 820 break; 821 default: 822 $newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val); 823 } 824 } 825 826 $this->prepare_tokens[] = &$newtokens; 827 end($this->prepare_tokens); 828 829 $k = key($this->prepare_tokens); 830 $this->prepare_types[$k] = $types; 831 $this->prepared_queries[$k] = implode(' ', $newtokens); 832 833 return $k; 834 } 835 836 // }}} 837 // {{{ autoPrepare() 838 839 /** 840 * Automaticaly generates an insert or update query and pass it to prepare() 841 * 842 * @param string $table the table name 843 * @param array $table_fields the array of field names 844 * @param int $mode a type of query to make: 845 * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE 846 * @param string $where for update queries: the WHERE clause to 847 * append to the SQL statement. Don't 848 * include the "WHERE" keyword. 849 * 850 * @return resource the query handle 851 * 852 * @uses DB_common::prepare(), DB_common::buildManipSQL() 853 */ 854 function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, 855 $where = false) 856 { 857 $query = $this->buildManipSQL($table, $table_fields, $mode, $where); 858 if (DB::isError($query)) { 859 return $query; 860 } 861 return $this->prepare($query); 862 } 863 864 // }}} 865 // {{{ autoExecute() 866 867 /** 868 * Automaticaly generates an insert or update query and call prepare() 869 * and execute() with it 870 * 871 * @param string $table the table name 872 * @param array $fields_values the associative array where $key is a 873 * field name and $value its value 874 * @param int $mode a type of query to make: 875 * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE 876 * @param string $where for update queries: the WHERE clause to 877 * append to the SQL statement. Don't 878 * include the "WHERE" keyword. 879 * 880 * @return mixed a new DB_result object for successful SELECT queries 881 * or DB_OK for successul data manipulation queries. 882 * A DB_Error object on failure. 883 * 884 * @uses DB_common::autoPrepare(), DB_common::execute() 885 */ 886 function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, 887 $where = false) 888 { 889 $sth = $this->autoPrepare($table, array_keys($fields_values), $mode, 890 $where); 891 if (DB::isError($sth)) { 892 return $sth; 893 } 894 $ret =& $this->execute($sth, array_values($fields_values)); 895 $this->freePrepared($sth); 896 return $ret; 897 898 } 899 900 // }}} 901 // {{{ buildManipSQL() 902 903 /** 904 * Produces an SQL query string for autoPrepare() 905 * 906 * Example: 907 * <pre> 908 * buildManipSQL('table_sql', array('field1', 'field2', 'field3'), 909 * DB_AUTOQUERY_INSERT); 910 * </pre> 911 * 912 * That returns 913 * <samp> 914 * INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) 915 * </samp> 916 * 917 * NOTES: 918 * - This belongs more to a SQL Builder class, but this is a simple 919 * facility. 920 * - Be carefull! If you don't give a $where param with an UPDATE 921 * query, all the records of the table will be updated! 922 * 923 * @param string $table the table name 924 * @param array $table_fields the array of field names 925 * @param int $mode a type of query to make: 926 * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE 927 * @param string $where for update queries: the WHERE clause to 928 * append to the SQL statement. Don't 929 * include the "WHERE" keyword. 930 * 931 * @return string the sql query for autoPrepare() 932 */ 933 function buildManipSQL($table, $table_fields, $mode, $where = false) 934 { 935 if (count($table_fields) == 0) { 936 return $this->raiseError(DB_ERROR_NEED_MORE_DATA); 937 } 938 $first = true; 939 switch ($mode) { 940 case DB_AUTOQUERY_INSERT: 941 $values = ''; 942 $names = ''; 943 foreach ($table_fields as $value) { 944 if ($first) { 945 $first = false; 946 } else { 947 $names .= ','; 948 $values .= ','; 949 } 950 $names .= $value; 951 $values .= '?'; 952 } 953 return "INSERT INTO $table ($names) VALUES ($values)"; 954 case DB_AUTOQUERY_UPDATE: 955 $set = ''; 956 foreach ($table_fields as $value) { 957 if ($first) { 958 $first = false; 959 } else { 960 $set .= ','; 961 } 962 $set .= "$value = ?"; 963 } 964 $sql = "UPDATE $table SET $set"; 965 if ($where) { 966 $sql .= " WHERE $where"; 967 } 968 return $sql; 969 default: 970 return $this->raiseError(DB_ERROR_SYNTAX); 971 } 972 } 973 974 // }}} 975 // {{{ execute() 976 977 /** 978 * Executes a DB statement prepared with prepare() 979 * 980 * Example 1. 981 * <code> 982 * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); 983 * $data = array( 984 * "John's text", 985 * "'it''s good'", 986 * 'filename.txt' 987 * ); 988 * $res =& $db->execute($sth, $data); 989 * </code> 990 * 991 * @param resource $stmt a DB statement resource returned from prepare() 992 * @param mixed $data array, string or numeric data to be used in 993 * execution of the statement. Quantity of items 994 * passed must match quantity of placeholders in 995 * query: meaning 1 placeholder for non-array 996 * parameters or 1 placeholder per array element. 997 * 998 * @return mixed a new DB_result object for successful SELECT queries 999 * or DB_OK for successul data manipulation queries. 1000 * A DB_Error object on failure. 1001 * 1002 * {@internal ibase and oci8 have their own execute() methods.}} 1003 * 1004 * @see DB_common::prepare() 1005 */ 1006 function &execute($stmt, $data = array()) 1007 { 1008 $realquery = $this->executeEmulateQuery($stmt, $data); 1009 if (DB::isError($realquery)) { 1010 return $realquery; 1011 } 1012 $result = $this->simpleQuery($realquery); 1013 1014 if ($result === DB_OK || DB::isError($result)) { 1015 return $result; 1016 } else { 1017 $tmp =& new DB_result($this, $result); 1018 return $tmp; 1019 } 1020 } 1021 1022 // }}} 1023 // {{{ executeEmulateQuery() 1024 1025 /** 1026 * Emulates executing prepared statements if the DBMS not support them 1027 * 1028 * @param resource $stmt a DB statement resource returned from execute() 1029 * @param mixed $data array, string or numeric data to be used in 1030 * execution of the statement. Quantity of items 1031 * passed must match quantity of placeholders in 1032 * query: meaning 1 placeholder for non-array 1033 * parameters or 1 placeholder per array element. 1034 * 1035 * @return mixed a string containing the real query run when emulating 1036 * prepare/execute. A DB_Error object on failure. 1037 * 1038 * @access protected 1039 * @see DB_common::execute() 1040 */ 1041 function executeEmulateQuery($stmt, $data = array()) 1042 { 1043 $stmt = (int)$stmt; 1044 $data = (array)$data; 1045 $this->last_parameters = $data; 1046 1047 if (count($this->prepare_types[$stmt]) != count($data)) { 1048 $this->last_query = $this->prepared_queries[$stmt]; 1049 return $this->raiseError(DB_ERROR_MISMATCH); 1050 } 1051 1052 $realquery = $this->prepare_tokens[$stmt][0]; 1053 1054 $i = 0; 1055 foreach ($data as $value) { 1056 if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) { 1057 $realquery .= $this->quoteSmart($value); 1058 } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) { 1059 $fp = @fopen($value, 'rb'); 1060 if (!$fp) { 1061 return $this->raiseError(DB_ERROR_ACCESS_VIOLATION); 1062 } 1063 $realquery .= $this->quoteSmart(fread($fp, filesize($value))); 1064 fclose($fp); 1065 } else { 1066 $realquery .= $value; 1067 } 1068 1069 $realquery .= $this->prepare_tokens[$stmt][++$i]; 1070 } 1071 1072 return $realquery; 1073 } 1074 1075 // }}} 1076 // {{{ executeMultiple() 1077 1078 /** 1079 * Performs several execute() calls on the same statement handle 1080 * 1081 * $data must be an array indexed numerically 1082 * from 0, one execute call is done for every "row" in the array. 1083 * 1084 * If an error occurs during execute(), executeMultiple() does not 1085 * execute the unfinished rows, but rather returns that error. 1086 * 1087 * @param resource $stmt query handle from prepare() 1088 * @param array $data numeric array containing the 1089 * data to insert into the query 1090 * 1091 * @return int DB_OK on success. A DB_Error object on failure. 1092 * 1093 * @see DB_common::prepare(), DB_common::execute() 1094 */ 1095 function executeMultiple($stmt, $data) 1096 { 1097 foreach ($data as $value) { 1098 $res =& $this->execute($stmt, $value); 1099 if (DB::isError($res)) { 1100 return $res; 1101 } 1102 } 1103 return DB_OK; 1104 } 1105 1106 // }}} 1107 // {{{ freePrepared() 1108 1109 /** 1110 * Frees the internal resources associated with a prepared query 1111 * 1112 * @param resource $stmt the prepared statement's PHP resource 1113 * @param bool $free_resource should the PHP resource be freed too? 1114 * Use false if you need to get data 1115 * from the result set later. 1116 * 1117 * @return bool TRUE on success, FALSE if $result is invalid 1118 * 1119 * @see DB_common::prepare() 1120 */ 1121 function freePrepared($stmt, $free_resource = true) 1122 { 1123 $stmt = (int)$stmt; 1124 if (isset($this->prepare_tokens[$stmt])) { 1125 unset($this->prepare_tokens[$stmt]); 1126 unset($this->prepare_types[$stmt]); 1127 unset($this->prepared_queries[$stmt]); 1128 return true; 1129 } 1130 return false; 1131 } 1132 1133 // }}} 1134 // {{{ modifyQuery() 1135 1136 /** 1137 * Changes a query string for various DBMS specific reasons 1138 * 1139 * It is defined here to ensure all drivers have this method available. 1140 * 1141 * @param string $query the query string to modify 1142 * 1143 * @return string the modified query string 1144 * 1145 * @access protected 1146 * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(), 1147 * DB_sqlite::modifyQuery() 1148 */ 1149 function modifyQuery($query) 1150 { 1151 return $query; 1152 } 1153 1154 // }}} 1155 // {{{ modifyLimitQuery() 1156 1157 /** 1158 * Adds LIMIT clauses to a query string according to current DBMS standards 1159 * 1160 * It is defined here to assure that all implementations 1161 * have this method defined. 1162 * 1163 * @param string $query the query to modify 1164 * @param int $from the row to start to fetching (0 = the first row) 1165 * @param int $count the numbers of rows to fetch 1166 * @param mixed $params array, string or numeric data to be used in 1167 * execution of the statement. Quantity of items 1168 * passed must match quantity of placeholders in 1169 * query: meaning 1 placeholder for non-array 1170 * parameters or 1 placeholder per array element. 1171 * 1172 * @return string the query string with LIMIT clauses added 1173 * 1174 * @access protected 1175 */ 1176 function modifyLimitQuery($query, $from, $count, $params = array()) 1177 { 1178 return $query; 1179 } 1180 1181 // }}} 1182 // {{{ query() 1183 1184 /** 1185 * Sends a query to the database server 1186 * 1187 * The query string can be either a normal statement to be sent directly 1188 * to the server OR if <var>$params</var> are passed the query can have 1189 * placeholders and it will be passed through prepare() and execute(). 1190 * 1191 * @param string $query the SQL query or the statement to prepare 1192 * @param mixed $params array, string or numeric data to be used in 1193 * execution of the statement. Quantity of items 1194 * passed must match quantity of placeholders in 1195 * query: meaning 1 placeholder for non-array 1196 * parameters or 1 placeholder per array element. 1197 * 1198 * @return mixed a new DB_result object for successful SELECT queries 1199 * or DB_OK for successul data manipulation queries. 1200 * A DB_Error object on failure. 1201 * 1202 * @see DB_result, DB_common::prepare(), DB_common::execute() 1203 */ 1204 function &query($query, $params = array()) 1205 { 1206 if (sizeof($params) > 0) { 1207 $sth = $this->prepare($query); 1208 if (DB::isError($sth)) { 1209 return $sth; 1210 } 1211 $ret =& $this->execute($sth, $params); 1212 $this->freePrepared($sth, false); 1213 return $ret; 1214 } else { 1215 $this->last_parameters = array(); 1216 $result = $this->simpleQuery($query); 1217 if ($result === DB_OK || DB::isError($result)) { 1218 return $result; 1219 } else { 1220 $tmp =& new DB_result($this, $result); 1221 return $tmp; 1222 } 1223 } 1224 } 1225 1226 // }}} 1227 // {{{ limitQuery() 1228 1229 /** 1230 * Generates and executes a LIMIT query 1231 * 1232 * @param string $query the query 1233 * @param intr $from the row to start to fetching (0 = the first row) 1234 * @param int $count the numbers of rows to fetch 1235 * @param mixed $params array, string or numeric data to be used in 1236 * execution of the statement. Quantity of items 1237 * passed must match quantity of placeholders in 1238 * query: meaning 1 placeholder for non-array 1239 * parameters or 1 placeholder per array element. 1240 * 1241 * @return mixed a new DB_result object for successful SELECT queries 1242 * or DB_OK for successul data manipulation queries. 1243 * A DB_Error object on failure. 1244 */ 1245 function &limitQuery($query, $from, $count, $params = array()) 1246 { 1247 $query = $this->modifyLimitQuery($query, $from, $count, $params); 1248 if (DB::isError($query)){ 1249 return $query; 1250 } 1251 $result =& $this->query($query, $params); 1252 if (is_a($result, 'DB_result')) { 1253 $result->setOption('limit_from', $from); 1254 $result->setOption('limit_count', $count); 1255 } 1256 return $result; 1257 } 1258 1259 // }}} 1260 // {{{ getOne() 1261 1262 /** 1263 * Fetches the first column of the first row from a query result 1264 * 1265 * Takes care of doing the query and freeing the results when finished. 1266 * 1267 * @param string $query the SQL query 1268 * @param mixed $params array, string or numeric data to be used in 1269 * execution of the statement. Quantity of items 1270 * passed must match quantity of placeholders in 1271 * query: meaning 1 placeholder for non-array 1272 * parameters or 1 placeholder per array element. 1273 * 1274 * @return mixed the returned value of the query. 1275 * A DB_Error object on failure. 1276 */ 1277 function &getOne($query, $params = array()) 1278 { 1279 $params = (array)$params; 1280 // modifyLimitQuery() would be nice here, but it causes BC issues 1281 if (sizeof($params) > 0) { 1282 $sth = $this->prepare($query); 1283 if (DB::isError($sth)) { 1284 return $sth; 1285 } 1286 $res =& $this->execute($sth, $params); 1287 $this->freePrepared($sth); 1288 } else { 1289 $res =& $this->query($query); 1290 } 1291 1292 if (DB::isError($res)) { 1293 return $res; 1294 } 1295 1296 $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED); 1297 $res->free(); 1298 1299 if ($err !== DB_OK) { 1300 return $err; 1301 } 1302 1303 return $row[0]; 1304 } 1305 1306 // }}} 1307 // {{{ getRow() 1308 1309 /** 1310 * Fetches the first row of data returned from a query result 1311 * 1312 * Takes care of doing the query and freeing the results when finished. 1313 * 1314 * @param string $query the SQL query 1315 * @param mixed $params array, string or numeric data to be used in 1316 * execution of the statement. Quantity of items 1317 * passed must match quantity of placeholders in 1318 * query: meaning 1 placeholder for non-array 1319 * parameters or 1 placeholder per array element. 1320 * @param int $fetchmode the fetch mode to use 1321 * 1322 * @return array the first row of results as an array. 1323 * A DB_Error object on failure. 1324 */ 1325 function &getRow($query, $params = array(), 1326 $fetchmode = DB_FETCHMODE_DEFAULT) 1327 { 1328 // compat check, the params and fetchmode parameters used to 1329 // have the opposite order 1330 if (!is_array($params)) { 1331 if (is_array($fetchmode)) { 1332 if ($params === null) { 1333 $tmp = DB_FETCHMODE_DEFAULT; 1334 } else { 1335 $tmp = $params; 1336 } 1337 $params = $fetchmode; 1338 $fetchmode = $tmp; 1339 } elseif ($params !== null) { 1340 $fetchmode = $params; 1341 $params = array(); 1342 } 1343 } 1344 // modifyLimitQuery() would be nice here, but it causes BC issues 1345 if (sizeof($params) > 0) { 1346 $sth = $this->prepare($query); 1347 if (DB::isError($sth)) { 1348 return $sth; 1349 } 1350 $res =& $this->execute($sth, $params); 1351 $this->freePrepared($sth); 1352 } else { 1353 $res =& $this->query($query); 1354 } 1355 1356 if (DB::isError($res)) { 1357 return $res; 1358 } 1359 1360 $err = $res->fetchInto($row, $fetchmode); 1361 1362 $res->free(); 1363 1364 if ($err !== DB_OK) { 1365 return $err; 1366 } 1367 1368 return $row; 1369 } 1370 1371 // }}} 1372 // {{{ getCol() 1373 1374 /** 1375 * Fetches a single column from a query result and returns it as an 1376 * indexed array 1377 * 1378 * @param string $query the SQL query 1379 * @param mixed $col which column to return (integer [column number, 1380 * starting at 0] or string [column name]) 1381 * @param mixed $params array, string or numeric data to be used in 1382 * execution of the statement. Quantity of items 1383 * passed must match quantity of placeholders in 1384 * query: meaning 1 placeholder for non-array 1385 * parameters or 1 placeholder per array element. 1386 * 1387 * @return array the results as an array. A DB_Error object on failure. 1388 * 1389 * @see DB_common::query() 1390 */ 1391 function &getCol($query, $col = 0, $params = array()) 1392 { 1393 $params = (array)$params; 1394 if (sizeof($params) > 0) { 1395 $sth = $this->prepare($query); 1396 1397 if (DB::isError($sth)) { 1398 return $sth; 1399 } 1400 1401 $res =& $this->execute($sth, $params); 1402 $this->freePrepared($sth); 1403 } else { 1404 $res =& $this->query($query); 1405 } 1406 1407 if (DB::isError($res)) { 1408 return $res; 1409 } 1410 1411 $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC; 1412 1413 if (!is_array($row = $res->fetchRow($fetchmode))) { 1414 $ret = array(); 1415 } else { 1416 if (!array_key_exists($col, $row)) { 1417 $ret =& $this->raiseError(DB_ERROR_NOSUCHFIELD); 1418 } else { 1419 $ret = array($row[$col]); 1420 while (is_array($row = $res->fetchRow($fetchmode))) { 1421 $ret[] = $row[$col]; 1422 } 1423 } 1424 } 1425 1426 $res->free(); 1427 1428 if (DB::isError($row)) { 1429 $ret = $row; 1430 } 1431 1432 return $ret; 1433 } 1434 1435 // }}} 1436 // {{{ getAssoc() 1437 1438 /** 1439 * Fetches an entire query result and returns it as an 1440 * associative array using the first column as the key 1441 * 1442 * If the result set contains more than two columns, the value 1443 * will be an array of the values from column 2-n. If the result 1444 * set contains only two columns, the returned value will be a 1445 * scalar with the value of the second column (unless forced to an 1446 * array with the $force_array parameter). A DB error code is 1447 * returned on errors. If the result set contains fewer than two 1448 * columns, a DB_ERROR_TRUNCATED error is returned. 1449 * 1450 * For example, if the table "mytable" contains: 1451 * 1452 * <pre> 1453 * ID TEXT DATE 1454 * -------------------------------- 1455 * 1 'one' 944679408 1456 * 2 'two' 944679408 1457 * 3 'three' 944679408 1458 * </pre> 1459 * 1460 * Then the call getAssoc('SELECT id,text FROM mytable') returns: 1461 * <pre> 1462 * array( 1463 * '1' => 'one', 1464 * '2' => 'two', 1465 * '3' => 'three', 1466 * ) 1467 * </pre> 1468 * 1469 * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: 1470 * <pre> 1471 * array( 1472 * '1' => array('one', '944679408'), 1473 * '2' => array('two', '944679408'), 1474 * '3' => array('three', '944679408') 1475 * ) 1476 * </pre> 1477 * 1478 * If the more than one row occurs with the same value in the 1479 * first column, the last row overwrites all previous ones by 1480 * default. Use the $group parameter if you don't want to 1481 * overwrite like this. Example: 1482 * 1483 * <pre> 1484 * getAssoc('SELECT category,id,name FROM mytable', false, null, 1485 * DB_FETCHMODE_ASSOC, true) returns: 1486 * 1487 * array( 1488 * '1' => array(array('id' => '4', 'name' => 'number four'), 1489 * array('id' => '6', 'name' => 'number six') 1490 * ), 1491 * '9' => array(array('id' => '4', 'name' => 'number four'), 1492 * array('id' => '6', 'name' => 'number six') 1493 * ) 1494 * ) 1495 * </pre> 1496 * 1497 * Keep in mind that database functions in PHP usually return string 1498 * values for results regardless of the database's internal type. 1499 * 1500 * @param string $query the SQL query 1501 * @param bool $force_array used only when the query returns 1502 * exactly two columns. If true, the values 1503 * of the returned array will be one-element 1504 * arrays instead of scalars. 1505 * @param mixed $params array, string or numeric data to be used in 1506 * execution of the statement. Quantity of 1507 * items passed must match quantity of 1508 * placeholders in query: meaning 1 1509 * placeholder for non-array parameters or 1510 * 1 placeholder per array element. 1511 * @param int $fetchmode the fetch mode to use 1512 * @param bool $group if true, the values of the returned array 1513 * is wrapped in another array. If the same 1514 * key value (in the first column) repeats 1515 * itself, the values will be appended to 1516 * this array instead of overwriting the 1517 * existing values. 1518 * 1519 * @return array the associative array containing the query results. 1520 * A DB_Error object on failure. 1521 */ 1522 function &getAssoc($query, $force_array = false, $params = array(), 1523 $fetchmode = DB_FETCHMODE_DEFAULT, $group = false) 1524 { 1525 $params = (array)$params; 1526 if (sizeof($params) > 0) { 1527 $sth = $this->prepare($query); 1528 1529 if (DB::isError($sth)) { 1530 return $sth; 1531 } 1532 1533 $res =& $this->execute($sth, $params); 1534 $this->freePrepared($sth); 1535 } else { 1536 $res =& $this->query($query); 1537 } 1538 1539 if (DB::isError($res)) { 1540 return $res; 1541 } 1542 if ($fetchmode == DB_FETCHMODE_DEFAULT) { 1543 $fetchmode = $this->fetchmode; 1544 } 1545 $cols = $res->numCols(); 1546 1547 if ($cols < 2) { 1548 $tmp =& $this->raiseError(DB_ERROR_TRUNCATED); 1549 return $tmp; 1550 } 1551 1552 $results = array(); 1553 1554 if ($cols > 2 || $force_array) { 1555 // return array values 1556 // XXX this part can be optimized 1557 if ($fetchmode == DB_FETCHMODE_ASSOC) { 1558 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) { 1559 reset($row); 1560 $key = current($row); 1561 unset($row[key($row)]); 1562 if ($group) { 1563 $results[$key][] = $row; 1564 } else { 1565 $results[$key] = $row; 1566 } 1567 } 1568 } elseif ($fetchmode == DB_FETCHMODE_OBJECT) { 1569 while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) { 1570 $arr = get_object_vars($row); 1571 $key = current($arr); 1572 if ($group) { 1573 $results[$key][] = $row; 1574 } else { 1575 $results[$key] = $row; 1576 } 1577 } 1578 } else { 1579 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { 1580 // we shift away the first element to get 1581 // indices running from 0 again 1582 $key = array_shift($row); 1583 if ($group) { 1584 $results[$key][] = $row; 1585 } else { 1586 $results[$key] = $row; 1587 } 1588 } 1589 } 1590 if (DB::isError($row)) { 1591 $results = $row; 1592 } 1593 } else { 1594 // return scalar values 1595 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { 1596 if ($group) { 1597 $results[$row[0]][] = $row[1]; 1598 } else { 1599 $results[$row[0]] = $row[1]; 1600 } 1601 } 1602 if (DB::isError($row)) { 1603 $results = $row; 1604 } 1605 } 1606 1607 $res->free(); 1608 1609 return $results; 1610 } 1611 1612 // }}} 1613 // {{{ getAll() 1614 1615 /** 1616 * Fetches all of the rows from a query result 1617 * 1618 * @param string $query the SQL query 1619 * @param mixed $params array, string or numeric data to be used in 1620 * execution of the statement. Quantity of 1621 * items passed must match quantity of 1622 * placeholders in query: meaning 1 1623 * placeholder for non-array parameters or 1624 * 1 placeholder per array element. 1625 * @param int $fetchmode the fetch mode to use: 1626 * + DB_FETCHMODE_ORDERED 1627 * + DB_FETCHMODE_ASSOC 1628 * + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED 1629 * + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED 1630 * 1631 * @return array the nested array. A DB_Error object on failure. 1632 */ 1633 function &getAll($query, $params = array(), 1634 $fetchmode = DB_FETCHMODE_DEFAULT) 1635 { 1636 // compat check, the params and fetchmode parameters used to 1637 // have the opposite order 1638 if (!is_array($params)) { 1639 if (is_array($fetchmode)) { 1640 if ($params === null) { 1641 $tmp = DB_FETCHMODE_DEFAULT; 1642 } else { 1643 $tmp = $params; 1644 } 1645 $params = $fetchmode; 1646 $fetchmode = $tmp; 1647 } elseif ($params !== null) { 1648 $fetchmode = $params; 1649 $params = array(); 1650 } 1651 } 1652 1653 if (sizeof($params) > 0) { 1654 $sth = $this->prepare($query); 1655 1656 if (DB::isError($sth)) { 1657 return $sth; 1658 } 1659 1660 $res =& $this->execute($sth, $params); 1661 $this->freePrepared($sth); 1662 } else { 1663 $res =& $this->query($query); 1664 } 1665 1666 if ($res === DB_OK || DB::isError($res)) { 1667 return $res; 1668 } 1669 1670 $results = array(); 1671 while (DB_OK === $res->fetchInto($row, $fetchmode)) { 1672 if ($fetchmode & DB_FETCHMODE_FLIPPED) { 1673 foreach ($row as $key => $val) { 1674 $results[$key][] = $val; 1675 } 1676 } else { 1677 $results[] = $row; 1678 } 1679 } 1680 1681 $res->free(); 1682 1683 if (DB::isError($row)) { 1684 $tmp =& $this->raiseError($row); 1685 return $tmp; 1686 } 1687 return $results; 1688 } 1689 1690 // }}} 1691 // {{{ autoCommit() 1692 1693 /** 1694 * Enables or disables automatic commits 1695 * 1696 * @param bool $onoff true turns it on, false turns it off 1697 * 1698 * @return int DB_OK on success. A DB_Error object if the driver 1699 * doesn't support auto-committing transactions. 1700 */ 1701 function autoCommit($onoff = false) 1702 { 1703 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1704 } 1705 1706 // }}} 1707 // {{{ commit() 1708 1709 /** 1710 * Commits the current transaction 1711 * 1712 * @return int DB_OK on success. A DB_Error object on failure. 1713 */ 1714 function commit() 1715 { 1716 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1717 } 1718 1719 // }}} 1720 // {{{ rollback() 1721 1722 /** 1723 * Reverts the current transaction 1724 * 1725 * @return int DB_OK on success. A DB_Error object on failure. 1726 */ 1727 function rollback() 1728 { 1729 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1730 } 1731 1732 // }}} 1733 // {{{ numRows() 1734 1735 /** 1736 * Determines the number of rows in a query result 1737 * 1738 * @param resource $result the query result idenifier produced by PHP 1739 * 1740 * @return int the number of rows. A DB_Error object on failure. 1741 */ 1742 function numRows($result) 1743 { 1744 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1745 } 1746 1747 // }}} 1748 // {{{ affectedRows() 1749 1750 /** 1751 * Determines the number of rows affected by a data maniuplation query 1752 * 1753 * 0 is returned for queries that don't manipulate data. 1754 * 1755 * @return int the number of rows. A DB_Error object on failure. 1756 */ 1757 function affectedRows() 1758 { 1759 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1760 } 1761 1762 // }}} 1763 // {{{ getSequenceName() 1764 1765 /** 1766 * Generates the name used inside the database for a sequence 1767 * 1768 * The createSequence() docblock contains notes about storing sequence 1769 * names. 1770 * 1771 * @param string $sqn the sequence's public name 1772 * 1773 * @return string the sequence's name in the backend 1774 * 1775 * @access protected 1776 * @see DB_common::createSequence(), DB_common::dropSequence(), 1777 * DB_common::nextID(), DB_common::setOption() 1778 */ 1779 function getSequenceName($sqn) 1780 { 1781 return sprintf($this->getOption('seqname_format'), 1782 preg_replace('/[^a-z0-9_.]/i', '_', $sqn)); 1783 } 1784 1785 // }}} 1786 // {{{ nextId() 1787 1788 /** 1789 * Returns the next free id in a sequence 1790 * 1791 * @param string $seq_name name of the sequence 1792 * @param boolean $ondemand when true, the seqence is automatically 1793 * created if it does not exist 1794 * 1795 * @return int the next id number in the sequence. 1796 * A DB_Error object on failure. 1797 * 1798 * @see DB_common::createSequence(), DB_common::dropSequence(), 1799 * DB_common::getSequenceName() 1800 */ 1801 function nextId($seq_name, $ondemand = true) 1802 { 1803 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1804 } 1805 1806 // }}} 1807 // {{{ createSequence() 1808 1809 /** 1810 * Creates a new sequence 1811 * 1812 * The name of a given sequence is determined by passing the string 1813 * provided in the <var>$seq_name</var> argument through PHP's sprintf() 1814 * function using the value from the <var>seqname_format</var> option as 1815 * the sprintf()'s format argument. 1816 * 1817 * <var>seqname_format</var> is set via setOption(). 1818 * 1819 * @param string $seq_name name of the new sequence 1820 * 1821 * @return int DB_OK on success. A DB_Error object on failure. 1822 * 1823 * @see DB_common::dropSequence(), DB_common::getSequenceName(), 1824 * DB_common::nextID() 1825 */ 1826 function createSequence($seq_name) 1827 { 1828 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1829 } 1830 1831 // }}} 1832 // {{{ dropSequence() 1833 1834 /** 1835 * Deletes a sequence 1836 * 1837 * @param string $seq_name name of the sequence to be deleted 1838 * 1839 * @return int DB_OK on success. A DB_Error object on failure. 1840 * 1841 * @see DB_common::createSequence(), DB_common::getSequenceName(), 1842 * DB_common::nextID() 1843 */ 1844 function dropSequence($seq_name) 1845 { 1846 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1847 } 1848 1849 // }}} 1850 // {{{ raiseError() 1851 1852 /** 1853 * Communicates an error and invoke error callbacks, etc 1854 * 1855 * Basically a wrapper for PEAR::raiseError without the message string. 1856 * 1857 * @param mixed integer error code, or a PEAR error object (all 1858 * other parameters are ignored if this parameter is 1859 * an object 1860 * @param int error mode, see PEAR_Error docs 1861 * @param mixed if error mode is PEAR_ERROR_TRIGGER, this is the 1862 * error level (E_USER_NOTICE etc). If error mode is 1863 * PEAR_ERROR_CALLBACK, this is the callback function, 1864 * either as a function name, or as an array of an 1865 * object and method name. For other error modes this 1866 * parameter is ignored. 1867 * @param string extra debug information. Defaults to the last 1868 * query and native error code. 1869 * @param mixed native error code, integer or string depending the 1870 * backend 1871 * 1872 * @return object the PEAR_Error object 1873 * 1874 * @see PEAR_Error 1875 */ 1876 function &raiseError($code = DB_ERROR, $mode = null, $options = null, 1877 $userinfo = null, $nativecode = null) 1878 { 1879 // The error is yet a DB error object 1880 if (is_object($code)) { 1881 // because we the static PEAR::raiseError, our global 1882 // handler should be used if it is set 1883 if ($mode === null && !empty($this->_default_error_mode)) { 1884 $mode = $this->_default_error_mode; 1885 $options = $this->_default_error_options; 1886 } 1887 $tmp = PEAR::raiseError($code, null, $mode, $options, 1888 null, null, true); 1889 return $tmp; 1890 } 1891 1892 if ($userinfo === null) { 1893 $userinfo = $this->last_query; 1894 } 1895 1896 if ($nativecode) { 1897 $userinfo .= ' [nativecode=' . trim($nativecode) . ']'; 1898 } else { 1899 $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']'; 1900 } 1901 1902 $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo, 1903 'DB_Error', true); 1904 return $tmp; 1905 } 1906 1907 // }}} 1908 // {{{ errorNative() 1909 1910 /** 1911 * Gets the DBMS' native error code produced by the last query 1912 * 1913 * @return mixed the DBMS' error code. A DB_Error object on failure. 1914 */ 1915 function errorNative() 1916 { 1917 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1918 } 1919 1920 // }}} 1921 // {{{ errorCode() 1922 1923 /** 1924 * Maps native error codes to DB's portable ones 1925 * 1926 * Uses the <var>$errorcode_map</var> property defined in each driver. 1927 * 1928 * @param string|int $nativecode the error code returned by the DBMS 1929 * 1930 * @return int the portable DB error code. Return DB_ERROR if the 1931 * current driver doesn't have a mapping for the 1932 * $nativecode submitted. 1933 */ 1934 function errorCode($nativecode) 1935 { 1936 if (isset($this->errorcode_map[$nativecode])) { 1937 return $this->errorcode_map[$nativecode]; 1938 } 1939 // Fall back to DB_ERROR if there was no mapping. 1940 return DB_ERROR; 1941 } 1942 1943 // }}} 1944 // {{{ errorMessage() 1945 1946 /** 1947 * Maps a DB error code to a textual message 1948 * 1949 * @param integer $dbcode the DB error code 1950 * 1951 * @return string the error message corresponding to the error code 1952 * submitted. FALSE if the error code is unknown. 1953 * 1954 * @see DB::errorMessage() 1955 */ 1956 function errorMessage($dbcode) 1957 { 1958 return DB::errorMessage($this->errorcode_map[$dbcode]); 1959 } 1960 1961 // }}} 1962 // {{{ tableInfo() 1963 1964 /** 1965 * Returns information about a table or a result set 1966 * 1967 * The format of the resulting array depends on which <var>$mode</var> 1968 * you select. The sample output below is based on this query: 1969 * <pre> 1970 * SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId 1971 * FROM tblFoo 1972 * JOIN tblBar ON tblFoo.fldId = tblBar.fldId 1973 * </pre> 1974 * 1975 * <ul> 1976 * <li> 1977 * 1978 * <kbd>null</kbd> (default) 1979 * <pre> 1980 * [0] => Array ( 1981 * [table] => tblFoo 1982 * [name] => fldId 1983 * [type] => int 1984 * [len] => 11 1985 * [flags] => primary_key not_null 1986 * ) 1987 * [1] => Array ( 1988 * [table] => tblFoo 1989 * [name] => fldPhone 1990 * [type] => string 1991 * [len] => 20 1992 * [flags] => 1993 * ) 1994 * [2] => Array ( 1995 * [table] => tblBar 1996 * [name] => fldId 1997 * [type] => int 1998 * [len] => 11 1999 * [flags] => primary_key not_null 2000 * ) 2001 * </pre> 2002 * 2003 * </li><li> 2004 * 2005 * <kbd>DB_TABLEINFO_ORDER</kbd> 2006 * 2007 * <p>In addition to the information found in the default output, 2008 * a notation of the number of columns is provided by the 2009 * <samp>num_fields</samp> element while the <samp>order</samp> 2010 * element provides an array with the column names as the keys and 2011 * their location index number (corresponding to the keys in the 2012 * the default output) as the values.</p> 2013 * 2014 * <p>If a result set has identical field names, the last one is 2015 * used.</p> 2016 * 2017 * <pre> 2018 * [num_fields] => 3 2019 * [order] => Array ( 2020 * [fldId] => 2 2021 * [fldTrans] => 1 2022 * ) 2023 * </pre> 2024 * 2025 * </li><li> 2026 * 2027 * <kbd>DB_TABLEINFO_ORDERTABLE</kbd> 2028 * 2029 * <p>Similar to <kbd>DB_TABLEINFO_ORDER</kbd> but adds more 2030 * dimensions to the array in which the table names are keys and 2031 * the field names are sub-keys. This is helpful for queries that 2032 * join tables which have identical field names.</p> 2033 * 2034 * <pre> 2035 * [num_fields] => 3 2036 * [ordertable] => Array ( 2037 * [tblFoo] => Array ( 2038 * [fldId] => 0 2039 * [fldPhone] => 1 2040 * ) 2041 * [tblBar] => Array ( 2042 * [fldId] => 2 2043 * ) 2044 * ) 2045 * </pre> 2046 * 2047 * </li> 2048 * </ul> 2049 * 2050 * The <samp>flags</samp> element contains a space separated list 2051 * of extra information about the field. This data is inconsistent 2052 * between DBMS's due to the way each DBMS works. 2053 * + <samp>primary_key</samp> 2054 * + <samp>unique_key</samp> 2055 * + <samp>multiple_key</samp> 2056 * + <samp>not_null</samp> 2057 * 2058 * Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp> 2059 * elements if <var>$result</var> is a table name. The following DBMS's 2060 * provide full information from queries: 2061 * + fbsql 2062 * + mysql 2063 * 2064 * If the 'portability' option has <samp>DB_PORTABILITY_LOWERCASE</samp> 2065 * turned on, the names of tables and fields will be lowercased. 2066 * 2067 * @param object|string $result DB_result object from a query or a 2068 * string containing the name of a table. 2069 * While this also accepts a query result 2070 * resource identifier, this behavior is 2071 * deprecated. 2072 * @param int $mode either unused or one of the tableInfo modes: 2073 * <kbd>DB_TABLEINFO_ORDERTABLE</kbd>, 2074 * <kbd>DB_TABLEINFO_ORDER</kbd> or 2075 * <kbd>DB_TABLEINFO_FULL</kbd> (which does both). 2076 * These are bitwise, so the first two can be 2077 * combined using <kbd>|</kbd>. 2078 * 2079 * @return array an associative array with the information requested. 2080 * A DB_Error object on failure. 2081 * 2082 * @see DB_common::setOption() 2083 */ 2084 function tableInfo($result, $mode = null) 2085 { 2086 /* 2087 * If the DB_<driver> class has a tableInfo() method, that one 2088 * overrides this one. But, if the driver doesn't have one, 2089 * this method runs and tells users about that fact. 2090 */ 2091 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 2092 } 2093 2094 // }}} 2095 // {{{ getTables() 2096 2097 /** 2098 * Lists the tables in the current database 2099 * 2100 * @return array the list of tables. A DB_Error object on failure. 2101 * 2102 * @deprecated Method deprecated some time before Release 1.2 2103 */ 2104 function getTables() 2105 { 2106 return $this->getListOf('tables'); 2107 } 2108 2109 // }}} 2110 // {{{ getListOf() 2111 2112 /** 2113 * Lists internal database information 2114 * 2115 * @param string $type type of information being sought. 2116 * Common items being sought are: 2117 * tables, databases, users, views, functions 2118 * Each DBMS's has its own capabilities. 2119 * 2120 * @return array an array listing the items sought. 2121 * A DB DB_Error object on failure. 2122 */ 2123 function getListOf($type) 2124 { 2125 $sql = $this->getSpecialQuery($type); 2126 if ($sql === null) { 2127 $this->last_query = ''; 2128 return $this->raiseError(DB_ERROR_UNSUPPORTED); 2129 } elseif (is_int($sql) || DB::isError($sql)) { 2130 // Previous error 2131 return $this->raiseError($sql); 2132 } elseif (is_array($sql)) { 2133 // Already the result 2134 return $sql; 2135 } 2136 // Launch this query 2137 return $this->getCol($sql); 2138 } 2139 2140 // }}} 2141 // {{{ getSpecialQuery() 2142 2143 /** 2144 * Obtains the query string needed for listing a given type of objects 2145 * 2146 * @param string $type the kind of objects you want to retrieve 2147 * 2148 * @return string the SQL query string or null if the driver doesn't 2149 * support the object type requested 2150 * 2151 * @access protected 2152 * @see DB_common::getListOf() 2153 */ 2154 function getSpecialQuery($type) 2155 { 2156 return $this->raiseError(DB_ERROR_UNSUPPORTED); 2157 } 2158 2159 // }}} 2160 // {{{ nextQueryIsManip() 2161 2162 /** 2163 * Sets (or unsets) a flag indicating that the next query will be a 2164 * manipulation query, regardless of the usual DB::isManip() heuristics. 2165 * 2166 * @param boolean true to set the flag overriding the isManip() behaviour, 2167 * false to clear it and fall back onto isManip() 2168 * 2169 * @return void 2170 * 2171 * @access public 2172 */ 2173 function nextQueryIsManip($manip) 2174 { 2175 $this->_next_query_manip = $manip; 2176 } 2177 2178 // }}} 2179 // {{{ _checkManip() 2180 2181 /** 2182 * Checks if the given query is a manipulation query. This also takes into 2183 * account the _next_query_manip flag and sets the _last_query_manip flag 2184 * (and resets _next_query_manip) according to the result. 2185 * 2186 * @param string The query to check. 2187 * 2188 * @return boolean true if the query is a manipulation query, false 2189 * otherwise 2190 * 2191 * @access protected 2192 */ 2193 function _checkManip($query) 2194 { 2195 if ($this->_next_query_manip || DB::isManip($query)) { 2196 $this->_last_query_manip = true; 2197 } else { 2198 $this->_last_query_manip = false; 2199 } 2200 $this->_next_query_manip = false; 2201 return $this->_last_query_manip; 2202 $manip = $this->_next_query_manip; 2203 } 2204 2205 // }}} 2206 // {{{ _rtrimArrayValues() 2207 2208 /** 2209 * Right-trims all strings in an array 2210 * 2211 * @param array $array the array to be trimmed (passed by reference) 2212 * 2213 * @return void 2214 * 2215 * @access protected 2216 */ 2217 function _rtrimArrayValues(&$array) 2218 { 2219 foreach ($array as $key => $value) { 2220 if (is_string($value)) { 2221 $array[$key] = rtrim($value); 2222 } 2223 } 2224 } 2225 2226 // }}} 2227 // {{{ _convertNullArrayValuesToEmpty() 2228 2229 /** 2230 * Converts all null values in an array to empty strings 2231 * 2232 * @param array $array the array to be de-nullified (passed by reference) 2233 * 2234 * @return void 2235 * 2236 * @access protected 2237 */ 2238 function _convertNullArrayValuesToEmpty(&$array) 2239 { 2240 foreach ($array as $key => $value) { 2241 if (is_null($value)) { 2242 $array[$key] = ''; 2243 } 2244 } 2245 } 2246 2247 // }}} 2248 } 2249 2250 /* 2251 * Local variables: 2252 * tab-width: 4 2253 * c-basic-offset: 4 2254 * End: 2255 */ 2256 2257 ?>
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 |