[ Index ] |
|
Code source de Mantis 1.1.0rc3 |
1 <?php 2 # Mantis - a php based bugtracking system 3 4 # Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 5 # Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net 6 7 # Mantis is free software: you can redistribute it and/or modify 8 # it under the terms of the GNU General Public License as published by 9 # the Free Software Foundation, either version 2 of the License, or 10 # (at your option) any later version. 11 # 12 # Mantis is distributed in the hope that it will be useful, 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # GNU General Public License for more details. 16 # 17 # You should have received a copy of the GNU General Public License 18 # along with Mantis. If not, see <http://www.gnu.org/licenses/>. 19 20 # -------------------------------------------------------- 21 # $Id: database_api.php,v 1.73.2.1 2007-10-13 22:35:22 giallu Exp $ 22 # -------------------------------------------------------- 23 24 ### Database ### 25 26 # This is the general interface for all database calls. 27 # Use this as a starting point to port to other databases 28 29 $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR; 30 31 require_once ( $t_core_dir . 'gpc_api.php' ); 32 33 # Do not explicitly include $t_core_dir to allow using system ADODB by including 34 # it in include path and removing the one distributed with Mantis (see #7907). 35 require_once ( 'adodb/adodb.inc.php' ); 36 37 # An array in which all executed queries are stored. This is used for profiling 38 $g_queries_array = array(); 39 40 # Stores whether a database connection was succesfully opened. 41 $g_db_connected = false; 42 43 # set adodb fetch mode 44 # most drivers don't implement this, but for mysql there is a small internal php performance gain for using it 45 if( $g_db_type == 'mysql' ) { 46 $ADODB_FETCH_MODE = ADODB_FETCH_BOTH; 47 } 48 49 # -------------------- 50 # Make a connection to the database 51 function db_connect( $p_dsn, $p_hostname = null, $p_username = null, $p_password = null, $p_database_name = null, $p_db_schema = null, $p_pconnect = false ) { 52 global $g_db_connected, $g_db; 53 54 if ( $p_dsn === false ) { 55 $t_db_type = config_get_global( 'db_type' ); 56 $g_db = ADONewConnection( $t_db_type ); 57 58 if ( $p_pconnect ) { 59 $t_result = $g_db->PConnect( $p_hostname, $p_username, $p_password, $p_database_name ); 60 } else { 61 $t_result = $g_db->Connect( $p_hostname, $p_username, $p_password, $p_database_name ); 62 } 63 } else { 64 $g_db = ADONewConnection( $p_dsn ); 65 $t_result = $g_db->IsConnected(); 66 } 67 68 if ( $t_result ) { 69 # For MySQL, the charset for the connection needs to be specified. 70 if ( db_is_mysql() ) { 71 $c_charset = db_prepare_string( lang_get( 'charset' ) ); 72 73 # @@@ Is there a way to translate any charset name to MySQL format? e.g. remote the dashes? 74 # @@@ Is this needed for other databases? 75 if ( strtolower( $c_charset ) === 'utf-8' ) { 76 db_query( 'SET NAMES UTF8' ); 77 } 78 } elseif ( db_is_db2() && $p_db_schema !== null && !is_blank( $p_db_schema ) ) { 79 $t_result2 = db_query( 'set schema ' . $p_db_schema ); 80 if ( $t_result2 === false ) { 81 db_error(); 82 trigger_error( ERROR_DB_CONNECT_FAILED, ERROR ); 83 return false; 84 } 85 } 86 } else { 87 db_error(); 88 trigger_error( ERROR_DB_CONNECT_FAILED, ERROR ); 89 return false; 90 } 91 92 $g_db_connected = true; 93 94 return true; 95 } 96 97 # -------------------- 98 # Make a persistent connection to the database 99 function db_pconnect( $p_dsn, $p_hostname = null, $p_username = null, $p_password = null, $p_database_name = null, $p_db_schema = null ) { 100 return db_connect( $p_dsn, $p_hostname, $p_username, $p_password, $p_database_name, $p_db_schema, /* $p_pconnect */ true ); 101 } 102 103 # -------------------- 104 # Returns whether a connection to the database exists 105 function db_is_connected() { 106 global $g_db_connected; 107 108 return $g_db_connected; 109 } 110 111 # -------------------- 112 # Checks if the database is MySQL 113 function db_is_mysql() { 114 $t_db_type = config_get( 'db_type' ); 115 116 switch( $t_db_type ) { 117 case 'mysql': 118 case 'mysqli': 119 return true; 120 } 121 122 return false; 123 } 124 125 # -------------------- 126 # Check is the database is PostgreSQL 127 function db_is_pgsql() { 128 $t_db_type = config_get( 'db_type' ); 129 130 switch( $t_db_type ) { 131 case 'postgres': 132 case 'postgres64': 133 case 'postgres7': 134 case 'pgsql': 135 return true; 136 } 137 138 return false; 139 } 140 141 # -------------------- 142 # Check is the database is DB2 143 function db_is_db2() { 144 $t_db_type = config_get( 'db_type' ); 145 146 switch( $t_db_type ) { 147 case 'db2': 148 return true; 149 } 150 151 return false; 152 } 153 154 # -------------------- 155 # execute query, requires connection to be opened 156 # If $p_error_on_failure is true (default) an error will be triggered 157 # if there is a problem executing the query. 158 function db_query( $p_query, $p_limit = -1, $p_offset = -1 ) { 159 global $g_queries_array, $g_db; 160 161 $t_start = microtime_float(); 162 163 if ( ( $p_limit != -1 ) || ( $p_offset != -1 ) ) { 164 $t_result = $g_db->SelectLimit( $p_query, $p_limit, $p_offset ); 165 } else { 166 $t_result = $g_db->Execute( $p_query ); 167 } 168 169 $t_elapsed = number_format( microtime_float() - $t_start, 4); 170 171 $t_backtrace = debug_backtrace(); 172 $t_caller = basename( $t_backtrace[0]['file'] ); 173 $t_caller .= ":" . $t_backtrace[0]['line']; 174 175 # Is this called from another function? 176 if ( isset( $t_backtrace[1] ) ) { 177 $t_caller .= ' ' . $t_backtrace[1]['function'] . '()'; 178 } else { 179 # or from a script directly? 180 $t_caller .= ' ' . $_SERVER['PHP_SELF']; 181 } 182 183 array_push ( $g_queries_array, array( $p_query, $t_elapsed, $t_caller ) ); 184 185 if ( !$t_result ) { 186 db_error($p_query); 187 trigger_error( ERROR_DB_QUERY_FAILED, ERROR ); 188 return false; 189 } else { 190 return $t_result; 191 } 192 } 193 194 # -------------------- 195 function db_num_rows( $p_result ) { 196 global $g_db; 197 198 return $p_result->RecordCount( ); 199 } 200 201 # -------------------- 202 function db_affected_rows() { 203 global $g_db; 204 205 return $g_db->Affected_Rows( ); 206 } 207 208 # -------------------- 209 function db_fetch_array( & $p_result ) { 210 global $g_db, $g_db_type; 211 212 if ( $p_result->EOF ) { 213 return false; 214 } 215 216 # mysql obeys FETCH_MODE_BOTH, hence ->fields works, other drivers do not support this 217 if( $g_db_type == 'mysql' ) { 218 $t_array = $p_result->fields; 219 $p_result->MoveNext(); 220 return $t_array; 221 } else { 222 $test = $p_result->GetRowAssoc(false); 223 $p_result->MoveNext(); 224 return $test; 225 } 226 } 227 228 # -------------------- 229 function db_result( $p_result, $p_index1=0, $p_index2=0 ) { 230 global $g_db; 231 232 if ( $p_result && ( db_num_rows( $p_result ) > 0 ) ) { 233 $p_result->Move( $p_index1 ); 234 $t_result = $p_result->GetArray(); 235 236 if ( isset( $t_result[0][$p_index2] ) ) { 237 return $t_result[0][$p_index2]; 238 } 239 240 // The numeric index doesn't exist. FETCH_MODE_ASSOC may have been used. 241 // Get 2nd dimension and make it numerically indexed 242 $t_result = array_values( $t_result[0] ); 243 return $t_result[$p_index2]; 244 } 245 246 return false; 247 } 248 249 # -------------------- 250 # return the last inserted id 251 function db_insert_id($p_table = null) { 252 global $g_db; 253 254 if ( isset($p_table) && db_is_pgsql() ) { 255 $query = "SELECT currval('".$p_table."_id_seq')"; 256 $result = db_query( $query ); 257 return db_result($result); 258 } 259 return $g_db->Insert_ID( ); 260 } 261 262 # -------------------- 263 # Check if the specified table exists. 264 # @param $p_table_name Table name. 265 # @returns true: table found, false: table not found. 266 function db_table_exists( $p_table_name ) { 267 global $g_db, $g_db_schema; 268 269 if ( is_blank( $p_table_name ) ) { 270 return false; // no tables found 271 } 272 273 if ( db_is_db2() ) { 274 // must pass schema 275 $t_tables = $g_db->MetaTables( 'TABLE', false, '', $g_db_schema ); 276 } else { 277 $t_tables = $g_db->MetaTables( 'TABLE' ); 278 } 279 280 # Can't use in_array() since it is case sensitive 281 $t_table_name = strtolower( $p_table_name ); 282 foreach ( $t_tables as $t_current_table ) { 283 if ( strtolower( $t_current_table ) == $t_table_name ) { 284 return true; 285 } 286 } 287 288 return false; 289 } 290 291 # -------------------- 292 function db_field_exists( $p_field_name, $p_table_name ) { 293 global $g_db; 294 return in_array ( $p_field_name , $g_db->MetaColumnNames( $p_table_name ) ) ; 295 } 296 297 # -------------------- 298 function db_field_names( $p_table_name ) { 299 global $g_db; 300 return $g_db->MetaColumnNames( $p_table_name ); 301 } 302 303 # -------------------- 304 # Check if there is an index defined on the specified table/field and with 305 # the specified type. 306 # 307 # @@@ thraxisp - this only works with MySQL 308 # 309 # $p_table: Name of table to check 310 # $p_field: Name of field to check 311 # $p_key: key type to check for (eg: PRI, MUL, ...etc) 312 function db_key_exists_on_field( $p_table, $p_field, $p_key ) { 313 $c_table = db_prepare_string( $p_table ); 314 $c_field = db_prepare_string( $p_field ); 315 $c_key = db_prepare_string( $p_key ); 316 317 $query = "DESCRIBE $c_table"; 318 $result = db_query( $query ); 319 $count = db_num_rows( $result ); 320 for ( $i=0 ; $i < $count ; $i++ ) { 321 $row = db_fetch_array( $result ); 322 323 if ( $row['Field'] == $c_field ) { 324 return ( $row['Key'] == $c_key ); 325 } 326 } 327 return false; 328 } 329 330 # -------------------- 331 function db_error_num() { 332 global $g_db; 333 334 return $g_db->ErrorNo(); 335 } 336 337 # -------------------- 338 function db_error_msg() { 339 global $g_db; 340 341 return $g_db->ErrorMsg(); 342 } 343 344 # -------------------- 345 # display both the error num and error msg 346 function db_error( $p_query=null ) { 347 if ( null !== $p_query ) { 348 error_parameters( db_error_num(), db_error_msg(), $p_query ); 349 } else { 350 error_parameters( db_error_num(), db_error_msg() ); 351 } 352 } 353 354 # -------------------- 355 # close the connection. 356 # Not really necessary most of the time since a connection is 357 # automatically closed when a page finishes loading. 358 function db_close() { 359 global $g_db; 360 361 $t_result = $g_db->Close(); 362 } 363 364 # -------------------- 365 # prepare a string before DB insertion 366 # @@@ should default be return addslashes( $p_string ); or generate an error 367 # @@@ Consider using ADODB escaping for all databases. 368 function db_prepare_string( $p_string ) { 369 global $g_db; 370 $t_db_type = config_get( 'db_type' ); 371 372 switch( $t_db_type ) { 373 case 'mssql': 374 case 'odbc_mssql': 375 case 'ado_mssql': 376 if( ini_get( 'magic_quotes_sybase' ) ) { 377 return addslashes( $p_string ); 378 } else { 379 ini_set( 'magic_quotes_sybase', true ); 380 $t_string = addslashes( $p_string ); 381 ini_set( 'magic_quotes_sybase', false ); 382 return $t_string; 383 } 384 # just making a point with the superfluous break;s I know it does not execute after a return ;-) 385 break; 386 case 'db2': 387 $t_escaped = $g_db->qstr( $p_string, false ); 388 return substr( $t_escaped, 1, strlen( $t_escaped ) - 2 ); 389 break; 390 case 'mssql': 391 break; 392 case 'odbc_mssql': 393 break; 394 case 'mysql': 395 return mysql_real_escape_string( $p_string ); 396 397 # For some reason mysqli_escape_string( $p_string ) always returns an empty 398 # string. This is happening with PHP v5.0.2. 399 case 'mysqli': 400 $t_escaped = $g_db->qstr( $p_string, false ); 401 return substr( $t_escaped, 1, strlen( $t_escaped ) - 2 ); 402 403 case 'postgres': 404 case 'postgres64': 405 case 'postgres7': 406 case 'pgsql': 407 return pg_escape_string( $p_string ); 408 409 default: 410 error_parameters( 'db_type', $t_db_type ); 411 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 412 } 413 } 414 415 # -------------------- 416 # prepare a binary string before DB insertion 417 function db_prepare_binary_string( $p_string ) { 418 $t_db_type = config_get( 'db_type' ); 419 420 switch( $t_db_type ) { 421 case 'mssql': 422 case 'odbc_mssql': 423 case 'ado_mssql': 424 $content = unpack("H*hex", $p_string); 425 return '0x' . $content['hex']; 426 break; 427 default: 428 return '\'' . db_prepare_string( $p_string ) . '\''; 429 break; 430 } 431 } 432 433 # -------------------- 434 # prepare a time string in "[h]h:mm" to an integer (minutes) before DB insertion 435 function db_prepare_time( $p_hhmm ) { 436 if ( is_blank( $p_hhmm ) ) { 437 return 0; 438 } 439 440 $t_a = explode( ':', $p_hhmm ); 441 $t_min = 0; 442 443 // time can be composed of max 3 parts (hh:mm:ss) 444 if ( count( $t_a ) > 3 ) { 445 error_parameters( 'p_hhmm', $p_hhmm ); 446 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 447 } 448 449 for ( $i = 0; $i < count( $t_a ); $i++ ) { 450 // all time parts should be integers and non-negative. 451 if ( !is_numeric( $t_a[$i] ) || ( (integer)$t_a[$i] < 0) ) { 452 error_parameters( 'p_hhmm', $p_hhmm ); 453 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 454 } 455 456 // minutes and seconds are not allowed to exceed 59. 457 if ( ( $i > 0 ) && ( $t_a[$i] > 59 ) ) { 458 error_parameters( 'p_hhmm', $p_hhmm ); 459 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 460 } 461 } 462 463 switch ( count( $t_a ) ) 464 { 465 case 1: 466 $t_min = (integer)$t_a[0]; 467 break; 468 469 case 2: 470 $t_min = (integer)$t_a[0] * 60 + (integer)$t_a[1]; 471 break; 472 473 case 3: // if seconds included, approxiate it to minutes 474 $t_min = (integer)$t_a[0] * 60 + (integer)$t_a[1]; 475 476 if ( (integer)$t_a[2] >= 30 ) { 477 $t_min++; 478 } 479 break; 480 } 481 482 return (int)$t_min; 483 } 484 485 # -------------------- 486 # prepare a date string in "yyyy-mm-dd" 487 function db_prepare_date( $p_yyyymmdd ) { 488 if ( is_blank( $p_yyyymmdd ) ) { 489 return ""; 490 } 491 492 $t_a = explode( '-', $p_yyyymmdd ); 493 494 // date can be composed of max 3 parts (yyyy-mm-dd) 495 if ( count( $t_a ) > 3 ) { 496 error_parameters( 'p_yyyymmdd', $p_yyyymmdd ); 497 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 498 } 499 500 // Check years 501 if ( !is_numeric( $t_a[0] ) || ( (integer)$t_a[0] < 1900 || (integer)$t_a[0] > 2100) ) { 502 error_parameters( 'p_yyyymmdd', $p_yyyymmdd ); 503 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 504 } 505 506 // Check months 507 if ( !is_numeric( $t_a[1] ) || ( (integer)$t_a[1] < 1 || (integer)$t_a[1] > 12) ) { 508 error_parameters( 'p_yyyymmdd', $p_yyyymmdd ); 509 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 510 } 511 512 // Check days 513 if ( !is_numeric( $t_a[2] ) || ( (integer)$t_a[2] < 1 || (integer)$t_a[2] > 31) ) { 514 error_parameters( 'p_yyyymmdd', $p_yyyymmdd ); 515 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 516 } 517 518 // Format 519 $t_formatted = $t_a[0] . '-'; 520 $t_formatted .= ($t_a[1] < 10 ? "0" . $t_a[1] : $t_a[1]) . '-'; 521 $t_formatted .= ($t_a[2] < 10 ? "0" . $t_a[2] : $t_a[2]); 522 523 return $t_formatted; 524 } 525 526 # -------------------- 527 # prepare an integer before DB insertion 528 function db_prepare_int( $p_int ) { 529 return (int)$p_int; 530 } 531 532 # -------------------- 533 # prepare a double before DB insertion 534 function db_prepare_double( $p_double ) { 535 return (double)$p_double; 536 } 537 538 # -------------------- 539 # prepare a boolean before DB insertion 540 function db_prepare_bool( $p_bool ) { 541 return (int)(bool)$p_bool; 542 } 543 544 # -------------------- 545 # return current timestamp for DB 546 function db_now() { 547 global $g_db; 548 549 return $g_db->DBTimeStamp(time()); 550 } 551 552 # -------------------- 553 # generate a unixtimestamp of a date 554 # > SELECT UNIX_TIMESTAMP(); 555 # -> 882226357 556 # > SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00'); 557 # -> 875996580 558 function db_timestamp( $p_date=null ) { 559 global $g_db; 560 561 if ( null !== $p_date ) { 562 $p_timestamp = $g_db->UnixTimeStamp($p_date); 563 } else { 564 $p_timestamp = time(); 565 } 566 return $g_db->DBTimeStamp($p_timestamp) ; 567 } 568 569 function db_unixtimestamp( $p_date=null ) { 570 global $g_db; 571 572 if ( null !== $p_date ) { 573 $p_timestamp = $g_db->UnixTimeStamp($p_date); 574 } else { 575 $p_timestamp = time(); 576 } 577 return $p_timestamp ; 578 } 579 580 # convert unix timestamp to db compatible date 581 function db_date( $p_timestamp=null ) { 582 global $g_db; 583 584 if ( null !== $p_timestamp ) { 585 $p_date = $g_db->UserTimeStamp($p_timestamp); 586 } else { 587 $p_date = $g_db->UserTimeStamp(time()); 588 } 589 return $p_date; 590 } 591 592 593 # -------------------- 594 # convert minutes to a time format [h]h:mm 595 function db_minutes_to_hhmm( $p_min = 0 ) { 596 return sprintf( '%02d:%02d', $p_min / 60, $p_min % 60 ); 597 } 598 599 # -------------------- 600 # A helper function that generates a case-sensitive or case-insensitive like phrase based on the current db type. 601 # $p_field_name - The name of the field to filter on. 602 # $p_value - The value that includes the pattern (can include % for wild cards) - not including the quotations. 603 # $p_case_sensitive - true: case sensitive, false: case insensitive 604 # returns (field LIKE 'value') OR (field ILIKE 'value') 605 # The field name and value are assumed to be safe to insert in a query (i.e. already cleaned). 606 function db_helper_like( $p_field_name, $p_value, $p_case_sensitive = false ) { 607 $t_like_keyword = 'LIKE'; 608 609 if ( $p_case_sensitive === false ) { 610 if ( db_is_pgsql() ) { 611 $t_like_keyword = 'ILIKE'; 612 } 613 } 614 615 return "($p_field_name $t_like_keyword '$p_value')"; 616 } 617 618 # -------------------- 619 # helper function to compare two dates against a certain number of days 620 # limitstring can be '> 1' '<= 2 ' etc 621 # @@@ Check if there is a way to do that using ADODB rather than implementing it here. 622 function db_helper_compare_days($p_date1, $p_date2, $p_limitstring) { 623 $t_db_type = config_get( 'db_type' ); 624 625 switch( $t_db_type ) { 626 case 'mssql': 627 case 'odbc_mssql': 628 case 'ado_mssql': 629 return "(DATEDIFF(day, $p_date2, $p_date1) ". $p_limitstring . ")"; 630 631 case 'mysql': 632 case 'mysqli': 633 return "(TO_DAYS($p_date1) - TO_DAYS($p_date2) ". $p_limitstring . ")"; 634 635 case 'postgres': 636 case 'postgres64': 637 case 'postgres7': 638 case 'pgsql': 639 return "(date_mi($p_date1::date, $p_date2::date) ". $p_limitstring . ")"; 640 641 case 'oci8': 642 return "(($p_date1 - $p_date2)" . $p_limitstring . ")"; 643 644 case 'db2': 645 // all DB2 UDB use days function 646 return "(days($p_date1) - days($p_date2) " . $p_limitstring . ")"; 647 648 default: 649 error_parameters( 'db_type', $t_db_type ); 650 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 651 } 652 } 653 654 # -------------------- 655 # count queries 656 function db_count_queries () { 657 global $g_queries_array; 658 659 return count( $g_queries_array ); 660 } 661 662 # -------------------- 663 # count unique queries 664 function db_count_unique_queries () { 665 global $g_queries_array; 666 667 $t_unique_queries = 0; 668 $t_shown_queries = array(); 669 foreach ($g_queries_array as $t_val_array) { 670 if ( ! in_array( $t_val_array[0], $t_shown_queries ) ) { 671 $t_unique_queries++; 672 array_push( $t_shown_queries, $t_val_array[0] ); 673 } 674 } 675 return $t_unique_queries; 676 } 677 678 # -------------------- 679 # get total time for queries 680 function db_time_queries () { 681 global $g_queries_array; 682 $t_count = count( $g_queries_array ); 683 $t_total = 0; 684 for ( $i = 0; $i < $t_count; $i++ ) { 685 $t_total += $g_queries_array[$i][1]; 686 } 687 return $t_total; 688 } 689 690 691 # -------------------- 692 693 if ( !isset( $g_skip_open_db ) ) { 694 if ( OFF == $g_use_persistent_connections ) { 695 db_connect( config_get_global( 'dsn', false ), $g_hostname, $g_db_username, $g_db_password, $g_database_name, config_get_global( 'db_schema' ) ); 696 } else { 697 db_pconnect( config_get_global( 'dsn', false ), $g_hostname, $g_db_username, $g_db_password, $g_database_name, config_get_global( 'db_schema' ) ); 698 } 699 } 700 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 09:42:17 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |