|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // $Id$ 00004 // 00005 // Definition of eZMySQLDB class 00006 // 00007 // Created on: <12-Feb-2002 15:54:17 bf> 00008 // 00009 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00010 // SOFTWARE NAME: eZ Publish 00011 // SOFTWARE RELEASE: 4.0.x 00012 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00013 // SOFTWARE LICENSE: GNU General Public License v2.0 00014 // NOTICE: > 00015 // This program is free software; you can redistribute it and/or 00016 // modify it under the terms of version 2.0 of the GNU General 00017 // Public License as published by the Free Software Foundation. 00018 // 00019 // This program is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 // GNU General Public License for more details. 00023 // 00024 // You should have received a copy of version 2.0 of the GNU General 00025 // Public License along with this program; if not, write to the Free 00026 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00027 // MA 02110-1301, USA. 00028 // 00029 // 00030 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00031 // 00032 00033 /*! 00034 \class eZMySQLDB ezmysqldb.php 00035 \ingroup eZDB 00036 \brief The eZMySQLDB class provides MySQL implementation of the database interface. 00037 00038 eZMySQLDB is the MySQL implementation of eZDB. 00039 \sa eZDB 00040 */ 00041 00042 require_once( "lib/ezutils/classes/ezdebug.php" ); 00043 //include_once( "lib/ezutils/classes/ezini.php" ); 00044 //include_once( "lib/ezdb/classes/ezdbinterface.php" ); 00045 00046 class eZMySQLDB extends eZDBInterface 00047 { 00048 /*! 00049 Create a new eZMySQLDB object and connects to the database backend. 00050 */ 00051 function eZMySQLDB( $parameters ) 00052 { 00053 $this->eZDBInterface( $parameters ); 00054 00055 $this->CharsetMapping = array( 'iso-8859-1' => 'latin1', 00056 'iso-8859-2' => 'latin2', 00057 'iso-8859-8' => 'hebrew', 00058 'iso-8859-7' => 'greek', 00059 'iso-8859-9' => 'latin5', 00060 'iso-8859-13' => 'latin7', 00061 'windows-1250' => 'cp1250', 00062 'windows-1251' => 'cp1251', 00063 'windows-1256' => 'cp1256', 00064 'windows-1257' => 'cp1257', 00065 'utf-8' => 'utf8', 00066 'koi8-r' => 'koi8r', 00067 'koi8-u' => 'koi8u' ); 00068 00069 if ( !extension_loaded( 'mysql' ) ) 00070 { 00071 if ( function_exists( 'eZAppendWarningItem' ) ) 00072 { 00073 eZAppendWarningItem( array( 'error' => array( 'type' => 'ezdb', 00074 'number' => eZDBInterface::ERROR_MISSING_EXTENSION ), 00075 'text' => 'MySQL extension was not found, the DB handler will not be initialized.' ) ); 00076 $this->IsConnected = false; 00077 } 00078 eZDebug::writeWarning( 'MySQL extension was not found, the DB handler will not be initialized.', 'eZMySQLDB' ); 00079 return; 00080 } 00081 00082 /// Connect to master server 00083 if ( $this->DBWriteConnection == false ) 00084 { 00085 $connection = $this->connect( $this->Server, $this->DB, $this->User, $this->Password, $this->SocketPath, $this->Charset, $this->Port ); 00086 if ( $this->IsConnected ) 00087 { 00088 $this->DBWriteConnection = $connection; 00089 } 00090 } 00091 00092 // Connect to slave 00093 if ( $this->DBConnection == false ) 00094 { 00095 if ( $this->UseSlaveServer === true ) 00096 { 00097 $connection = $this->connect( $this->SlaveServer, $this->SlaveDB, $this->SlaveUser, $this->SlavePassword, $this->SocketPath, $this->Charset, $this->SlavePort ); 00098 } 00099 else 00100 { 00101 $connection =& $this->DBWriteConnection; 00102 } 00103 00104 if ( $connection and $this->DBWriteConnection ) 00105 { 00106 $this->DBConnection = $connection; 00107 $this->IsConnected = true; 00108 } 00109 } 00110 00111 // Initialize TempTableList 00112 $this->TempTableList = array(); 00113 00114 eZDebug::createAccumulatorGroup( 'mysql_total', 'Mysql Total' ); 00115 } 00116 00117 /*! 00118 \private 00119 Opens a new connection to a MySQL database and returns the connection 00120 */ 00121 function connect( $server, $db, $user, $password, $socketPath, $charset = null, $port = false ) 00122 { 00123 // if a port is specified, we add it to $server, this is how mysql_(p)connect accepts a port number 00124 if ( $port ) 00125 { 00126 $server .= ':' . $port; 00127 } 00128 00129 $connection = false; 00130 00131 if ( $socketPath !== false ) 00132 { 00133 ini_set( "mysql.default_socket", $socketPath ); 00134 } 00135 00136 if ( $this->UsePersistentConnection == true ) 00137 { 00138 $connection = mysql_pconnect( $server, $user, $password ); 00139 } 00140 else 00141 { 00142 $connection = mysql_connect( $server, $user, $password, true ); 00143 } 00144 $dbErrorText = mysql_error(); 00145 $maxAttempts = $this->connectRetryCount(); 00146 $waitTime = $this->connectRetryWaitTime(); 00147 $numAttempts = 1; 00148 while ( $connection == false and $numAttempts <= $maxAttempts ) 00149 { 00150 sleep( $waitTime ); 00151 if ( $this->UsePersistentConnection == true ) 00152 { 00153 $connection = mysql_pconnect( $this->Server, $this->User, $this->Password ); 00154 } 00155 else 00156 { 00157 $connection = mysql_connect( $this->Server, $this->User, $this->Password ); 00158 } 00159 $numAttempts++; 00160 } 00161 $this->setError(); 00162 00163 $this->IsConnected = true; 00164 00165 if ( $connection == false ) 00166 { 00167 eZDebug::writeError( "Connection error: Couldn't connect to database. Please try again later or inform the system administrator.\n$dbErrorText", "eZMySQLDB" ); 00168 $this->IsConnected = false; 00169 } 00170 00171 if ( $this->IsConnected && $db != null ) 00172 { 00173 $ret = mysql_select_db( $db, $connection ); 00174 $this->setError(); 00175 if ( !$ret ) 00176 { 00177 eZDebug::writeError( "Connection error: " . mysql_errno( $connection ) . ": " . mysql_error( $connection ), "eZMySQLDB" ); 00178 $this->IsConnected = false; 00179 } 00180 } 00181 00182 if ( $charset !== null ) 00183 { 00184 $originalCharset = $charset; 00185 //include_once( 'lib/ezi18n/classes/ezcharsetinfo.php' ); 00186 $charset = eZCharsetInfo::realCharsetCode( $charset ); 00187 // Convert charset names into something MySQL will understand 00188 if ( isset( $this->CharsetMapping[ $charset ] ) ) 00189 $charset = $this->CharsetMapping[ $charset ]; 00190 } 00191 00192 if ( $this->IsConnected and $charset !== null and $this->isCharsetSupported( $charset ) ) 00193 { 00194 $versionInfo = $this->databaseServerVersion(); 00195 00196 // We require MySQL 4.1.1 to use the new character set functionality, 00197 // MySQL 4.1.0 does not have a full implementation of this, see: 00198 // http://dev.mysql.com/doc/mysql/en/Charset.html 00199 if ( version_compare( $versionInfo['string'], '4.1.1' ) >= 0 ) 00200 { 00201 $query = "SET NAMES '" . $charset . "'"; 00202 $status = mysql_query( $query, $connection ); 00203 $this->reportQuery( 'eZMySQLDB', $query, false, false ); 00204 if ( !$status ) 00205 { 00206 $this->setError(); 00207 eZDebug::writeWarning( "Connection warning: " . mysql_errno( $connection ) . ": " . mysql_error( $connection ), "eZMySQLDB" ); 00208 } 00209 } 00210 } 00211 00212 return $connection; 00213 } 00214 00215 /*! 00216 \reimp 00217 */ 00218 function databaseName() 00219 { 00220 return 'mysql'; 00221 } 00222 00223 /*! 00224 \reimp 00225 */ 00226 function bindingType( ) 00227 { 00228 return eZDBInterface::BINDING_NO; 00229 } 00230 00231 /*! 00232 \reimp 00233 */ 00234 function bindVariable( $value, $fieldDef = false ) 00235 { 00236 return $value; 00237 } 00238 00239 /*! 00240 Checks if the requested character set matches the one used in the database. 00241 00242 \return \c true if it matches or \c false if it differs. 00243 \param[out] $currentCharset The charset that the database uses. 00244 will only be set if the match fails. 00245 Note: This will be specific to the database. 00246 00247 \note There will be no check for databases using MySQL 4.1.0 or lower since 00248 they do not have proper character set handling. 00249 */ 00250 function checkCharset( $charset, &$currentCharset ) 00251 { 00252 // If we don't have a database yet we shouldn't check it 00253 if ( !$this->DB ) 00254 return true; 00255 00256 $versionInfo = $this->databaseServerVersion(); 00257 00258 // We require MySQL 4.1.1 to use the new character set functionality, 00259 // MySQL 4.1.0 does not have a full implementation of this, see: 00260 // http://dev.mysql.com/doc/mysql/en/Charset.html 00261 // Older version should not check character sets 00262 if ( version_compare( $versionInfo['string'], '4.1.1' ) < 0 ) 00263 return true; 00264 00265 //include_once( 'lib/ezi18n/classes/ezcharsetinfo.php' ); 00266 00267 if ( is_array( $charset ) ) 00268 { 00269 foreach ( $charset as $charsetItem ) 00270 $realCharset[] = eZCharsetInfo::realCharsetCode( $charsetItem ); 00271 } 00272 else 00273 $realCharset = eZCharsetInfo::realCharsetCode( $charset ); 00274 00275 return $this->checkCharsetPriv( $realCharset, $currentCharset ); 00276 } 00277 00278 /*! 00279 \private 00280 */ 00281 function checkCharsetPriv( $charset, &$currentCharset ) 00282 { 00283 $query = "SHOW CREATE DATABASE `{$this->DB}`"; 00284 $status = mysql_query( $query, $this->DBConnection ); 00285 $this->reportQuery( 'eZMySQLDB', $query, false, false ); 00286 if ( !$status ) 00287 { 00288 $this->setError(); 00289 eZDebug::writeWarning( "Connection warning: " . mysql_errno( $this->DBConnection ) . ": " . mysql_error( $this->DBConnection ), "eZMySQLDB" ); 00290 return false; 00291 } 00292 00293 $numRows = mysql_num_rows( $status ); 00294 if ( $numRows == 0 ) 00295 return false; 00296 00297 for ( $i = 0; $i < $numRows; ++$i ) 00298 { 00299 $tmpRow = mysql_fetch_array( $status, MYSQL_ASSOC ); 00300 if ( $tmpRow['Database'] == $this->DB ) 00301 { 00302 $createText = $tmpRow['Create Database']; 00303 if ( preg_match( '#DEFAULT CHARACTER SET ([a-zA-Z0-9_-]+)#', $createText, $matches ) ) 00304 { 00305 $currentCharset = $matches[1]; 00306 //include_once( 'lib/ezi18n/classes/ezcharsetinfo.php' ); 00307 $currentCharset = eZCharsetInfo::realCharsetCode( $currentCharset ); 00308 // Convert charset names into something MySQL will understand 00309 00310 $key = array_search( $currentCharset, $this->CharsetMapping ); 00311 $unmappedCurrentCharset = ( $key === false ) ? $currentCharset : $key; 00312 00313 if ( is_array( $charset ) ) 00314 { 00315 if ( in_array( $unmappedCurrentCharset, $charset ) ) 00316 { 00317 return $unmappedCurrentCharset; 00318 } 00319 } 00320 else if ( $unmappedCurrentCharset == $charset ) 00321 { 00322 return true; 00323 } 00324 return false; 00325 } 00326 break; 00327 } 00328 } 00329 return true; 00330 } 00331 00332 /*! 00333 \reimp 00334 */ 00335 function query( $sql, $server = false ) 00336 { 00337 if ( $this->IsConnected ) 00338 { 00339 eZDebug::accumulatorStart( 'mysql_query', 'mysql_total', 'Mysql_queries' ); 00340 $orig_sql = $sql; 00341 // The converted sql should not be output 00342 if ( $this->InputTextCodec ) 00343 { 00344 eZDebug::accumulatorStart( 'mysql_conversion', 'mysql_total', 'String conversion in mysql' ); 00345 $sql = $this->InputTextCodec->convertString( $sql ); 00346 eZDebug::accumulatorStop( 'mysql_conversion' ); 00347 } 00348 00349 if ( $this->OutputSQL ) 00350 { 00351 $this->startTimer(); 00352 } 00353 00354 $sql = trim( $sql ); 00355 00356 // Check if we need to use the master or slave server by default 00357 if ( $server === false ) 00358 { 00359 $server = strncasecmp( $sql, 'select', 6 ) === 0 && $this->TransactionCounter == 0 ? 00360 eZDBInterface::SERVER_SLAVE : eZDBInterface::SERVER_MASTER; 00361 } 00362 00363 $connection = ( $server == eZDBInterface::SERVER_SLAVE ) ? $this->DBConnection : $this->DBWriteConnection; 00364 00365 $analysisText = false; 00366 // If query analysis is enable we need to run the query 00367 // with an EXPLAIN in front of it 00368 // Then we build a human-readable table out of the result 00369 if ( $this->QueryAnalysisOutput ) 00370 { 00371 $analysisResult = mysql_query( 'EXPLAIN ' . $sql, $connection ); 00372 if ( $analysisResult ) 00373 { 00374 $numRows = mysql_num_rows( $analysisResult ); 00375 $rows = array(); 00376 if ( $numRows > 0 ) 00377 { 00378 for ( $i = 0; $i < $numRows; ++$i ) 00379 { 00380 if ( $this->InputTextCodec ) 00381 { 00382 $tmpRow = mysql_fetch_array( $analysisResult, MYSQL_ASSOC ); 00383 $convRow = array(); 00384 foreach( $tmpRow as $key => $row ) 00385 { 00386 $convRow[$key] = $this->OutputTextCodec->convertString( $row ); 00387 } 00388 $rows[$i] = $convRow; 00389 } 00390 else 00391 $rows[$i] = mysql_fetch_array( $analysisResult, MYSQL_ASSOC ); 00392 } 00393 } 00394 00395 // Figure out all columns and their maximum display size 00396 $columns = array(); 00397 foreach ( $rows as $row ) 00398 { 00399 foreach ( $row as $col => $data ) 00400 { 00401 if ( !isset( $columns[$col] ) ) 00402 $columns[$col] = array( 'name' => $col, 00403 'size' => strlen( $col ) ); 00404 $columns[$col]['size'] = max( $columns[$col]['size'], strlen( $data ) ); 00405 } 00406 } 00407 00408 $analysisText = ''; 00409 $delimiterLine = array(); 00410 // Generate the column line and the vertical delimiter 00411 // The look of the table is taken from the MySQL CLI client 00412 // It looks like this: 00413 // +-------+-------+ 00414 // | col_a | col_b | 00415 // +-------+-------+ 00416 // | txt | 42 | 00417 // +-------+-------+ 00418 foreach ( $columns as $col ) 00419 { 00420 $delimiterLine[] = str_repeat( '-', $col['size'] + 2 ); 00421 $colLine[] = ' ' . str_pad( $col['name'], $col['size'], ' ', STR_PAD_RIGHT ) . ' '; 00422 } 00423 $delimiterLine = '+' . join( '+', $delimiterLine ) . "+\n"; 00424 $analysisText = $delimiterLine; 00425 $analysisText .= '|' . join( '|', $colLine ) . "|\n"; 00426 $analysisText .= $delimiterLine; 00427 00428 // Go trough all data and pad them to create the table correctly 00429 foreach ( $rows as $row ) 00430 { 00431 $rowLine = array(); 00432 foreach ( $columns as $col ) 00433 { 00434 $name = $col['name']; 00435 $size = $col['size']; 00436 $data = isset( $row[$name] ) ? $row[$name] : ''; 00437 // Align numerical values to the right (ie. pad left) 00438 $rowLine[] = ' ' . str_pad( $row[$name], $size, ' ', 00439 is_numeric( $row[$name] ) ? STR_PAD_LEFT : STR_PAD_RIGHT ) . ' '; 00440 } 00441 $analysisText .= '|' . join( '|', $rowLine ) . "|\n"; 00442 $analysisText .= $delimiterLine; 00443 } 00444 00445 // Reduce memory usage 00446 unset( $rows, $delimiterLine, $colLine, $columns ); 00447 } 00448 } 00449 00450 $result = mysql_query( $sql, $connection ); 00451 00452 if ( $this->RecordError and !$result ) 00453 $this->setError(); 00454 00455 if ( $this->OutputSQL ) 00456 { 00457 $this->endTimer(); 00458 00459 if ($this->timeTaken() > $this->SlowSQLTimeout) 00460 { 00461 $num_rows = mysql_affected_rows( $connection ); 00462 $text = $sql; 00463 00464 // If we have some analysis text we append this to the SQL output 00465 if ( $analysisText !== false ) 00466 $text = "EXPLAIN\n" . $text . "\n\nANALYSIS:\n" . $analysisText; 00467 00468 $this->reportQuery( ( $server == eZDBInterface::SERVER_MASTER ? 'on master : ' : '' ) . 'eZMySQLDB', $text, $num_rows, $this->timeTaken() ); 00469 } 00470 } 00471 eZDebug::accumulatorStop( 'mysql_query' ); 00472 if ( $result ) 00473 { 00474 return $result; 00475 } 00476 else 00477 { 00478 eZDebug::writeError( "Query error: " . mysql_error( $connection ) . ". Query: ". $sql, "eZMySQLDB" ); 00479 $oldRecordError = $this->RecordError; 00480 // Turn off error handling while we unlock 00481 $this->RecordError = false; 00482 mysql_query( 'UNLOCK TABLES', $connection ); 00483 $this->RecordError = $oldRecordError; 00484 00485 $this->reportError(); 00486 00487 return false; 00488 } 00489 } 00490 else 00491 { 00492 eZDebug::writeError( "Trying to do a query without being connected to a database!", "eZMySQLDB" ); 00493 } 00494 00495 00496 } 00497 00498 /*! 00499 \reimp 00500 */ 00501 function arrayQuery( $sql, $params = array(), $server = false ) 00502 { 00503 $retArray = array(); 00504 if ( $this->IsConnected ) 00505 { 00506 $limit = false; 00507 $offset = 0; 00508 $column = false; 00509 // check for array parameters 00510 if ( is_array( $params ) ) 00511 { 00512 if ( isset( $params["limit"] ) and is_numeric( $params["limit"] ) ) 00513 $limit = $params["limit"]; 00514 00515 if ( isset( $params["offset"] ) and is_numeric( $params["offset"] ) ) 00516 $offset = $params["offset"]; 00517 00518 if ( isset( $params["column"] ) and ( is_numeric( $params["column"] ) or is_string( $params["column"] ) ) ) 00519 $column = $params["column"]; 00520 } 00521 00522 if ( $limit !== false and is_numeric( $limit ) ) 00523 { 00524 $sql .= "\nLIMIT $offset, $limit "; 00525 } 00526 else if ( $offset !== false and is_numeric( $offset ) and $offset > 0 ) 00527 { 00528 $sql .= "\nLIMIT $offset, 18446744073709551615"; // 2^64-1 00529 } 00530 $result = $this->query( $sql, $server ); 00531 00532 if ( $result == false ) 00533 { 00534 $this->reportQuery( 'eZMySQLDB', $sql, false, false ); 00535 return false; 00536 } 00537 00538 $numRows = mysql_num_rows( $result ); 00539 if ( $numRows > 0 ) 00540 { 00541 if ( !is_string( $column ) ) 00542 { 00543 eZDebug::accumulatorStart( 'mysql_loop', 'mysql_total', 'Looping result' ); 00544 for ( $i=0; $i < $numRows; $i++ ) 00545 { 00546 if ( $this->InputTextCodec ) 00547 { 00548 $tmpRow = mysql_fetch_array( $result, MYSQL_ASSOC ); 00549 $convRow = array(); 00550 foreach( $tmpRow as $key => $row ) 00551 { 00552 eZDebug::accumulatorStart( 'mysql_conversion', 'mysql_total', 'String conversion in mysql' ); 00553 $convRow[$key] = $this->OutputTextCodec->convertString( $row ); 00554 eZDebug::accumulatorStop( 'mysql_conversion' ); 00555 } 00556 $retArray[$i + $offset] = $convRow; 00557 } 00558 else 00559 $retArray[$i + $offset] = mysql_fetch_array( $result, MYSQL_ASSOC ); 00560 } 00561 eZDebug::accumulatorStop( 'mysql_loop' ); 00562 00563 } 00564 else 00565 { 00566 eZDebug::accumulatorStart( 'mysql_loop', 'mysql_total', 'Looping result' ); 00567 for ( $i=0; $i < $numRows; $i++ ) 00568 { 00569 $tmp_row = mysql_fetch_array( $result, MYSQL_ASSOC ); 00570 if ( $this->InputTextCodec ) 00571 { 00572 eZDebug::accumulatorStart( 'mysql_conversion', 'mysql_total', 'String conversion in mysql' ); 00573 $retArray[$i + $offset] = $this->OutputTextCodec->convertString( $tmp_row[$column] ); 00574 eZDebug::accumulatorStop( 'mysql_conversion' ); 00575 } 00576 else 00577 $retArray[$i + $offset] =& $tmp_row[$column]; 00578 } 00579 eZDebug::accumulatorStop( 'mysql_loop' ); 00580 } 00581 } 00582 } 00583 return $retArray; 00584 } 00585 00586 function subString( $string, $from, $len = null ) 00587 { 00588 if ( $len == null ) 00589 { 00590 return " substring( $string from $from ) "; 00591 }else 00592 { 00593 return " substring( $string from $from for $len ) "; 00594 } 00595 } 00596 00597 function concatString( $strings = array() ) 00598 { 00599 $str = implode( "," , $strings ); 00600 return " concat( $str ) "; 00601 } 00602 00603 function md5( $str ) 00604 { 00605 return " MD5( $str ) "; 00606 } 00607 00608 function bitAnd( $arg1, $arg2 ) 00609 { 00610 return 'cast(' . $arg1 . ' & ' . $arg2 . ' AS SIGNED ) '; 00611 } 00612 00613 function bitOr( $arg1, $arg2 ) 00614 { 00615 return 'cast( ' . $arg1 . ' | ' . $arg2 . ' AS SIGNED ) '; 00616 } 00617 00618 /*! 00619 \reimp 00620 */ 00621 function supportedRelationTypeMask() 00622 { 00623 return eZDBInterface::RELATION_TABLE_BIT; 00624 } 00625 00626 /*! 00627 \reimp 00628 */ 00629 function supportedRelationTypes() 00630 { 00631 return array( eZDBInterface::RELATION_TABLE ); 00632 } 00633 00634 /*! 00635 \reimp 00636 */ 00637 function relationCounts( $relationMask ) 00638 { 00639 if ( $relationMask & eZDBInterface::RELATION_TABLE_BIT ) 00640 return $this->relationCount(); 00641 else 00642 return 0; 00643 } 00644 00645 /*! 00646 \reimp 00647 */ 00648 function relationCount( $relationType = eZDBInterface::RELATION_TABLE ) 00649 { 00650 if ( $relationType != eZDBInterface::RELATION_TABLE ) 00651 { 00652 eZDebug::writeError( "Unsupported relation type '$relationType'", 'eZMySQLDB::relationCount' ); 00653 return false; 00654 } 00655 $count = false; 00656 if ( $this->IsConnected ) 00657 { 00658 $query = "SHOW TABLES FROM `" . $this->DB . "`"; 00659 $result = @mysql_query( $query, $this->DBConnection ); 00660 $this->reportQuery( 'eZMySQLDB', $query, false, false ); 00661 $count = mysql_num_rows( $result ); 00662 mysql_free_result( $result ); 00663 } 00664 return $count; 00665 } 00666 00667 /*! 00668 \reimp 00669 */ 00670 function relationList( $relationType = eZDBInterface::RELATION_TABLE ) 00671 { 00672 if ( $relationType != eZDBInterface::RELATION_TABLE ) 00673 { 00674 eZDebug::writeError( "Unsupported relation type '$relationType'", 'eZMySQLDB::relationList' ); 00675 return false; 00676 } 00677 $tables = array(); 00678 if ( $this->IsConnected ) 00679 { 00680 $query = "SHOW TABLES FROM `" . $this->DB . "`"; 00681 $result = @mysql_query( $query, $this->DBConnection ); 00682 $this->reportQuery( 'eZMySQLDB', $query, false, false ); 00683 $count = mysql_num_rows( $result ); 00684 for ( $i = 0; $i < $count; ++ $i ) 00685 { 00686 $table = mysql_fetch_array( $result ); 00687 $tables[] = $table[0]; 00688 } 00689 mysql_free_result( $result ); 00690 } 00691 return $tables; 00692 } 00693 00694 /*! 00695 \reimp 00696 */ 00697 function eZTableList( $server = eZDBInterface::SERVER_MASTER ) 00698 { 00699 $tables = array(); 00700 if ( $this->IsConnected ) 00701 { 00702 if ( $this->UseSlaveServer && $server == eZDBInterface::SERVER_SLAVE ) 00703 { 00704 $connection = $this->DBConnection; 00705 $db = $this->SlaveDB; 00706 } 00707 else 00708 { 00709 $connection = $this->DBWriteConnection; 00710 $db = $this->DB; 00711 } 00712 00713 $query = "SHOW TABLES FROM `" . $db . "`"; 00714 $result = @mysql_query( $query, $connection ); 00715 $this->reportQuery( 'eZMySQLDB', $query, false, false ); 00716 $count = mysql_num_rows( $result ); 00717 for ( $i = 0; $i < $count; ++ $i ) 00718 { 00719 $table = mysql_fetch_array( $result ); 00720 $tableName = $table[0]; 00721 if ( substr( $tableName, 0, 2 ) == 'ez' ) 00722 { 00723 $tables[$tableName] = eZDBInterface::RELATION_TABLE; 00724 } 00725 } 00726 mysql_free_result( $result ); 00727 } 00728 return $tables; 00729 } 00730 00731 /*! 00732 \reimp 00733 */ 00734 function relationMatchRegexp( $relationType ) 00735 { 00736 return "#^ez#"; 00737 } 00738 00739 /*! 00740 \reimp 00741 */ 00742 function removeRelation( $relationName, $relationType ) 00743 { 00744 $relationTypeName = $this->relationName( $relationType ); 00745 if ( !$relationTypeName ) 00746 { 00747 eZDebug::writeError( "Unknown relation type '$relationType'", 'eZMySQLDB::removeRelation' ); 00748 return false; 00749 } 00750 00751 if ( $this->IsConnected ) 00752 { 00753 $sql = "DROP $relationTypeName $relationName"; 00754 return $this->query( $sql ); 00755 } 00756 return false; 00757 } 00758 00759 /*! 00760 \reimp 00761 */ 00762 function lock( $table ) 00763 { 00764 if ( $this->IsConnected ) 00765 { 00766 if ( is_array( $table ) ) 00767 { 00768 $lockQuery = "LOCK TABLES"; 00769 $first = true; 00770 foreach( array_keys( $table ) as $tableKey ) 00771 { 00772 if ( $first == true ) 00773 $first = false; 00774 else 00775 $lockQuery .= ","; 00776 $lockQuery .= " " . $table[$tableKey]['table'] . " WRITE"; 00777 } 00778 $this->query( $lockQuery ); 00779 } 00780 else 00781 { 00782 $this->query( "LOCK TABLES $table WRITE" ); 00783 } 00784 } 00785 } 00786 00787 /*! 00788 \reimp 00789 */ 00790 function unlock() 00791 { 00792 if ( $this->IsConnected ) 00793 { 00794 $this->query( "UNLOCK TABLES" ); 00795 } 00796 } 00797 00798 /*! 00799 \reimp 00800 The query to start the transaction. 00801 */ 00802 function beginQuery() 00803 { 00804 return $this->query("BEGIN WORK"); 00805 } 00806 00807 /*! 00808 \reimp 00809 The query to commit the transaction. 00810 */ 00811 function commitQuery() 00812 { 00813 return $this->query( "COMMIT" ); 00814 } 00815 00816 /*! 00817 \reimp 00818 The query to cancel the transaction. 00819 */ 00820 function rollbackQuery() 00821 { 00822 return $this->query( "ROLLBACK" ); 00823 } 00824 00825 /*! 00826 \reimp 00827 */ 00828 function lastSerialID( $table = false, $column = false ) 00829 { 00830 if ( $this->IsConnected ) 00831 { 00832 $id = mysql_insert_id( $this->DBWriteConnection ); 00833 return $id; 00834 } 00835 else 00836 return false; 00837 } 00838 00839 /*! 00840 \reimp 00841 */ 00842 function escapeString( $str ) 00843 { 00844 if ( $this->IsConnected ) 00845 { 00846 return mysql_real_escape_string( $str, $this->DBConnection ); 00847 } 00848 else 00849 { 00850 return mysql_escape_string( $str ); 00851 } 00852 } 00853 00854 /*! 00855 \reimp 00856 */ 00857 function close() 00858 { 00859 if ( $this->IsConnected ) 00860 { 00861 mysql_close( $this->DBConnection ); 00862 mysql_close( $this->DBWriteConnection ); 00863 } 00864 } 00865 00866 /*! 00867 \reimp 00868 */ 00869 function createDatabase( $dbName ) 00870 { 00871 if ( $this->DBConnection != false ) 00872 { 00873 mysql_create_db( $dbName, $this->DBConnection ); 00874 $this->setError(); 00875 } 00876 } 00877 00878 /*! 00879 \reimp 00880 */ 00881 function setError() 00882 { 00883 if ( $this->DBConnection ) 00884 { 00885 $this->ErrorMessage = mysql_error( $this->DBConnection ); 00886 $this->ErrorNumber = mysql_errno( $this->DBConnection ); 00887 } 00888 else 00889 { 00890 $this->ErrorMessage = mysql_error(); 00891 $this->ErrorNumber = mysql_errno(); 00892 } 00893 } 00894 00895 /*! 00896 \reimp 00897 */ 00898 function availableDatabases() 00899 { 00900 $databaseArray = mysql_list_dbs( $this->DBConnection ); 00901 00902 if ( $this->errorNumber() != 0 ) 00903 { 00904 return null; 00905 } 00906 00907 $databases = array(); 00908 $i = 0; 00909 $numRows = mysql_num_rows( $databaseArray ); 00910 if ( count( $numRows ) == 0 ) 00911 { 00912 return false; 00913 } 00914 00915 $dbServerVersion = $this->databaseServerVersion(); 00916 $dbServerMainVersion = $dbServerVersion['values'][0]; 00917 00918 while ( $i < $numRows ) 00919 { 00920 // we don't allow "mysql" or "information_schema" database to be shown anywhere 00921 $curDB = mysql_db_name( $databaseArray, $i ); 00922 if ( strcasecmp( $curDB, 'mysql' ) != 0 && strcasecmp( $curDB, 'information_schema' ) != 0 ) 00923 { 00924 $databases[] = $curDB; 00925 } 00926 ++$i; 00927 } 00928 return $databases; 00929 } 00930 00931 /*! 00932 \reimp 00933 */ 00934 function databaseServerVersion() 00935 { 00936 $versionInfo = mysql_get_server_info(); 00937 00938 $versionArray = explode( '.', $versionInfo ); 00939 00940 return array( 'string' => $versionInfo, 00941 'values' => $versionArray ); 00942 } 00943 00944 /*! 00945 \reimp 00946 */ 00947 function databaseClientVersion() 00948 { 00949 $versionInfo = mysql_get_client_info(); 00950 00951 $versionArray = explode( '.', $versionInfo ); 00952 00953 return array( 'string' => $versionInfo, 00954 'values' => $versionArray ); 00955 } 00956 00957 /*! 00958 \reimp 00959 */ 00960 function isCharsetSupported( $charset ) 00961 { 00962 if ( $charset == 'utf-8' ) 00963 { 00964 $versionInfo = $this->databaseServerVersion(); 00965 00966 // We require MySQL 4.1.1 to use the new character set functionality, 00967 // MySQL 4.1.0 does not have a full implementation of this, see: 00968 // http://dev.mysql.com/doc/mysql/en/Charset.html 00969 return ( version_compare( $versionInfo['string'], '4.1.1' ) >= 0 ); 00970 } 00971 else 00972 { 00973 return true; 00974 } 00975 } 00976 00977 function supportsDefaultValuesInsertion() 00978 { 00979 return false; 00980 } 00981 00982 public $CharsetMapping; 00983 public $TempTableList; 00984 00985 /// \privatesection 00986 } 00987 00988 ?>