[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
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, Frank M. Kromann | 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@dybnet.de> | 43 // +----------------------------------------------------------------------+ 44 // 45 // $Id: fbsql.php,v 1.16.4.16 2004/04/08 17:19:00 lsmith Exp $ 46 // 47 48 require_once ('MDB/Common.php'); 49 50 /** 51 * MDB FrontBase driver 52 * 53 * Notes: 54 * - This driver is fairly untested at this time and shoukd be considered 55 * alpha quality for this reason 56 * 57 * @package MDB 58 * @category Database 59 * @author Lukas Smith <smith@dybnet.de> 60 * @author Frank M. Kromann <frank@kromann.info> 61 */ 62 class MDB_fbsql extends MDB_Common 63 { 64 // {{{ properties 65 66 var $connection = 0; 67 var $connected_host; 68 var $connected_user; 69 var $connected_password; 70 var $connected_port; 71 var $opened_persistent = ''; 72 73 var $escape_quotes = "'"; 74 var $decimal_factor = 1.0; 75 76 var $max_text_length = 32768; 77 78 var $highest_fetched_row = array(); 79 var $columns = array(); 80 81 // }}} 82 // {{{ constructor 83 84 /** 85 * Constructor 86 */ 87 function MDB_fbsql() 88 { 89 $this->MDB_Common(); 90 $this->phptype = 'fbsql'; 91 $this->dbsyntax = 'fbsql'; 92 93 $this->supported['Sequences'] = 1; 94 $this->supported['Indexes'] = 1; 95 $this->supported['AffectedRows'] = 1; 96 $this->supported['Summaryfunctions'] = 1; 97 $this->supported['OrderByText'] = 1; 98 $this->supported['CurrId'] = 0; 99 $this->supported['SelectRowRanges'] = 1; 100 $this->supported['LOBs'] = 1; 101 $this->supported['Replace'] = 1; 102 $this->supported['SubSelects'] = 1; 103 104 $this->decimal_factor = pow(10.0, $this->decimal_places); 105 106 $this->errorcode_map = array( 107 1004 => MDB_ERROR_CANNOT_CREATE, 108 1005 => MDB_ERROR_CANNOT_CREATE, 109 1006 => MDB_ERROR_CANNOT_CREATE, 110 1007 => MDB_ERROR_ALREADY_EXISTS, 111 1008 => MDB_ERROR_CANNOT_DROP, 112 1046 => MDB_ERROR_NODBSELECTED, 113 1050 => MDB_ERROR_ALREADY_EXISTS, 114 1051 => MDB_ERROR_NOSUCHTABLE, 115 1054 => MDB_ERROR_NOSUCHFIELD, 116 1062 => MDB_ERROR_ALREADY_EXISTS, 117 1064 => MDB_ERROR_SYNTAX, 118 1100 => MDB_ERROR_NOT_LOCKED, 119 1136 => MDB_ERROR_VALUE_COUNT_ON_ROW, 120 1146 => MDB_ERROR_NOSUCHTABLE, 121 ); 122 } 123 124 // }}} 125 // {{{ errorNative() 126 127 /** 128 * Get the native error code of the last error (if any) that 129 * occured on the current connection. 130 * 131 * @access public 132 * 133 * @return int native FrontBase error code 134 */ 135 function errorNative() 136 { 137 return @fbsql_errno($this->connection); 138 } 139 140 // }}} 141 // {{{ fbsqlRaiseError() 142 143 /** 144 * This method is used to communicate an error and invoke error 145 * callbacks etc. Basically a wrapper for MDB::raiseError 146 * that checks for native error msgs. 147 * 148 * @param integer $errno error code 149 * @param string $message userinfo message 150 * @return object a PEAR error object 151 * @access public 152 * @see PEAR_Error 153 */ 154 function fbsqlRaiseError($errno = NULL, $message = NULL) 155 { 156 if ($errno == NULL) { 157 if ($this->connection) { 158 $errno = @fbsql_errno($this->connection); 159 } else { 160 $errno = @fbsql_errno(); 161 } 162 } 163 if ($this->connection) { 164 $error = @fbsql_errno($this->connection); 165 } else { 166 $error = @fbsql_error(); 167 } 168 return($this->raiseError($this->errorCode($errno), NULL, NULL, 169 $message, $error)); 170 } 171 172 // }}} 173 // {{{ autoCommit() 174 175 /** 176 * Define whether database changes done on the database be automatically 177 * committed. This function may also implicitly start or end a transaction. 178 * 179 * @param boolean $auto_commit flag that indicates whether the database 180 * changes should be committed right after 181 * executing every query statement. If this 182 * argument is 0 a transaction implicitly 183 * started. Otherwise, if a transaction is 184 * in progress it is ended by committing any 185 * database changes that were pending. 186 * 187 * @access public 188 * 189 * @return mixed MDB_OK on success, a MDB error on failure 190 */ 191 function autoCommit($auto_commit) 192 { 193 $this->debug('AutoCommit: '.($auto_commit ? 'On' : 'Off')); 194 if (!isset($this->supported['Transactions'])) { 195 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 196 'Auto-commit transactions: transactions are not in use')); 197 } 198 if ($this->auto_commit == $auto_commit) { 199 return(MDB_OK); 200 } 201 if ($this->connection) { 202 if ($auto_commit) { 203 $result = $this->query('COMMIT'); 204 if (MDB::isError($result)) { 205 return($result); 206 } 207 $result = $this->query('SET COMMIT TRUE'); 208 } else { 209 $result = $this->query('SET COMMIT FALSE'); 210 } 211 if (MDB::isError($result)) { 212 return($result); 213 } 214 } 215 $this->auto_commit = $auto_commit; 216 $this->in_transaction = !$auto_commit; 217 return(MDB_OK); 218 } 219 220 // }}} 221 // {{{ commit() 222 223 /** 224 * Commit the database changes done during a transaction that is in 225 * progress. This function may only be called when auto-committing is 226 * disabled, otherwise it will fail. Therefore, a new transaction is 227 * implicitly started after committing the pending changes. 228 * 229 * @access public 230 * 231 * @return mixed MDB_OK on success, a MDB error on failure 232 */ 233 function commit() 234 { 235 $this->debug('Commit Transaction'); 236 if (!isset($this->supported['Transactions'])) { 237 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 238 'Commit transactions: transactions are not in use')); 239 } 240 if ($this->auto_commit) { 241 return($this->raiseError(MDB_ERROR, NULL, NULL, 242 'Commit transactions: transaction changes are being auto commited')); 243 } 244 return($this->query('COMMIT')); 245 } 246 247 // }}} 248 // {{{ rollback() 249 250 /** 251 * Cancel any database changes done during a transaction that is in 252 * progress. This function may only be called when auto-committing is 253 * disabled, otherwise it will fail. Therefore, a new transaction is 254 * implicitly started after canceling the pending changes. 255 * 256 * @access public 257 * 258 * @return mixed MDB_OK on success, a MDB error on failure 259 */ 260 function rollback() 261 { 262 $this->debug('Rollback Transaction'); 263 if (!isset($this->supported['Transactions'])) { 264 return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 265 'Rollback transactions: transactions are not in use')); 266 } 267 if ($this->auto_commit) { 268 return($this->raiseError(MDB_ERROR, NULL, NULL, 269 'Rollback transactions: transactions can not be rolled back when changes are auto commited')); 270 } 271 return($this->query('ROLLBACK')); 272 } 273 274 // }}} 275 // {{{ connect() 276 277 /** 278 * Connect to the database 279 * 280 * @return TRUE on success, MDB_Error on failure 281 **/ 282 function connect() 283 { 284 $port = (isset($this->port) ? $this->port : 0); 285 if($this->connection != 0) { 286 if (!strcmp($this->connected_host, $this->host) 287 && !strcmp($this->connected_user, $this->user) 288 && !strcmp($this->connected_password, $this->password) 289 && !strcmp($this->connected_port, $port) 290 && $this->opened_persistent == $this->options['persistent']) 291 { 292 return(MDB_OK); 293 } 294 @fbsql_close($this->connection); 295 $this->connection = 0; 296 $this->affected_rows = -1; 297 } 298 if(!PEAR::loadExtension($this->phptype)) { 299 return(PEAR::raiseError(NULL, MDB_ERROR_NOT_FOUND, 300 NULL, NULL, 'extension '.$this->phptype.' is not compiled into PHP', 301 'MDB_Error', TRUE)); 302 } 303 304 $function = ($this->options['persistent'] ? 'fbsql_pconnect' : 'fbsql_connect'); 305 if(!function_exists($function)) { 306 return($this->raiseError(MDB_ERROR_UNSUPPORTED)); 307 } 308 309 @ini_set('track_errors', TRUE); 310 $this->connection = @$function( 311 $port > 0 ? $port : $this->host, 312 $this->user, $this->password); 313 @ini_restore('track_errors'); 314 if ($this->connection <= 0) { 315 return($this->raiseError(MDB_ERROR_CONNECT_FAILED, NULL, NULL, 316 $php_errormsg)); 317 } 318 319 if (isset($this->supported['Transactions']) && !$this->auto_commit) { 320 if (!@fbsql_query('SET AUTOCOMMIT FALSE;', $this->connection)) { 321 @fbsql_close($this->connection); 322 $this->connection = 0; 323 $this->affected_rows = -1; 324 return($this->raiseError()); 325 } 326 $this->in_transaction = TRUE; 327 } 328 $this->connected_host = $this->host; 329 $this->connected_user = $this->user; 330 $this->connected_password = $this->password; 331 $this->connected_port = $port; 332 $this->opened_persistent = $this->options['persistent']; 333 return(MDB_OK); 334 } 335 336 // }}} 337 // {{{ _close() 338 /** 339 * all the RDBMS specific things needed close a DB connection 340 * 341 * @return boolean 342 * @access private 343 **/ 344 function _close() 345 { 346 if ($this->connection != 0) { 347 if (isset($this->supported['Transactions']) && !$this->auto_commit) { 348 $result = $this->autoCommit(TRUE); 349 } 350 @fbsql_close($this->connection); 351 $this->connection = 0; 352 $this->affected_rows = -1; 353 if (isset($result) && MDB::isError($result)) { 354 return($result); 355 } 356 357 unset($GLOBALS['_MDB_databases'][$this->database]); 358 return(TRUE); 359 } 360 return(FALSE); 361 } 362 363 // }}} 364 // {{{ query() 365 366 /** 367 * Send a query to the database and return any results 368 * 369 * @access public 370 * 371 * @param string $query the SQL query 372 * @param mixed $types array that contains the types of the columns in 373 * the result set 374 * 375 * @return mixed a result handle or MDB_OK on success, a MDB error on failure 376 */ 377 function query($query, $types = NULL) 378 { 379 $this->debug("Query: $query"); 380 $ismanip = MDB::isManip($query); 381 $this->last_query = $query; 382 $first = $this->first_selected_row; 383 $limit = $this->selected_row_limit; 384 $this->first_selected_row = $this->selected_row_limit = 0; 385 386 $result = $this->connect(); 387 if (MDB::isError($result)) { 388 return($result); 389 } 390 if($limit > 0) { 391 if (!$ismanip) { 392 $query = str_replace('SELECT', "SELECT TOP($first,$limit)", $query); 393 } 394 } 395 396 if ($this->database_name != '') { 397 if(!@fbsql_select_db($this->database_name, $this->connection)) { 398 return($this->fbsqlRaiseError()); 399 } 400 } 401 402 // Add ; to the end of the query. This is required by FrontBase 403 $query .= ';'; 404 if ($result = @fbsql_query($query, $this->connection)) { 405 if ($ismanip) { 406 $this->affected_rows = @fbsql_affected_rows($this->connection); 407 return(MDB_OK); 408 } else { 409 $result_value = intval($result); 410 $this->highest_fetched_row[$result_value] = -1; 411 if ($types != NULL) { 412 if (!is_array($types)) { 413 $types = array($types); 414 } 415 if (MDB::isError($err = $this->setResultTypes($result, $types))) { 416 $this->freeResult($result); 417 return($err); 418 } 419 } 420 return($result); 421 } 422 } 423 return($this->fbsqlRaiseError()); 424 } 425 426 // }}} 427 // {{{ getColumnNames() 428 429 /** 430 * Retrieve the names of columns returned by the DBMS in a query result. 431 * 432 * @param resource $result result identifier 433 * @return mixed an associative array variable 434 * that will hold the names of columns. The 435 * indexes of the array are the column names 436 * mapped to lower case and the values are the 437 * respective numbers of the columns starting 438 * from 0. Some DBMS may not return any 439 * columns when the result set does not 440 * contain any rows. 441 * 442 * a MDB error on failure 443 * @access public 444 */ 445 function getColumnNames($result) 446 { 447 $result_value = intval($result); 448 if (!isset($this->highest_fetched_row[$result_value])) { 449 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 450 'Get column names: it was specified an inexisting result set')); 451 } 452 if (!isset($this->columns[$result_value])) { 453 $this->columns[$result_value] = array(); 454 $columns = @fbsql_num_fields($result); 455 for($column = 0; $column < $columns; $column++) { 456 $field_name = @fbsql_field_name($result, $column); 457 if ($this->options['optimize'] == 'portability') { 458 $field_name = strtolower($field_name); 459 } 460 $this->columns[$result_value][$field_name] = $column; 461 } 462 } 463 return($this->columns[$result_value]); 464 } 465 466 // }}} 467 // {{{ numCols() 468 469 /** 470 * Count the number of columns returned by the DBMS in a query result. 471 * 472 * @param resource $result result identifier 473 * @access public 474 * @return mixed integer value with the number of columns, a MDB error 475 * on failure 476 */ 477 function numCols($result) 478 { 479 if (!isset($this->highest_fetched_row[intval($result)])) { 480 return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL, 481 'numCols: it was specified an inexisting result set')); 482 } 483 return(@fbsql_num_fields($result)); 484 } 485 486 // }}} 487 // {{{ endOfResult() 488 489 /** 490 * check if the end of the result set has been reached 491 * 492 * @param resource $result result identifier 493 * @return mixed TRUE or FALSE on sucess, a MDB error on failure 494 * @access public 495 */ 496 function endOfResult($result) 497 { 498 $result_value = intval($result); 499 if (!isset($this->highest_fetched_row[$result_value])) { 500 return($this->raiseError(MDB_ERROR, NULL, NULL, 501 'End of result: attempted to check the end of an unknown result')); 502 } 503 return($this->highest_fetched_row[$result_value] >= $this->numRows($result)-1); 504 } 505 506 // }}} 507 // {{{ fetch() 508 509 /** 510 * fetch value from a result set 511 * 512 * @param resource $result result identifier 513 * @param int $row number of the row where the data can be found 514 * @param int $field field number where the data can be found 515 * @return mixed string on success, a MDB error on failure 516 * @access public 517 */ 518 function fetch($result, $row, $field) 519 { 520 $result_value = intval($result); 521 $this->highest_fetched_row[$result_value] = 522 max($this->highest_fetched_row[$result_value], $row); 523 if (is_string($field)) { 524 if (intval($field) != $field) { 525 $field = strtoupper($field); 526 } 527 else 528 { 529 $field = intval($field); 530 } 531 } 532 $res = @fbsql_result($result, $row, $field); 533 if ($res === FALSE && $res != NULL) { 534 return($this->fbsqlRaiseError()); 535 } 536 return($res); 537 } 538 539 // }}} 540 // {{{ fetchClob() 541 542 /** 543 * fetch a clob value from a result set 544 * 545 * @param resource $result result identifier 546 * @param int $row number of the row where the data can be found 547 * @param int $field field number where the data can be found 548 * @return mixed content of the specified data cell, a MDB error on failure, 549 * a MDB error on failure 550 * @access public 551 */ 552 function fetchClob($result, $row, $field) 553 { 554 return($this->fetchLob($result, $row, $field)); 555 } 556 557 // }}} 558 // {{{ fetchBlob() 559 560 /** 561 * fetch a blob value from a result set 562 * 563 * @param resource $result result identifier 564 * @param int $row number of the row where the data can be found 565 * @param int $field field number where the data can be found 566 * @return mixed content of the specified data cell, a MDB error on failure 567 * @access public 568 */ 569 function fetchBlob($result, $row, $field) 570 { 571 return($this->fetchLob($result, $row, $field)); 572 } 573 574 // }}} 575 // {{{ convertResult() 576 577 /** 578 * convert a value to a RDBMS indepdenant MDB type 579 * 580 * @param mixed $value value to be converted 581 * @param int $type constant that specifies which type to convert to 582 * @return mixed converted value 583 * @access public 584 */ 585 function convertResult($value, $type) 586 { 587 switch($type) { 588 case MDB_TYPE_BOOLEAN: 589 return ($value == 'T') ? TRUE : FALSE; 590 case MDB_TYPE_DECIMAL: 591 return(sprintf('%.'.$this->decimal_places.'f', doubleval($value)/$this->decimal_factor)); 592 case MDB_TYPE_FLOAT: 593 return(doubleval($value)); 594 case MDB_TYPE_TIME: 595 if ($value[0] == '+') { 596 return (substr($value, 1)); 597 } else { 598 return($value); 599 } 600 default: 601 return($this->_baseConvertResult($value, $type)); 602 } 603 } 604 605 // }}} 606 // {{{ numRows() 607 608 /** 609 * returns the number of rows in a result object 610 * 611 * @param ressource $result a valid result ressouce pointer 612 * @return mixed MDB_Error or the number of rows 613 * @access public 614 */ 615 function numRows($result) 616 { 617 return(@fbsql_num_rows($result)); 618 } 619 620 // }}} 621 // {{{ freeResult() 622 623 /** 624 * Free the internal resources associated with $result. 625 * 626 * @param $result result identifier 627 * @return boolean TRUE on success, FALSE if $result is invalid 628 * @access public 629 */ 630 function freeResult($result) 631 { 632 $result_value = intval($result); 633 if(isset($this->highest_fetched_row[$result_value])) { 634 unset($this->highest_fetched_row[$result_value]); 635 } 636 if(isset($this->columns[$result_value])) { 637 unset($this->columns[$result_value]); 638 } 639 if(isset($this->result_types[$result_value])) { 640 unset($this->result_types[$result_value]); 641 } 642 return(@fbsql_free_result($result)); 643 } 644 645 // }}} 646 // {{{ getIntegerDeclaration() 647 648 /** 649 * Obtain DBMS specific SQL code portion needed to declare an integer type 650 * field to be used in statements like CREATE TABLE. 651 * 652 * @param string $name name the field to be declared. 653 * @param string $field associative array with the name of the properties 654 * of the field being declared as array indexes. 655 * Currently, the types of supported field 656 * properties are as follows: 657 * 658 * unsigned 659 * Boolean flag that indicates whether the field 660 * should be declared as unsigned integer if 661 * possible. 662 * 663 * default 664 * Integer value to be used as default for this 665 * field. 666 * 667 * notnull 668 * Boolean flag that indicates whether this field is 669 * constrained to not be set to NULL. 670 * @return string DBMS specific SQL code portion that should be used to 671 * declare the specified field. 672 * @access public 673 */ 674 function getIntegerDeclaration($name, $field) 675 { 676 if (isset($field['unsigned'])) { 677 $this->warnings[] = "unsigned integer field \"$name\" is being 678 declared as signed integer"; 679 } 680 return("$name INT".(isset($field["default"]) 681 ? " DEFAULT ".$field["default"] 682 : "").(isset($field["notnull"]) ? " NOT NULL" : "")); 683 } 684 685 // }}} 686 // {{{ getTextDeclaration() 687 688 /** 689 * Obtain DBMS specific SQL code portion needed to declare an text type 690 * field to be used in statements like CREATE TABLE. 691 * 692 * @param string $name name the field to be declared. 693 * @param string $field associative array with the name of the properties 694 * of the field being declared as array indexes. Currently, the types 695 * of supported field properties are as follows: 696 * 697 * length 698 * Integer value that determines the maximum length of the text 699 * field. If this argument is missing the field should be 700 * declared to have the longest length allowed by the DBMS. 701 * 702 * default 703 * Text value to be used as default for this field. 704 * 705 * notnull 706 * Boolean flag that indicates whether this field is constrained 707 * to not be set to NULL. 708 * @return string DBMS specific SQL code portion that should be used to 709 * declare the specified field. 710 * @access public 711 */ 712 function getTextDeclaration($name, $field) 713 { 714 return((isset($field["length"]) 715 ? "$name VARCHAR (".$field["length"].")" 716 : "$name VARCHAR(".$this->max_text_length.")").(isset($field["default"]) 717 ? " DEFAULT ".$this->GetTextValue($field["default"]) 718 : "").(isset($field["notnull"]) ? " NOT NULL" : "")); 719 } 720 721 // }}} 722 // {{{ getClobDeclaration() 723 724 /** 725 * Obtain DBMS specific SQL code portion needed to declare an character 726 * large object type field to be used in statements like CREATE TABLE. 727 * 728 * @param string $name name the field to be declared. 729 * @param string $field associative array with the name of the 730 * properties of the field being declared as array 731 * indexes. Currently, the types of supported field 732 * properties are as follows: 733 * 734 * length 735 * Integer value that determines the maximum length 736 * of the large object field. If this argument is 737 * missing the field should be declared to have the 738 * longest length allowed by the DBMS. 739 * 740 * notnull 741 * Boolean flag that indicates whether this field 742 * is constrained to not be set to NULL. 743 * @return string DBMS specific SQL code portion that should be used to 744 * declare the specified field. 745 * @access public 746 */ 747 function getClobDeclaration($name, $field) 748 { 749 return("$name CLOB". 750 (isset($field['notnull']) ? ' NOT NULL' : '')); 751 } 752 753 // }}} 754 // {{{ getBlobDeclaration() 755 756 /** 757 * Obtain DBMS specific SQL code portion needed to declare an binary large 758 * object type field to be used in statements like CREATE TABLE. 759 * 760 * @param string $name name the field to be declared. 761 * @param string $field associative array with the name of the properties 762 * of the field being declared as array indexes. 763 * Currently, the types of supported field 764 * properties are as follows: 765 * 766 * length 767 * Integer value that determines the maximum length 768 * of the large object field. If this argument is 769 * missing the field should be declared to have the 770 * longest length allowed by the DBMS. 771 * 772 * notnull 773 * Boolean flag that indicates whether this field is 774 * constrained to not be set to NULL. 775 * @return string DBMS specific SQL code portion that should be used to 776 * declare the specified field. 777 * @access public 778 */ 779 function getBlobDeclaration($name, $field) 780 { 781 return("$name BLOB". 782 (isset($field['notnull']) ? ' NOT NULL' : '')); 783 } 784 785 // }}} 786 // {{{ getBooleanDeclaration() 787 788 /** 789 * Obtain DBMS specific SQL code portion needed to declare a boolean type 790 * field to be used in statements like CREATE TABLE. 791 * 792 * @param string $name name the field to be declared. 793 * @param string $field associative array with the name of the properties 794 * of the field being declared as array indexes. Currently, the types 795 * of supported field properties are as follows: 796 * 797 * default 798 * Boolean value to be used as default for this field. 799 * 800 * notnullL 801 * Boolean flag that indicates whether this field is constrained 802 * to not be set to NULL. 803 * @return string DBMS specific SQL code portion that should be used to 804 * declare the specified field. 805 * @access public 806 */ 807 function getBooleanDeclaration($name, $field) 808 { 809 return("$name BOOLEAN" . (isset($field['default']) 810 ? ' DEFAULT ' . $this->getBooleanValue($field['default']) 811 : '') . (isset($field['notnull']) ? ' NOT NULL' : '')); 812 } 813 814 // }}} 815 // {{{ getDateDeclaration() 816 817 /** 818 * Obtain DBMS specific SQL code portion needed to declare an date type 819 * field to be used in statements like CREATE TABLE. 820 * 821 * @param string $name name the field to be declared. 822 * @param string $field associative array with the name of the properties 823 * of the field being declared as array indexes. 824 * Currently, the types of supported field properties 825 * are as follows: 826 * 827 * default 828 * Date value to be used as default for this field. 829 * 830 * notnull 831 * Boolean flag that indicates whether this field is 832 * constrained to not be set to NULL. 833 * @return string DBMS specific SQL code portion that should be used to 834 * declare the specified field. 835 * @access public 836 */ 837 function getDateDeclaration($name, $field) 838 { 839 return("$name DATE". 840 (isset($field['default']) ? " DEFAULT DATE'".$field['default']."'" : ''). 841 (isset($field['notnull']) ? ' NOT NULL' : '') 842 ); 843 } 844 845 // }}} 846 // {{{ getTimestampDeclaration() 847 848 /** 849 * Obtain DBMS specific SQL code portion needed to declare an timestamp 850 * type field to be used in statements like CREATE TABLE. 851 * 852 * @param string $name name the field to be declared. 853 * @param string $field associative array with the name of the properties 854 * of the field being declared as array indexes. 855 * Currently, the types of supported field 856 * properties are as follows: 857 * 858 * default 859 * Time stamp value to be used as default for this 860 * field. 861 * 862 * notnull 863 * Boolean flag that indicates whether this field is 864 * constrained to not be set to NULL. 865 * @return string DBMS specific SQL code portion that should be used to 866 * declare the specified field. 867 * @access public 868 */ 869 function getTimestampDeclaration($name, $field) 870 { 871 return("$name TIMESTAMP". 872 (isset($field['default']) ? " DEFAULT TIMESTAMP'".$field['default']."'" : ''). 873 (isset($field['notnull']) ? ' NOT NULL' : '') 874 ); 875 } 876 877 // }}} 878 // {{{ getTimeDeclaration() 879 880 /** 881 * Obtain DBMS specific SQL code portion needed to declare an time type 882 * field to be used in statements like CREATE TABLE. 883 * 884 * @param string $name name the field to be declared. 885 * @param string $field associative array with the name of the properties 886 * of the field being declared as array indexes. 887 * Currently, the types of supported field 888 * properties are as follows: 889 * 890 * default 891 * Time value to be used as default for this field. 892 * 893 * notnull 894 * Boolean flag that indicates whether this field is 895 * constrained to not be set to NULL. 896 * @return string DBMS specific SQL code portion that should be used to 897 * declare the specified field. 898 * @access public 899 */ 900 function getTimeDeclaration($name, $field) 901 { 902 return("$name TIME". 903 (isset($field['default']) ? " DEFAULT TIME'".$field['default']."'" : ''). 904 (isset($field['notnull']) ? ' NOT NULL' : '') 905 ); 906 } 907 908 // }}} 909 // {{{ getFloatDeclaration() 910 911 /** 912 * Obtain DBMS specific SQL code portion needed to declare an float type 913 * field to be used in statements like CREATE TABLE. 914 * 915 * @param string $name name the field to be declared. 916 * @param string $field associative array with the name of the properties 917 * of the field being declared as array indexes. 918 * Currently, the types of supported field 919 * properties are as follows: 920 * 921 * default 922 * Integer value to be used as default for this 923 * field. 924 * 925 * notnull 926 * Boolean flag that indicates whether this field is 927 * constrained to not be set to NULL. 928 * @return string DBMS specific SQL code portion that should be used to 929 * declare the specified field. 930 * @access public 931 */ 932 function getFloatDeclaration($name, $field) 933 { 934 return("$name FLOAT". 935 (isset($field['default']) ? 936 ' DEFAULT '.$this->getFloatValue($field['default']) : ''). 937 (isset($field['notnull']) ? ' NOT NULL' : '') 938 ); 939 } 940 941 // }}} 942 // {{{ getDecimalDeclaration() 943 944 /** 945 * Obtain DBMS specific SQL code portion needed to declare an decimal type 946 * field to be used in statements like CREATE TABLE. 947 * 948 * @param string $name name the field to be declared. 949 * @param string $field associative array with the name of the properties 950 * of the field being declared as array indexes. 951 * Currently, the types of supported field 952 * properties are as follows: 953 * 954 * default 955 * Integer value to be used as default for this 956 * field. 957 * 958 * notnull 959 * Boolean flag that indicates whether this field is 960 * constrained to not be set to NULL. 961 * @return string DBMS specific SQL code portion that should be used to 962 * declare the specified field. 963 * @access public 964 */ 965 function getDecimalDeclaration($name, $field) 966 { 967 return("$name REAL". 968 (isset($field['default']) ? 969 ' DEFAULT '.$this->getDecimalValue($field['default']) : ''). 970 (isset($field['notnull']) ? ' NOT NULL' : '') 971 ); 972 } 973 974 // }}} 975 // {{{ getClobValue() 976 977 /** 978 * Convert a text value into a DBMS specific format that is suitable to 979 * compose query statements. 980 * 981 * @param resource $prepared_query query handle from prepare() 982 * @param $parameter 983 * @param $clob 984 * @return string text string that represents the given argument value in 985 * a DBMS specific format. 986 * @access public 987 */ 988 function getClobValue($prepared_query, $parameter, $clob) 989 { 990 $value = "'"; 991 while(!$this->endOfLob($clob)) { 992 $result = $this->readLob($clob, $data, $this->options['lob_buffer_length']); 993 if (MDB::isError($result)) { 994 return($result); 995 } 996 $value .= $this->_quote($data); 997 } 998 $value .= "'"; 999 return($value); 1000 } 1001 1002 // }}} 1003 // {{{ freeClobValue() 1004 1005 /** 1006 * free a character large object 1007 * 1008 * @param resource $prepared_query query handle from prepare() 1009 * @param string $clob 1010 * @return MDB_OK 1011 * @access public 1012 */ 1013 function freeClobValue($prepared_query, $clob) 1014 { 1015 unset($this->lobs[$clob]); 1016 return(MDB_OK); 1017 } 1018 1019 // }}} 1020 // {{{ getBlobValue() 1021 1022 /** 1023 * Convert a text value into a DBMS specific format that is suitable to 1024 * compose query statements. 1025 * 1026 * @param resource $prepared_query query handle from prepare() 1027 * @param $parameter 1028 * @param $blob 1029 * @return string text string that represents the given argument value in 1030 * a DBMS specific format. 1031 * @access public 1032 */ 1033 function getBlobValue($prepared_query, $parameter, $blob) 1034 { 1035 $value = "'"; 1036 while(!$this->endOfLob($blob)) { 1037 $result = $this->readLob($blob, $data, $this->options['lob_buffer_length']); 1038 if (MDB::isError($result)) { 1039 return($result); 1040 } 1041 $value .= addslashes($data); 1042 } 1043 $value .= "'"; 1044 return($value); 1045 } 1046 1047 // }}} 1048 // {{{ freeBlobValue() 1049 1050 /** 1051 * free a binary large object 1052 * 1053 * @param resource $prepared_query query handle from prepare() 1054 * @param string $blob 1055 * @return MDB_OK 1056 * @access public 1057 */ 1058 function freeBlobValue($prepared_query, $blob) 1059 { 1060 unset($this->lobs[$blob]); 1061 return(MDB_OK); 1062 } 1063 1064 // }}} 1065 // {{{ getBooleanValue() 1066 1067 /** 1068 * Convert a text value into a DBMS specific format that is suitable to 1069 * compose query statements. 1070 * 1071 * @param string $value text string value that is intended to be converted. 1072 * @return string text string that represents the given argument value in 1073 * a DBMS specific format. 1074 * @access public 1075 */ 1076 function getBooleanValue($value) 1077 { 1078 return(($value === NULL) ? 'NULL' : ($value ? "True" : "False")); 1079 } 1080 1081 // }}} 1082 // {{{ getDateValue() 1083 1084 /** 1085 * Convert a text value into a DBMS specific format that is suitable to 1086 * compose query statements. 1087 * 1088 * @param string $value text string value that is intended to be converted. 1089 * @return string text string that represents the given argument value in 1090 * a DBMS specific format. 1091 * @access public 1092 */ 1093 function getDateValue($value) 1094 { 1095 return(($value === NULL) ? 'NULL' : "DATE'$value'"); 1096 } 1097 1098 // }}} 1099 // {{{ getTimestampValue() 1100 1101 /** 1102 * Convert a text value into a DBMS specific format that is suitable to 1103 * compose query statements. 1104 * 1105 * @param string $value text string value that is intended to be converted. 1106 * @return string text string that represents the given argument value in 1107 * a DBMS specific format. 1108 * @access public 1109 */ 1110 function getTimestampValue($value) 1111 { 1112 return(($value === NULL) ? 'NULL' : "TIMESTAMP'$value'"); 1113 } 1114 1115 // }}} 1116 // {{{ getTimeValue() 1117 1118 /** 1119 * Convert a text value into a DBMS specific format that is suitable to 1120 * compose query statements. 1121 * 1122 * @param string $value text string value that is intended to be converted. 1123 * @return string text string that represents the given argument value in 1124 * a DBMS specific format. 1125 * @access public 1126 */ 1127 function getTimeValue($value) 1128 { 1129 return(($value === NULL) ? 'NULL' : "TIME'$value'"); 1130 } 1131 1132 // }}} 1133 // {{{ getFloatValue() 1134 1135 /** 1136 * Convert a text value into a DBMS specific format that is suitable to 1137 * compose query statements. 1138 * 1139 * @param string $value text string value that is intended to be converted. 1140 * @return string text string that represents the given argument value in 1141 * a DBMS specific format. 1142 * @access public 1143 */ 1144 function getFloatValue($value) 1145 { 1146 return(($value === NULL) ? 'NULL' : (float)$value); 1147 } 1148 1149 // }}} 1150 // {{{ getDecimalValue() 1151 1152 /** 1153 * Convert a text value into a DBMS specific format that is suitable to 1154 * compose query statements. 1155 * 1156 * @param string $value text string value that is intended to be converted. 1157 * @return string text string that represents the given argument value in 1158 * a DBMS specific format. 1159 * @access public 1160 */ 1161 function getDecimalValue($value) 1162 { 1163 return(($value === NULL) 1164 ? 'NULL' 1165 : strval(round(doubleval($value)*$this->decimal_factor))); 1166 } 1167 1168 // }}} 1169 // {{{ nextId() 1170 1171 /** 1172 * returns the next free id of a sequence 1173 * 1174 * @param string $seq_name name of the sequence 1175 * @param boolean $ondemand when true the seqence is 1176 * automatic created, if it 1177 * not exists 1178 * 1179 * @return mixed MDB_Error or id 1180 * @access public 1181 */ 1182 function nextId($seq_name, $ondemand = TRUE) 1183 { 1184 $sequence_name = $this->getSequenceName($seq_name); 1185 $this->expectError(MDB_ERROR_NOSUCHTABLE); 1186 $result = $this->query("INSERT INTO $sequence_name VALUES (NULL)"); 1187 $this->popExpect(); 1188 if ($ondemand && MDB::isError($result) && 1189 $result->getCode() == MDB_ERROR_NOSUCHTABLE) 1190 { 1191 // Since we are create the sequence on demand 1192 // we know the first id = 1 so initialize the 1193 // sequence at 2 1194 $result = $this->createSequence($seq_name, 2); 1195 if (MDB::isError($result)) { 1196 return($this->raiseError(MDB_ERROR, NULL, NULL, 1197 'Next ID: on demand sequence could not be created')); 1198 } else { 1199 // First ID of a newly created sequence is 1 1200 return(1); 1201 } 1202 } 1203 $value = intval(@fbsql_insert_id()); 1204 $res = $this->query("DELETE FROM $sequence_name WHERE ".$this->options['sequence_col_name']." < $value"); 1205 if (MDB::isError($res)) { 1206 $this->warnings[] = 'Next ID: could not delete previous sequence table values'; 1207 } 1208 return($value); 1209 } 1210 1211 // }}} 1212 // {{{ fetchInto() 1213 1214 /** 1215 * Fetch a row and return data in an array. 1216 * 1217 * @param resource $result result identifier 1218 * @param int $fetchmode ignored 1219 * @param int $rownum the row number to fetch 1220 * @return mixed data array or NULL on success, a MDB error on failure 1221 * @access public 1222 */ 1223 function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL) 1224 { 1225 $result_value = intval($result); 1226 if ($rownum == NULL) { 1227 ++$this->highest_fetched_row[$result_value]; 1228 } else { 1229 if (!@fbsql_data_seek($result, $rownum)) { 1230 return(NULL); 1231 } 1232 $this->highest_fetched_row[$result_value] = 1233 max($this->highest_fetched_row[$result_value], $rownum); 1234 } 1235 if ($fetchmode == MDB_FETCHMODE_DEFAULT) { 1236 $fetchmode = $this->fetchmode; 1237 } 1238 if ($fetchmode & MDB_FETCHMODE_ASSOC) { 1239 $row = @fbsql_fetch_assoc($result); 1240 if (is_array($row) && $this->options['optimize'] == 'portability') { 1241 $row = array_change_key_case($row, CASE_LOWER); 1242 } 1243 } else { 1244 $row = @fbsql_fetch_row($result); 1245 } 1246 if (!$row) { 1247 if($this->options['autofree']) { 1248 $this->freeResult($result); 1249 } 1250 return(NULL); 1251 } 1252 if (isset($this->result_types[$result_value])) { 1253 $row = $this->convertResultRow($result, $row); 1254 } 1255 return($row); 1256 } 1257 1258 // }}} 1259 // {{{ nextResult() 1260 1261 /** 1262 * Move the internal fbsql result pointer to the next available result 1263 * 1264 * @param a valid result resource 1265 * @return true if a result is available otherwise return false 1266 * @access public 1267 */ 1268 function nextResult($result) 1269 { 1270 return(@fbsql_next_result($result)); 1271 } 1272 1273 // }}} 1274 // {{{ tableInfo() 1275 1276 /** 1277 * returns meta data about the result set 1278 * 1279 * @param resource $result result identifier 1280 * @param mixed $mode depends on implementation 1281 * @return array an nested array, or a MDB error 1282 * @access public 1283 */ 1284 function tableInfo($result, $mode = NULL) { 1285 $count = 0; 1286 $id = 0; 1287 $res = array(); 1288 1289 /* 1290 * depending on $mode, metadata returns the following values: 1291 * 1292 * - mode is false (default): 1293 * $result[]: 1294 * [0]['table'] table name 1295 * [0]['name'] field name 1296 * [0]['type'] field type 1297 * [0]['len'] field length 1298 * [0]['flags'] field flags 1299 * 1300 * - mode is MDB_TABLEINFO_ORDER 1301 * $result[]: 1302 * ['num_fields'] number of metadata records 1303 * [0]['table'] table name 1304 * [0]['name'] field name 1305 * [0]['type'] field type 1306 * [0]['len'] field length 1307 * [0]['flags'] field flags 1308 * ['order'][field name] index of field named 'field name' 1309 * The last one is used, if you have a field name, but no index. 1310 * Test: if (isset($result['meta']['myfield'])) { ... 1311 * 1312 * - mode is MDB_TABLEINFO_ORDERTABLE 1313 * the same as above. but additionally 1314 * ['ordertable'][table name][field name] index of field 1315 * named 'field name' 1316 * 1317 * this is, because if you have fields from different 1318 * tables with the same field name * they override each 1319 * other with MDB_TABLEINFO_ORDER 1320 * 1321 * you can combine MDB_TABLEINFO_ORDER and 1322 * MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER | 1323 * MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL 1324 */ 1325 1326 // if $result is a string, then we want information about a 1327 // table without a resultset 1328 if (is_string($result)) { 1329 $id = @fbsql_list_fields($this->database_name, 1330 $result, $this->connection); 1331 if (empty($id)) { 1332 return($this->fbsqlRaiseError()); 1333 } 1334 } else { // else we want information about a resultset 1335 $id = $result; 1336 if (empty($id)) { 1337 return($this->fbsqlRaiseError()); 1338 } 1339 } 1340 1341 $count = @fbsql_num_fields($id); 1342 1343 // made this IF due to performance (one if is faster than $count if's) 1344 if (empty($mode)) { 1345 for ($i = 0; $i<$count; $i++) { 1346 $res[$i]['table'] = @fbsql_field_table ($id, $i); 1347 $res[$i]['name'] = @fbsql_field_name ($id, $i); 1348 $res[$i]['type'] = @fbsql_field_type ($id, $i); 1349 $res[$i]['len'] = @fbsql_field_len ($id, $i); 1350 $res[$i]['flags'] = @fbsql_field_flags ($id, $i); 1351 } 1352 } else { // full 1353 $res['num_fields'] = $count; 1354 1355 for ($i = 0; $i<$count; $i++) { 1356 $res[$i]['table'] = @fbsql_field_table ($id, $i); 1357 $res[$i]['name'] = @fbsql_field_name ($id, $i); 1358 $res[$i]['type'] = @fbsql_field_type ($id, $i); 1359 $res[$i]['len'] = @fbsql_field_len ($id, $i); 1360 $res[$i]['flags'] = @fbsql_field_flags ($id, $i); 1361 if ($mode & MDB_TABLEINFO_ORDER) { 1362 $res['order'][$res[$i]['name']] = $i; 1363 } 1364 if ($mode & MDB_TABLEINFO_ORDERTABLE) { 1365 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; 1366 } 1367 } 1368 } 1369 1370 // free the result only if we were called on a table 1371 if (is_string($result)) { 1372 @fbsql_free_result($id); 1373 } 1374 return($res); 1375 } 1376 } 1377 1378 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |