| [ Index ] |
|
Code source de Dolibarr 2.0.1 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2003 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: Stig Bakken <ssb@php.net> | 17 // +----------------------------------------------------------------------+ 18 // 19 // $Id: common.php,v 1.2 2004/07/20 17:41:40 rodolphe Exp $ 20 // 21 // Base class for DB implementations. 22 // 23 24 /** 25 * DB_common is a base class for DB implementations, and must be 26 * inherited by all such. 27 */ 28 29 require_once DOL_DOCUMENT_ROOT."/includes/pear/PEAR.php"; 30 31 class DB_common extends DOLIPEAR 32 { 33 // {{{ properties 34 /** 35 * assoc of capabilities for this DB implementation 36 * $features['limit'] => 'emulate' => emulate with fetch row by number 37 * 'alter' => alter the query 38 * false => skip rows 39 * @var array 40 */ 41 var $features; 42 43 /** 44 * assoc mapping native error codes to DB ones 45 * @var array 46 */ 47 var $errorcode_map; 48 49 /** 50 * DB type (mysql, oci8, odbc etc.) 51 * @var string 52 */ 53 var $type; 54 55 /** 56 * @var string 57 */ 58 var $prepare_tokens; 59 60 /** 61 * @var string 62 */ 63 var $prepare_types; 64 65 /** 66 * @var string 67 */ 68 var $prepared_queries; 69 70 /** 71 * @var integer 72 */ 73 var $prepare_maxstmt = 0; 74 75 /** 76 * @var string 77 */ 78 var $last_query = ''; 79 80 /** 81 * @var integer 82 */ 83 var $fetchmode = DB_FETCHMODE_ORDERED; 84 85 /** 86 * @var string 87 */ 88 var $fetchmode_object_class = 'stdClass'; 89 90 /** 91 * $options["persistent"] -> boolean persistent connection true|false? 92 * $options["optimize"] -> string 'performance' or 'portability' 93 * $options["debug"] -> integer numeric debug level 94 * @var array 95 */ 96 var $options = array( 97 'persistent' => false, 98 'optimize' => 'performance', 99 'debug' => 0, 100 'seqname_format' => '%s_seq', 101 'autofree' => false 102 ); 103 104 /** 105 * DB handle 106 * @var resource 107 */ 108 var $dbh; 109 110 // }}} 111 // {{{ toString() 112 /** 113 * String conversation 114 * 115 * @return string 116 * @access private 117 */ 118 function toString() 119 { 120 $info = get_class($this); 121 $info .= ": (phptype=" . $this->phptype . 122 ", dbsyntax=" . $this->dbsyntax . 123 ")"; 124 125 if ($this->connection) { 126 $info .= " [connected]"; 127 } 128 129 return $info; 130 } 131 132 // }}} 133 // {{{ constructor 134 /** 135 * Constructor 136 */ 137 function DB_common() 138 { 139 $this->DOLIPEAR('DB_Error'); 140 $this->features = array(); 141 $this->errorcode_map = array(); 142 $this->fetchmode = DB_FETCHMODE_ORDERED; 143 } 144 145 // }}} 146 // {{{ quoteString() 147 148 /** 149 * Quotes a string so it can be safely used within string delimiters 150 * in a query (preserved for compatibility issues, quote() is preffered). 151 * 152 * @return string quoted string 153 * @access public 154 * @see quote() 155 */ 156 function quoteString($string) 157 { 158 $string = $this->quote($string); 159 if ($string{0} == "'") { 160 return substr($string, 1, -1); 161 } 162 return $string; 163 } 164 165 /** 166 * Quotes a string so it can be safely used in a query. It will return 167 * the string with single quotes around. Other backend quote styles 168 * should override this method. 169 * 170 * @param string $string the input string to quote 171 * 172 * @return string The NULL string or the string quotes 173 * in magic_quote_sybase style 174 */ 175 function quote($string) 176 { 177 return ($string === null) ? 'NULL' : "'".str_replace("'", "''", $string)."'"; 178 } 179 180 // }}} 181 // {{{ provides() 182 183 /** 184 * Tell whether a DB implementation or its backend extension 185 * supports a given feature. 186 * 187 * @param array $feature name of the feature (see the DB class doc) 188 * @return bool whether this DB implementation supports $feature 189 * @access public 190 */ 191 192 function provides($feature) 193 { 194 return $this->features[$feature]; 195 } 196 197 // }}} 198 // {{{ errorCode() 199 200 /** 201 * Map native error codes to DB's portable ones. Requires that 202 * the DB implementation's constructor fills in the $errorcode_map 203 * property. 204 * 205 * @param mixed $nativecode the native error code, as returned by the backend 206 * database extension (string or integer) 207 * 208 * @return int a portable DB error code, or FALSE if this DB 209 * implementation has no mapping for the given error code. 210 * 211 * @access public 212 */ 213 214 function errorCode($nativecode) 215 { 216 if (isset($this->errorcode_map[$nativecode])) { 217 return $this->errorcode_map[$nativecode]; 218 } 219 // Fall back to DB_ERROR if there was no mapping. 220 return DB_ERROR; 221 } 222 223 // }}} 224 // {{{ errorMessage() 225 226 /** 227 * Map a DB error code to a textual message. This is actually 228 * just a wrapper for DB::errorMessage(). 229 * 230 * @param integer $dbcode the DB error code 231 * 232 * @return string the corresponding error message, of FALSE 233 * if the error code was unknown 234 * 235 * @access public 236 */ 237 238 function errorMessage($dbcode) 239 { 240 return DB::errorMessage($this->errorcode_map[$dbcode]); 241 } 242 243 // }}} 244 // {{{ raiseError() 245 246 /** 247 * This method is used to communicate an error and invoke error 248 * callbacks etc. Basically a wrapper for PEAR::raiseError 249 * without the message string. 250 * 251 * @param mixed integer error code, or a PEAR error object (all 252 * other parameters are ignored if this parameter is 253 * an object 254 * 255 * @param int error mode, see PEAR_Error docs 256 * 257 * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the 258 * error level (E_USER_NOTICE etc). If error mode is 259 * PEAR_ERROR_CALLBACK, this is the callback function, 260 * either as a function name, or as an array of an 261 * object and method name. For other error modes this 262 * parameter is ignored. 263 * 264 * @param string Extra debug information. Defaults to the last 265 * query and native error code. 266 * 267 * @param mixed Native error code, integer or string depending the 268 * backend. 269 * 270 * @return object a PEAR error object 271 * 272 * @access public 273 * @see PEAR_Error 274 */ 275 function &raiseError($code = DB_ERROR, $mode = null, $options = null, 276 $userinfo = null, $nativecode = null) 277 { 278 // The error is yet a DB error object 279 if (is_object($code)) { 280 // because we the static PEAR::raiseError, our global 281 // handler should be used if it is set 282 if ($mode === null && !empty($this->_default_error_mode)) { 283 $mode = $this->_default_error_mode; 284 $options = $this->_default_error_options; 285 } 286 return DOLIPEAR::raiseError($code, null, $mode, $options, null, null, true); 287 } 288 289 if ($userinfo === null) { 290 $userinfo = $this->last_query; 291 } 292 293 if ($nativecode) { 294 $userinfo .= " [nativecode=$nativecode]"; 295 } 296 297 return DOLIPEAR::raiseError(null, $code, $mode, $options, $userinfo, 298 'DB_Error', true); 299 } 300 301 // }}} 302 // {{{ setFetchMode() 303 304 /** 305 * Sets which fetch mode should be used by default on queries 306 * on this connection. 307 * 308 * @param integer $fetchmode DB_FETCHMODE_ORDERED or 309 * DB_FETCHMODE_ASSOC, possibly bit-wise OR'ed with 310 * DB_FETCHMODE_FLIPPED. 311 * 312 * @param string $object_class The class of the object 313 * to be returned by the fetch methods when 314 * the DB_FETCHMODE_OBJECT mode is selected. 315 * If no class is specified by default a cast 316 * to object from the assoc array row will be done. 317 * There is also the posibility to use and extend the 318 * 'DB_Row' class. 319 * 320 * @see DB_FETCHMODE_ORDERED 321 * @see DB_FETCHMODE_ASSOC 322 * @see DB_FETCHMODE_FLIPPED 323 * @see DB_FETCHMODE_OBJECT 324 * @see DB_Row::DB_Row() 325 * @access public 326 */ 327 328 function setFetchMode($fetchmode, $object_class = null) 329 { 330 switch ($fetchmode) { 331 case DB_FETCHMODE_OBJECT: 332 if ($object_class) { 333 $this->fetchmode_object_class = $object_class; 334 } 335 case DB_FETCHMODE_ORDERED: 336 case DB_FETCHMODE_ASSOC: 337 $this->fetchmode = $fetchmode; 338 break; 339 default: 340 return $this->raiseError('invalid fetchmode mode'); 341 } 342 } 343 344 // }}} 345 // {{{ setOption() 346 /** 347 * set the option for the db class 348 * 349 * @param string $option option name 350 * @param mixed $value value for the option 351 * 352 * @return mixed DB_OK or DB_Error 353 */ 354 function setOption($option, $value) 355 { 356 if (isset($this->options[$option])) { 357 $this->options[$option] = $value; 358 return DB_OK; 359 } 360 return $this->raiseError("unknown option $option"); 361 } 362 363 // }}} 364 // {{{ getOption() 365 /** 366 * returns the value of an option 367 * 368 * @param string $option option name 369 * 370 * @return mixed the option value 371 */ 372 function getOption($option) 373 { 374 if (isset($this->options[$option])) { 375 return $this->options[$option]; 376 } 377 return $this->raiseError("unknown option $option"); 378 } 379 380 // }}} 381 // {{{ prepare() 382 383 /** 384 * Prepares a query for multiple execution with execute(). 385 * With some database backends, this is emulated. 386 * prepare() requires a generic query as string like 387 * "INSERT INTO numbers VALUES(?,?,?)". The ? are wildcards. 388 * Types of wildcards: 389 * ? - a quoted scalar value, i.e. strings, integers 390 * & - requires a file name, the content of the file 391 * insert into the query (i.e. saving binary data 392 * in a db) 393 * ! - value is inserted 'as is' 394 * 395 * @param string the query to prepare 396 * 397 * @return resource handle for the query 398 * 399 * @access public 400 * @see execute 401 */ 402 403 function prepare($query) 404 { 405 $tokens = split("[\&\?\!]", $query); 406 $token = 0; 407 $types = array(); 408 $qlen = strlen($query); 409 for ($i = 0; $i < $qlen; $i++) { 410 switch ($query[$i]) { 411 case '?': 412 $types[$token++] = DB_PARAM_SCALAR; 413 break; 414 case '&': 415 $types[$token++] = DB_PARAM_OPAQUE; 416 break; 417 case '!': 418 $types[$token++] = DB_PARAM_MISC; 419 break; 420 } 421 } 422 423 $this->prepare_tokens[] = &$tokens; 424 end($this->prepare_tokens); 425 426 $k = key($this->prepare_tokens); 427 $this->prepare_types[$k] = $types; 428 $this->prepared_queries[$k] = &$query; 429 430 return $k; 431 } 432 433 // }}} 434 // {{{ autoPrepare() 435 436 /** 437 * Make automaticaly an insert or update query and call prepare() with it 438 * 439 * @param string $table name of the table 440 * @param array $table_fields ordered array containing the fields names 441 * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE) 442 * @param string $where in case of update queries, this string will be put after the sql WHERE statement 443 * @return resource handle for the query 444 * @see buildManipSQL 445 * @access public 446 */ 447 function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, $where = false) 448 { 449 $query = $this->buildManipSQL($table, $table_fields, $mode, $where); 450 return $this->prepare($query); 451 } 452 453 // {{{ 454 // }}} autoExecute() 455 456 /** 457 * Make automaticaly an insert or update query and call prepare() and execute() with it 458 * 459 * @param string $table name of the table 460 * @param array $fields_values assoc ($key=>$value) where $key is a field name and $value its value 461 * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE) 462 * @param string $where in case of update queries, this string will be put after the sql WHERE statement 463 * @return mixed a new DB_Result or a DB_Error when fail 464 * @see buildManipSQL 465 * @see autoPrepare 466 * @access public 467 */ 468 function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, $where = false) 469 { 470 $sth = $this->autoPrepare($table, array_keys($fields_values), $mode, $where); 471 $ret = $this->execute($sth, array_values($fields_values)); 472 $this->freePrepared($sth); 473 return $ret; 474 475 } 476 477 // {{{ 478 // }}} buildManipSQL() 479 480 /** 481 * Make automaticaly an sql query for prepare() 482 * 483 * Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), DB_AUTOQUERY_INSERT) 484 * will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) 485 * NB : - This belongs more to a SQL Builder class, but this is a simple facility 486 * - Be carefull ! If you don't give a $where param with an UPDATE query, all 487 * the records of the table will be updated ! 488 * 489 * @param string $table name of the table 490 * @param array $table_fields ordered array containing the fields names 491 * @param int $mode type of query to make (DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE) 492 * @param string $where in case of update queries, this string will be put after the sql WHERE statement 493 * @return string sql query for prepare() 494 * @access public 495 */ 496 function buildManipSQL($table, $table_fields, $mode, $where = false) 497 { 498 if (count($table_fields) == 0) { 499 $this->raiseError(DB_ERROR_NEED_MORE_DATA); 500 } 501 $first = true; 502 switch ($mode) { 503 case DB_AUTOQUERY_INSERT: 504 $values = ''; 505 $names = ''; 506 while (list(, $value) = each($table_fields)) { 507 if ($first) { 508 $first = false; 509 } else { 510 $names .= ','; 511 $values .= ','; 512 } 513 $names .= $value; 514 $values .= '?'; 515 } 516 return "INSERT INTO $table ($names) VALUES ($values)"; 517 break; 518 case DB_AUTOQUERY_UPDATE: 519 $set = ''; 520 while (list(, $value) = each($table_fields)) { 521 if ($first) { 522 $first = false; 523 } else { 524 $set .= ','; 525 } 526 $set .= "$value = ?"; 527 } 528 $sql = "UPDATE $table SET $set"; 529 if ($where) { 530 $sql .= " WHERE $where"; 531 } 532 return $sql; 533 break; 534 default: 535 $this->raiseError(DB_ERROR_SYNTAX); 536 } 537 } 538 539 // }}} 540 // {{{ execute() 541 /** 542 * Executes a prepared SQL query 543 * With execute() the generic query of prepare is 544 * assigned with the given data array. The values 545 * of the array inserted into the query in the same 546 * order like the array order 547 * 548 * @param resource $stmt query handle from prepare() 549 * @param array $data numeric array containing the 550 * data to insert into the query 551 * 552 * @return mixed a new DB_Result or a DB_Error when fail 553 * 554 * @access public 555 * @see prepare() 556 */ 557 function &execute($stmt, $data = false) 558 { 559 $realquery = $this->executeEmulateQuery($stmt, $data); 560 if (DB::isError($realquery)) { 561 return $realquery; 562 } 563 $result = $this->simpleQuery($realquery); 564 565 if (DB::isError($result) || $result === DB_OK) { 566 return $result; 567 } else { 568 return new DB_result($this, $result); 569 } 570 } 571 572 // }}} 573 // {{{ executeEmulateQuery() 574 575 /** 576 * Emulates the execute statement, when not supported 577 * 578 * @param resource $stmt query handle from prepare() 579 * @param array $data numeric array containing the 580 * data to insert into the query 581 * 582 * @return mixed a string containing the real query run when emulating 583 * prepare/execute. A DB error code is returned on failure. 584 * 585 * @access private 586 * @see execute() 587 */ 588 589 function executeEmulateQuery($stmt, $data = false) 590 { 591 $p = &$this->prepare_tokens; 592 593 if (!isset($this->prepare_tokens[$stmt]) || 594 !is_array($this->prepare_tokens[$stmt]) || 595 !sizeof($this->prepare_tokens[$stmt])) 596 { 597 return $this->raiseError(DB_ERROR_INVALID); 598 } 599 600 $qq = &$this->prepare_tokens[$stmt]; 601 $qp = sizeof($qq) - 1; 602 603 if ((!$data && $qp > 0) || 604 (!is_array($data) && $qp > 1) || 605 (is_array($data) && $qp > sizeof($data))) 606 { 607 $this->last_query = $this->prepared_queries[$stmt]; 608 return $this->raiseError(DB_ERROR_NEED_MORE_DATA); 609 } 610 611 $realquery = $qq[0]; 612 for ($i = 0; $i < $qp; $i++) { 613 $type = $this->prepare_types[$stmt][$i]; 614 if ($type == DB_PARAM_OPAQUE) { 615 if (is_array($data)) { 616 $fp = fopen($data[$i], 'r'); 617 } else { 618 $fp = fopen($data, 'r'); 619 } 620 621 $pdata = ''; 622 623 if ($fp) { 624 while (($buf = fread($fp, 4096)) != false) { 625 $pdata .= $buf; 626 } 627 fclose($fp); 628 } 629 } else { 630 if (is_array($data)) { 631 $pdata = &$data[$i]; 632 } else { 633 $pdata = &$data; 634 } 635 } 636 637 $realquery .= ($type != DB_PARAM_MISC) ? $this->quote($pdata) : $pdata; 638 $realquery .= $qq[$i + 1]; 639 } 640 641 return $realquery; 642 } 643 644 // }}} 645 // {{{ executeMultiple() 646 647 /** 648 * This function does several execute() calls on the same 649 * statement handle. $data must be an array indexed numerically 650 * from 0, one execute call is done for every "row" in the array. 651 * 652 * If an error occurs during execute(), executeMultiple() does not 653 * execute the unfinished rows, but rather returns that error. 654 * 655 * @param resource $stmt query handle from prepare() 656 * @param array $data numeric array containing the 657 * data to insert into the query 658 * 659 * @return mixed DB_OK or DB_Error 660 * 661 * @access public 662 * @see prepare(), execute() 663 */ 664 665 function executeMultiple( $stmt, &$data ) 666 { 667 for($i = 0; $i < sizeof( $data ); $i++) { 668 $res = $this->execute($stmt, $data[$i]); 669 if (DB::isError($res)) { 670 return $res; 671 } 672 } 673 return DB_OK; 674 } 675 676 // }}} 677 // {{{ freePrepared() 678 679 /* 680 * Free the resource used in a prepared query 681 * 682 * @param $stmt The resurce returned by the prepare() function 683 * @see prepare() 684 */ 685 function freePrepared($stmt) 686 { 687 // Free the internal prepared vars 688 if (isset($this->prepare_tokens[$stmt])) { 689 unset($this->prepare_tokens[$stmt]); 690 unset($this->prepare_types[$stmt]); 691 unset($this->prepared_queries[$stmt]); 692 return true; 693 } 694 return false; 695 } 696 697 // }}} 698 // {{{ modifyQuery() 699 700 /** 701 * This method is used by backends to alter queries for various 702 * reasons. It is defined here to assure that all implementations 703 * have this method defined. 704 * 705 * @param string $query query to modify 706 * 707 * @return the new (modified) query 708 * 709 * @access private 710 */ 711 function modifyQuery($query) { 712 return $query; 713 } 714 715 // }}} 716 // {{{ modifyLimitQuery() 717 /** 718 * This method is used by backends to alter limited queries 719 * 720 * @param string $query query to modify 721 * @param integer $from the row to start to fetching 722 * @param integer $count the numbers of rows to fetch 723 * 724 * @return the new (modified) query 725 * 726 * @access private 727 */ 728 729 function modifyLimitQuery($query, $from, $count) 730 { 731 return $query; 732 } 733 734 // }}} 735 // {{{ query() 736 737 /** 738 * Send a query to the database and return any results with a 739 * DB_result object. 740 * 741 * @access public 742 * 743 * @param string $query the SQL query or the statement to prepare 744 * @param string $params the data to be added to the query 745 * @return mixed a DB_result object or DB_OK on success, a DB 746 * error on failure 747 * 748 * @see DB::isError 749 * @see DB_common::prepare 750 * @see DB_common::execute 751 */ 752 function &query($query, $params = array()) { 753 if (sizeof($params) > 0) { 754 $sth = $this->prepare($query); 755 if (DB::isError($sth)) { 756 return $sth; 757 } 758 $ret = $this->execute($sth, $params); 759 $this->freePrepared($sth); 760 return $ret; 761 } else { 762 $result = $this->simpleQuery($query); 763 if (DB::isError($result) || $result === DB_OK) { 764 return $result; 765 } else { 766 return new DB_result($this, $result); 767 } 768 } 769 } 770 771 // }}} 772 // {{{ limitQuery() 773 /** 774 * Generates a limited query 775 * 776 * @param string $query query 777 * @param integer $from the row to start to fetching 778 * @param integer $count the numbers of rows to fetch 779 * @param array $params required for a statement 780 * 781 * @return mixed a DB_Result object, DB_OK or a DB_Error 782 * 783 * @access public 784 */ 785 function &limitQuery($query, $from, $count, $params = array()) 786 { 787 $query = $this->modifyLimitQuery($query, $from, $count); 788 $result = $this->query($query, $params); 789 if (get_class($result) == 'db_result') { 790 $result->setOption('limit_from', $from); 791 $result->setOption('limit_count', $count); 792 } 793 return $result; 794 } 795 796 // }}} 797 // {{{ getOne() 798 799 /** 800 * Fetch the first column of the first row of data returned from 801 * a query. Takes care of doing the query and freeing the results 802 * when finished. 803 * 804 * @param string $query the SQL query 805 * @param array $params if supplied, prepare/execute will be used 806 * with this array as execute parameters 807 * 808 * @return mixed DB_Error or the returned value of the query 809 * 810 * @access public 811 */ 812 813 function &getOne($query, $params = array()) 814 { 815 settype($params, "array"); 816 if (sizeof($params) > 0) { 817 $sth = $this->prepare($query); 818 if (DB::isError($sth)) { 819 return $sth; 820 } 821 $res = $this->execute($sth, $params); 822 $this->freePrepared($sth); 823 } else { 824 $res = $this->query($query); 825 } 826 827 if (DB::isError($res)) { 828 return $res; 829 } 830 831 $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED); 832 833 $res->free(); 834 835 if ($err !== DB_OK) { 836 return $err; 837 } 838 839 return $row[0]; 840 } 841 842 // }}} 843 // {{{ getRow() 844 845 /** 846 * Fetch the first row of data returned from a query. Takes care 847 * of doing the query and freeing the results when finished. 848 * 849 * @param string $query the SQL query 850 * @param integer $fetchmode the fetch mode to use 851 * @param array $params array if supplied, prepare/execute will be used 852 * with this array as execute parameters 853 * @access public 854 * @return array the first row of results as an array indexed from 855 * 0, or a DB error code. 856 */ 857 858 function &getRow($query, 859 $params = null, 860 $fetchmode = DB_FETCHMODE_DEFAULT) 861 { 862 // compat check, the params and fetchmode parameters used to 863 // have the opposite order 864 if (!is_array($params)) { 865 if (is_array($fetchmode)) { 866 $tmp = $params; 867 $params = $fetchmode; 868 $fetchmode = $tmp; 869 } elseif ($params !== null) { 870 $fetchmode = $params; 871 $params = null; 872 } 873 } 874 $params = (empty($params)) ? array() : $params; 875 $fetchmode = (empty($fetchmode)) ? DB_FETCHMODE_DEFAULT : $fetchmode; 876 settype($params, 'array'); 877 if (sizeof($params) > 0) { 878 $sth = $this->prepare($query); 879 if (DB::isError($sth)) { 880 return $sth; 881 } 882 $res = $this->execute($sth, $params); 883 $this->freePrepared($sth); 884 } else { 885 $res = $this->query($query); 886 } 887 888 if (DB::isError($res)) { 889 return $res; 890 } 891 892 $err = $res->fetchInto($row, $fetchmode); 893 894 $res->free(); 895 896 if ($err !== DB_OK) { 897 return $err; 898 } 899 900 return $row; 901 } 902 903 // }}} 904 // {{{ getCol() 905 906 /** 907 * Fetch a single column from a result set and return it as an 908 * indexed array. 909 * 910 * @param string $query the SQL query 911 * 912 * @param mixed $col which column to return (integer [column number, 913 * starting at 0] or string [column name]) 914 * 915 * @param array $params array if supplied, prepare/execute will be used 916 * with this array as execute parameters 917 * @access public 918 * 919 * @return array an indexed array with the data from the first 920 * row at index 0, or a DB error code. 921 */ 922 923 function &getCol($query, $col = 0, $params = array()) 924 { 925 settype($params, "array"); 926 if (sizeof($params) > 0) { 927 $sth = $this->prepare($query); 928 929 if (DB::isError($sth)) { 930 return $sth; 931 } 932 933 $res = $this->execute($sth, $params); 934 $this->freePrepared($sth); 935 } else { 936 $res = $this->query($query); 937 } 938 939 if (DB::isError($res)) { 940 return $res; 941 } 942 943 $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC; 944 $ret = array(); 945 946 while (is_array($row = $res->fetchRow($fetchmode))) { 947 $ret[] = $row[$col]; 948 } 949 950 $res->free(); 951 952 if (DB::isError($row)) { 953 $ret = $row; 954 } 955 956 return $ret; 957 } 958 959 // }}} 960 // {{{ getAssoc() 961 962 /** 963 * Fetch the entire result set of a query and return it as an 964 * associative array using the first column as the key. 965 * 966 * If the result set contains more than two columns, the value 967 * will be an array of the values from column 2-n. If the result 968 * set contains only two columns, the returned value will be a 969 * scalar with the value of the second column (unless forced to an 970 * array with the $force_array parameter). A DB error code is 971 * returned on errors. If the result set contains fewer than two 972 * columns, a DB_ERROR_TRUNCATED error is returned. 973 * 974 * For example, if the table "mytable" contains: 975 * 976 * ID TEXT DATE 977 * -------------------------------- 978 * 1 'one' 944679408 979 * 2 'two' 944679408 980 * 3 'three' 944679408 981 * 982 * Then the call getAssoc('SELECT id,text FROM mytable') returns: 983 * array( 984 * '1' => 'one', 985 * '2' => 'two', 986 * '3' => 'three', 987 * ) 988 * 989 * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: 990 * array( 991 * '1' => array('one', '944679408'), 992 * '2' => array('two', '944679408'), 993 * '3' => array('three', '944679408') 994 * ) 995 * 996 * If the more than one row occurs with the same value in the 997 * first column, the last row overwrites all previous ones by 998 * default. Use the $group parameter if you don't want to 999 * overwrite like this. Example: 1000 * 1001 * getAssoc('SELECT category,id,name FROM mytable', false, null, 1002 * DB_FETCHMODE_ASSOC, true) returns: 1003 * array( 1004 * '1' => array(array('id' => '4', 'name' => 'number four'), 1005 * array('id' => '6', 'name' => 'number six') 1006 * ), 1007 * '9' => array(array('id' => '4', 'name' => 'number four'), 1008 * array('id' => '6', 'name' => 'number six') 1009 * ) 1010 * ) 1011 * 1012 * Keep in mind that database functions in PHP usually return string 1013 * values for results regardless of the database's internal type. 1014 * 1015 * @param string $query the SQL query 1016 * 1017 * @param boolean $force_array used only when the query returns 1018 * exactly two columns. If true, the values of the returned array 1019 * will be one-element arrays instead of scalars. 1020 * 1021 * @param array $params array if supplied, prepare/execute will be used 1022 * with this array as execute parameters 1023 * 1024 * @param boolean $group if true, the values of the returned array 1025 * is wrapped in another array. If the same 1026 * key value (in the first column) repeats 1027 * itself, the values will be appended to 1028 * this array instead of overwriting the 1029 * existing values. 1030 * 1031 * @access public 1032 * 1033 * @return array associative array with results from the query. 1034 */ 1035 1036 function &getAssoc($query, $force_array = false, $params = array(), 1037 $fetchmode = DB_FETCHMODE_ORDERED, $group = false) 1038 { 1039 settype($params, "array"); 1040 if (sizeof($params) > 0) { 1041 $sth = $this->prepare($query); 1042 1043 if (DB::isError($sth)) { 1044 return $sth; 1045 } 1046 1047 $res = $this->execute($sth, $params); 1048 $this->freePrepared($sth); 1049 } else { 1050 $res = $this->query($query); 1051 } 1052 1053 if (DB::isError($res)) { 1054 return $res; 1055 } 1056 1057 $cols = $res->numCols(); 1058 1059 if ($cols < 2) { 1060 return $this->raiseError(DB_ERROR_TRUNCATED); 1061 } 1062 1063 $results = array(); 1064 1065 if ($cols > 2 || $force_array) { 1066 // return array values 1067 // XXX this part can be optimized 1068 if ($fetchmode == DB_FETCHMODE_ASSOC) { 1069 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) { 1070 reset($row); 1071 $key = current($row); 1072 unset($row[key($row)]); 1073 if ($group) { 1074 $results[$key][] = $row; 1075 } else { 1076 $results[$key] = $row; 1077 } 1078 } 1079 } else { 1080 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { 1081 // we shift away the first element to get 1082 // indices running from 0 again 1083 $key = array_shift($row); 1084 if ($group) { 1085 $results[$key][] = $row; 1086 } else { 1087 $results[$key] = $row; 1088 } 1089 } 1090 } 1091 if (DB::isError($row)) { 1092 $results = $row; 1093 } 1094 } else { 1095 // return scalar values 1096 while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { 1097 if ($group) { 1098 $results[$row[0]][] = $row[1]; 1099 } else { 1100 $results[$row[0]] = $row[1]; 1101 } 1102 } 1103 if (DB::isError($row)) { 1104 $results = $row; 1105 } 1106 } 1107 1108 $res->free(); 1109 1110 return $results; 1111 } 1112 1113 // }}} 1114 // {{{ getAll() 1115 1116 /** 1117 * Fetch all the rows returned from a query. 1118 * 1119 * @param string $query the SQL query 1120 * 1121 * @param array $params array if supplied, prepare/execute will be used 1122 * with this array as execute parameters 1123 * @param integer $fetchmode the fetch mode to use 1124 * 1125 * @access public 1126 * @return array an nested array, or a DB error 1127 */ 1128 1129 function &getAll($query, 1130 $params = null, 1131 $fetchmode = DB_FETCHMODE_DEFAULT) 1132 { 1133 // compat check, the params and fetchmode parameters used to 1134 // have the opposite order 1135 if (!is_array($params)) { 1136 if (is_array($fetchmode)) { 1137 $tmp = $params; 1138 $params = $fetchmode; 1139 $fetchmode = $tmp; 1140 } elseif ($params !== null) { 1141 $fetchmode = $params; 1142 $params = null; 1143 } 1144 } 1145 $params = (empty($params)) ? array() : $params; 1146 $fetchmode = (empty($fetchmode)) ? DB_FETCHMODE_DEFAULT : $fetchmode; 1147 settype($params, "array"); 1148 if (sizeof($params) > 0) { 1149 $sth = $this->prepare($query); 1150 1151 if (DB::isError($sth)) { 1152 return $sth; 1153 } 1154 1155 $res = $this->execute($sth, $params); 1156 $this->freePrepared($sth); 1157 } else { 1158 $res = $this->query($query); 1159 } 1160 1161 if (DB::isError($res)) { 1162 return $res; 1163 } 1164 1165 $results = array(); 1166 while (DB_OK === $res->fetchInto($row, $fetchmode)) { 1167 if ($fetchmode & DB_FETCHMODE_FLIPPED) { 1168 foreach ($row as $key => $val) { 1169 $results[$key][] = $val; 1170 } 1171 } else { 1172 $results[] = $row; 1173 } 1174 } 1175 1176 $res->free(); 1177 1178 if (DB::isError($row)) { 1179 return $this->raiseError($row); 1180 } 1181 return $results; 1182 } 1183 1184 // }}} 1185 // {{{ autoCommit() 1186 /** 1187 * enable automatic Commit 1188 * 1189 * @param boolean $onoff 1190 * @return mixed DB_Error 1191 * 1192 * @access public 1193 */ 1194 function autoCommit($onoff=false) 1195 { 1196 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1197 } 1198 1199 // }}} 1200 // {{{ commit() 1201 /** 1202 * starts a Commit 1203 * 1204 * @return mixed DB_Error 1205 * 1206 * @access public 1207 */ 1208 function commit() 1209 { 1210 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1211 } 1212 1213 // }}} 1214 // {{{ rollback() 1215 /** 1216 * starts a rollback 1217 * 1218 * @return mixed DB_Error 1219 * 1220 * @access public 1221 */ 1222 function rollback() 1223 { 1224 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1225 } 1226 1227 // }}} 1228 // {{{ numRows() 1229 /** 1230 * returns the number of rows in a result object 1231 * 1232 * @param object DB_Result the result object to check 1233 * 1234 * @return mixed DB_Error or the number of rows 1235 * 1236 * @access public 1237 */ 1238 function numRows($result) 1239 { 1240 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1241 } 1242 1243 // }}} 1244 // {{{ affectedRows() 1245 /** 1246 * returns the affected rows of a query 1247 * 1248 * @return mixed DB_Error or number of rows 1249 * 1250 * @access public 1251 */ 1252 function affectedRows() 1253 { 1254 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1255 } 1256 1257 // }}} 1258 // {{{ errorNative() 1259 /** 1260 * returns an errormessage, provides by the database 1261 * 1262 * @return mixed DB_Error or message 1263 * 1264 * @access public 1265 */ 1266 function errorNative() 1267 { 1268 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1269 } 1270 1271 // }}} 1272 // {{{ nextId() 1273 /** 1274 * returns the next free id of a sequence 1275 * 1276 * @param string $seq_name name of the sequence 1277 * @param boolean $ondemand when true the seqence is 1278 * automatic created, if it 1279 * not exists 1280 * 1281 * @return mixed DB_Error or id 1282 */ 1283 function nextId($seq_name, $ondemand = true) 1284 { 1285 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1286 } 1287 1288 // }}} 1289 // {{{ createSequence() 1290 /** 1291 * creates a new sequence 1292 * 1293 * @param string $seq_name name of the new sequence 1294 * 1295 * @return mixed DB_Error 1296 * 1297 * @access public 1298 */ 1299 function createSequence($seq_name) 1300 { 1301 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1302 } 1303 1304 // }}} 1305 // {{{ dropSequence() 1306 /** 1307 * deletes a sequence 1308 * 1309 * @param string $seq_name name of the sequence 1310 * 1311 * @return mixed DB_Error 1312 * 1313 * @access public 1314 */ 1315 function dropSequence($seq_name) 1316 { 1317 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1318 } 1319 1320 // }}} 1321 // {{{ tableInfo() 1322 /** 1323 * returns meta data about the result set 1324 * 1325 * @param object DB_Result $result the result object to analyse 1326 * @param mixed $mode depends on implementation 1327 * 1328 * @return mixed DB_Error 1329 * 1330 * @access public 1331 */ 1332 function tableInfo($result, $mode = null) 1333 { 1334 return $this->raiseError(DB_ERROR_NOT_CAPABLE); 1335 } 1336 1337 // }}} 1338 // {{{ getTables() 1339 /** 1340 * @deprecated 1341 */ 1342 function getTables() 1343 { 1344 return $this->getListOf('tables'); 1345 } 1346 1347 // }}} 1348 // {{{ getListOf() 1349 /** 1350 * list internal DB info 1351 * valid values for $type are db dependent, 1352 * often: databases, users, view, functions 1353 * 1354 * @param string $type type of requested info 1355 * 1356 * @return mixed DB_Error or the requested data 1357 * 1358 * @access public 1359 */ 1360 function getListOf($type) 1361 { 1362 $sql = $this->getSpecialQuery($type); 1363 if ($sql === null) { // No support 1364 return $this->raiseError(DB_ERROR_UNSUPPORTED); 1365 } elseif (is_int($sql) || DB::isError($sql)) { // Previous error 1366 return $this->raiseError($sql); 1367 } elseif (is_array($sql)) { // Already the result 1368 return $sql; 1369 } 1370 return $this->getCol($sql); // Launch this query 1371 } 1372 // }}} 1373 // {{{ getSequenceName() 1374 1375 function getSequenceName($sqn) 1376 { 1377 return sprintf($this->getOption("seqname_format"), 1378 preg_replace('/[^a-z0-9_]/i', '_', $sqn)); 1379 } 1380 1381 // }}} 1382 } 1383 1384 // Used by many drivers 1385 if (!function_exists('array_change_key_case')) { 1386 define('CASE_UPPER', 1); 1387 define('CASE_LOWER', 0); 1388 function &array_change_key_case(&$array, $case) { 1389 $casefunc = ($case == CASE_LOWER) ? 'strtolower' : 'strtoupper'; 1390 $ret = array(); 1391 foreach ($array as $key => $value) { 1392 $ret[$casefunc($key)] = $value; 1393 } 1394 return $ret; 1395 } 1396 } 1397 1398 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 12:29:37 2007 | par Balluche grâce à PHPXref 0.7 |
|