| [ 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 // | Authors: Stig Bakken <ssb@php.net> | 17 // | Tomas V.V.Cox <cox@idecnet.com> | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: DB.php,v 1.2 2004/07/20 17:41:40 rodolphe Exp $ 21 // 22 // Database independent query interface. 23 // 24 25 //require_once "PEAR.php"; 26 require_once DOL_DOCUMENT_ROOT."/includes/pear/PEAR.php"; 27 // {{{ constants 28 // {{{ error codes 29 /* 30 * The method mapErrorCode in each DB_dbtype implementation maps 31 * native error codes to one of these. 32 * 33 * If you add an error code here, make sure you also add a textual 34 * version of it in DB::errorMessage(). 35 */ 36 37 define("DB_OK", 1); 38 define("DB_ERROR", -1); 39 define("DB_ERROR_SYNTAX", -2); 40 define("DB_ERROR_CONSTRAINT", -3); 41 define("DB_ERROR_NOT_FOUND", -4); 42 define("DB_ERROR_ALREADY_EXISTS", -5); 43 define("DB_ERROR_UNSUPPORTED", -6); 44 define("DB_ERROR_MISMATCH", -7); 45 define("DB_ERROR_INVALID", -8); 46 define("DB_ERROR_NOT_CAPABLE", -9); 47 define("DB_ERROR_TRUNCATED", -10); 48 define("DB_ERROR_INVALID_NUMBER", -11); 49 define("DB_ERROR_INVALID_DATE", -12); 50 define("DB_ERROR_DIVZERO", -13); 51 define("DB_ERROR_NODBSELECTED", -14); 52 define("DB_ERROR_CANNOT_CREATE", -15); 53 define("DB_ERROR_CANNOT_DELETE", -16); 54 define("DB_ERROR_CANNOT_DROP", -17); 55 define("DB_ERROR_NOSUCHTABLE", -18); 56 define("DB_ERROR_NOSUCHFIELD", -19); 57 define("DB_ERROR_NEED_MORE_DATA", -20); 58 define("DB_ERROR_NOT_LOCKED", -21); 59 define("DB_ERROR_VALUE_COUNT_ON_ROW", -22); 60 define("DB_ERROR_INVALID_DSN", -23); 61 define("DB_ERROR_CONNECT_FAILED", -24); 62 define("DB_ERROR_EXTENSION_NOT_FOUND",-25); 63 define("DB_ERROR_ACCESS_VIOLATION", -26); 64 define("DB_ERROR_NOSUCHDB", -27); 65 66 // }}} 67 // {{{ warning codes 68 /* 69 * Warnings are not detected as errors by DB::isError(), and are not 70 * fatal. You can detect whether an error is in fact a warning with 71 * DB::isWarning(). 72 * 73 * @deprecated 74 */ 75 76 define('DB_WARNING', -1000); 77 define('DB_WARNING_READ_ONLY', -1001); 78 79 // }}} 80 // {{{ prepared statement-related 81 /* 82 * These constants are used when storing information about prepared 83 * statements (using the "prepare" method in DB_dbtype). 84 * 85 * The prepare/execute model in DB is mostly borrowed from the ODBC 86 * extension, in a query the "?" character means a scalar parameter. 87 * There are two extensions though, a "&" character means an opaque 88 * parameter. An opaque parameter is simply a file name, the real 89 * data are in that file (useful for putting uploaded files into your 90 * database and such). The "!" char means a parameter that must be 91 * left as it is. 92 * They modify the quote behavoir: 93 * DB_PARAM_SCALAR (?) => 'original string quoted' 94 * DB_PARAM_OPAQUE (&) => 'string from file quoted' 95 * DB_PARAM_MISC (!) => original string 96 */ 97 98 define('DB_PARAM_SCALAR', 1); 99 define('DB_PARAM_OPAQUE', 2); 100 define('DB_PARAM_MISC', 3); 101 102 // }}} 103 // {{{ binary data-related 104 /* 105 * These constants define different ways of returning binary data 106 * from queries. Again, this model has been borrowed from the ODBC 107 * extension. 108 * 109 * DB_BINMODE_PASSTHRU sends the data directly through to the browser 110 * when data is fetched from the database. 111 * DB_BINMODE_RETURN lets you return data as usual. 112 * DB_BINMODE_CONVERT returns data as well, only it is converted to 113 * hex format, for example the string "123" would become "313233". 114 */ 115 116 define('DB_BINMODE_PASSTHRU', 1); 117 define('DB_BINMODE_RETURN', 2); 118 define('DB_BINMODE_CONVERT', 3); 119 120 // }}} 121 // {{{ fetch modes 122 /** 123 * This is a special constant that tells DB the user hasn't specified 124 * any particular get mode, so the default should be used. 125 */ 126 127 define('DB_FETCHMODE_DEFAULT', 0); 128 129 /** 130 * Column data indexed by numbers, ordered from 0 and up 131 */ 132 133 define('DB_FETCHMODE_ORDERED', 1); 134 135 /** 136 * Column data indexed by column names 137 */ 138 139 define('DB_FETCHMODE_ASSOC', 2); 140 141 /** 142 * Column data as object properties 143 */ 144 145 define('DB_FETCHMODE_OBJECT', 3); 146 147 /** 148 * For multi-dimensional results: normally the first level of arrays 149 * is the row number, and the second level indexed by column number or name. 150 * DB_FETCHMODE_FLIPPED switches this order, so the first level of arrays 151 * is the column name, and the second level the row number. 152 */ 153 154 define('DB_FETCHMODE_FLIPPED', 4); 155 156 /* for compatibility */ 157 158 define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); 159 define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); 160 define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); 161 162 // }}} 163 // {{{ tableInfo() && autoPrepare()-related 164 /** 165 * these are constants for the tableInfo-function 166 * they are bitwised or'ed. so if there are more constants to be defined 167 * in the future, adjust DB_TABLEINFO_FULL accordingly 168 */ 169 170 define('DB_TABLEINFO_ORDER', 1); 171 define('DB_TABLEINFO_ORDERTABLE', 2); 172 define('DB_TABLEINFO_FULL', 3); 173 174 /* 175 * Used by autoPrepare() 176 */ 177 define('DB_AUTOQUERY_INSERT', 1); 178 define('DB_AUTOQUERY_UPDATE', 2); 179 180 // }}} 181 // }}} 182 183 // {{{ class DB 184 /** 185 * The main "DB" class is simply a container class with some static 186 * methods for creating DB objects as well as some utility functions 187 * common to all parts of DB. 188 * 189 * The object model of DB is as follows (indentation means inheritance): 190 * 191 * DB The main DB class. This is simply a utility class 192 * with some "static" methods for creating DB objects as 193 * well as common utility functions for other DB classes. 194 * 195 * DB_common The base for each DB implementation. Provides default 196 * | implementations (in OO lingo virtual methods) for 197 * | the actual DB implementations as well as a bunch of 198 * | query utility functions. 199 * | 200 * +-DB_mysql The DB implementation for MySQL. Inherits DB_common. 201 * When calling DB::factory or DB::connect for MySQL 202 * connections, the object returned is an instance of this 203 * class. 204 * 205 * @package DB 206 * @author Stig Bakken <ssb@php.net> 207 * @since PHP 4.0 208 */ 209 210 class DB 211 { 212 // {{{ &factory() 213 /** 214 * Create a new DB connection object for the specified database 215 * type 216 * 217 * @param string $type database type, for example "mysql" 218 * 219 * @return mixed a newly created DB object, or a DB error code on 220 * error 221 * 222 * access public 223 */ 224 225 function &factory($type) 226 { 227 include_once(DOL_DOCUMENT_ROOT."/includes/pear/DB/$type}.php"); 228 229 $classname = "DB_$type}"; 230 231 if (!class_exists($classname)) { 232 return DOLIPEAR::raiseError(null, DB_ERROR_NOT_FOUND, 233 null, null, null, 'DB_Error', true); 234 } 235 236 @$obj =& new $classname; 237 238 return $obj; 239 } 240 241 // }}} 242 // {{{ &connect() 243 /** 244 * Create a new DB connection object and connect to the specified 245 * database 246 * 247 * @param mixed $dsn "data source name", see the DB::parseDSN 248 * method for a description of the dsn format. Can also be 249 * specified as an array of the format returned by DB::parseDSN. 250 * 251 * @param mixed $options An associative array of option names and 252 * their values. For backwards compatibility, this parameter may 253 * also be a boolean that tells whether the connection should be 254 * persistent. See DB_common::setOption for more information on 255 * connection options. 256 * 257 * @return mixed a newly created DB connection object, or a DB 258 * error object on error 259 * 260 * @see DB::parseDSN 261 * @see DB::isError 262 * @see DB_common::setOption 263 */ 264 function &connect($dsn, $options = false) 265 { 266 if (is_array($dsn)) { 267 $dsninfo = $dsn; 268 } else { 269 $dsninfo = DB::parseDSN($dsn); 270 } 271 $type = $dsninfo["phptype"]; 272 273 if (is_array($options) && isset($options["debug"]) && 274 $options["debug"] >= 2) { 275 // expose php errors with sufficient debug level 276 include_once DOL_DOCUMENT_ROOT."/includes/pear/DB/$type}.php"; 277 } else { 278 include_once DOL_DOCUMENT_ROOT."/includes/pear/DB/$type}.php"; 279 } 280 281 $classname = "DB_$type}"; 282 if (!class_exists($classname)) { 283 return DOLIPEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, 284 "Unable to include the DB/{$type}.php file for `$dsn'", 285 'DB_Error', true); 286 } 287 288 @$obj =& new $classname; 289 290 if (is_array($options)) { 291 foreach ($options as $option => $value) { 292 $test = $obj->setOption($option, $value); 293 if (DB::isError($test)) { 294 return $test; 295 } 296 } 297 } else { 298 $obj->setOption('persistent', $options); 299 } 300 $err = $obj->connect($dsninfo, $obj->getOption('persistent')); 301 if (DB::isError($err)) { 302 $err->addUserInfo($dsn); 303 return $err; 304 } 305 306 return $obj; 307 } 308 309 // }}} 310 // {{{ apiVersion() 311 /** 312 * Return the DB API version 313 * 314 * @return int the DB API version number 315 * 316 * @access public 317 */ 318 function apiVersion() 319 { 320 return 2; 321 } 322 323 // }}} 324 // {{{ isError() 325 /** 326 * Tell whether a result code from a DB method is an error 327 * 328 * @param int $value result code 329 * 330 * @return bool whether $value is an error 331 * 332 * @access public 333 */ 334 function isError($value) 335 { 336 return (is_object($value) && 337 (get_class($value) == 'db_error' || 338 is_subclass_of($value, 'db_error'))); 339 } 340 341 // }}} 342 // {{{ isConnection() 343 /** 344 * Tell whether a value is a DB connection 345 * 346 * @param mixed $value value to test 347 * 348 * @return bool whether $value is a DB connection 349 * 350 * @access public 351 */ 352 function isConnection($value) 353 { 354 return (is_object($value) && 355 is_subclass_of($value, 'db_common') && 356 method_exists($value, 'simpleQuery')); 357 } 358 359 // }}} 360 // {{{ isManip() 361 /** 362 * Tell whether a query is a data manipulation query (insert, 363 * update or delete) or a data definition query (create, drop, 364 * alter, grant, revoke). 365 * 366 * @access public 367 * 368 * @param string $query the query 369 * 370 * @return boolean whether $query is a data manipulation query 371 */ 372 function isManip($query) 373 { 374 $manips = 'INSERT|UPDATE|DELETE|'.'REPLACE|CREATE|DROP|'. 375 'ALTER|GRANT|REVOKE|'.'LOCK|UNLOCK'; 376 if (preg_match('/^\s*"?('.$manips.')\s+/i', $query)) { 377 return true; 378 } 379 return false; 380 } 381 382 // }}} 383 // {{{ errorMessage() 384 /** 385 * Return a textual error message for a DB error code 386 * 387 * @param integer $value error code 388 * 389 * @return string error message, or false if the error code was 390 * not recognized 391 */ 392 function errorMessage($value) 393 { 394 static $errorMessages; 395 if (!isset($errorMessages)) { 396 $errorMessages = array( 397 DB_ERROR => 'unknown error', 398 DB_ERROR_ALREADY_EXISTS => 'already exists', 399 DB_ERROR_CANNOT_CREATE => 'can not create', 400 DB_ERROR_CANNOT_DELETE => 'can not delete', 401 DB_ERROR_CANNOT_DROP => 'can not drop', 402 DB_ERROR_CONSTRAINT => 'constraint violation', 403 DB_ERROR_DIVZERO => 'division by zero', 404 DB_ERROR_INVALID => 'invalid', 405 DB_ERROR_INVALID_DATE => 'invalid date or time', 406 DB_ERROR_INVALID_NUMBER => 'invalid number', 407 DB_ERROR_MISMATCH => 'mismatch', 408 DB_ERROR_NODBSELECTED => 'no database selected', 409 DB_ERROR_NOSUCHFIELD => 'no such field', 410 DB_ERROR_NOSUCHTABLE => 'no such table', 411 DB_ERROR_NOT_CAPABLE => 'DB backend not capable', 412 DB_ERROR_NOT_FOUND => 'not found', 413 DB_ERROR_NOT_LOCKED => 'not locked', 414 DB_ERROR_SYNTAX => 'syntax error', 415 DB_ERROR_UNSUPPORTED => 'not supported', 416 DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', 417 DB_ERROR_INVALID_DSN => 'invalid DSN', 418 DB_ERROR_CONNECT_FAILED => 'connect failed', 419 DB_OK => 'no error', 420 DB_WARNING => 'unknown warning', 421 DB_WARNING_READ_ONLY => 'read only', 422 DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', 423 DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', 424 DB_ERROR_NOSUCHDB => 'no such database', 425 DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', 426 DB_ERROR_TRUNCATED => 'truncated' 427 ); 428 } 429 430 if (DB::isError($value)) { 431 $value = $value->getCode(); 432 } 433 434 return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[DB_ERROR]; 435 } 436 437 // }}} 438 // {{{ parseDSN() 439 /** 440 * Parse a data source name 441 * 442 * A array with the following keys will be returned: 443 * phptype: Database backend used in PHP (mysql, odbc etc.) 444 * dbsyntax: Database used with regards to SQL syntax etc. 445 * protocol: Communication protocol to use (tcp, unix etc.) 446 * hostspec: Host specification (hostname[:port]) 447 * database: Database to use on the DBMS server 448 * username: User name for login 449 * password: Password for login 450 * 451 * The format of the supplied DSN is in its fullest form: 452 * 453 * phptype(dbsyntax)://username:password@protocol+hostspec/database 454 * 455 * Most variations are allowed: 456 * 457 * phptype://username:password@protocol+hostspec:110//usr/db_file.db 458 * phptype://username:password@hostspec/database_name 459 * phptype://username:password@hostspec 460 * phptype://username@hostspec 461 * phptype://hostspec/database 462 * phptype://hostspec 463 * phptype(dbsyntax) 464 * phptype 465 * 466 * @param string $dsn Data Source Name to be parsed 467 * 468 * @return array an associative array 469 * 470 * @author Tomas V.V.Cox <cox@idecnet.com> 471 */ 472 function parseDSN($dsn) 473 { 474 if (is_array($dsn)) { 475 return $dsn; 476 } 477 478 $parsed = array( 479 'phptype' => false, 480 'dbsyntax' => false, 481 'username' => false, 482 'password' => false, 483 'protocol' => false, 484 'hostspec' => false, 485 'port' => false, 486 'socket' => false, 487 'database' => false 488 ); 489 490 // Find phptype and dbsyntax 491 if (($pos = strpos($dsn, '://')) !== false) { 492 $str = substr($dsn, 0, $pos); 493 $dsn = substr($dsn, $pos + 3); 494 } else { 495 $str = $dsn; 496 $dsn = NULL; 497 } 498 499 // Get phptype and dbsyntax 500 // $str => phptype(dbsyntax) 501 if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { 502 $parsed['phptype'] = $arr[1]; 503 $parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2]; 504 } else { 505 $parsed['phptype'] = $str; 506 $parsed['dbsyntax'] = $str; 507 } 508 509 if (empty($dsn)) { 510 return $parsed; 511 } 512 513 // Get (if found): username and password 514 // $dsn => username:password@protocol+hostspec/database 515 if (($at = strrpos($dsn,'@')) !== false) { 516 $str = substr($dsn, 0, $at); 517 $dsn = substr($dsn, $at + 1); 518 if (($pos = strpos($str, ':')) !== false) { 519 $parsed['username'] = rawurldecode(substr($str, 0, $pos)); 520 $parsed['password'] = rawurldecode(substr($str, $pos + 1)); 521 } else { 522 $parsed['username'] = rawurldecode($str); 523 } 524 } 525 526 // Find protocol and hostspec 527 528 // $dsn => proto(proto_opts)/database 529 if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { 530 $proto = $match[1]; 531 $proto_opts = (!empty($match[2])) ? $match[2] : false; 532 $dsn = $match[3]; 533 534 // $dsn => protocol+hostspec/database (old format) 535 } else { 536 if (strpos($dsn, '+') !== false) { 537 list($proto, $dsn) = explode('+', $dsn, 2); 538 } 539 if (strpos($dsn, '/') !== false) { 540 list($proto_opts, $dsn) = explode('/', $dsn, 2); 541 } else { 542 $proto_opts = $dsn; 543 $dsn = null; 544 } 545 } 546 547 // process the different protocol options 548 $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; 549 $proto_opts = rawurldecode($proto_opts); 550 if ($parsed['protocol'] == 'tcp') { 551 if (strpos($proto_opts, ':') !== false) { 552 list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts); 553 } else { 554 $parsed['hostspec'] = $proto_opts; 555 } 556 } elseif ($parsed['protocol'] == 'unix') { 557 $parsed['socket'] = $proto_opts; 558 } 559 560 // Get dabase if any 561 // $dsn => database 562 if (!empty($dsn)) { 563 // /database 564 if (($pos = strpos($dsn, '?')) === false) { 565 $parsed['database'] = $dsn; 566 // /database?param1=value1¶m2=value2 567 } else { 568 $parsed['database'] = substr($dsn, 0, $pos); 569 $dsn = substr($dsn, $pos + 1); 570 if (strpos($dsn, '&') !== false) { 571 $opts = explode('&', $dsn); 572 } else { // database?param1=value1 573 $opts = array($dsn); 574 } 575 foreach ($opts as $opt) { 576 list($key, $value) = explode('=', $opt); 577 if (!isset($parsed[$key])) { // don't allow params overwrite 578 $parsed[$key] = rawurldecode($value); 579 } 580 } 581 } 582 } 583 584 return $parsed; 585 } 586 587 // }}} 588 // {{{ assertExtension() 589 /** 590 * Load a PHP database extension if it is not loaded already. 591 * 592 * @access public 593 * 594 * @param string $name the base name of the extension (without the .so or 595 * .dll suffix) 596 * 597 * @return boolean true if the extension was already or successfully 598 * loaded, false if it could not be loaded 599 */ 600 function assertExtension($name) 601 { 602 if (!extension_loaded($name)) { 603 $dlext = OS_WINDOWS ? '.dll' : '.so'; 604 $dlprefix = OS_WINDOWS ? 'php_' : ''; 605 @dl($dlprefix . $name . $dlext); 606 return extension_loaded($name); 607 } 608 return true; 609 } 610 // }}} 611 } 612 // }}} 613 614 // {{{ class DB_Error 615 /** 616 * DB_Error implements a class for reporting portable database error 617 * messages. 618 * 619 * @package DB 620 * @author Stig Bakken <ssb@php.net> 621 */ 622 class DB_Error extends DOLIPEAR_Error 623 { 624 // {{{ constructor 625 /** 626 * DB_Error constructor. 627 * 628 * @param mixed $code DB error code, or string with error message. 629 * @param integer $mode what "error mode" to operate in 630 * @param integer $level what error level to use for $mode & PEAR_ERROR_TRIGGER 631 * @param mixed $debuginfo additional debug info, such as the last query 632 * 633 * @access public 634 * 635 * @see PEAR_Error 636 */ 637 638 function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, 639 $level = E_USER_NOTICE, $debuginfo = null) 640 { 641 if (is_int($code)) { 642 $this->DOLIPEAR_Error('DB Error: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo); 643 } else { 644 $this->DOLIPEAR_Error("DB Error: $code", DB_ERROR, $mode, $level, $debuginfo); 645 } 646 } 647 // }}} 648 } 649 // }}} 650 651 // {{{ class DB_Result 652 /** 653 * This class implements a wrapper for a DB result set. 654 * A new instance of this class will be returned by the DB implementation 655 * after processing a query that returns data. 656 * 657 * @package DB 658 * @author Stig Bakken <ssb@php.net> 659 */ 660 661 class DB_result 662 { 663 // {{{ properties 664 665 var $dbh; 666 var $result; 667 var $row_counter = null; 668 /** 669 * for limit queries, the row to start fetching 670 * @var integer 671 */ 672 var $limit_from = null; 673 674 /** 675 * for limit queries, the number of rows to fetch 676 * @var integer 677 */ 678 var $limit_count = null; 679 680 // }}} 681 // {{{ constructor 682 /** 683 * DB_result constructor. 684 * @param resource &$dbh DB object reference 685 * @param resource $result result resource id 686 * @param array $options assoc array with optional result options 687 */ 688 689 function DB_result(&$dbh, $result, $options = array()) 690 { 691 $this->dbh = &$dbh; 692 $this->result = $result; 693 foreach ($options as $key => $value) { 694 $this->setOption($key, $value); 695 } 696 $this->limit_type = $dbh->features['limit']; 697 $this->autofree = $dbh->options['autofree']; 698 $this->fetchmode = $dbh->fetchmode; 699 $this->fetchmode_object_class = $dbh->fetchmode_object_class; 700 } 701 702 function setOption($key, $value = null) 703 { 704 switch ($key) { 705 case 'limit_from': 706 $this->limit_from = $value; break; 707 case 'limit_count'; 708 $this->limit_count = $value; break; 709 } 710 } 711 712 // }}} 713 // {{{ fetchRow() 714 /** 715 * Fetch and return a row of data (it uses driver->fetchInto for that) 716 * @param int $fetchmode format of fetched row 717 * @param int $rownum the row number to fetch 718 * 719 * @return array a row of data, NULL on no more rows or PEAR_Error on error 720 * 721 * @access public 722 */ 723 function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null) 724 { 725 if ($fetchmode === DB_FETCHMODE_DEFAULT) { 726 $fetchmode = $this->fetchmode; 727 } 728 if ($fetchmode === DB_FETCHMODE_OBJECT) { 729 $fetchmode = DB_FETCHMODE_ASSOC; 730 $object_class = $this->fetchmode_object_class; 731 } 732 if ($this->limit_from !== null) { 733 if ($this->row_counter === null) { 734 $this->row_counter = $this->limit_from; 735 // Skip rows 736 if ($this->limit_type == false) { 737 $i = 0; 738 while ($i++ < $this->limit_from) { 739 $this->dbh->fetchInto($this->result, $arr, $fetchmode); 740 } 741 } 742 } 743 if ($this->row_counter >= ( 744 $this->limit_from + $this->limit_count)) 745 { 746 if ($this->autofree) { 747 $this->free(); 748 } 749 return null; 750 } 751 if ($this->limit_type == 'emulate') { 752 $rownum = $this->row_counter; 753 } 754 $this->row_counter++; 755 } 756 $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); 757 if ($res === DB_OK) { 758 if (isset($object_class)) { 759 // default mode specified in DB_common::fetchmode_object_class property 760 if ($object_class == 'stdClass') { 761 $arr = (object) $arr; 762 } else { 763 $arr = &new $object_class($arr); 764 } 765 } 766 return $arr; 767 } 768 if ($res == null && $this->autofree) { 769 $this->free(); 770 } 771 return $res; 772 } 773 774 // }}} 775 // {{{ fetchInto() 776 /** 777 * Fetch a row of data into an existing variable. 778 * 779 * @param mixed &$arr reference to data containing the row 780 * @param integer $fetchmod format of fetched row 781 * @param integer $rownum the row number to fetch 782 * 783 * @return mixed DB_OK on success, NULL on no more rows or 784 * a DB_Error object on error 785 * 786 * @access public 787 */ 788 function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null) 789 { 790 if ($fetchmode === DB_FETCHMODE_DEFAULT) { 791 $fetchmode = $this->fetchmode; 792 } 793 if ($fetchmode === DB_FETCHMODE_OBJECT) { 794 $fetchmode = DB_FETCHMODE_ASSOC; 795 $object_class = $this->fetchmode_object_class; 796 } 797 if ($this->limit_from !== null) { 798 if ($this->row_counter === null) { 799 $this->row_counter = $this->limit_from; 800 // Skip rows 801 if ($this->limit_type == false) { 802 $i = 0; 803 while ($i++ < $this->limit_from) { 804 $this->dbh->fetchInto($this->result, $arr, $fetchmode); 805 } 806 } 807 } 808 if ($this->row_counter >= ( 809 $this->limit_from + $this->limit_count)) 810 { 811 if ($this->autofree) { 812 $this->free(); 813 } 814 return null; 815 } 816 if ($this->limit_type == 'emulate') { 817 $rownum = $this->row_counter; 818 } 819 820 $this->row_counter++; 821 } 822 $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); 823 if ($res === DB_OK) { 824 if (isset($object_class)) { 825 // default mode specified in DB_common::fetchmode_object_class property 826 if ($object_class == 'stdClass') { 827 $arr = (object) $arr; 828 } else { 829 $arr = new $object_class($arr); 830 } 831 } 832 return DB_OK; 833 } 834 if ($res == null && $this->autofree) { 835 $this->free(); 836 } 837 return $res; 838 } 839 840 // }}} 841 // {{{ numCols() 842 /** 843 * Get the the number of columns in a result set. 844 * 845 * @return int the number of columns, or a DB error 846 * 847 * @access public 848 */ 849 function numCols() 850 { 851 return $this->dbh->numCols($this->result); 852 } 853 854 // }}} 855 // {{{ numRows() 856 /** 857 * Get the number of rows in a result set. 858 * 859 * @return int the number of rows, or a DB error 860 * 861 * @access public 862 */ 863 function numRows() 864 { 865 return $this->dbh->numRows($this->result); 866 } 867 868 // }}} 869 // {{{ nextResult() 870 /** 871 * Get the next result if a batch of queries was executed. 872 * 873 * @return bool true if a new result is available or false if not. 874 * 875 * @access public 876 */ 877 function nextResult() 878 { 879 return $this->dbh->nextResult($this->result); 880 } 881 882 // }}} 883 // {{{ free() 884 /** 885 * Frees the resources allocated for this result set. 886 * @return int error code 887 * 888 * @access public 889 */ 890 function free() 891 { 892 $err = $this->dbh->freeResult($this->result); 893 if(DB::isError($err)) { 894 return $err; 895 } 896 $this->result = false; 897 return true; 898 } 899 900 // }}} 901 // {{{ tableInfo() 902 /** 903 * @deprecated 904 */ 905 function tableInfo($mode = null) 906 { 907 return $this->dbh->tableInfo($this->result, $mode); 908 } 909 910 // }}} 911 // {{{ getRowCounter() 912 /** 913 * returns the actual row number 914 * @return integer 915 */ 916 function getRowCounter() 917 { 918 return $this->row_counter; 919 } 920 // }}} 921 } 922 // }}} 923 924 // {{{ class DB_Row 925 /** 926 * Pear DB Row Object 927 * @see DB_common::setFetchMode() 928 */ 929 class DB_row 930 { 931 // {{{ constructor 932 /** 933 * constructor 934 * 935 * @param resource row data as array 936 */ 937 function DB_row(&$arr) 938 { 939 for (reset($arr); $key = key($arr); next($arr)) { 940 $this->$key = &$arr[$key]; 941 } 942 } 943 944 // }}} 945 } 946 // }}} 947 948 ?>
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 |
|