1<?php 2// +----------------------------------------------------------------------+ 3// | PHP Version 4 | 4// +----------------------------------------------------------------------+ 5// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox, | 6// | Stig. S. Bakken, Lukas Smith | 7// | All rights reserved. | 8// +----------------------------------------------------------------------+ 9// | MDB is a merge of PEAR DB and Metabases that provides a unified DB | 10// | API as well as database abstraction for PHP applications. | 11// | This LICENSE is in the BSD license style. | 12// | | 13// | Redistribution and use in source and binary forms, with or without | 14// | modification, are permitted provided that the following conditions | 15// | are met: | 16// | | 17// | Redistributions of source code must retain the above copyright | 18// | notice, this list of conditions and the following disclaimer. | 19// | | 20// | Redistributions in binary form must reproduce the above copyright | 21// | notice, this list of conditions and the following disclaimer in the | 22// | documentation and/or other materials provided with the distribution. | 23// | | 24// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | 25// | Lukas Smith nor the names of his contributors may be used to endorse | 26// | or promote products derived from this software without specific prior| 27// | written permission. | 28// | | 29// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 30// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 31// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 32// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 33// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 34// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 35// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| 36// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 37// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 38// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| 39// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 40// | POSSIBILITY OF SUCH DAMAGE. | 41// +----------------------------------------------------------------------+ 42// | Author: Lukas Smith <smith@backendmedia.com> | 43// +----------------------------------------------------------------------+ 44// 45// $Id: Common.php,v 1.114.4.22 2004/04/08 19:11:58 lsmith Exp $ 46 47/** 48 * @package MDB 49 * @author Lukas Smith <smith@backendmedia.com> 50 */ 51 52// }}} 53// {{{ MDB_defaultDebugOutput() 54 55/** 56 * default debug output handler 57 * 58 * @param object $db reference to an MDB database object 59 * @param string $message message that should be appended to the debug 60 * variable 61 * @return string the corresponding error message, of FALSE 62 * if the error code was unknown 63 * @access public 64 */ 65function MDB_defaultDebugOutput(&$db, $message) 66{ 67 $db->debug_output .= $db->database . " $message" . $db->getOption('log_line_break'); 68} 69 70/** 71 * MDB_Common: Base class that is extended by each MDB driver 72 * 73 * @package MDB 74 * @category Database 75 * @author Lukas Smith <smith@backendmedia.com> 76 */ 77class MDB_Common extends PEAR 78{ 79 // {{{ properties 80 /** 81 * index of the MDB object withing the global $_MDB_databases array 82 * @var integer 83 * @access private 84 */ 85 var $database = 0; 86 87 /** 88 * @var string 89 * @access private 90 */ 91 var $host = ''; 92 93 /** 94 * @var string 95 * @access private 96 */ 97 var $port = ''; 98 99 /** 100 * @var string 101 * @access private 102 */ 103 var $user = ''; 104 105 /** 106 * @var string 107 * @access private 108 */ 109 var $password = ''; 110 111 /** 112 * @var string 113 * @access private 114 */ 115 var $database_name = ''; 116 117 /** 118 * @var array 119 * @access private 120 */ 121 var $supported = array(); 122 123 /** 124 * $options["persistent"] -> boolean persistent connection true|false? 125 * $options["debug"] -> integer numeric debug level 126 * $options["autofree"] -> boolean 127 * $options["lob_buffer_length"] -> integer LOB buffer length 128 * $options["log_line_break"] -> string line-break format 129 * $options["seqname_format"] -> string pattern for sequence name 130 * $options["includelob"] -> boolean 131 * $options["includemanager"] -> boolean 132 * $options["UseTransactions"] -> boolean 133 * $options["optimize"] -> string 'performance' or 'portability' 134 * @var array 135 * @access private 136 */ 137 var $options = array( 138 'persistent' => FALSE, 139 'debug' => FALSE, 140 'autofree' => FALSE, 141 'lob_buffer_length' => 8192, 142 'log_line_break' => "\n", 143 'seqname_format' => '%s_seq', 144 'sequence_col_name' => 'sequence', 145 'includelob' => FALSE, 146 'includemanager' => FALSE, 147 'UseTransactions' => FALSE, 148 'optimize' => 'performance', 149 ); 150 151 /** 152 * @var string 153 * @access private 154 */ 155 var $escape_quotes = ''; 156 157 /** 158 * @var integer 159 * @access private 160 */ 161 var $decimal_places = 2; 162 163 /** 164 * @var string 165 * @access private 166 */ 167 var $manager_included_constant = ''; 168 169 /** 170 * @var string 171 * @access private 172 */ 173 var $manager_include = ''; 174 175 /** 176 * @var string 177 * @access private 178 */ 179 var $manager_class_name = ''; 180 181 /** 182 * @var object 183 * @access private 184 */ 185 var $manager; 186 187 /** 188 * @var array 189 * @access private 190 */ 191 var $warnings = array(); 192 193 /** 194 * @var string 195 * @access private 196 */ 197 var $debug = ''; 198 199 /** 200 * @var string 201 * @access private 202 */ 203 var $debug_output = ''; 204 205 /** 206 * @var boolean 207 * @access private 208 */ 209 var $pass_debug_handle = FALSE; 210 211 /** 212 * @var boolean 213 * @access private 214 */ 215 var $auto_commit = TRUE; 216 217 /** 218 * @var boolean 219 * @access private 220 */ 221 var $in_transaction = FALSE; 222 223 /** 224 * @var integer 225 * @access private 226 */ 227 var $first_selected_row = 0; 228 229 /** 230 * @var integer 231 * @access private 232 */ 233 var $selected_row_limit = 0; 234 235 /** 236 * DB type (mysql, oci8, odbc etc.) 237 * @var string 238 * @access private 239 */ 240 var $type; 241 242 /** 243 * @var array 244 * @access private 245 */ 246 var $prepared_queries = array(); 247 248 /** 249 * @var array 250 * @access private 251 */ 252 var $result_types; 253 254 /** 255 * @var string 256 * @access private 257 */ 258 var $last_query = ''; 259 260 /** 261 * @var integer 262 * @access private 263 */ 264 var $fetchmode = MDB_FETCHMODE_ORDERED; 265 266 /** 267 * @var integer 268 * @access private 269 */ 270 var $affected_rows = -1; 271 272 /** 273 * @var array 274 * @access private 275 */ 276 var $lobs = array(); 277 278 /** 279 * @var array 280 * @access private 281 */ 282 var $clobs = array(); 283 284 /** 285 * @var array 286 * @access private 287 */ 288 var $blobs = array(); 289 290 // }}} 291 // {{{ constructor 292 293 /** 294 * Constructor 295 */ 296 function MDB_Common() 297 { 298 $database = count($GLOBALS['_MDB_databases']) + 1; 299 $GLOBALS['_MDB_databases'][$database] = &$this; 300 $this->database = $database; 301 302 $this->PEAR('MDB_Error'); 303 $this->supported = array(); 304 $this->errorcode_map = array(); 305 $this->fetchmode = MDB_FETCHMODE_ORDERED; 306 } 307 308 // }}} 309 // {{{ __toString() 310 311 /** 312 * String conversation 313 * 314 * @return string 315 * @access public 316 */ 317 function __toString() 318 { 319 $info = get_class($this); 320 $info .= ': (phptype = ' . $this->phptype . ', dbsyntax = ' . $this->dbsyntax . ')'; 321 if ($this->connection) { 322 $info .= ' [connected]'; 323 } 324 return($info); 325 } 326 327 // }}} 328 // {{{ errorCode() 329 330 /** 331 * Map native error codes to MDB's portable ones. Requires that 332 * the DB implementation's constructor fills in the $errorcode_map 333 * property. 334 * 335 * @param mixed $nativecode the native error code, as returned by the 336 * backend database extension (string or integer) 337 * @return int a portable MDB error code, or FALSE if this MDB 338 * implementation has no mapping for the given error code. 339 * @access public 340 */ 341 function errorCode($nativecode) 342 { 343 if (isset($this->errorcode_map[$nativecode])) { 344 return($this->errorcode_map[$nativecode]); 345 } 346 // Fall back to MDB_ERROR if there was no mapping. 347 return(MDB_ERROR); 348 } 349 350 // }}} 351 // {{{ errorMessage() 352 353 /** 354 * Map a MDB error code to a textual message. This is actually 355 * just a wrapper for MDB::errorMessage(). 356 * 357 * @param integer $dbcode the MDB error code 358 * @return string the corresponding error message, of FALSE 359 * if the error code was unknown 360 * @access public 361 */ 362 function errorMessage($dbcode) 363 { 364 return(MDB::errorMessage($this->errorcode_map[$dbcode])); 365 } 366 367 // }}} 368 // {{{ raiseError() 369 370 /** 371 * This method is used to communicate an error and invoke error 372 * callbacks etc. Basically a wrapper for PEAR::raiseError 373 * without the message string. 374 * 375 * @param mixed $code integer error code, or a PEAR error object (all 376 * other parameters are ignored if this parameter is an object 377 * @param int $mode error mode, see PEAR_Error docs 378 * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the 379 * error level (E_USER_NOTICE etc). If error mode is 380 * PEAR_ERROR_CALLBACK, this is the callback function, either as a 381 * function name, or as an array of an object and method name. For 382 * other error modes this parameter is ignored. 383 * @param string $userinfo Extra debug information. Defaults to the last 384 * query and native error code. 385 * @param mixed $nativecode Native error code, integer or string depending 386 * the backend. 387 * @return object a PEAR error object 388 * @access public 389 * @see PEAR_Error 390 */ 391 function &raiseError($code = MDB_ERROR, $mode = NULL, $options = NULL, 392 $userinfo = NULL, $nativecode = NULL) 393 { 394 // The error is yet a MDB error object 395 if (is_object($code)) { 396 // because we the static PEAR::raiseError, our global 397 // handler should be used if it is set 398 if ($mode === null && !empty($this->_default_error_mode)) { 399 $mode = $this->_default_error_mode; 400 $options = $this->_default_error_options; 401 } 402 $err = PEAR::raiseError($code, NULL, $mode, $options, NULL, NULL, TRUE); 403 return($err); 404 } 405 406 if ($userinfo === NULL) { 407 $userinfo = $this->last_query; 408 } 409 410 if ($nativecode) { 411 $userinfo .= ' [nativecode=' . trim($nativecode) . ']'; 412 } 413 414 $err = PEAR::raiseError(NULL, $code, $mode, $options, $userinfo, 'MDB_Error', TRUE); 415 return($err); 416 } 417 418 // }}} 419 // {{{ errorNative() 420 421 /** 422 * returns an errormessage, provides by the database 423 * 424 * @return mixed MDB_Error or message 425 * @access public 426 */ 427 function errorNative() 428 { 429 return($this->raiseError(MDB_ERROR_NOT_CAPABLE)); 430 } 431 432 // }}} 433 // {{{ resetWarnings() 434 435 /** 436 * reset the warning array 437 * 438 * @access public 439 */ 440 function resetWarnings() 441 { 442 $this->warnings = array(); 443 } 444 445 // }}} 446 // {{{ getWarnings() 447 448 /** 449 * get all warnings in reverse order. 450 * This means that the last warning is the first element in the array 451 * 452 * @return array with warnings 453 * @access public 454 * @see resetWarnings() 455 */ 456 function getWarnings() 457 { 458 return array_reverse($this->warnings); 459 } 460 461 // }}} 462 // {{{ setOption() 463 464 /** 465 * set the option for the db class 466 * 467 * @param string $option option name 468 * @param mixed $value value for the option 469 * @return mixed MDB_OK or MDB_Error 470 * @access public 471 */ 472 function setOption($option, $value) 473 { 474 if (isset($this->options[$option])) { 475 $this->options[$option] = $value; 476 return MDB_OK; 477 } 478 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option")); 479 } 480 481 // }}} 482 // {{{ getOption() 483 484 /** 485 * returns the value of an option 486 * 487 * @param string $option option name 488 * @return mixed the option value or error object 489 * @access public 490 */ 491 function getOption($option) 492 { 493 if (isset($this->options[$option])) { 494 return($this->options[$option]); 495 } 496 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option")); 497 } 498 499 // }}} 500 // {{{ captureDebugOutput() 501 502 /** 503 * set a debug handler 504 * 505 * @param string $capture name of the function that should be used in 506 * debug() 507 * @access public 508 * @see debug() 509 */ 510 function captureDebugOutput($capture) 511 { 512 $this->pass_debug_handle = $capture; 513 $this->debug = ($capture ? 'MDB_defaultDebugOutput' : ''); 514 } 515 516 // }}} 517 // {{{ debug() 518 519 /** 520 * set a debug message 521 * 522 * @param string $message Message with information for the user. 523 * @access public 524 */ 525 function debug($message) 526 { 527 if (strcmp($function = $this->debug, '')) { 528 if ($this->pass_debug_handle) { 529 $function($this, $message); 530 } else { 531 $function($message); 532 } 533 } 534 } 535 536 // }}} 537 // {{{ debugOutput() 538 539 /** 540 * output debug info 541 * 542 * @return string content of the debug_output class variable 543 * @access public 544 */ 545 function debugOutput() 546 { 547 return($this->debug_output); 548 } 549 550 // }}} 551 // {{{ setError() (deprecated) 552 553 /** 554 * set an error (deprecated) 555 * 556 * @param string $scope Scope of the error message 557 * (usually the method tht caused the error) 558 * @param string $message Message with information for the user. 559 * @return boolean FALSE 560 * @access private 561 */ 562 function setError($scope, $message) 563 { 564 $this->last_error = $message; 565 $this->debug($scope . ': ' . $message); 566 if (($function = $this->error_handler) != '') { 567 $error = array( 568 'Scope' => $scope, 569 'Message' => $message 570 ); 571 $function($this, $error); 572 } 573 return(0); 574 } 575 576 // }}} 577 // {{{ setErrorHandler() (deprecated) 578 579 /** 580 * Specify a function that is called when an error occurs. 581 * 582 * @param string $function Name of the function that will be called on 583 * error. If an empty string is specified, no handler function is 584 * called on error. The error handler function receives two arguments. 585 * The first argument a reference to the driver class object that 586 * triggered the error. 587 * 588 * The second argument is a reference to an associative array that 589 * provides details about the error that occured. These details provide 590 * more information than it is returned by the MetabaseError function. 591 * 592 * These are the currently supported error detail entries: 593 * 594 * Scope 595 * String that indicates the scope of the driver object class 596 * within which the error occured. 597 * 598 * Message 599 * Error message as is returned by the MetabaseError function. 600 * @return string name of last function 601 * @access public 602 */ 603 function setErrorHandler($function) 604 { 605 $last_function = $this->error_handler; 606 $this->error_handler = $function; 607 return($last_function); 608 } 609 610 // }}} 611 // {{{ error() (deprecated) 612 613 /** 614 * Retrieve the error message text associated with the last operation that 615 * failed. Some functions may fail but they do not return the reason that 616 * makes them to fail. This function is meant to retrieve a textual 617 * description of the failure cause. 618 * 619 * @return string the error message text associated with the last failure. 620 * @access public 621 */ 622 function error() 623 { 624 return($this->last_error); 625 } 626 627 // }}} 628 // {{{ _quote() 629 630 /** 631 * Quotes a string so it can be safely used in a query. It will quote 632 * the text so it can safely be used within a query. 633 * 634 * @param string $text the input string to quote 635 * @return string quoted string 636 * @access private 637 */ 638 function _quote($text) 639 { 640 if (strcmp($this->escape_quotes, "'")) { 641 $text = str_replace($this->escape_quotes, $this->escape_quotes . $this->escape_quotes, $text); 642 } 643 return str_replace("'", $this->escape_quotes . "'", $text); 644 } 645 646 // }}} 647 // {{{ quoteIdentifier() 648 649 /** 650 * Quote a string so it can be safely used as a table or column name 651 * 652 * Delimiting style depends on which database driver is being used. 653 * 654 * NOTE: just because you CAN use delimited identifiers doesn't mean 655 * you SHOULD use them. In general, they end up causing way more 656 * problems than they solve. 657 * 658 * Portability is broken by using the following characters inside 659 * delimited identifiers: 660 * + backtick (<kbd>`</kbd>) -- due to MySQL 661 * + double quote (<kbd>"</kbd>) -- due to Oracle 662 * + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access 663 * 664 * Delimited identifiers are known to generally work correctly under 665 * the following drivers: 666 * + mssql 667 * + mysql 668 * + mysqli 669 * + oci8 670 * + odbc(access) 671 * + odbc(db2) 672 * + pgsql 673 * + sqlite 674 * + sybase 675 * 676 * InterBase doesn't seem to be able to use delimited identifiers 677 * via PHP 4. They work fine under PHP 5. 678 * 679 * @param string $str identifier name to be quoted 680 * 681 * @return string quoted identifier string 682 * 683 * @access public 684 */ 685 function quoteIdentifier($str) 686 { 687 return '"' . str_replace('"', '""', $str) . '"'; 688 } 689 690 // }}} 691 // {{{ _loadModule() 692 693 /** 694 * loads an module 695 * 696 * @param string $scope information about what method is being loaded, 697 * that is used for error messages 698 * @param string $module name of the module that should be loaded 699 * (only used for error messages) 700 * @param string $included_constant name of the constant that should be 701 * defined when the module has been loaded 702 * @param string $include name of the script that includes the module 703 * @access private 704 */ 705 function _loadModule($scope, $module, $included_constant, $include) 706 { 707 if (strlen($included_constant) == 0 || !defined($included_constant)) { 708 if($include) { 709 $include = 'MDB/Modules/'.$include; 710 if(MDB::isError($debug = $this->getOption('debug')) || $debug > 2) { 711 include_once($include); 712 } else { 713 @include_once($include); 714 } 715 } else { 716 return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL, 717 $scope . ': it was not specified an existing ' . $module . ' file (' . $include . ')')); 718 } 719 } 720 return(MDB_OK); 721 } 722 723 // }}} 724 // {{{ loadLob() 725 726 /** 727 * loads the LOB module 728 * 729 * @param string $scope information about what method is being loaded, 730 * that is used for error messages 731 * @access public 732 */ 733 function loadLob($scope = '') 734 { 735 if (defined('MDB_LOB_INCLUDED')) { 736 return(MDB_OK); 737 } 738 $result = $this->_loadModule($scope, 'LOB', 739 'MDB_LOB_INCLUDED', 'LOB.php'); 740 if (MDB::isError($result)) { 741 return($result); 742 } 743 return(MDB_OK); 744 } 745 746 // }}} 747 // {{{ loadManager() 748 749 /** 750 * loads the Manager module 751 * 752 * @param string $scope information about what method is being loaded, 753 * that is used for error messages 754 * @access public 755 */ 756 function loadManager($scope = '') 757 { 758 if (isset($this->manager) && is_object($this->manager)) { 759 return(MDB_OK); 760 } 761 $result = $this->_loadModule($scope, 'Manager', 762 'MDB_MANAGER_'.strtoupper($this->phptype).'_INCLUDED', 763 'Manager/'.$this->phptype.'.php'); 764 if (MDB::isError($result)) { 765 return($result); 766 } 767 $class_name = 'MDB_Manager_'.$this->dbsyntax; 768 if (!class_exists($class_name)) { 769 return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL, 770 'Unable to load extension')); 771 } 772 @$this->manager = new $class_name; 773 return(MDB_OK); 774 } 775 776 // }}} 777 // {{{ autoCommit() 778 779 /** 780 * Define whether database changes done on the database be automatically 781 * committed. This function may also implicitly start or end a transaction. 782 * 783 * @param boolean $auto_commit flag that indicates whether the database 784 * changes should be committed right after executing every query 785 * statement. If this argument is 0 a transaction implicitly started. 786 * Otherwise, if a transaction is in progress it is ended by committing 787 * any database changes that were pending. 788 * @return mixed MDB_OK on success, a MDB error on failure 789 * @access public 790 */ 791 function autoCommit($auto_commit) 792 { 793 $this->debug('AutoCommit: ' . ($auto_commit ? 'On' : 'Off')); 794 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 795 'Auto-commit transactions: transactions are not supported')); 796 } 797 798 // }}} 799 // {{{ commit() 800 801 /** 802 * Commit the database changes done during a transaction that is in 803 * progress. This function may only be called when auto-committing is 804 * disabled, otherwise it will fail. Therefore, a new transaction is 805 * implicitly started after committing the pending changes. 806 * 807 * @return mixed MDB_OK on success, a MDB error on failure 808 * @access public 809 */ 810 function commit() 811 { 812 $this->debug('Commit Transaction'); 813 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 814 'Commit transaction: commiting transactions are not supported')); 815 } 816 817 // }}} 818 // {{{ rollback() 819 820 /** 821 * Cancel any database changes done during a transaction that is in 822 * progress. This function may only be called when auto-committing is 823 * disabled, otherwise it will fail. Therefore, a new transaction is 824 * implicitly started after canceling the pending changes. 825 * 826 * @return mixed MDB_OK on success, a MDB error on failure 827 * @access public 828 */ 829 function rollback() 830 { 831 $this->debug('Rollback Transaction'); 832 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 833 'Rollback transaction: rolling back transactions are not supported')); 834 } 835 836 // }}} 837 // {{{ disconnect() 838 839 /** 840 * Log out and disconnect from the database. 841 * 842 * @return mixed TRUE on success, FALSE if not connected and error 843 * object on error 844 * @access public 845 */ 846 function disconnect() 847 { 848 if ($this->in_transaction && !MDB::isError($this->rollback()) && !MDB::isError($this->autoCommit(TRUE))) { 849 $this->in_transaction = FALSE; 850 } 851 return($this->_close()); 852 } 853 854 // }}} 855 // {{{ _close() 856 857 /** 858 * all the RDBMS specific things needed to close a DB connection 859 * 860 * @access private 861 */ 862 function _close() 863 { 864 unset($GLOBALS['_MDB_databases'][$this->database]); 865 } 866 867 // }}} 868 // {{{ setDatabase() 869 870 /** 871 * Select a different database 872 * 873 * @param string $name name of the database that should be selected 874 * @return string name of the database previously connected to 875 * @access public 876 */ 877 function setDatabase($name) 878 { 879 $previous_database_name = $this->database_name; 880 $this->database_name = $name; 881 return($previous_database_name); 882 } 883 884 // }}} 885 // {{{ setDSN() 886 887 /** 888 * set the DSN 889 * 890 * @param mixed $dsninfo DSN string or array 891 * @return MDB_OK 892 * @access public 893 */ 894 function setDSN($dsn) 895 { 896 $dsninfo = MDB::parseDSN($dsn); 897 if(isset($dsninfo['hostspec'])) { 898 $this->host = $dsninfo['hostspec']; 899 } 900 if(isset($dsninfo['port'])) { 901 $this->port = $dsninfo['port']; 902 } 903 if(isset($dsninfo['username'])) { 904 $this->user = $dsninfo['username']; 905 } 906 if(isset($dsninfo['password'])) { 907 $this->password = $dsninfo['password']; 908 } 909 if(isset($dsninfo['database'])) { 910 $this->database_name = $dsninfo['database']; 911 } 912 return(MDB_OK); 913 } 914 915 // }}} 916 // {{{ getDSN() 917 918 /** 919 * return the DSN as a string 920 * 921 * @param string $type type to return 922 * @return mixed DSN in the chosen type 923 * @access public 924 */ 925 function getDSN($type = 'string') 926 { 927 switch($type) { 928 case 'array': 929 $dsn = array( 930 'phptype' => $this->phptype, 931 'username' => $this->user, 932 'password' => $this->password, 933 'hostspec' => $this->host, 934 'database' => $this->database_name 935 ); 936 break; 937 default: 938 $dsn = $this->phptype.'://'.$this->user.':' 939 .$this->password.'@'.$this->host 940 .($this->port ? (':'.$this->port) : '') 941 .'/'.$this->database_name; 942 break; 943 } 944 return($dsn); 945 } 946 947 // }}} 948 // {{{ createDatabase() 949 950 /** 951 * create a new database 952 * 953 * @param string $name name of the database that should be created 954 * @return mixed MDB_OK on success, a MDB error on failure 955 * @access public 956 */ 957 function createDatabase($name) 958 { 959 $result = $this->loadManager('Create database'); 960 if (MDB::isError($result)) { 961 return($result); 962 } 963 return($this->manager->createDatabase($this, $name)); 964 } 965 966 // }}} 967 // {{{ dropDatabase() 968 969 /** 970 * drop an existing database 971 * 972 * @param string $name name of the database that should be dropped 973 * @return mixed MDB_OK on success, a MDB error on failure 974 * @access public 975 */ 976 function dropDatabase($name) 977 { 978 $result = $this->loadManager('Drop database'); 979 if (MDB::isError($result)) { 980 return($result); 981 } 982 return($this->manager->dropDatabase($this, $name)); 983 } 984 985 // }}} 986 // {{{ createTable() 987 988 /** 989 * create a new table 990 * 991 * @param string $name Name of the database that should be created 992 * @param array $fields Associative array that contains the definition of 993 * each field of the new table. The indexes of the array entries are 994 * the names of the fields of the table an the array entry values are 995 * associative arrays like those that are meant to be passed with the 996 * field definitions to get[Type]Declaration() functions. 997 * 998 * Example 999 * array( 1000 * 'id' => array( 1001 * 'type' => 'integer', 1002 * 'unsigned' => 1 1003 * 'notnull' => 1 1004 * 'default' => 0 1005 * ), 1006 * 'name' => array( 1007 * 'type' => 'text', 1008 * 'length' => 12 1009 * ), 1010 * 'password' => array( 1011 * 'type' => 'text', 1012 * 'length' => 12 1013 * ) 1014 * ); 1015 * @return mixed MDB_OK on success, a MDB error on failure 1016 * @access public 1017 */ 1018 function createTable($name, $fields) 1019 { 1020 $result = $this->loadManager('Create table'); 1021 if (MDB::isError($result)) { 1022 return($result); 1023 } 1024 return($this->manager->createTable($this, $name, $fields)); 1025 } 1026 1027 // }}} 1028 // {{{ dropTable() 1029 1030 /** 1031 * drop an existing table 1032 * 1033 * @param string $name name of the table that should be dropped 1034 * @return mixed MDB_OK on success, a MDB error on failure 1035 * @access public 1036 */ 1037 function dropTable($name) 1038 { 1039 $result = $this->loadManager('Drop table'); 1040 if (MDB::isError($result)) { 1041 return($result); 1042 } 1043 return($this->manager->dropTable($this, $name)); 1044 } 1045 1046 // }}} 1047 // {{{ alterTable() 1048 1049 /** 1050 * alter an existing table 1051 * 1052 * @param string $name name of the table that is intended to be changed. 1053 * @param array $changes associative array that contains the details of 1054 * each type of change that is intended to be performed. The types of 1055 * changes that are currently supported are defined as follows: 1056 * 1057 * name 1058 * New name for the table. 1059 * 1060 * AddedFields 1061 * Associative array with the names of fields to be added as indexes of 1062 * the array. The value of each entry of the array should be set to 1063 * another associative array with the properties of the fields to be 1064 * added. The properties of the fields should be the same as defined by 1065 * the Metabase parser. 1066 * 1067 * Additionally, there should be an entry named Declaration that is 1068 * expected to contain the portion of the field declaration already in 1069 * DBMS specific SQL code as it is used in the CREATE TABLE statement. 1070 * 1071 * RemovedFields 1072 * Associative array with the names of fields to be removed as indexes of 1073 * the array. Currently the values assigned to each entry are ignored. An 1074 * empty array should be used for future compatibility. 1075 * 1076 * RenamedFields 1077 * Associative array with the names of fields to be renamed as indexes of 1078 * the array. The value of each entry of the array should be set to another 1079 * associative array with the entry named name with the new field name and 1080 * the entry named Declaration that is expected to contain the portion of 1081 * the field declaration already in DBMS specific SQL code as it is used 1082 * in the CREATE TABLE statement. 1083 * 1084 * ChangedFields 1085 * Associative array with the names of the fields to be changed as indexes 1086 * of the array. Keep in mind that if it is intended to change either the 1087 * name of a field and any other properties, the ChangedFields array 1088 * entries should have the new names of the fields as array indexes. 1089 * 1090 * The value of each entry of the array should be set to another 1091 * associative array with the properties of the fields to that are meant 1092 * to be changed as array entries. These entries should be assigned to the 1093 * new values of the respective properties. The properties of the fields 1094 * should be the* same as defined by the Metabase parser. 1095 * 1096 * If the default property is meant to be added, removed or changed, there 1097 * should also be an entry with index ChangedDefault assigned to 1. 1098 * Similarly, if the notnull constraint is to be added or removed, there 1099 * should also be an entry with index ChangedNotNull assigned to 1. 1100 * 1101 * Additionally, there should be an entry named Declaration that is 1102 * expected to contain the portion of the field changed declaration 1103 * already in DBMS specific SQL code as it is used in the CREATE TABLE 1104 * statement. 1105 * 1106 * Example 1107 * array( 1108 * 'name' => 'userlist', 1109 * 'AddedFields' => array( 1110 * 'quota' => array( 1111 * 'type' => 'integer', 1112 * 'unsigned' => 1, 1113 * 'Declaration' => 'quota INT' 1114 * ) 1115 * ), 1116 * 'RemovedFields' => array( 1117 * 'file_limit' => array(), 1118 * 'time_limit' => array() 1119 * ), 1120 * 'ChangedFields' => array( 1121 * 'gender' => array( 1122 * 'default' => 'M', 1123 * 'ChangeDefault' => 1, 1124 * 'Declaration' => "gender CHAR(1) DEFAULT 'M'" 1125 * ) 1126 * ), 1127 * 'RenamedFields' => array( 1128 * 'sex' => array( 1129 * 'name' => 'gender', 1130 * 'Declaration' => "gender CHAR(1) DEFAULT 'M'" 1131 * ) 1132 * ) 1133 * ) 1134 * 1135 * @param boolean $check indicates whether the function should just check 1136 * if the DBMS driver can perform the requested table alterations if 1137 * the value is TRUE or actually perform them otherwise. 1138 * @return mixed MDB_OK on success, a MDB error on failure 1139 * @access public 1140 */ 1141 function alterTable($name, $changes, $check) 1142 { 1143 $result = $this->loadManager('Alter table'); 1144 if (MDB::isError($result)) { 1145 return($result); 1146 } 1147 return($this->manager->alterTable($this, $name, $changes, $check)); 1148 } 1149 1150 // }}} 1151 // {{{ listDatabases() 1152 1153 /** 1154 * list all databases 1155 * 1156 * @return mixed data array on success, a MDB error on failure 1157 * @access public 1158 */ 1159 function listDatabases() 1160 { 1161 $result = $this->loadManager('List databases'); 1162 if (MDB::isError($result)) { 1163 return($result); 1164 } 1165 return($this->manager->listDatabases($this)); 1166 } 1167 1168 // }}} 1169 // {{{ listUsers() 1170 1171 /** 1172 * list all users 1173 * 1174 * @return mixed data array on success, a MDB error on failure 1175 * @access public 1176 */ 1177 function listUsers() 1178 { 1179 $result = $this->loadManager('List users'); 1180 if (MDB::isError($result)) { 1181 return($result); 1182 } 1183 return($this->manager->listUsers($this)); 1184 } 1185 1186 // }}} 1187 // {{{ listViews() 1188 1189 /** 1190 * list all viewes in the current database 1191 * 1192 * @return mixed data array on success, a MDB error on failure 1193 * @access public 1194 */ 1195 function listViews() 1196 { 1197 $result = $this->loadManager('List views'); 1198 if (MDB::isError($result)) { 1199 return($result); 1200 } 1201 return($this->manager->listViews($this)); 1202 } 1203 1204 // }}} 1205 // {{{ listFunctions() 1206 1207 /** 1208 * list all functions in the current database 1209 * 1210 * @return mixed data array on success, a MDB error on failure 1211 * @access public 1212 */ 1213 function listFunctions() 1214 { 1215 $result = $this->loadManager('List functions'); 1216 if (MDB::isError($result)) { 1217 return($result); 1218 } 1219 return($this->manager->listFunctions($this)); 1220 } 1221 1222 // }}} 1223 // {{{ listTables() 1224 1225 /** 1226 * list all tables in the current database 1227 * 1228 * @return mixed data array on success, a MDB error on failure 1229 * @access public 1230 */ 1231 function listTables() 1232 { 1233 $result = $this->loadManager('List tables'); 1234 if (MDB::isError($result)) { 1235 return($result); 1236 } 1237 return($this->manager->listTables($this)); 1238 } 1239 1240 // }}} 1241 // {{{ listTableFields() 1242 1243 /** 1244 * list all fields in a tables in the current database 1245 * 1246 * @param string $table name of table that should be used in method 1247 * @return mixed data array on success, a MDB error on failure 1248 * @access public 1249 */ 1250 function listTableFields($table) 1251 { 1252 $result = $this->loadManager('List table fields'); 1253 if (MDB::isError($result)) { 1254 return($result); 1255 } 1256 return($this->manager->listTableFields($this, $table)); 1257 } 1258 1259 // }}} 1260 // {{{ getTableFieldDefinition() 1261 1262 /** 1263 * get the stucture of a field into an array 1264 * 1265 * @param string $table name of table that should be used in method 1266 * @param string $fields name of field that should be used in method 1267 * @return mixed data array on success, a MDB error on failure 1268 * @access public 1269 */ 1270 function getTableFieldDefinition($table, $field) 1271 { 1272 $result = $this->loadManager('Get table field definition'); 1273 if (MDB::isError($result)) { 1274 return($result); 1275 } 1276 return($this->manager->getTableFieldDefinition($this, $table, $field)); 1277 } 1278 1279 // }}} 1280 // {{{ getFieldDeclaration() 1281 1282 /** 1283 * get declaration of a field 1284 * 1285 * @param string $field_name name of the field to be created 1286 * @param string $field associative array with the name of the properties 1287 * of the field being declared as array indexes. Currently, the types 1288 * of supported field properties are as follows: 1289 * 1290 * default 1291 * Boolean value to be used as default for this field. 1292 * 1293 * notnull 1294 * Boolean flag that indicates whether this field is constrained 1295 * to not be set to NULL. 1296 * @return mixed string on success, a MDB error on failure 1297 * @access public 1298 */ 1299 function getFieldDeclaration($field_name, $field) 1300 { 1301 $result = $this->loadManager('Get table field definition'); 1302 if (MDB::isError($result)) { 1303 return($result); 1304 } 1305 return($this->manager->getFieldDeclaration($this, $field_name, $field)); 1306 } 1307 1308 // }}} 1309 // {{{ getFieldDeclarationList() 1310 1311 /** 1312 * get declaration of a number of field in bulk 1313 * 1314 * @param string $fields a multidimensional associative array. 1315 * The first dimension determines the field name, while the second 1316 * dimension is keyed with the name of the properties 1317 * of the field being declared as array indexes. Currently, the types 1318 * of supported field properties are as follows: 1319 * 1320 * default 1321 * Boolean value to be used as default for this field. 1322 * 1323 * notnull 1324 * Boolean flag that indicates whether this field is constrained 1325 * to not be set to NULL. 1326 * 1327 * default 1328 * Boolean value to be used as default for this field. 1329 * 1330 * notnull 1331 * Boolean flag that indicates whether this field is constrained 1332 * to not be set to NULL. 1333 * @return mixed string on success, a MDB error on failure 1334 * @access public 1335 */ 1336 function getFieldDeclarationList($fields) 1337 { 1338 $result = $this->loadManager('Get table field list'); 1339 if (MDB::isError($result)) { 1340 return($result); 1341 } 1342 return($this->manager->getFieldDeclarationList($this, $fields)); 1343 } 1344 1345 // }}} 1346 // {{{ _isSequenceName() 1347 1348 /** 1349 * list all tables in the current database 1350 * 1351 * @param string $sqn string that containts name of a potential sequence 1352 * @return mixed name of the sequence if $sqn is a name of a sequence, else FALSE 1353 * @access private 1354 */ 1355 function _isSequenceName($sqn) 1356 { 1357 $result = $this->loadManager('is sequence name'); 1358 if (MDB::isError($result)) { 1359 return($result); 1360 } 1361 return($this->manager->_isSequenceName($this, $sqn)); 1362 } 1363 1364 // }}} 1365 // {{{ createIndex() 1366 1367 /** 1368 * get the stucture of a field into an array 1369 * 1370 * @param string $table name of the table on which the index is to be 1371 * created 1372 * @param string $name name of the index to be created 1373 * @param array $definition associative array that defines properties of 1374 * the index to be created. Currently, only one property named FIELDS 1375 * is supported. This property is also an associative with the names 1376 * of the index fields as array indexes. Each entry of this array is 1377 * set to another type of associative array that specifies properties 1378 * of the index that are specific to each field. 1379 * 1380 * Currently, only the sorting property is supported. It should be 1381 * used to define the sorting direction of the index. It may be set 1382 * to either ascending or descending. Not all DBMS support index 1383 * sorting direction configuration. The DBMS drivers of those that do 1384 * not support it ignore this property. Use the function support() to 1385 * determine whether the DBMS driver can manage indexes. 1386 * 1387 * Example 1388 * array( 1389 * 'FIELDS' => array( 1390 * 'user_name' => array( 1391 * 'sorting' => 'ascending' 1392 * ), 1393 * 'last_login' => array() 1394 * ) 1395 * ) 1396 * @return mixed MDB_OK on success, a MDB error on failure 1397 * @access public 1398 */ 1399 function createIndex($table, $name, $definition) 1400 { 1401 $result = $this->loadManager('Create index'); 1402 if (MDB::isError($result)) { 1403 return($result); 1404 } 1405 return($this->manager->createIndex($this, $table, $name, $definition)); 1406 } 1407 1408 // }}} 1409 // {{{ dropIndex() 1410 1411 /** 1412 * drop existing index 1413 * 1414 * @param string $table name of table that should be used in method 1415 * @param string $name name of the index to be dropped 1416 * @return mixed MDB_OK on success, a MDB error on failure 1417 * @access public 1418 */ 1419 function dropIndex($table, $name) 1420 { 1421 $result = $this->loadManager('Drop index'); 1422 if (MDB::isError($result)) { 1423 return($result); 1424 } 1425 return($this->manager->dropIndex($this, $table , $name)); 1426 } 1427 1428 // }}} 1429 // {{{ listTableIndexes() 1430 1431 /** 1432 * list all indexes in a table 1433 * 1434 * @param string $table name of table that should be used in method 1435 * @return mixed data array on success, a MDB error on failure 1436 * @access public 1437 */ 1438 function listTableIndexes($table) 1439 { 1440 $result = $this->loadManager('List table index'); 1441 if (MDB::isError($result)) { 1442 return($result); 1443 } 1444 return($this->manager->listTableIndexes($this, $table)); 1445 } 1446 1447 // }}} 1448 // {{{ getTableIndexDefinition() 1449 1450 /** 1451 * get the stucture of an index into an array 1452 * 1453 * @param string $table name of table that should be used in method 1454 * @param string $index name of index that should be used in method 1455 * @return mixed data array on success, a MDB error on failure 1456 * @access public 1457 */ 1458 function getTableIndexDefinition($table, $index) 1459 { 1460 $result = $this->loadManager('Get table index definition'); 1461 if (MDB::isError($result)) { 1462 return($result); 1463 } 1464 return($this->manager->getTableIndexDefinition($this, $table, $index)); 1465 } 1466 1467 // }}} 1468 // {{{ createSequence() 1469 1470 /** 1471 * create sequence 1472 * 1473 * @param string $name name of the sequence to be created 1474 * @param string $start start value of the sequence; default is 1 1475 * @return mixed MDB_OK on success, a MDB error on failure 1476 * @access public 1477 */ 1478 function createSequence($name, $start = 1) 1479 { 1480 $result = $this->loadManager('Create sequence'); 1481 if (MDB::isError($result)) { 1482 return($result); 1483 } 1484 return($this->manager->createSequence($this, $name, $start)); 1485 } 1486 1487 // }}} 1488 // {{{ dropSequence() 1489 1490 /** 1491 * drop existing sequence 1492 * 1493 * @param string $name name of the sequence to be dropped 1494 * @return mixed MDB_OK on success, a MDB error on failure 1495 * @access public 1496 */ 1497 function dropSequence($name) 1498 { 1499 $result = $this->loadManager('Drop sequence'); 1500 if (MDB::isError($result)) { 1501 return($result); 1502 } 1503 return($this->manager->dropSequence($this, $name)); 1504 } 1505 1506 // }}} 1507 // {{{ listSequences() 1508 1509 /** 1510 * list all tables in the current database 1511 * 1512 * @return mixed data array on success, a MDB error on failure 1513 * @access public 1514 */ 1515 function listSequences() 1516 { 1517 $result = $this->loadManager('List sequences'); 1518 if (MDB::isError($result)) { 1519 return($result); 1520 } 1521 return($this->manager->listSequences($this)); 1522 } 1523 1524 // }}} 1525 // {{{ getSequenceDefinition() 1526 1527 /** 1528 * get the stucture of a sequence into an array 1529 * 1530 * @param string $sequence name of sequence that should be used in method 1531 * @return mixed data array on success, a MDB error on failure 1532 * @access public 1533 */ 1534 function getSequenceDefinition($sequence) 1535 { 1536 $result = $this->loadManager('Get sequence definition'); 1537 if (MDB::isError($result)) { 1538 return($result); 1539 } 1540 return($this->manager->getSequenceDefinition($this, $sequence)); 1541 } 1542 1543 // }}} 1544 // {{{ query() 1545 1546 /** 1547 * Send a query to the database and return any results 1548 * 1549 * @param string $query the SQL query 1550 * @param mixed $types array that contains the types of the columns in 1551 * the result set 1552 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 1553 * @access public 1554 */ 1555 function query($query, $types = NULL) 1556 { 1557 $this->debug("Query: $query"); 1558 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Query: database queries are not implemented')); 1559 } 1560 1561 // }}} 1562 // {{{ setSelectedRowRange() 1563 1564 /** 1565 * set the range of the next query 1566 * 1567 * @param string $first first row to select 1568 * @param string $limit number of rows to select 1569 * @return mixed MDB_OK on success, a MDB error on failure 1570 * @access public 1571 */ 1572 function setSelectedRowRange($first, $limit) 1573 { 1574 if (!isset($this->supported['SelectRowRanges'])) { 1575 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 1576 'Set selected row range: selecting row ranges is not supported by this driver')); 1577 } 1578 $first = (int)$first; 1579 if ($first < 0) { 1580 return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 1581 'Set selected row range: it was not specified a valid first selected range row')); 1582 } 1583 $limit = (int)$limit; 1584 if ($limit < 1) { 1585 return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 1586 'Set selected row range: it was not specified a valid selected range row limit')); 1587 } 1588 $this->first_selected_row = $first; 1589 $this->selected_row_limit = $limit; 1590 return(MDB_OK); 1591 } 1592 1593 // }}} 1594 // {{{ limitQuery() 1595 1596 /** 1597 * Generates a limited query 1598 * 1599 * @param string $query query 1600 * @param mixed $types array that contains the types of the columns in 1601 * the result set 1602 * @param integer $from the row to start to fetching 1603 * @param integer $count the numbers of rows to fetch 1604 * @return mixed a valid ressource pointer or a MDB_Error 1605 * @access public 1606 */ 1607 function limitQuery($query, $types = NULL, $from, $count) 1608 { 1609 $result = $this->setSelectedRowRange($from, $count); 1610 if (MDB::isError($result)) { 1611 return($result); 1612 } 1613 return($this->query($query, $types)); 1614 } 1615 1616 // }}} 1617 // {{{ subSelect() 1618 1619 /** 1620 * simple subselect emulation: leaves the query untouched for all RDBMS 1621 * that support subselects 1622 * 1623 * @access public 1624 * 1625 * @param string $query the SQL query for the subselect that may only 1626 * return a column 1627 * @param string $quote determines if the data needs to be quoted before 1628 * being returned 1629 * 1630 * @return string the query 1631 */ 1632 function subSelect($query, $quote = FALSE) 1633 { 1634 if ($this->supported['SubSelects'] == 1) { 1635 return($query); 1636 } 1637 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Subselect: subselect not implemented')); 1638 } 1639 1640 // }}} 1641 // {{{ replace() 1642 1643 /** 1644 * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT 1645 * query, except that if there is already a row in the table with the same 1646 * key field values, the REPLACE query just updates its values instead of 1647 * inserting a new row. 1648 * 1649 * The REPLACE type of query does not make part of the SQL standards. Since 1650 * pratically only MySQL implements it natively, this type of query is 1651 * emulated through this method for other DBMS using standard types of 1652 * queries inside a transaction to assure the atomicity of the operation. 1653 * 1654 * @param string $table name of the table on which the REPLACE query will 1655 * be executed. 1656 * @param array $fields associative array that describes the fields and the 1657 * values that will be inserted or updated in the specified table. The 1658 * indexes of the array are the names of all the fields of the table. 1659 * The values of the array are also associative arrays that describe 1660 * the values and other properties of the table fields. 1661 * 1662 * Here follows a list of field properties that need to be specified: 1663 * 1664 * Value 1665 * Value to be assigned to the specified field. This value may be 1666 * of specified in database independent type format as this 1667 * function can perform the necessary datatype conversions. 1668 * 1669 * Default: this property is required unless the Null property is 1670 * set to 1. 1671 * 1672 * Type 1673 * Name of the type of the field. Currently, all types Metabase 1674 * are supported except for clob and blob. 1675 * 1676 * Default: no type conversion 1677 * 1678 * Null 1679 * Boolean property that indicates that the value for this field 1680 * should be set to NULL. 1681 * 1682 * The default value for fields missing in INSERT queries may be 1683 * specified the definition of a table. Often, the default value 1684 * is already NULL, but since the REPLACE may be emulated using 1685 * an UPDATE query, make sure that all fields of the table are 1686 * listed in this function argument array. 1687 * 1688 * Default: 0 1689 * 1690 * Key 1691 * Boolean property that indicates that this field should be 1692 * handled as a primary key or at least as part of the compound 1693 * unique index of the table that will determine the row that will 1694 * updated if it exists or inserted a new row otherwise. 1695 * 1696 * This function will fail if no key field is specified or if the 1697 * value of a key field is set to NULL because fields that are 1698 * part of unique index they may not be NULL. 1699 * 1700 * Default: 0 1701 * @return mixed MDB_OK on success, a MDB error on failure 1702 * @access public 1703 */ 1704 function replace($table, $fields) 1705 { 1706 if (!$this->supported['Replace']) { 1707 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Replace: replace query is not supported')); 1708 } 1709 $count = count($fields); 1710 for($keys = 0, $condition = $insert = $values = '', reset($fields), $field = 0; 1711 $field < $count; 1712 next($fields), $field++) 1713 { 1714 $name = key($fields); 1715 if ($field > 0) { 1716 $insert .= ', '; 1717 $values .= ', '; 1718 } 1719 $insert .= $name; 1720 if (isset($fields[$name]['Null']) && $fields[$name]['Null']) { 1721 $value = 'NULL'; 1722 } else { 1723 if(isset($fields[$name]['Type'])) { 1724 switch ($fields[$name]['Type']) { 1725 case 'text': 1726 $value = $this->getTextValue($fields[$name]['Value']); 1727 break; 1728 case 'boolean': 1729 $value = $this->getBooleanValue($fields[$name]['Value']); 1730 break; 1731 case 'integer': 1732 $value = $this->getIntegerValue($fields[$name]['Value']); 1733 break; 1734 case 'decimal': 1735 $value = $this->getDecimalValue($fields[$name]['Value']); 1736 break; 1737 case 'float': 1738 $value = $this->getFloatValue($fields[$name]['Value']); 1739 break; 1740 case 'date': 1741 $value = $this->getDateValue($fields[$name]['Value']); 1742 break; 1743 case 'time': 1744 $value = $this->getTimeValue($fields[$name]['Value']); 1745 break; 1746 case 'timestamp': 1747 $value = $this->getTimestampValue($fields[$name]['Value']); 1748 break; 1749 default: 1750 return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL, 1751 'no supported type for field "' . $name . '" specified')); 1752 } 1753 } else { 1754 $value = $fields[$name]['Value']; 1755 } 1756 } 1757 $values .= $value; 1758 if (isset($fields[$name]['Key']) && $fields[$name]['Key']) { 1759 if ($value === 'NULL') { 1760 return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL, 1761 'key values may not be NULL')); 1762 } 1763 $condition .= ($keys ? ' AND ' : ' WHERE ') . $name . '=' . $value; 1764 $keys++; 1765 } 1766 } 1767 if ($keys == 0) { 1768 return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL, 1769 'not specified which fields are keys')); 1770 } 1771 $in_transaction = $this->in_transaction; 1772 if (!$in_transaction && MDB::isError($result = $this->autoCommit(FALSE))) { 1773 return($result); 1774 } 1775 $success = $this->query("DELETE FROM $table$condition"); 1776 if (!MDB::isError($success)) { 1777 $affected_rows = $this->affected_rows; 1778 $success = $this->query("INSERT INTO $table ($insert) VALUES ($values)"); 1779 $affected_rows += $this->affected_rows; 1780 } 1781 1782 if (!$in_transaction) { 1783 if (!MDB::isError($success)) { 1784 if (!MDB::isError($success = $this->commit()) 1785 && !MDB::isError($success = $this->autoCommit(TRUE)) 1786 && isset($this->supported['AffectedRows']) 1787 ) { 1788 $this->affected_rows = $affected_rows; 1789 } 1790 } else { 1791 $this->rollback(); 1792 $this->autoCommit(TRUE); 1793 } 1794 } 1795 return($success); 1796 } 1797 1798 // }}} 1799 // {{{ prepareQuery() 1800 1801 /** 1802 * Prepares a query for multiple execution with execute(). 1803 * With some database backends, this is emulated. 1804 * prepareQuery() requires a generic query as string like 1805 * 'INSERT INTO numbers VALUES(?,?,?)'. The ? are wildcards. 1806 * Types of wildcards: 1807 * ? - a quoted scalar value, i.e. strings, integers 1808 * 1809 * @param string $ the query to prepare 1810 * @return mixed resource handle for the prepared query on success, a DB 1811 * error on failure 1812 * @access public 1813 * @see execute 1814 */ 1815 function prepareQuery($query) 1816 { 1817 $this->debug("PrepareQuery: $query"); 1818 $positions = array(); 1819 for($position = 0; 1820 $position < strlen($query) && is_integer($question = strpos($query, '?', $position)); 1821 ) { 1822 if (is_integer($quote = strpos($query, "'", $position)) 1823 && $quote < $question 1824 ) { 1825 if (!is_integer($end_quote = strpos($query, "'", $quote + 1))) { 1826 return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 1827 'Prepare query: query with an unterminated text string specified')); 1828 } 1829 switch ($this->escape_quotes) { 1830 case '': 1831 case "'": 1832 $position = $end_quote + 1; 1833 break; 1834 default: 1835 if ($end_quote == $quote + 1) { 1836 $position = $end_quote + 1; 1837 } else { 1838 if ($query[$end_quote-1] == $this->escape_quotes) { 1839 $position = $end_quote; 1840 } else { 1841 $position = $end_quote + 1; 1842 } 1843 } 1844 break; 1845 } 1846 } else { 1847 $positions[] = $question; 1848 $position = $question + 1; 1849 } 1850 } 1851 $this->prepared_queries[] = array( 1852 'Query' => $query, 1853 'Positions' => $positions, 1854 'Values' => array(), 1855 'Types' => array() 1856 ); 1857 $prepared_query = count($this->prepared_queries); 1858 if ($this->selected_row_limit > 0) { 1859 $this->prepared_queries[$prepared_query-1]['First'] = $this->first_selected_row; 1860 $this->prepared_queries[$prepared_query-1]['Limit'] = $this->selected_row_limit; 1861 } 1862 return($prepared_query); 1863 } 1864 1865 // }}} 1866 // {{{ _validatePreparedQuery() 1867 1868 /** 1869 * validate that a handle is infact a prepared query 1870 * 1871 * @param int $prepared_query argument is a handle that was returned by 1872 * the function prepareQuery() 1873 * @access private 1874 */ 1875 function _validatePreparedQuery($prepared_query) 1876 { 1877 if ($prepared_query < 1 || $prepared_query > count($this->prepared_queries)) { 1878 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 1879 'Validate prepared query: invalid prepared query')); 1880 } 1881 if (gettype($this->prepared_queries[$prepared_query-1]) != 'array') { 1882 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 1883 'Validate prepared query: prepared query was already freed')); 1884 } 1885 return(MDB_OK); 1886 } 1887 1888 // }}} 1889 // {{{ freePreparedQuery() 1890 1891 /** 1892 * Release resources allocated for the specified prepared query. 1893 * 1894 * @param int $prepared_query argument is a handle that was returned by 1895 * the function prepareQuery() 1896 * @return mixed MDB_OK on success, a MDB error on failure 1897 * @access public 1898 */ 1899 function freePreparedQuery($prepared_query) 1900 { 1901 $result = $this->_validatePreparedQuery($prepared_query); 1902 if (MDB::isError($result)) { 1903 return($result); 1904 } 1905 $this->prepared_queries[$prepared_query-1] = ''; 1906 return(MDB_OK); 1907 } 1908 1909 // }}} 1910 // {{{ _executePreparedQuery() 1911 1912 /** 1913 * Execute a prepared query statement. 1914 * 1915 * @param int $prepared_query argument is a handle that was returned by 1916 * the function prepareQuery() 1917 * @param string $query query to be executed 1918 * @param array $types array that contains the types of the columns in 1919 * the result set 1920 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 1921 * @access private 1922 */ 1923 function _executePreparedQuery($prepared_query, $query, $types = NULL) 1924 { 1925 return($this->query($query, $types)); 1926 } 1927 1928 // }}} 1929 // {{{ executeQuery() 1930 1931 /** 1932 * Execute a prepared query statement. 1933 * 1934 * @param int $prepared_query argument is a handle that was returned by 1935 * the function prepareQuery() 1936 * @param array $types array that contains the types of the columns in the 1937 * result set 1938 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 1939 * @access public 1940 */ 1941 function executeQuery($prepared_query, $types = NULL) 1942 { 1943 $result = $this->_validatePreparedQuery($prepared_query); 1944 if (MDB::isError($result)) { 1945 return($result); 1946 } 1947 $index = $prepared_query-1; 1948 $success = MDB_OK; 1949 $this->clobs[$prepared_query] = $this->blobs[$prepared_query] = array(); 1950 $query = ''; 1951 for($last_position = $position = 0; 1952 $position < count($this->prepared_queries[$index]['Positions']); 1953 $position++) { 1954 if (!isset($this->prepared_queries[$index]['Values'][$position])) { 1955 return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL, 1956 'Execute query: it was not defined query argument '.($position + 1))); 1957 } 1958 $current_position = $this->prepared_queries[$index]['Positions'][$position]; 1959 $query .= substr($this->prepared_queries[$index]['Query'], $last_position, $current_position - $last_position); 1960 $value = $this->prepared_queries[$index]['Values'][$position]; 1961 if ($this->prepared_queries[$index]['IsNULL'][$position]) { 1962 $query .= $value; 1963 } else { 1964 switch ($this->prepared_queries[$index]['Types'][$position]) { 1965 case 'clob': 1966 if (!MDB::isError($success = $this->getClobValue($prepared_query, $position + 1, $value))) { 1967 $this->clobs[$prepared_query][$position + 1] = $success; 1968 $query .= $this->clobs[$prepared_query][$position + 1]; 1969 } 1970 break; 1971 case 'blob': 1972 if (!MDB::isError($success = $this->getBlobValue($prepared_query, $position + 1, $value))) { 1973 $this->blobs[$prepared_query][$position + 1] = $success; 1974 $query .= $this->blobs[$prepared_query][$position + 1]; 1975 } 1976 break; 1977 default: 1978 $query .= $value; 1979 break; 1980 } 1981 } 1982 $last_position = $current_position + 1; 1983 } 1984 if (!MDB::isError($success)) { 1985 $query .= substr($this->prepared_queries[$index]['Query'], $last_position); 1986 if ($this->selected_row_limit > 0) { 1987 $this->prepared_queries[$index]['First'] = $this->first_selected_row; 1988 $this->prepared_queries[$index]['Limit'] = $this->selected_row_limit; 1989 } 1990 if (isset($this->prepared_queries[$index]['Limit']) 1991 && $this->prepared_queries[$index]['Limit'] > 0 1992 ) { 1993 $this->first_selected_row = $this->prepared_queries[$index]['First']; 1994 $this->selected_row_limit = $this->prepared_queries[$index]['Limit']; 1995 } else { 1996 $this->first_selected_row = $this->selected_row_limit = 0; 1997 } 1998 $success = $this->_executePreparedQuery($prepared_query, $query, $types); 1999 } 2000 for(reset($this->clobs[$prepared_query]), $clob = 0; 2001 $clob < count($this->clobs[$prepared_query]); 2002 $clob++, next($this->clobs[$prepared_query])) { 2003 $this->freeClobValue($prepared_query, key($this->clobs[$prepared_query]), $this->clobs[$prepared_query][key($this->clobs[$prepared_query])], $success); 2004 } 2005 unset($this->clobs[$prepared_query]); 2006 for(reset($this->blobs[$prepared_query]), $blob = 0; 2007 $blob < count($this->blobs[$prepared_query]); 2008 $blob++, next($this->blobs[$prepared_query])) { 2009 $this->freeBlobValue($prepared_query, key($this->blobs[$prepared_query]), $this->blobs[$prepared_query][key($this->blobs[$prepared_query])], $success); 2010 } 2011 unset($this->blobs[$prepared_query]); 2012 return($success); 2013 } 2014 2015 // }}} 2016 // {{{ execute() 2017 2018 /** 2019 * Executes a prepared SQL query 2020 * With execute() the generic query of prepare is assigned with the given 2021 * data array. The values of the array inserted into the query in the same 2022 * order like the array order 2023 * 2024 * @param resource $prepared_query query handle from prepare() 2025 * @param array $types array that contains the types of the columns in 2026 * the result set 2027 * @param array $params numeric array containing the data to insert into 2028 * the query 2029 * @param array $param_types array that contains the types of the values 2030 * defined in $params 2031 * @return mixed a new result handle or a MDB_Error when fail 2032 * @access public 2033 * @see prepare() 2034 */ 2035 function execute($prepared_query, $types = NULL, $params = FALSE, $param_types = NULL) 2036 { 2037 $this->setParamArray($prepared_query, $params, $param_types); 2038 2039 return($this->executeQuery($prepared_query, $types)); 2040 } 2041 2042 // }}} 2043 // {{{ executeMultiple() 2044 2045 /** 2046 * This function does several execute() calls on the same statement handle. 2047 * $params must be an array indexed numerically from 0, one execute call is 2048 * done for every 'row' in the array. 2049 * 2050 * If an error occurs during execute(), executeMultiple() does not execute 2051 * the unfinished rows, but rather returns that error. 2052 * 2053 * @param resource $stmt query handle from prepare() 2054 * @param array $types array that contains the types of the columns in 2055 * the result set 2056 * @param array $params numeric array containing the 2057 * data to insert into the query 2058 * @param array $parAM_types array that contains the types of the values 2059 * defined in $params 2060 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 2061 * @access public 2062 * @see prepare(), execute() 2063 */ 2064 function executeMultiple($prepared_query, $types = NULL, $params, $param_types = NULL) 2065 { 2066 for($i = 0, $j = count($params); $i < $j; $i++) { 2067 $result = $this->execute($prepared_query, $types, $params[$i], $param_types); 2068 if (MDB::isError($result)) { 2069 return($result); 2070 } 2071 } 2072 return(MDB_OK); 2073 } 2074 2075 // }}} 2076 // {{{ setParam() 2077 2078 /** 2079 * Set the value of a parameter of a prepared query. 2080 * 2081 * @param int $prepared_query argument is a handle that was returned 2082 * by the function prepareQuery() 2083 * @param int $parameter the order number of the parameter in the query 2084 * statement. The order number of the first parameter is 1. 2085 * @param string $type designation of the type of the parameter to be set. 2086 * The designation of the currently supported types is as follows: 2087 * text, boolean, integer, decimal, float, date, time, timestamp, 2088 * clob, blob 2089 * @param mixed $value value that is meant to be assigned to specified 2090 * parameter. The type of the value depends on the $type argument. 2091 * @param boolean $is_null flag that indicates whether whether the 2092 * parameter is a NULL 2093 * @param string $field name of the field that is meant to be assigned 2094 * with this parameter value when it is of type clob or blob 2095 * @return mixed MDB_OK on success, a MDB error on failure 2096 * @access public 2097 */ 2098 function setParam($prepared_query, $parameter, $type, $value, $is_null = 0, $field = '') 2099 { 2100 $result = $this->_validatePreparedQuery($prepared_query); 2101 if (MDB::isError($result)) { 2102 return($result); 2103 } 2104 $index = $prepared_query - 1; 2105 if ($parameter < 1 || $parameter > count($this->prepared_queries[$index]['Positions'])) { 2106 return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 2107 'Query set: it was not specified a valid argument number')); 2108 } 2109 $this->prepared_queries[$index]['Values'][$parameter-1] = $value; 2110 $this->prepared_queries[$index]['Types'][$parameter-1] = $type; 2111 $this->prepared_queries[$index]['Fields'][$parameter-1] = $field; 2112 $this->prepared_queries[$index]['IsNULL'][$parameter-1] = $is_null; 2113 return(MDB_OK); 2114 } 2115 2116 // }}} 2117 // {{{ setParamArray() 2118 2119 /** 2120 * Set the values of multiple a parameter of a prepared query in bulk. 2121 * 2122 * @param int $prepared_query argument is a handle that was returned by 2123 * the function prepareQuery() 2124 * @param array $params array thats specifies all necessary infromation 2125 * for setParam() the array elements must use keys corresponding to 2126 * the number of the position of the parameter. 2127 * @param array $types array thats specifies the types of the fields 2128 * @return mixed MDB_OK on success, a MDB error on failure 2129 * @access public 2130 * @see setParam() 2131 */ 2132 function setParamArray($prepared_query, $params, $types = NULL) 2133 { 2134 if (is_array($types)) { 2135 if (count($params) != count($types)) { 2136 return $this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 2137 'setParamArray: the number of given types ('.count($types).')' 2138 .'is not corresponding to the number of given parameters ('.count($params).')'); 2139 } 2140 for($i = 0, $j = count($params); $i < $j; ++$i) { 2141 switch ($types[$i]) { 2142 case 'NULL': 2143 $success = $this->setParam($prepared_query, $i + 1, $params[$i][0], 'NULL', 1, ''); 2144 break; 2145 case 'text': 2146 $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i])); 2147 break; 2148 case 'clob': 2149 $success = $this->setParam($prepared_query, $i + 1, 'clob', $params[$i][0], 0, $params[$i][1]); 2150 break; 2151 case 'blob': 2152 $success = $this->setParam($prepared_query, $i + 1, 'blob', $params[$i][0], 0, $params[$i][1]); 2153 break; 2154 case 'integer': 2155 $success = $this->setParam($prepared_query, $i + 1, 'integer', $this->getIntegerValue($params[$i])); 2156 break; 2157 case 'boolean': 2158 $success = $this->setParam($prepared_query, $i + 1, 'boolean', $this->getBooleanValue($params[$i])); 2159 break; 2160 case 'date': 2161 $success = $this->setParam($prepared_query, $i + 1, 'date', $this->getDateValue($params[$i])); 2162 break; 2163 case 'timestamp': 2164 $success = $this->setParam($prepared_query, $i + 1, 'timestamp', $this->getTimestampValue($params[$i])); 2165 break; 2166 case 'time': 2167 $success = $this->setParam($prepared_query, $i + 1, 'time', $this->getTimeValue($params[$i])); 2168 break; 2169 case 'float': 2170 $success = $this->setParam($prepared_query, $i + 1, 'float', $this->getFloatValue($params[$i])); 2171 break; 2172 case 'decimal': 2173 $success = $this->setParam($prepared_query, $i + 1, 'decimal', $this->getDecimalValue($params[$i])); 2174 break; 2175 default: 2176 $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i])); 2177 break; 2178 } 2179 if (MDB::isError($success)) { 2180 return($success); 2181 } 2182 } 2183 } else { 2184 for($i = 0, $j = count($params); $i < $j; ++$i) { 2185 $success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i])); 2186 if (MDB::isError($success)) { 2187 return($success); 2188 } 2189 } 2190 } 2191 return(MDB_OK); 2192 } 2193 2194 // }}} 2195 // {{{ setParamNull() 2196 2197 /** 2198 * Set the value of a parameter of a prepared query to NULL. 2199 * 2200 * @param int $prepared_query argument is a handle that was returned by 2201 * the function prepareQuery() 2202 * @param int $parameter order number of the parameter in the query 2203 * statement. The order number of the first parameter is 1. 2204 * @param string $type designation of the type of the parameter to be set. 2205 * The designation of the currently supported types is list in the 2206 * usage of the function setParam() 2207 * @return mixed MDB_OK on success, a MDB error on failure 2208 * @access public 2209 * @see setParam() 2210 */ 2211 function setParamNull($prepared_query, $parameter, $type) 2212 { 2213 return($this->setParam($prepared_query, $parameter, $type, 'NULL', 1, '')); 2214 } 2215 2216 // }}} 2217 // {{{ setParamText() 2218 2219 /** 2220 * Set a parameter of a prepared query with a text value. 2221 * 2222 * @param int $prepared_query argument is a handle that was returned by 2223 * the function prepareQuery() 2224 * @param int $parameter order number of the parameter in the query 2225 * statement. The order number of the first parameter is 1. 2226 * @param string $value text value that is meant to be assigned to 2227 * specified parameter. 2228 * @return mixed MDB_OK on success, a MDB error on failure 2229 * @access public 2230 * @see setParam() 2231 */ 2232 function setParamText($prepared_query, $parameter, $value) 2233 { 2234 return($this->setParam($prepared_query, $parameter, 'text', $this->getTextValue($value))); 2235 } 2236 2237 // }}} 2238 // {{{ setParamClob() 2239 2240 /** 2241 * Set a parameter of a prepared query with a character large object value. 2242 * 2243 * @param int $prepared_query argument is a handle that was returned by 2244 * the function prepareQuery() 2245 * @param int $parameter order number of the parameter in the query 2246 * statement. The order number of the first parameter is 1. 2247 * @param int $value handle of large object created with createLOB() 2248 * function from which it will be read the data value that is meant 2249 * to be assigned to specified parameter. 2250 * @param string $field name of the field of a INSERT or UPDATE query to 2251 * which it will be assigned the value to specified parameter. 2252 * @return mixed MDB_OK on success, a MDB error on failure 2253 * @access public 2254 * @see setParam() 2255 */ 2256 function setParamClob($prepared_query, $parameter, $value, $field) 2257 { 2258 return($this->setParam($prepared_query, $parameter, 'clob', $value, 0, $field)); 2259 } 2260 2261 // }}} 2262 // {{{ setParamBlob() 2263 2264 /** 2265 * Set a parameter of a prepared query with a binary large object value. 2266 * 2267 * @param int $prepared_query argument is a handle that was returned by 2268 * the function prepareQuery() 2269 * @param int $parameter order number of the parameter in the query 2270 * statement. The order number of the first parameter is 1. 2271 * @param int $value handle of large object created with createLOB() 2272 * function from which it will be read the data value that is meant 2273 * to be assigned to specified parameter. 2274 * @param string $field name of the field of a INSERT or UPDATE query to 2275 * which it will be assigned the value to specified parameter. 2276 * @return mixed MDB_OK on success, a MDB error on failure 2277 * @access public 2278 * @see setParam() 2279 */ 2280 function setParamBlob($prepared_query, $parameter, $value, $field) 2281 { 2282 return($this->setParam($prepared_query, $parameter, 'blob', $value, 0, $field)); 2283 } 2284 2285 // }}} 2286 // {{{ setParamInteger() 2287 2288 /** 2289 * Set a parameter of a prepared query with a text value. 2290 * 2291 * @param int $prepared_query argument is a handle that was returned by 2292 * the function prepareQuery() 2293 * @param int $parameter order number of the parameter in the query 2294 * statement. The order number of the first parameter is 1. 2295 * @param int $value an integer value that is meant to be assigned to 2296 * specified parameter. 2297 * @return mixed MDB_OK on success, a MDB error on failure 2298 * @access public 2299 * @see setParam() 2300 */ 2301 function setParamInteger($prepared_query, $parameter, $value) 2302 { 2303 return($this->setParam($prepared_query, $parameter, 'integer', $this->getIntegerValue($value))); 2304 } 2305 2306 // }}} 2307 // {{{ setParamBoolean() 2308 2309 /** 2310 * Set a parameter of a prepared query with a boolean value. 2311 * 2312 * @param int $prepared_query argument is a handle that was returned by 2313 * the function prepareQuery() 2314 * @param int $parameter order number of the parameter in the query 2315 * statement. The order number of the first parameter is 1. 2316 * @param boolean $value boolean value that is meant to be assigned to 2317 * specified parameter. 2318 * @return mixed MDB_OK on success, a MDB error on failure 2319 * @access public 2320 * @see setParam() 2321 */ 2322 function setParamBoolean($prepared_query, $parameter, $value) 2323 { 2324 return($this->setParam($prepared_query, $parameter, 'boolean', $this->getBooleanValue($value))); 2325 } 2326 2327 // }}} 2328 // {{{ setParamDate() 2329 2330 /** 2331 * Set a parameter of a prepared query with a date value. 2332 * 2333 * @param int $prepared_query argument is a handle that was returned by 2334 * the function prepareQuery() 2335 * @param int $parameter order number of the parameter in the query 2336 * statement. The order number of the first parameter is 1. 2337 * @param string $value date value that is meant to be assigned to 2338 * specified parameter. 2339 * @return mixed MDB_OK on success, a MDB error on failure 2340 * @access public 2341 * @see setParam() 2342 */ 2343 function setParamDate($prepared_query, $parameter, $value) 2344 { 2345 return($this->setParam($prepared_query, $parameter, 'date', $this->getDateValue($value))); 2346 } 2347 2348 // }}} 2349 // {{{ setParamTimestamp() 2350 2351 /** 2352 * Set a parameter of a prepared query with a time stamp value. 2353 * 2354 * @param int $prepared_query argument is a handle that was returned by 2355 * the function prepareQuery() 2356 * @param int $parameter order number of the parameter in the query 2357 * statement. The order number of the first parameter is 1. 2358 * @param string $value time stamp value that is meant to be assigned to 2359 * specified parameter. 2360 * @return mixed MDB_OK on success, a MDB error on failure 2361 * @access public 2362 * @see setParam() 2363 */ 2364 function setParamTimestamp($prepared_query, $parameter, $value) 2365 { 2366 return($this->setParam($prepared_query, $parameter, 'timestamp', $this->getTimestampValue($value))); 2367 } 2368 2369 // }}} 2370 // {{{ setParamTime() 2371 2372 /** 2373 * Set a parameter of a prepared query with a time value. 2374 * 2375 * @param int $prepared_query argument is a handle that was returned by 2376 * the function prepareQuery() 2377 * @param int $parameter order number of the parameter in the query 2378 * statement. The order number of the first parameter is 1. 2379 * @param string $value time value that is meant to be assigned to 2380 * specified parameter. 2381 * @return mixed MDB_OK on success, a MDB error on failure 2382 * @access public 2383 * @see setParam() 2384 */ 2385 function setParamTime($prepared_query, $parameter, $value) 2386 { 2387 return($this->setParam($prepared_query, $parameter, 'time', $this->getTimeValue($value))); 2388 } 2389 2390 // }}} 2391 // {{{ setParamFloat() 2392 2393 /** 2394 * Set a parameter of a prepared query with a float value. 2395 * 2396 * @param int $prepared_query argument is a handle that was returned by 2397 * the function prepareQuery() 2398 * @param int $parameter order number of the parameter in the query 2399 * statement. The order number of the first parameter is 1. 2400 * @param string $value float value that is meant to be assigned to 2401 * specified parameter. 2402 * @return mixed MDB_OK on success, a MDB error on failure 2403 * @access public 2404 * @see setParam() 2405 */ 2406 function setParamFloat($prepared_query, $parameter, $value) 2407 { 2408 return($this->setParam($prepared_query, $parameter, 'float', $this->getFloatValue($value))); 2409 } 2410 2411 // }}} 2412 // {{{ setParamDecimal() 2413 2414 /** 2415 * Set a parameter of a prepared query with a decimal value. 2416 * 2417 * @param int $prepared_query argument is a handle that was returned by 2418 * the function prepareQuery() 2419 * @param int $parameter order number of the parameter in the query 2420 * statement. The order number of the first parameter is 1. 2421 * @param string $value decimal value that is meant to be assigned to 2422 * specified parameter. 2423 * @return mixed MDB_OK on success, a MDB error on failure 2424 * @access public 2425 * @see setParam() 2426 */ 2427 function setParamDecimal($prepared_query, $parameter, $value) 2428 { 2429 return($this->setParam($prepared_query, $parameter, 'decimal', $this->getDecimalValue($value))); 2430 } 2431 2432 // }}} 2433 // {{{ setResultTypes() 2434 2435 /** 2436 * Define the list of types to be associated with the columns of a given 2437 * result set. 2438 * 2439 * This function may be called before invoking fetchInto(), fetchOne(), 2440 * fetchRow(), fetchCol() and fetchAll() so that the necessary data type 2441 * conversions are performed on the data to be retrieved by them. If this 2442 * function is not called, the type of all result set columns is assumed 2443 * to be text, thus leading to not perform any conversions. 2444 * 2445 * @param resource $result result identifier 2446 * @param string $types array variable that lists the 2447 * data types to be expected in the result set columns. If this array 2448 * contains less types than the number of columns that are returned 2449 * in the result set, the remaining columns are assumed to be of the 2450 * type text. Currently, the types clob and blob are not fully 2451 * supported. 2452 * @return mixed MDB_OK on success, a MDB error on failure 2453 * @access public 2454 */ 2455 function setResultTypes($result, $types) 2456 { 2457 $result_value = intval($result); 2458 if (isset($this->result_types[$result_value])) { 2459 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 2460 'Set result types: attempted to redefine the types of the columns of a result set')); 2461 } 2462 $columns = $this->numCols($result); 2463 if (MDB::isError($columns)) { 2464 return($columns); 2465 } 2466 if ($columns < count($types)) { 2467 return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 2468 'Set result types: it were specified more result types (' . count($types) . ') than result columns (' . $columns . ')')); 2469 } 2470 $valid_types = array( 2471 'text' => MDB_TYPE_TEXT, 2472 'boolean' => MDB_TYPE_BOOLEAN, 2473 'integer' => MDB_TYPE_INTEGER, 2474 'decimal' => MDB_TYPE_DECIMAL, 2475 'float' => MDB_TYPE_FLOAT, 2476 'date' => MDB_TYPE_DATE, 2477 'time' => MDB_TYPE_TIME, 2478 'timestamp' => MDB_TYPE_TIMESTAMP, 2479 'clob' => MDB_TYPE_CLOB, 2480 'blob' => MDB_TYPE_BLOB 2481 ); 2482 for($column = 0; $column < count($types); $column++) { 2483 if (!isset($valid_types[$types[$column]])) { 2484 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2485 'Set result types: ' . $types[$column] . ' is not a supported column type')); 2486 } 2487 $this->result_types[$result_value][$column] = $valid_types[$types[$column]]; 2488 } 2489 while ($column < $columns) { 2490 $this->result_types[$result_value][$column] = MDB_TYPE_TEXT; 2491 $column++; 2492 } 2493 return(MDB_OK); 2494 } 2495 2496 // }}} 2497 // {{{ affectedRows() 2498 2499 /** 2500 * returns the affected rows of a query 2501 * 2502 * @return mixed MDB_Error or number of rows 2503 * @access public 2504 */ 2505 function affectedRows() 2506 { 2507 if ($this->affected_rows == -1) { 2508 return($this->raiseError(MDB_ERROR_NEED_MORE_DATA)); 2509 } 2510 return($this->affected_rows); 2511 } 2512 2513 // }}} 2514 // {{{ getColumnNames() 2515 2516 /** 2517 * Retrieve the names of columns returned by the DBMS in a query result. 2518 * 2519 * @param resource $result result identifier 2520 * @return mixed associative array variable 2521 * that holds the names of columns. The indexes of the array are 2522 * the column names mapped to lower case and the values are the 2523 * respective numbers of the columns starting from 0. Some DBMS may 2524 * not return any columns when the result set does not contain any 2525 * rows. 2526 * a MDB error on failure 2527 * @access public 2528 */ 2529 function getColumnNames($result) 2530 { 2531 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2532 'Get column names: obtaining result column names is not implemented')); 2533 } 2534 2535 // }}} 2536 // {{{ numCols() 2537 2538 /** 2539 * Count the number of columns returned by the DBMS in a query result. 2540 * 2541 * @param resource $result result identifier 2542 * @return mixed integer value with the number of columns, a MDB error 2543 * on failure 2544 * @access public 2545 */ 2546 function numCols($result) 2547 { 2548 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2549 'Number of columns: obtaining the number of result columns is not implemented')); 2550 } 2551 2552 // }}} 2553 // {{{ endOfResult() 2554 2555 /** 2556 * check if the end of the result set has been reached 2557 * 2558 * @param resource $result result identifier 2559 * @return mixed TRUE or FALSE on sucess, a MDB error on failure 2560 * @access public 2561 */ 2562 function endOfResult($result) 2563 { 2564 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2565 'End of result: end of result method not implemented')); 2566 } 2567 2568 // }}} 2569 // {{{ setFetchMode() 2570 2571 /** 2572 * Sets which fetch mode should be used by default on queries 2573 * on this connection. 2574 * 2575 * @param integer $fetchmode MDB_FETCHMODE_ORDERED or MDB_FETCHMODE_ASSOC, 2576 * possibly bit-wise OR'ed with MDB_FETCHMODE_FLIPPED. 2577 * @access public 2578 * @see MDB_FETCHMODE_ORDERED 2579 * @see MDB_FETCHMODE_ASSOC 2580 * @see MDB_FETCHMODE_FLIPPED 2581 */ 2582 function setFetchMode($fetchmode) 2583 { 2584 switch ($fetchmode) { 2585 case MDB_FETCHMODE_ORDERED: 2586 case MDB_FETCHMODE_ASSOC: 2587 $this->fetchmode = $fetchmode; 2588 break; 2589 default: 2590 return($this->raiseError('invalid fetchmode mode')); 2591 } 2592 } 2593 2594 // }}} 2595 // {{{ fetch() 2596 2597 /** 2598 * fetch value from a result set 2599 * 2600 * @param resource $result result identifier 2601 * @param int $row number of the row where the data can be found 2602 * @param int $field field number where the data can be found 2603 * @return mixed string on success, a MDB error on failure 2604 * @access public 2605 */ 2606 function fetch($result, $row, $field) 2607 { 2608 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2609 'Fetch: fetch result method not implemented')); 2610 } 2611 2612 // }}} 2613 // {{{ fetchLob() 2614 2615 /** 2616 * fetch a lob value from a result set 2617 * 2618 * @param resource $result result identifier 2619 * @param int $row number of the row where the data can be found 2620 * @param int $field field number where the data can be found 2621 * @return mixed string on success, a MDB error on failure 2622 * @access public 2623 */ 2624 function fetchLob($result, $row, $field) 2625 { 2626 $lob = count($this->lobs) + 1; 2627 $this->lobs[$lob] = array( 2628 'Result' => $result, 2629 'Row' => $row, 2630 'Field' => $field, 2631 'Position' => 0 2632 ); 2633 $dst_lob = array( 2634 'Database' => $this, 2635 'Error' => '', 2636 'Type' => 'resultlob', 2637 'ResultLOB' => $lob 2638 ); 2639 if (MDB::isError($lob = $this->createLob($dst_lob))) { 2640 return($this->raiseError(MDB_ERROR, NULL, NULL, 2641 'Fetch LOB result: ' . $dst_lob['Error'])); 2642 } 2643 return($lob); 2644 } 2645 2646 // }}} 2647 // {{{ _retrieveLob() 2648 2649 /** 2650 * fetch a float value from a result set 2651 * 2652 * @param int $lob handle to a lob created by the createLob() function 2653 * @return mixed MDB_OK on success, a MDB error on failure 2654 * @access private 2655 */ 2656 function _retrieveLob($lob) 2657 { 2658 if (!isset($this->lobs[$lob])) { 2659 return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL, 2660 'Fetch LOB result: it was not specified a valid lob')); 2661 } 2662 if (!isset($this->lobs[$lob]['Value'])) { 2663 $this->lobs[$lob]['Value'] = $this->fetch($this->lobs[$lob]['Result'], $this->lobs[$lob]['Row'], $this->lobs[$lob]['Field']); 2664 } 2665 return(MDB_OK); 2666 } 2667 2668 // }}} 2669 // {{{ endOfResultLob() 2670 2671 /** 2672 * Determine whether it was reached the end of the large object and 2673 * therefore there is no more data to be read for the its input stream. 2674 * 2675 * @param int $lob handle to a lob created by the createLob() function 2676 * @return mixed TRUE or FALSE on success, a MDB error on failure 2677 * @access public 2678 */ 2679 function endOfResultLob($lob) 2680 { 2681 $result = $this->_retrieveLob($lob); 2682 if (MDB::isError($result)) { 2683 return($result); 2684 } 2685 return($this->lobs[$lob]['Position'] >= strlen($this->lobs[$lob]['Value'])); 2686 } 2687 2688 // }}} 2689 // {{{ _readResultLob() 2690 2691 /** 2692 * Read data from large object input stream. 2693 * 2694 * @param int $lob handle to a lob created by the createLob() function 2695 * @param blob $data reference to a variable that will hold data to be 2696 * read from the large object input stream 2697 * @param int $length integer value that indicates the largest ammount of 2698 * data to be read from the large object input stream. 2699 * @return mixed length on success, a MDB error on failure 2700 * @access private 2701 */ 2702 function _readResultLob($lob, &$data, $length) 2703 { 2704 $result = $this->_retrieveLob($lob); 2705 if (MDB::isError($result)) { 2706 return($result); 2707 } 2708 $length = min($length, strlen($this->lobs[$lob]['Value']) - $this->lobs[$lob]['Position']); 2709 $data = substr($this->lobs[$lob]['Value'], $this->lobs[$lob]['Position'], $length); 2710 $this->lobs[$lob]['Position'] += $length; 2711 return($length); 2712 } 2713 2714 // }}} 2715 // {{{ _destroyResultLob() 2716 2717 /** 2718 * Free any resources allocated during the lifetime of the large object 2719 * handler object. 2720 * 2721 * @param int $lob handle to a lob created by the createLob() function 2722 * @access private 2723 */ 2724 function _destroyResultLob($lob) 2725 { 2726 if (isset($this->lobs[$lob])) { 2727 $this->lobs[$lob] = ''; 2728 } 2729 } 2730 2731 // }}} 2732 // {{{ fetchClob() 2733 2734 /** 2735 * fetch a clob value from a result set 2736 * 2737 * @param resource $result result identifier 2738 * @param int $row number of the row where the data can be found 2739 * @param int $field field number where the data can be found 2740 * @return mixed content of the specified data cell, a MDB error on failure, 2741 * a MDB error on failure 2742 * @access public 2743 */ 2744 function fetchClob($result, $row, $field) 2745 { 2746 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2747 'fetch clob result method is not implemented')); 2748 } 2749 2750 // }}} 2751 // {{{ fetchBlob() 2752 2753 /** 2754 * fetch a blob value from a result set 2755 * 2756 * @param resource $result result identifier 2757 * @param int $row number of the row where the data can be found 2758 * @param int $field field number where the data can be found 2759 * @return mixed content of the specified data cell, a MDB error on failure 2760 * @access public 2761 */ 2762 function fetchBlob($result, $row, $field) 2763 { 2764 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 2765 'fetch blob result method is not implemented')); 2766 } 2767 2768 // }}} 2769 // {{{ resultIsNull() 2770 2771 /** 2772 * Determine whether the value of a query result located in given row and 2773 * field is a NULL. 2774 * 2775 * @param resource $result result identifier 2776 * @param int $row number of the row where the data can be found 2777 * @param int $field field number where the data can be found 2778 * @return mixed TRUE or FALSE on success, a MDB error on failure 2779 * @access public 2780 */ 2781 function resultIsNull($result, $row, $field) 2782 { 2783 $result = $this->fetch($result, $row, $field); 2784 if (MDB::isError($result)) { 2785 return($result); 2786 } 2787 return(!isset($result)); 2788 } 2789 2790 // }}} 2791 // {{{ _baseConvertResult() 2792 2793 /** 2794 * general type conversion method 2795 * 2796 * @param mixed $value refernce to a value to be converted 2797 * @param int $type constant that specifies which type to convert to 2798 * @return object a MDB error on failure 2799 * @access private 2800 */ 2801 function _baseConvertResult($value, $type) 2802 { 2803 switch ($type) { 2804 case MDB_TYPE_TEXT: 2805 return($value); 2806 case MDB_TYPE_BLOB: 2807 return($value); 2808 case MDB_TYPE_CLOB: 2809 return($value); 2810 case MDB_TYPE_INTEGER: 2811 return(intval($value)); 2812 case MDB_TYPE_BOOLEAN: 2813 return ($value == 'Y') ? TRUE : FALSE; 2814 case MDB_TYPE_DECIMAL: 2815 return($value); 2816 case MDB_TYPE_FLOAT: 2817 return(doubleval($value)); 2818 case MDB_TYPE_DATE: 2819 return($value); 2820 case MDB_TYPE_TIME: 2821 return($value); 2822 case MDB_TYPE_TIMESTAMP: 2823 return($value); 2824 case MDB_TYPE_CLOB: 2825 return($value); 2826 case MDB_TYPE_BLOB: 2827 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 2828 'BaseConvertResult: attempt to convert result value to an unsupported type ' . $type)); 2829 default: 2830 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 2831 'BaseConvertResult: attempt to convert result value to an unknown type ' . $type)); 2832 } 2833 } 2834 2835 // }}} 2836 // {{{ convertResult() 2837 2838 /** 2839 * convert a value to a RDBMS indepdenant MDB type 2840 * 2841 * @param mixed $value value to be converted 2842 * @param int $type constant that specifies which type to convert to 2843 * @return mixed converted value or a MDB error on failure 2844 * @access public 2845 */ 2846 function convertResult($value, $type) 2847 { 2848 return($this->_baseConvertResult($value, $type)); 2849 } 2850 2851 // }}} 2852 // {{{ convertResultRow() 2853 2854 /** 2855 * convert a result row 2856 * 2857 * @param resource $result result identifier 2858 * @param array $row array with data 2859 * @return mixed MDB_OK on success, a MDB error on failure 2860 * @access public 2861 */ 2862 function convertResultRow($result, $row) 2863 { 2864 $result_value = intval($result); 2865 if (isset($this->result_types[$result_value])) { 2866 $current_column = -1; 2867 foreach($row as $key => $column) { 2868 ++$current_column; 2869 if (!isset($this->result_types[$result_value][$current_column]) 2870 ||!isset($column) 2871 ) { 2872 continue; 2873 } 2874 switch ($type = $this->result_types[$result_value][$current_column]) { 2875 case MDB_TYPE_TEXT: 2876 case MDB_TYPE_BLOB: 2877 case MDB_TYPE_CLOB: 2878 break; 2879 case MDB_TYPE_INTEGER: 2880 $row[$key] = intval($row[$key]); 2881 break; 2882 default: 2883 $value = $this->convertResult($row[$key], $type); 2884 if (MDB::isError($value)) { 2885 return $value; 2886 } 2887 $row[$key] = $value; 2888 break; 2889 } 2890 } 2891 } 2892 return ($row); 2893 } 2894 2895 // }}} 2896 // {{{ fetchDate() 2897 2898 /** 2899 * fetch a date value from a result set 2900 * 2901 * @param resource $result result identifier 2902 * @param int $row number of the row where the data can be found 2903 * @param int $field field number where the data can be found 2904 * @return mixed content of the specified data cell, a MDB error on failure 2905 * @access public 2906 */ 2907 function fetchDate($result, $row, $field) 2908 { 2909 $value = $this->fetch($result, $row, $field); 2910 return($this->convertResult($value, MDB_TYPE_DATE)); 2911 } 2912 2913 // }}} 2914 // {{{ fetchTimestamp() 2915 2916 /** 2917 * fetch a timestamp value from a result set 2918 * 2919 * @param resource $result result identifier 2920 * @param int $row number of the row where the data can be found 2921 * @param int $field field number where the data can be found 2922 * @return mixed content of the specified data cell, a MDB error on failure 2923 * @access public 2924 */ 2925 function fetchTimestamp($result, $row, $field) 2926 { 2927 $value = $this->fetch($result, $row, $field); 2928 return($this->convertResult($value, MDB_TYPE_TIMESTAMP)); 2929 } 2930 2931 // }}} 2932 // {{{ fetchTime() 2933 2934 /** 2935 * fetch a time value from a result set 2936 * 2937 * @param resource $result result identifier 2938 * @param int $row number of the row where the data can be found 2939 * @param int $field field number where the data can be found 2940 * @return mixed content of the specified data cell, a MDB error on failure 2941 * @access public 2942 */ 2943 function fetchTime($result, $row, $field) 2944 { 2945 $value = $this->fetch($result, $row, $field); 2946 return($this->convertResult($value, MDB_TYPE_TIME)); 2947 } 2948 2949 // }}} 2950 // {{{ fetchBoolean() 2951 2952 /** 2953 * fetch a boolean value from a result set 2954 * 2955 * @param resource $result result identifier 2956 * @param int $row number of the row where the data can be found 2957 * @param int $field field number where the data can be found 2958 * @return mixed content of the specified data cell, a MDB error on failure 2959 * @access public 2960 */ 2961 function fetchBoolean($result, $row, $field) 2962 { 2963 $value = $this->fetch($result, $row, $field); 2964 return($this->convertResult($value, MDB_TYPE_BOOLEAN)); 2965 } 2966 2967 // }}} 2968 // {{{ fetchFloat() 2969 2970 /** 2971 * fetch a float value from a result set 2972 * 2973 * @param resource $result result identifier 2974 * @param int $row number of the row where the data can be found 2975 * @param int $field field number where the data can be found 2976 * @return mixed content of the specified data cell, a MDB error on failure 2977 * @access public 2978 */ 2979 function fetchFloat($result, $row, $field) 2980 { 2981 $value = $this->fetch($result, $row, $field); 2982 return($this->convertResult($value, MDB_TYPE_FLOAT)); 2983 } 2984 2985 // }}} 2986 // {{{ fetchDecimal() 2987 2988 /** 2989 * fetch a decimal value from a result set 2990 * 2991 * @param resource $result result identifier 2992 * @param int $row number of the row where the data can be found 2993 * @param int $field field number where the data can be found 2994 * @return mixed content of the specified data cell, a MDB error on failure 2995 * @access public 2996 */ 2997 function fetchDecimal($result, $row, $field) 2998 { 2999 $value = $this->fetch($result, $row, $field); 3000 return($this->convertResult($value, MDB_TYPE_DECIMAL)); 3001 } 3002 3003 // }}} 3004 // {{{ numRows() 3005 3006 /** 3007 * returns the number of rows in a result object 3008 * 3009 * @param ressource $result a valid result ressouce pointer 3010 * @return mixed MDB_Error or the number of rows 3011 * @access public 3012 */ 3013 function numRows($result) 3014 { 3015 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Num Rows: number of rows method not implemented')); 3016 } 3017 3018 // }}} 3019 // {{{ freeResult() 3020 3021 /** 3022 * Free the internal resources associated with $result. 3023 * 3024 * @param $result result identifier 3025 * @return boolean TRUE on success, FALSE if $result is invalid 3026 * @access public 3027 */ 3028 function freeResult($result) 3029 { 3030 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Free Result: free result method not implemented')); 3031 } 3032 3033 // }}} 3034 // {{{ getIntegerDeclaration() 3035 3036 /** 3037 * Obtain DBMS specific SQL code portion needed to declare an integer type 3038 * field to be used in statements like CREATE TABLE. 3039 * 3040 * @param string $name name the field to be declared. 3041 * @param string $field associative array with the name of the properties 3042 * of the field being declared as array indexes. Currently, the types 3043 * of supported field properties are as follows: 3044 * 3045 * unsigned 3046 * Boolean flag that indicates whether the field should be 3047 * declared as unsigned integer if possible. 3048 * 3049 * default 3050 * Integer value to be used as default for this field. 3051 * 3052 * notnull 3053 * Boolean flag that indicates whether this field is constrained 3054 * to not be set to NULL. 3055 * @return string DBMS specific SQL code portion that should be used to 3056 * declare the specified field. 3057 * @access public 3058 */ 3059 function getIntegerDeclaration($name, $field) 3060 { 3061 if (isset($field['unsigned'])) { 3062 $this->warnings[] = "unsigned integer field \"$name\" is being 3063 declared as signed integer"; 3064 } 3065 return("$name INT" . (isset($field['default']) ? ' DEFAULT ' . $field['default'] : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3066 } 3067 3068 // }}} 3069 // {{{ getTextDeclaration() 3070 3071 /** 3072 * Obtain DBMS specific SQL code portion needed to declare an text type 3073 * field to be used in statements like CREATE TABLE. 3074 * 3075 * @param string $name name the field to be declared. 3076 * @param string $field associative array with the name of the properties 3077 * of the field being declared as array indexes. Currently, the types 3078 * of supported field properties are as follows: 3079 * 3080 * length 3081 * Integer value that determines the maximum length of the text 3082 * field. If this argument is missing the field should be 3083 * declared to have the longest length allowed by the DBMS. 3084 * 3085 * default 3086 * Text value to be used as default for this field. 3087 * 3088 * notnull 3089 * Boolean flag that indicates whether this field is constrained 3090 * to not be set to NULL. 3091 * @return string DBMS specific SQL code portion that should be used to 3092 * declare the specified field. 3093 * @access public 3094 */ 3095 function getTextDeclaration($name, $field) 3096 { 3097 return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3098 } 3099 3100 // }}} 3101 // {{{ getClobDeclaration() 3102 3103 /** 3104 * Obtain DBMS specific SQL code portion needed to declare an character 3105 * large object type field to be used in statements like CREATE TABLE. 3106 * 3107 * @param string $name name the field to be declared. 3108 * @param string $field associative array with the name of the properties 3109 * of the field being declared as array indexes. Currently, the types 3110 * of supported field properties are as follows: 3111 * 3112 * length 3113 * Integer value that determines the maximum length of the large 3114 * object field. If this argument is missing the field should be 3115 * declared to have the longest length allowed by the DBMS. 3116 * 3117 * notnull 3118 * Boolean flag that indicates whether this field is constrained 3119 * to not be set to NULL. 3120 * @return string DBMS specific SQL code portion that should be used to 3121 * declare the specified field. 3122 * @access public 3123 */ 3124 function getClobDeclaration($name, $field) 3125 { 3126 return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3127 } 3128 3129 // }}} 3130 // {{{ getBlobDeclaration() 3131 3132 /** 3133 * Obtain DBMS specific SQL code portion needed to declare an binary large 3134 * object type field to be used in statements like CREATE TABLE. 3135 * 3136 * @param string $name name the field to be declared. 3137 * @param string $field associative array with the name of the properties 3138 * of the field being declared as array indexes. Currently, the types 3139 * of supported field properties are as follows: 3140 * 3141 * length 3142 * Integer value that determines the maximum length of the large 3143 * object field. If this argument is missing the field should be 3144 * declared to have the longest length allowed by the DBMS. 3145 * 3146 * notnull 3147 * Boolean flag that indicates whether this field is constrained 3148 * to not be set to NULL. 3149 * @return string DBMS specific SQL code portion that should be used to 3150 * declare the specified field. 3151 * @access public 3152 */ 3153 function getBlobDeclaration($name, $field) 3154 { 3155 return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3156 } 3157 3158 // }}} 3159 // {{{ getBooleanDeclaration() 3160 3161 /** 3162 * Obtain DBMS specific SQL code portion needed to declare a boolean type 3163 * field to be used in statements like CREATE TABLE. 3164 * 3165 * @param string $name name the field to be declared. 3166 * @param string $field associative array with the name of the properties 3167 * of the field being declared as array indexes. Currently, the types 3168 * of supported field properties are as follows: 3169 * 3170 * default 3171 * Boolean value to be used as default for this field. 3172 * 3173 * notnullL 3174 * Boolean flag that indicates whether this field is constrained 3175 * to not be set to NULL. 3176 * @return string DBMS specific SQL code portion that should be used to 3177 * declare the specified field. 3178 * @access public 3179 */ 3180 function getBooleanDeclaration($name, $field) 3181 { 3182 return("$name CHAR (1)" . (isset($field['default']) ? ' DEFAULT ' . $this->getBooleanValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3183 } 3184 3185 // }}} 3186 // {{{ getDateDeclaration() 3187 3188 /** 3189 * Obtain DBMS specific SQL code portion needed to declare a date type 3190 * field to be used in statements like CREATE TABLE. 3191 * 3192 * @param string $name name the field to be declared. 3193 * @param string $field associative array with the name of the properties 3194 * of the field being declared as array indexes. Currently, the types 3195 * of supported field properties are as follows: 3196 * 3197 * default 3198 * Date value to be used as default for this field. 3199 * 3200 * notnull 3201 * Boolean flag that indicates whether this field is constrained 3202 * to not be set to NULL. 3203 * @return string DBMS specific SQL code portion that should be used to 3204 * declare the specified field. 3205 * @access public 3206 */ 3207 function getDateDeclaration($name, $field) 3208 { 3209 return("$name CHAR (" . strlen("YYYY-MM-DD") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getDateValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3210 } 3211 3212 // }}} 3213 // {{{ getTimestampDeclaration() 3214 3215 /** 3216 * Obtain DBMS specific SQL code portion needed to declare a timestamp 3217 * field to be used in statements like CREATE TABLE. 3218 * 3219 * @param string $name name the field to be declared. 3220 * @param string $field associative array with the name of the properties 3221 * of the field being declared as array indexes. Currently, the types 3222 * of supported field properties are as follows: 3223 * 3224 * default 3225 * Timestamp value to be used as default for this field. 3226 * 3227 * notnull 3228 * Boolean flag that indicates whether this field is constrained 3229 * to not be set to NULL. 3230 * @return string DBMS specific SQL code portion that should be used to 3231 * declare the specified field. 3232 * @access public 3233 */ 3234 function getTimestampDeclaration($name, $field) 3235 { 3236 return("$name CHAR (" . strlen("YYYY-MM-DD HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimestampValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3237 } 3238 3239 // }}} 3240 // {{{ getTimeDeclaration() 3241 3242 /** 3243 * Obtain DBMS specific SQL code portion needed to declare a time 3244 * field to be used in statements like CREATE TABLE. 3245 * 3246 * @param string $name name the field to be declared. 3247 * @param string $field associative array with the name of the properties 3248 * of the field being declared as array indexes. Currently, the types 3249 * of supported field properties are as follows: 3250 * 3251 * default 3252 * Time value to be used as default for this field. 3253 * 3254 * notnull 3255 * Boolean flag that indicates whether this field is constrained 3256 * to not be set to NULL. 3257 * @return string DBMS specific SQL code portion that should be used to 3258 * declare the specified field. 3259 * @access public 3260 */ 3261 function getTimeDeclaration($name, $field) 3262 { 3263 return("$name CHAR (" . strlen("HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimeValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3264 } 3265 3266 // }}} 3267 // {{{ getFloatDeclaration() 3268 3269 /** 3270 * Obtain DBMS specific SQL code portion needed to declare a float type 3271 * field to be used in statements like CREATE TABLE. 3272 * 3273 * @param string $name name the field to be declared. 3274 * @param string $field associative array with the name of the properties 3275 * of the field being declared as array indexes. Currently, the types 3276 * of supported field properties are as follows: 3277 * 3278 * default 3279 * Float value to be used as default for this field. 3280 * 3281 * notnull 3282 * Boolean flag that indicates whether this field is constrained 3283 * to not be set to NULL. 3284 * @return string DBMS specific SQL code portion that should be used to 3285 * declare the specified field. 3286 * @access public 3287 */ 3288 function getFloatDeclaration($name, $field) 3289 { 3290 return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getFloatValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3291 } 3292 3293 // }}} 3294 // {{{ getDecimalDeclaration() 3295 3296 /** 3297 * Obtain DBMS specific SQL code portion needed to declare a decimal type 3298 * field to be used in statements like CREATE TABLE. 3299 * 3300 * @param string $name name the field to be declared. 3301 * @param string $field associative array with the name of the properties 3302 * of the field being declared as array indexes. Currently, the types 3303 * of supported field properties are as follows: 3304 * 3305 * default 3306 * Decimal value to be used as default for this field. 3307 * 3308 * notnull 3309 * Boolean flag that indicates whether this field is constrained 3310 * to not be set to NULL. 3311 * @return string DBMS specific SQL code portion that should be used to 3312 * declare the specified field. 3313 * @access public 3314 */ 3315 function getDecimalDeclaration($name, $field) 3316 { 3317 return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getDecimalValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 3318 } 3319 3320 // }}} 3321 // {{{ getIntegerValue() 3322 3323 /** 3324 * Convert a text value into a DBMS specific format that is suitable to 3325 * compose query statements. 3326 * 3327 * @param string $value text string value that is intended to be converted. 3328 * @return string text string that represents the given argument value in 3329 * a DBMS specific format. 3330 * @access public 3331 */ 3332 function getIntegerValue($value) 3333 { 3334 return(($value === NULL) ? 'NULL' : (int)$value); 3335 } 3336 3337 // }}} 3338 // {{{ getTextValue() 3339 3340 /** 3341 * Convert a text value into a DBMS specific format that is suitable to 3342 * compose query statements. 3343 * 3344 * @param string $value text string value that is intended to be converted. 3345 * @return string text string that already contains any DBMS specific 3346 * escaped character sequences. 3347 * @access public 3348 */ 3349 function getTextValue($value) 3350 { 3351 return(($value === NULL) ? 'NULL' : "'".$this->_quote($value)."'"); 3352 } 3353 3354 // }}} 3355 // {{{ getClobValue() 3356 3357 /** 3358 * Convert a text value into a DBMS specific format that is suitable to 3359 * compose query statements. 3360 * 3361 * @param resource $prepared_query query handle from prepare() 3362 * @param $parameter 3363 * @param $clob 3364 * @return string text string that represents the given argument value in 3365 * a DBMS specific format. 3366 * @access public 3367 */ 3368 function getClobValue($prepared_query, $parameter, $clob) 3369 { 3370 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 3371 'Get CLOB field value: prepared queries with values of type "clob" are not yet supported')); 3372 } 3373 3374 // }}} 3375 // {{{ freeClobValue() 3376 3377 /** 3378 * free a character large object 3379 * 3380 * @param resource $prepared_query query handle from prepare() 3381 * @param string $blob 3382 * @param string $value 3383 * @access public 3384 */ 3385 function freeClobValue($prepared_query, $clob, &$value) 3386 { 3387 } 3388 3389 // }}} 3390 // {{{ getBlobValue() 3391 3392 /** 3393 * Convert a text value into a DBMS specific format that is suitable to 3394 * compose query statements. 3395 * 3396 * @param resource $prepared_query query handle from prepare() 3397 * @param $parameter 3398 * @param $blob 3399 * @return string text string that represents the given argument value in 3400 * a DBMS specific format. 3401 * @access public 3402 */ 3403 function getBlobValue($prepared_query, $parameter, $blob) 3404 { 3405 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 3406 'Get BLOB field value: prepared queries with values of type "blob" are not yet supported')); 3407 } 3408 3409 // }}} 3410 // {{{ freeBlobValue() 3411 3412 /** 3413 * free a binary large object 3414 * 3415 * @param resource $prepared_query query handle from prepare() 3416 * @param string $blob 3417 * @param string $value 3418 * @access public 3419 */ 3420 function freeBlobValue($prepared_query, $blob, &$value) 3421 { 3422 } 3423 3424 // }}} 3425 // {{{ getBooleanValue() 3426 3427 /** 3428 * Convert a text value into a DBMS specific format that is suitable to 3429 * compose query statements. 3430 * 3431 * @param string $value text string value that is intended to be converted. 3432 * @return string text string that represents the given argument value in 3433 * a DBMS specific format. 3434 * @access public 3435 */ 3436 function getBooleanValue($value) 3437 { 3438 return(($value === NULL) ? 'NULL' : ($value ? "'Y'" : "'N'")); 3439 } 3440 3441 // }}} 3442 // {{{ getDateValue() 3443 3444 /** 3445 * Convert a text value into a DBMS specific format that is suitable to 3446 * compose query statements. 3447 * 3448 * @param string $value text string value that is intended to be converted. 3449 * @return string text string that represents the given argument value in 3450 * a DBMS specific format. 3451 * @access public 3452 */ 3453 function getDateValue($value) 3454 { 3455 return(($value === NULL) ? 'NULL' : "'$value'"); 3456 } 3457 3458 // }}} 3459 // {{{ getTimestampValue() 3460 3461 /** 3462 * Convert a text value into a DBMS specific format that is suitable to 3463 * compose query statements. 3464 * 3465 * @param string $value text string value that is intended to be converted. 3466 * @return string text string that represents the given argument value in 3467 * a DBMS specific format. 3468 * @access public 3469 */ 3470 function getTimestampValue($value) 3471 { 3472 return(($value === NULL) ? 'NULL' : "'$value'"); 3473 } 3474 3475 // }}} 3476 // {{{ getTimeValue() 3477 3478 /** 3479 * Convert a text value into a DBMS specific format that is suitable to 3480 * compose query statements. 3481 * 3482 * @param string $value text string value that is intended to be converted. 3483 * @return string text string that represents the given argument value in 3484 * a DBMS specific format. 3485 * @access public 3486 */ 3487 function getTimeValue($value) 3488 { 3489 return(($value === NULL) ? 'NULL' : "'$value'"); 3490 } 3491 3492 // }}} 3493 // {{{ getFloatValue() 3494 3495 /** 3496 * Convert a text value into a DBMS specific format that is suitable to 3497 * compose query statements. 3498 * 3499 * @param string $value text string value that is intended to be converted. 3500 * @return string text string that represents the given argument value in 3501 * a DBMS specific format. 3502 * @access public 3503 */ 3504 function getFloatValue($value) 3505 { 3506 return(($value === NULL) ? 'NULL' : "'$value'"); 3507 } 3508 3509 // }}} 3510 // {{{ getDecimalValue() 3511 3512 /** 3513 * Convert a text value into a DBMS specific format that is suitable to 3514 * compose query statements. 3515 * 3516 * @param string $value text string value that is intended to be converted. 3517 * @return string text string that represents the given argument value in 3518 * a DBMS specific format. 3519 * @access public 3520 */ 3521 function getDecimalValue($value) 3522 { 3523 return(($value === NULL) ? 'NULL' : "'$value'"); 3524 } 3525 3526 // }}} 3527 // {{{ getValue() 3528 3529 /** 3530 * Convert a text value into a DBMS specific format that is suitable to 3531 * compose query statements. 3532 * 3533 * @param string $type type to which the value should be converted to 3534 * @param string $value text string value that is intended to be converted. 3535 * @return string text string that represents the given argument value in 3536 * a DBMS specific format. 3537 * @access public 3538 */ 3539 function getValue($type, $value) 3540 { 3541 if (empty($type)) { 3542 return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL, 3543 'getValue: called without type to convert to')); 3544 } 3545 if (method_exists($this,"get{$type}Value")) { 3546 return $this->{"get{$type}Value"}($value); 3547 } 3548 return $value; 3549 } 3550 3551 // }}} 3552 // {{{ support() 3553 3554 /** 3555 * Tell whether a DB implementation or its backend extension 3556 * supports a given feature. 3557 * 3558 * @param string $feature name of the feature (see the MDB class doc) 3559 * @return boolean whether this DB implementation supports $feature 3560 * @access public 3561 */ 3562 function support($feature) 3563 { 3564 return(isset($this->supported[$feature]) && $this->supported[$feature]); 3565 } 3566 3567 // }}} 3568 // {{{ getSequenceName() 3569 3570 /** 3571 * adds sequence name formating to a sequence name 3572 * 3573 * @param string $sqn name of the sequence 3574 * @return string formatted sequence name 3575 * @access public 3576 */ 3577 function getSequenceName($sqn) 3578 { 3579 return sprintf($this->options['seqname_format'], 3580 preg_replace('/[^a-z0-9_]/i', '_', $sqn)); 3581 } 3582 3583 // }}} 3584 // {{{ nextId() 3585 3586 /** 3587 * returns the next free id of a sequence 3588 * 3589 * @param string $seq_name name of the sequence 3590 * @param boolean $ondemand when TRUE the seqence is 3591 * automatic created, if it 3592 * not exists 3593 * @return mixed MDB_Error or id 3594 * @access public 3595 */ 3596 function nextId($seq_name, $ondemand = FALSE) 3597 { 3598 return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL, 3599 'Next Sequence: getting next sequence value not supported')); 3600 } 3601 3602 // }}} 3603 // {{{ currId() 3604 3605 /** 3606 * returns the current id of a sequence 3607 * 3608 * @param string $seq_name name of the sequence 3609 * @return mixed MDB_Error or id 3610 * @access public 3611 */ 3612 function currId($seq_name) 3613 { 3614 $this->warnings[] = 'database does not support getting current 3615 sequence value, the sequence value was incremented'; 3616 $this->expectError(MDB_ERROR_NOT_CAPABLE); 3617 $id = $this->nextId($seq_name); 3618 $this->popExpect(MDB_ERROR_NOT_CAPABLE); 3619 if (MDB::isError($id)) { 3620 if ($id->getCode() == MDB_ERROR_NOT_CAPABLE) { 3621 return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL, 3622 'Current Sequence: getting current sequence value not supported')); 3623 } 3624 return($id); 3625 } 3626 return($id); 3627 } 3628 3629 // }}} 3630 // {{{ fetchInto() 3631 3632 /** 3633 * Fetch a row and return data in an array. 3634 * 3635 * @param resource $result result identifier 3636 * @param int $fetchmode ignored 3637 * @param int $rownum the row number to fetch 3638 * @return mixed data array or NULL on success, a MDB error on failure 3639 * @access public 3640 */ 3641 function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL) 3642 { 3643 $result_value = intval($result); 3644 if (MDB::isError($this->endOfResult($result))) { 3645 $this->freeResult($result); 3646 $result = $this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL, 3647 'Fetch field: result set is empty'); 3648 } 3649 if ($rownum == NULL) { 3650 ++$this->highest_fetched_row[$result_value]; 3651 $rownum = $this->highest_fetched_row[$result_value]; 3652 } else { 3653 $this->highest_fetched_row[$result_value] = 3654 max($this->highest_fetched_row[$result_value], $row); 3655 } 3656 if ($fetchmode == MDB_FETCHMODE_DEFAULT) { 3657 $fetchmode = $this->fetchmode; 3658 } 3659 $columns = $this->numCols($result); 3660 if (MDB::isError($columns)) { 3661 return($columns); 3662 } 3663 if ($fetchmode & MDB_FETCHMODE_ASSOC) { 3664 $column_names = $this->getColumnNames($result); 3665 } 3666 for($column = 0; $column < $columns; $column++) { 3667 if (!$this->resultIsNull($result, $rownum, $column)) { 3668 $value = $this->fetch($result, $rownum, $column); 3669 if ($value === FALSE) { 3670 if ($this->options['autofree']) { 3671 $this->freeResult($result); 3672 } 3673 return(NULL); 3674 } elseif (MDB::isError($value)) { 3675 if ($value->getMessage() == '') { 3676 if ($this->options['autofree']) { 3677 $this->freeResult($result); 3678 } 3679 return(NULL); 3680 } else { 3681 return($value); 3682 } 3683 } 3684 } 3685 $row[$column] = $value; 3686 } 3687 if ($fetchmode & MDB_FETCHMODE_ASSOC) { 3688 $row = array_combine($column_names, $row); 3689 if (is_array($row) && $this->options['optimize'] == 'portability') { 3690 $row = array_change_key_case($row, CASE_LOWER); 3691 } 3692 } 3693 if (isset($this->result_types[$result_value])) { 3694 $row = $this->convertResultRow($result, $row); 3695 } 3696 return($row); 3697 } 3698 3699 // }}} 3700 // {{{ fetchOne() 3701 3702 /** 3703 * Fetch and return a field of data (it uses fetchInto for that) 3704 * 3705 * @param resource $result result identifier 3706 * @return mixed data on success, a MDB error on failure 3707 * @access public 3708 */ 3709 function fetchOne($result) 3710 { 3711 $row = $this->fetchInto($result, MDB_FETCHMODE_ORDERED); 3712 if (!$this->options['autofree'] || $row != NULL) { 3713 $this->freeResult($result); 3714 } 3715 if (is_array($row)) { 3716 return($row[0]); 3717 } 3718 return($row); 3719 } 3720 3721 // }}} 3722 // {{{ fetchRow() 3723 3724 /** 3725 * Fetch and return a row of data (it uses fetchInto for that) 3726 * 3727 * @param resource $result result identifier 3728 * @param int $fetchmode how the array data should be indexed 3729 * @param int $rownum the row number to fetch 3730 * @return mixed data array on success, a MDB error on failure 3731 * @access public 3732 */ 3733 function fetchRow($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL) 3734 { 3735 $row = $this->fetchInto($result, $fetchmode, $rownum); 3736 if (!$this->options['autofree'] || $row != NULL) { 3737 $this->freeResult($result); 3738 } 3739 return($row); 3740 } 3741 3742 // }}} 3743 // {{{ fetchCol() 3744 3745 /** 3746 * Fetch and return a column of data (it uses fetchInto for that) 3747 * 3748 * @param resource $result result identifier 3749 * @param int $colnum the row number to fetch 3750 * @return mixed data array on success, a MDB error on failure 3751 * @access public 3752 */ 3753 function fetchCol($result, $colnum = 0) 3754 { 3755 $fetchmode = is_numeric($colnum) ? MDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC; 3756 $column = array(); 3757 $row = $this->fetchInto($result, $fetchmode); 3758 if (is_array($row)) { 3759 if (!array_key_exists($colnum, $row)) { 3760 return($this->raiseError(MDB_ERROR_TRUNCATED)); 3761 } 3762 do { 3763 $column[] = $row[$colnum]; 3764 } while (is_array($row = $this->fetchInto($result, $fetchmode))); 3765 } 3766 if (!$this->options['autofree']) { 3767 $this->freeResult($result); 3768 } 3769 if (MDB::isError($row)) { 3770 return($row); 3771 } 3772 return($column); 3773 } 3774 3775 // }}} 3776 // {{{ fetchAll() 3777 3778 /** 3779 * Fetch and return a column of data (it uses fetchInto for that) 3780 * 3781 * @param resource $result result identifier 3782 * @param int $fetchmode how the array data should be indexed 3783 * @param boolean $rekey if set to TRUE, the $all will have the first 3784 * column as its first dimension 3785 * @param boolean $force_array used only when the query returns exactly 3786 * two columns. If TRUE, the values of the returned array will be 3787 * one-element arrays instead of scalars. 3788 * @param boolean $group if TRUE, the values of the returned array is 3789 * wrapped in another array. If the same key value (in the first 3790 * column) repeats itself, the values will be appended to this array 3791 * instead of overwriting the existing values. 3792 * @return mixed data array on success, a MDB error on failure 3793 * @access public 3794 * @see getAssoc() 3795 */ 3796 function fetchAll($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rekey = FALSE, $force_array = FALSE, $group = FALSE) 3797 { 3798 if ($rekey) { 3799 $cols = $this->numCols($result); 3800 if (MDB::isError($cols)) { 3801 return($cols); 3802 } 3803 if ($cols < 2) { 3804 return($this->raiseError(MDB_ERROR_TRUNCATED)); 3805 } 3806 } 3807 $all = array(); 3808 while (is_array($row = $this->fetchInto($result, $fetchmode))) { 3809 if ($rekey) { 3810 if ($fetchmode & MDB_FETCHMODE_ASSOC) { 3811 $key = reset($row); 3812 unset($row[key($row)]); 3813 } else { 3814 $key = array_shift($row); 3815 } 3816 if (!$force_array && count($row) == 1) { 3817 $row = array_shift($row); 3818 } 3819 if ($group) { 3820 $all[$key][] = $row; 3821 } else { 3822 $all[$key] = $row; 3823 } 3824 } else { 3825 if ($fetchmode & MDB_FETCHMODE_FLIPPED) { 3826 foreach ($row as $key => $val) { 3827 $all[$key][] = $val; 3828 } 3829 } else { 3830 $all[] = $row; 3831 } 3832 } 3833 } 3834 if (!$this->options['autofree']) { 3835 $this->freeResult($result); 3836 } 3837 if (MDB::isError($row)) { 3838 return($row); 3839 } 3840 return($all); 3841 } 3842 3843 // }}} 3844 // {{{ queryOne() 3845 3846 /** 3847 * Execute the specified query, fetch the value from the first column of 3848 * the first row of the result set and then frees 3849 * the result set. 3850 * 3851 * @param string $query the SELECT query statement to be executed. 3852 * @param string $type optional argument that specifies the expected 3853 * datatype of the result set field, so that an eventual conversion 3854 * may be performed. The default datatype is text, meaning that no 3855 * conversion is performed 3856 * @return mixed field value on success, a MDB error on failure 3857 * @access public 3858 */ 3859 function queryOne($query, $type = NULL) 3860 { 3861 if ($type != NULL) { 3862 $type = array($type); 3863 } 3864 $result = $this->query($query, $type); 3865 if (MDB::isError($result)) { 3866 return($result); 3867 } 3868 return($this->fetchOne($result)); 3869 } 3870 3871 // }}} 3872 // {{{ queryRow() 3873 3874 /** 3875 * Execute the specified query, fetch the values from the first 3876 * row of the result set into an array and then frees 3877 * the result set. 3878 * 3879 * @param string $query the SELECT query statement to be executed. 3880 * @param array $types optional array argument that specifies a list of 3881 * expected datatypes of the result set columns, so that the eventual 3882 * conversions may be performed. The default list of datatypes is 3883 * empty, meaning that no conversion is performed. 3884 * @param int $fetchmode how the array data should be indexed 3885 * @return mixed data array on success, a MDB error on failure 3886 * @access public 3887 */ 3888 function queryRow($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT) 3889 { 3890 $result = $this->query($query, $types); 3891 if (MDB::isError($result)) { 3892 return($result); 3893 } 3894 return($this->fetchRow($result, $fetchmode)); 3895 } 3896 3897 // }}} 3898 // {{{ queryCol() 3899 3900 /** 3901 * Execute the specified query, fetch the value from the first column of 3902 * each row of the result set into an array and then frees the result set. 3903 * 3904 * @param string $query the SELECT query statement to be executed. 3905 * @param string $type optional argument that specifies the expected 3906 * datatype of the result set field, so that an eventual conversion 3907 * may be performed. The default datatype is text, meaning that no 3908 * conversion is performed 3909 * @param int $colnum the row number to fetch 3910 * @return mixed data array on success, a MDB error on failure 3911 * @access public 3912 */ 3913 function queryCol($query, $type = NULL, $colnum = 0) 3914 { 3915 if ($type != NULL) { 3916 $type = array($type); 3917 } 3918 $result = $this->query($query, $type); 3919 if (MDB::isError($result)) { 3920 return($result); 3921 } 3922 return($this->fetchCol($result, $colnum)); 3923 } 3924 3925 // }}} 3926 // {{{ queryAll() 3927 3928 /** 3929 * Execute the specified query, fetch all the rows of the result set into 3930 * a two dimensional array and then frees the result set. 3931 * 3932 * @param string $query the SELECT query statement to be executed. 3933 * @param array $types optional array argument that specifies a list of 3934 * expected datatypes of the result set columns, so that the eventual 3935 * conversions may be performed. The default list of datatypes is 3936 * empty, meaning that no conversion is performed. 3937 * @param int $fetchmode how the array data should be indexed 3938 * @param boolean $rekey if set to TRUE, the $all will have the first 3939 * column as its first dimension 3940 * @param boolean $force_array used only when the query returns exactly 3941 * two columns. If TRUE, the values of the returned array will be 3942 * one-element arrays instead of scalars. 3943 * @param boolean $group if TRUE, the values of the returned array is 3944 * wrapped in another array. If the same key value (in the first 3945 * column) repeats itself, the values will be appended to this array 3946 * instead of overwriting the existing values. 3947 * @return mixed data array on success, a MDB error on failure 3948 * @access public 3949 */ 3950 function queryAll($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT, 3951 $rekey = FALSE, $force_array = FALSE, $group = FALSE) 3952 { 3953 if (MDB::isError($result = $this->query($query, $types))) { 3954 return($result); 3955 } 3956 return($this->fetchAll($result, $fetchmode, $rekey, $force_array, $group)); 3957 } 3958 3959 // }}} 3960 // {{{ getOne() 3961 3962 /** 3963 * Fetch the first column of the first row of data returned from 3964 * a query. Takes care of doing the query and freeing the results 3965 * when finished. 3966 * 3967 * @param string $query the SQL query 3968 * @param string $type string that contains the type of the column in the 3969 * result set 3970 * @param array $params if supplied, prepare/execute will be used 3971 * with this array as execute parameters 3972 * @param array $param_types array that contains the types of the values 3973 * defined in $params 3974 * @return mixed MDB_Error or the returned value of the query 3975 * @access public 3976 */ 3977 function getOne($query, $type = NULL, $params = array(), $param_types = NULL) 3978 { 3979 if ($type != NULL) { 3980 $type = array($type); 3981 } 3982 settype($params, 'array'); 3983 if (count($params) > 0) { 3984 $prepared_query = $this->prepareQuery($query); 3985 if (MDB::isError($prepared_query)) { 3986 return($prepared_query); 3987 } 3988 $this->setParamArray($prepared_query, $params, $param_types); 3989 $result = $this->executeQuery($prepared_query, $type); 3990 } else { 3991 $result = $this->query($query, $type); 3992 } 3993 3994 if (MDB::isError($result)) { 3995 return($result); 3996 } 3997 3998 $value = $this->fetchOne($result, MDB_FETCHMODE_ORDERED); 3999 if (MDB::isError($value)) { 4000 return($value); 4001 } 4002 if (isset($prepared_query)) { 4003 $result = $this->freePreparedQuery($prepared_query); 4004 if (MDB::isError($result)) { 4005 return($result); 4006 } 4007 } 4008 4009 return($value); 4010 } 4011 4012 // }}} 4013 // {{{ getRow() 4014 4015 /** 4016 * Fetch the first row of data returned from a query. Takes care 4017 * of doing the query and freeing the results when finished. 4018 * 4019 * @param string $query the SQL query 4020 * @param array $types array that contains the types of the columns in 4021 * the result set 4022 * @param array $params array if supplied, prepare/execute will be used 4023 * with this array as execute parameters 4024 * @param array $param_types array that contains the types of the values 4025 * defined in $params 4026 * @param integer $fetchmode the fetch mode to use 4027 * @return array the first row of results as an array indexed from 4028 * 0, or a MDB error code. 4029 * @access public 4030 */ 4031 function getRow($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT) 4032 { 4033 settype($params, 'array'); 4034 if (count($params) > 0) { 4035 $prepared_query = $this->prepareQuery($query); 4036 if (MDB::isError($prepared_query)) { 4037 return($prepared_query); 4038 } 4039 $this->setParamArray($prepared_query, $params, $param_types); 4040 $result = $this->executeQuery($prepared_query, $types); 4041 } else { 4042 $result = $this->query($query, $types); 4043 } 4044 4045 if (MDB::isError($result)) { 4046 return($result); 4047 } 4048 4049 $row = $this->fetchRow($result, $fetchmode); 4050 if (MDB::isError($row)) { 4051 return($row); 4052 } 4053 if (isset($prepared_query)) { 4054 $result = $this->freePreparedQuery($prepared_query); 4055 if (MDB::isError($result)) { 4056 return($result); 4057 } 4058 } 4059 4060 return($row); 4061 } 4062 4063 // }}} 4064 // {{{ getCol() 4065 4066 /** 4067 * Fetch a single column from a result set and return it as an 4068 * indexed array. 4069 * 4070 * @param string $query the SQL query 4071 * @param string $type string that contains the type of the column in the 4072 * result set 4073 * @param array $params array if supplied, prepare/execute will be used 4074 * with this array as execute parameters 4075 * @param array $param_types array that contains the types of the values 4076 * defined in $params 4077 * @param mixed $colnum which column to return(integer [column number, 4078 * starting at 0] or string [column name]) 4079 * @return array an indexed array with the data from the first 4080 * row at index 0, or a MDB error code. 4081 * @access public 4082 */ 4083 function getCol($query, $type = NULL, $params = array(), $param_types = NULL, $colnum = 0) 4084 { 4085 if ($type != NULL) { 4086 $type = array($type); 4087 } 4088 settype($params, 'array'); 4089 if (count($params) > 0) { 4090 $prepared_query = $this->prepareQuery($query); 4091 4092 if (MDB::isError($prepared_query)) { 4093 return($prepared_query); 4094 } 4095 $this->setParamArray($prepared_query, $params, $param_types); 4096 $result = $this->executeQuery($prepared_query, $type); 4097 } else { 4098 $result = $this->query($query, $type); 4099 } 4100 4101 if (MDB::isError($result)) { 4102 return($result); 4103 } 4104 4105 $col = $this->fetchCol($result, $colnum); 4106 if (MDB::isError($col)) { 4107 return($col); 4108 } 4109 if (isset($prepared_query)) { 4110 $result = $this->freePreparedQuery($prepared_query); 4111 if (MDB::isError($result)) { 4112 return($result); 4113 } 4114 } 4115 return($col); 4116 } 4117 4118 // }}} 4119 // {{{ getAssoc() 4120 4121 /** 4122 * Fetch the entire result set of a query and return it as an 4123 * associative array using the first column as the key. 4124 * 4125 * If the result set contains more than two columns, the value 4126 * will be an array of the values from column 2-n. If the result 4127 * set contains only two columns, the returned value will be a 4128 * scalar with the value of the second column (unless forced to an 4129 * array with the $force_array parameter). A MDB error code is 4130 * returned on errors. If the result set contains fewer than two 4131 * columns, a MDB_ERROR_TRUNCATED error is returned. 4132 * 4133 * For example, if the table 'mytable' contains: 4134 * 4135 * ID TEXT DATE 4136 * -------------------------------- 4137 * 1 'one' 944679408 4138 * 2 'two' 944679408 4139 * 3 'three' 944679408 4140 * 4141 * Then the call getAssoc('SELECT id,text FROM mytable') returns: 4142 * array( 4143 * '1' => 'one', 4144 * '2' => 'two', 4145 * '3' => 'three', 4146 * ) 4147 * 4148 * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: 4149 * array( 4150 * '1' => array('one', '944679408'), 4151 * '2' => array('two', '944679408'), 4152 * '3' => array('three', '944679408') 4153 * ) 4154 * 4155 * If the more than one row occurs with the same value in the 4156 * first column, the last row overwrites all previous ones by 4157 * default. Use the $group parameter if you don't want to 4158 * overwrite like this. Example: 4159 * 4160 * getAssoc('SELECT category,id,name FROM mytable', NULL, NULL 4161 * MDB_FETCHMODE_ASSOC, FALSE, TRUE) returns: 4162 * array( 4163 * '1' => array(array('id' => '4', 'name' => 'number four'), 4164 * array('id' => '6', 'name' => 'number six') 4165 * ), 4166 * '9' => array(array('id' => '4', 'name' => 'number four'), 4167 * array('id' => '6', 'name' => 'number six') 4168 * ) 4169 * ) 4170 * 4171 * Keep in mind that database functions in PHP usually return string 4172 * values for results regardless of the database's internal type. 4173 * 4174 * @param string $query the SQL query 4175 * @param array $types array that contains the types of the columns in 4176 * the result set 4177 * @param array $params array if supplied, prepare/execute will be used 4178 * with this array as execute parameters 4179 * @param array $param_types array that contains the types of the values 4180 * defined in $params 4181 * @param boolean $force_array used only when the query returns 4182 * exactly two columns. If TRUE, the values of the returned array 4183 * will be one-element arrays instead of scalars. 4184 * @param boolean $group if TRUE, the values of the returned array 4185 * is wrapped in another array. If the same key value (in the first 4186 * column) repeats itself, the values will be appended to this array 4187 * instead of overwriting the existing values. 4188 * @return array associative array with results from the query. 4189 * @access public 4190 */ 4191 function getAssoc($query, $types = NULL, $params = array(), $param_types = NULL, 4192 $fetchmode = MDB_FETCHMODE_ORDERED, $force_array = FALSE, $group = FALSE) 4193 { 4194 settype($params, 'array'); 4195 if (count($params) > 0) { 4196 $prepared_query = $this->prepareQuery($query); 4197 4198 if (MDB::isError($prepared_query)) { 4199 return($prepared_query); 4200 } 4201 $this->setParamArray($prepared_query, $params, $param_types); 4202 $result = $this->executeQuery($prepared_query, $types); 4203 } else { 4204 $result = $this->query($query, $types); 4205 } 4206 4207 if (MDB::isError($result)) { 4208 return($result); 4209 } 4210 4211 $all = $this->fetchAll($result, $fetchmode, TRUE, $force_array, $group); 4212 if (MDB::isError($all)) { 4213 return($all); 4214 } 4215 if (isset($prepared_query)) { 4216 $result = $this->freePreparedQuery($prepared_query); 4217 if (MDB::isError($result)) { 4218 return($result); 4219 } 4220 } 4221 return($all); 4222 } 4223 4224 // }}} 4225 // {{{ getAll() 4226 4227 /** 4228 * Fetch all the rows returned from a query. 4229 * 4230 * @param string $query the SQL query 4231 * @param array $types array that contains the types of the columns in 4232 * the result set 4233 * @param array $params array if supplied, prepare/execute will be used 4234 * with this array as execute parameters 4235 * @param array $param_types array that contains the types of the values 4236 * defined in $params 4237 * @param integer $fetchmode the fetch mode to use 4238 * @return array an nested array, or a MDB error 4239 * @access public 4240 */ 4241 function getAll($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT) 4242 { 4243 settype($params, 'array'); 4244 if (count($params) > 0) { 4245 $prepared_query = $this->prepareQuery($query); 4246 4247 if (MDB::isError($prepared_query)) { 4248 return($prepared_query); 4249 } 4250 $this->setParamArray($prepared_query, $params, $param_types); 4251 $result = $this->executeQuery($prepared_query, $types); 4252 } else { 4253 $result = $this->query($query, $types); 4254 } 4255 4256 if (MDB::isError($result)) { 4257 return($result); 4258 } 4259 4260 $all = $this->fetchAll($result, $fetchmode); 4261 if (MDB::isError($all)) { 4262 return($all); 4263 } 4264 if (isset($prepared_query)) { 4265 $result = $this->freePreparedQuery($prepared_query); 4266 if (MDB::isError($result)) { 4267 return($result); 4268 } 4269 } 4270 return($all); 4271 } 4272 4273 // }}} 4274 // {{{ tableInfo() 4275 4276 /** 4277 * returns meta data about the result set 4278 * 4279 * @param resource $result result identifier 4280 * @param mixed $mode depends on implementation 4281 * @return array an nested array, or a MDB error 4282 * @access public 4283 */ 4284 function tableInfo($result, $mode = NULL) 4285 { 4286 return($this->raiseError(MDB_ERROR_NOT_CAPABLE)); 4287 } 4288 4289 // }}} 4290 // {{{ createLob() 4291 4292 /** 4293 * Create a handler object of a specified class with functions to 4294 * retrieve data from a large object data stream. 4295 * 4296 * @param array $arguments An associative array with parameters to create 4297 * the handler object. The array indexes are the names of 4298 * the parameters and the array values are the respective 4299 * parameter values. 4300 * 4301 * Some parameters are specific of the class of each type 4302 * of handler object that is created. The following 4303 * parameters are common to all handler object classes: 4304 * 4305 * Type 4306 * 4307 * Name of the type of the built-in supported class 4308 * that will be used to create the handler object. 4309 * There are currently four built-in types of handler 4310 * object classes: data, resultlob, inputfile and 4311 * outputfile. 4312 * 4313 * The data handler class is the default class. It 4314 * simply reads data from a given data string. 4315 * 4316 * The resultlob handler class is meant to read data 4317 * from a large object retrieved from a query result. 4318 * This class is not used directly by applications. 4319 * 4320 * The inputfile handler class is meant to read data 4321 * from a file to use in prepared queries with large 4322 * object field parameters. 4323 * 4324 * The outputfile handler class is meant to write to 4325 * a file data from result columns with large object 4326 * fields. The functions to read from this type of 4327 * large object do not return any data. Instead, the 4328 * data is just written to the output file with the 4329 * data retrieved from a specified large object handle. 4330 * 4331 * Class 4332 * 4333 * Name of the class of the handler object that will be 4334 * created if the Type argument is not specified. This 4335 * argument should be used when you need to specify a 4336 * custom handler class. 4337 * 4338 * Database 4339 * 4340 * Database object as returned by MDB::connect. 4341 * This is an option argument needed by some handler 4342 * classes like resultlob. 4343 * 4344 * The following arguments are specific of the inputfile 4345 * handler class: 4346 * 4347 * File 4348 * 4349 * Integer handle value of a file already opened 4350 * for writing. 4351 * 4352 * FileName 4353 * 4354 * Name of a file to be opened for writing if the 4355 * File argument is not specified. 4356 * 4357 * The following arguments are specific of the outputfile 4358 * handler class: 4359 * 4360 * File 4361 * 4362 * Integer handle value of a file already opened 4363 * for writing. 4364 * 4365 * FileName 4366 * 4367 * Name of a file to be opened for writing if the 4368 * File argument is not specified. 4369 * 4370 * BufferLength 4371 * 4372 * Integer value that specifies the length of a 4373 * buffer that will be used to read from the 4374 * specified large object. 4375 * 4376 * LOB 4377 * 4378 * Integer handle value that specifies a large 4379 * object from which the data to be stored in the 4380 * output file will be written. 4381 * 4382 * Result 4383 * 4384 * Integer handle value as returned by the function 4385 * MDB::query() or MDB::executeQuery() that specifies 4386 * the result set that contains the large object value 4387 * to be retrieved. If the LOB argument is specified, 4388 * this argument is ignored. 4389 * 4390 * Row 4391 * 4392 * Integer value that specifies the number of the 4393 * row of the result set that contains the large 4394 * object value to be retrieved. If the LOB 4395 * argument is specified, this argument is ignored. 4396 * 4397 * Field 4398 * 4399 * Integer or string value that specifies the 4400 * number or the name of the column of the result 4401 * set that contains the large object value to be 4402 * retrieved. If the LOB argument is specified, 4403 * this argument is ignored. 4404 * 4405 * Binary 4406 * 4407 * Boolean value that specifies whether the large 4408 * object column to be retrieved is of binary type 4409 * (blob) or otherwise is of character type (clob). 4410 * If the LOB argument is specified, this argument 4411 * is ignored. 4412 * 4413 * The following argument is specific of the data 4414 * handler class: 4415 * 4416 * Data 4417 * 4418 * String of data that will be returned by the class 4419 * when it requested with the readLOB() method. 4420 * 4421 * The following argument is specific of the resultlob 4422 * handler class: 4423 * 4424 * ResultLOB 4425 * 4426 * Integer handle value of a large object result 4427 * row field. 4428 * @return integer handle value that should be passed as argument insubsequent 4429 * calls to functions that retrieve data from the large object input stream. 4430 * @access public 4431 */ 4432 function createLob($arguments) 4433 { 4434 $result = $this->loadLob('Create LOB'); 4435 if (MDB::isError($result)) { 4436 return($result); 4437 } 4438 $class_name = 'MDB_LOB'; 4439 if (isset($arguments['Type'])) { 4440 switch ($arguments['Type']) { 4441 case 'data': 4442 break; 4443 case 'resultlob': 4444 $class_name = 'MDB_LOB_Result'; 4445 break; 4446 case 'inputfile': 4447 $class_name = 'MDB_LOB_Input_File'; 4448 break; 4449 case 'outputfile': 4450 $class_name = 'MDB_LOB_Output_File'; 4451 break; 4452 default: 4453 if (isset($arguments['Error'])) { 4454 $arguments['Error'] = $arguments['Type'] . ' is not a valid type of large object'; 4455 } 4456 return($this->raiseError()); 4457 } 4458 } else { 4459 if (isset($arguments['Class'])) { 4460 $class = $arguments['Class']; 4461 } 4462 } 4463 $lob = count($GLOBALS['_MDB_lobs']) + 1; 4464 $GLOBALS['_MDB_lobs'][$lob] = &new $class_name; 4465 if (isset($arguments['Database'])) { 4466 $GLOBALS['_MDB_lobs'][$lob]->database = $arguments['Database']; 4467 } else { 4468 $GLOBALS['_MDB_lobs'][$lob]->database = &$this; 4469 } 4470 if (MDB::isError($result = $GLOBALS['_MDB_lobs'][$lob]->create($arguments))) { 4471 $GLOBALS['_MDB_lobs'][$lob]->database->destroyLob($lob); 4472 return($result); 4473 } 4474 return($lob); 4475 } 4476 4477 // }}} 4478 // {{{ readLob() 4479 4480 /** 4481 * Read data from large object input stream. 4482 * 4483 * @param integer $lob argument handle that is returned by the 4484 * MDB::createLob() method. 4485 * @param string $data reference to a variable that will hold data 4486 * to be read from the large object input stream 4487 * @param integer $length value that indicates the largest ammount ofdata 4488 * to be read from the large object input stream. 4489 * @return mixed the effective number of bytes read from the large object 4490 * input stream on sucess or an MDB error object. 4491 * @access public 4492 * @see endOfLob() 4493 */ 4494 function readLob($lob, &$data, $length) 4495 { 4496 return($GLOBALS['_MDB_lobs'][$lob]->readLob($data, $length)); 4497 } 4498 4499 // }}} 4500 // {{{ endOfLob() 4501 4502 /** 4503 * Determine whether it was reached the end of the large object and 4504 * therefore there is no more data to be read for the its input stream. 4505 * 4506 * @param integer $lob argument handle that is returned by the 4507 * MDB::createLob() method. 4508 * @access public 4509 * @return boolean flag that indicates whether it was reached the end of the large object input stream 4510 */ 4511 function endOfLob($lob) 4512 { 4513 return($GLOBALS['_MDB_lobs'][$lob]->endOfLob()); 4514 } 4515 4516 // }}} 4517 // {{{ destroyLob() 4518 4519 /** 4520 * Free any resources allocated during the lifetime of the large object 4521 * handler object. 4522 * 4523 * @param integer $lob argument handle that is returned by the 4524 * MDB::createLob() method. 4525 * @access public 4526 */ 4527 function destroyLob($lob) 4528 { 4529 $GLOBALS['_MDB_lobs'][$lob]->destroy(); 4530 unset($GLOBALS['_MDB_lobs'][$lob]); 4531 } 4532 4533 // }}} 4534 // {{{ Destructor 4535 4536 /** 4537 * this function closes open transactions to be executed at shutdown 4538 * 4539 * @access private 4540 */ 4541 function _MDB_Common() 4542 { 4543 if ($this->in_transaction && !MDB::isError($this->rollback())) { 4544 $this->autoCommit(TRUE); 4545 } 4546 } 4547}; 4548?> 4549