eZ Publish  [4.0]
ezmysqldb.php
Go to the documentation of this file.
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 ?>