eZ Publish  [4.0]
ezconvertmysqltabletype.php
Go to the documentation of this file.
00001 #!/usr/bin/env php
00002 <?php
00003 //
00004 // Created on: <21-Apr-2004 09:51:56 kk>
00005 //
00006 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00007 // SOFTWARE NAME: eZ Publish
00008 // SOFTWARE RELEASE: 4.0.x
00009 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00010 // SOFTWARE LICENSE: GNU General Public License v2.0
00011 // NOTICE: >
00012 //   This program is free software; you can redistribute it and/or
00013 //   modify it under the terms of version 2.0  of the GNU General
00014 //   Public License as published by the Free Software Foundation.
00015 //
00016 //   This program is distributed in the hope that it will be useful,
00017 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //   GNU General Public License for more details.
00020 //
00021 //   You should have received a copy of version 2.0 of the GNU General
00022 //   Public License along with this program; if not, write to the Free
00023 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00024 //   MA 02110-1301, USA.
00025 //
00026 //
00027 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00028 //
00029 
00030 //include_once( 'lib/ezutils/classes/ezcli.php' );
00031 //include_once( 'kernel/classes/ezscript.php' );
00032 
00033 require 'autoload.php';
00034 
00035 $cli = eZCLI::instance();
00036 $script = eZScript::instance( array( 'description' => ( "eZ Publish Database Converter\n\n" .
00037                                                         "Convert the database to the given type\n".
00038                                                         "ezconvertmysqltabletype.php [--host=VALUE --user=VALUE --database=VALUE [--password=VALUE]] [--list] [--newtype=TYPE] [--usecopy]" ),
00039                                      'use-session' => false,
00040                                      'use-modules' => false,
00041                                      'use-extensions' => false ) );
00042 
00043 $script->startup();
00044 
00045 $options = $script->getOptions( "[host:][user:][password:][database:][list][newtype:][usecopy]",
00046                                 "",
00047                                 array(
00048                                        'list' => "List the table types",
00049                                        'host' => "Connect to host database",
00050                                        'user' => "User for login to the database",
00051                                        'password' => "Password to use when connecting to the database",
00052                                        'newtype' => "Convert the database to the given type.\nType can either be: myisam or innodb\n".
00053                                                     "Make sure that you have made a BACKUP UP of YOUR DATABASE!",
00054                                        'usecopy' => "To convert the table we rename the original table and copy the data to the new table structure.\n".
00055                                                     "This conversion method is much slower and has a higher risk to corrupt the data in the database.\n".
00056                                                     "However this option may circumvent the MySQL crash on the ALTER query." )
00057                               );
00058 $script->initialize();
00059 
00060 $host = $options['host'];
00061 $user = $options['user'];
00062 
00063 $password = is_string( $options['password'] ) ? $options['password'] : "";
00064 $database = $options['database'];
00065 $listMode = $options['list'];
00066 $newType = $options["newtype"];
00067 $usecopy = $options["usecopy"];
00068 
00069 checkParameters( $cli, $script, $options, $host, $user, $password, $database, $listMode, $newType );
00070 $db = connectToDatabase( $cli, $script, $host, $user, $password, $database );
00071 
00072 // If the listMode parameter is set or no newType is assigned then show the list.
00073 if ( $listMode || !isset( $newType ) )
00074 {
00075     listTypes( $cli, $db );
00076 }
00077 else
00078 {
00079     setNewType( $cli, $db, $newType, $usecopy );
00080 }
00081 
00082 /**
00083  *  Check whether the parameters are correctly set.
00084 **/
00085 function checkParameters( $cli, $script, $options, $host, $user, $password, $database, $listMode, $newType )
00086 {
00087     // Extra parameters are not tolerated.
00088     if ( count ( $options['arguments'] ) != 0 )
00089     {
00090             $cli->error( "Unknown parameters" );
00091             $script->shutdown( 1 );
00092     }
00093 
00094     // Host, User, and database are like the three musketeers.
00095     // Either the three parameters must be set or none.
00096     if ( isset( $host ) || isset( $user ) || isset( $database ) )
00097     {
00098         if ( !isset( $host ) || !isset( $user ) || !isset( $database ) )
00099         {
00100             $cli->error( "Use the host, user, database, and optionally a password together." );
00101             $script->shutdown( 1 );
00102         }
00103     }
00104 
00105     // If the newType is set, check whether the given type exist.
00106     if ( $newType )
00107     {
00108         switch ( strtolower( $newType ) )
00109         {
00110             case "innodb": break;
00111             case "myisam": break;
00112 
00113             default: $cli->error( "New table type not supported." );
00114                      $script->shutDown( 1 );
00115         }
00116     }
00117 }
00118 
00119 // Creates a displayable string for the end-user explaining
00120 // which database, host, user and password which were tried
00121 function eZTriedDatabaseString( $database, $host, $user, $password )
00122 {
00123     $msg = "'$database'";
00124     if ( strlen( $host ) > 0 )
00125     {
00126         $msg .= " at host '$host'";
00127     }
00128     else
00129     {
00130         $msg .= " locally";
00131     }
00132     if ( strlen( $user ) > 0 )
00133     {
00134         $msg .= " with user '$user'";
00135     }
00136     if ( strlen( $password ) > 0 )
00137         $msg .= " and with a password";
00138     return $msg;
00139 }
00140 
00141 /**
00142  * Connect to the database
00143 **/
00144 function connectToDatabase( $cli, $script, $host, $user, $password, $database )
00145 {
00146     //include_once( 'lib/ezdb/classes/ezdb.php' );
00147 
00148     if ( $user )
00149     {
00150         $db = eZDB::instance( "mysql",
00151                            array( 'server' => $host,
00152                                   'user' => $user,
00153                                   'password' => $password,
00154                                   'database' => $database ) );
00155     } else
00156     {
00157          $db = eZDB::instance();
00158          if ( $db->databaseName() != "mysql" )
00159          {
00160             $cli->error( 'This script can only show and convert mysql databases.' );
00161             $script->shutdown( 1 );
00162          }
00163     }
00164 
00165     if ( !is_object( $db ) )
00166     {
00167         $cli->error( 'Could not initialize database:' );
00168         $cli->error( '* No database handler was found for mysql' );
00169         $script->shutdown( 1 );
00170     }
00171     if ( !$db or !$db->isConnected() )
00172     {
00173         $cli->error( "Could not initialize database:" );
00174         $cli->error( "* Tried database " . eZTriedDatabaseString( $database, $host, $user, $password ) );
00175 
00176         // Fetch the database error message if there is one
00177         // It will give more feedback to the user what is wrong
00178         $msg = $db->errorMessage();
00179         if ( $msg )
00180         {
00181             $number = $db->errorNumber();
00182             if ( $number > 0 )
00183                 $msg .= '(' . $number . ')';
00184             $cli->error( '* ' . $msg );
00185         }
00186         $script->shutdown( 1 );
00187     }
00188 
00189     return $db;
00190 }
00191 
00192 function getTableType( $db, $tableName )
00193 {
00194     $res = $db->arrayQuery( "SHOW CREATE TABLE `$tableName`" );
00195     preg_match( '/(?:TYPE|ENGINE)=(\w*)/', $res[0]["Create Table"], $grep );
00196     return $grep[1];
00197 }
00198 
00199 function listTypes( $cli, $db )
00200 {
00201     $tables = $db->arrayQuery( "show tables" );
00202 
00203     $spaces = str_pad ( ' ', 35 );
00204     $cli->notice( "Table $spaces Type" );
00205     $cli->notice( "----- $spaces ----" );
00206     foreach ( $tables as $table )
00207     {
00208         $tableName = current( $table );
00209         $tableType = getTableType( $db, $tableName );
00210 
00211         $spaces = str_pad(' ', 40 - strlen( $tableName ) );
00212         $eZpublishTable = strncmp( $tableName, "ez", 2 ) == 0 ? "" : "(non eZ Publish)";
00213         $cli->notice( "$tableName $spaces $tableType $eZpublishTable" );
00214     }
00215 }
00216 
00217 function alterType( $db, $tableName, $newType )
00218 {
00219      $db->query( "ALTER TABLE $tableName ENGINE=$newType" );
00220 }
00221 
00222 function renameTable( $db, $tableFrom, $tableTo )
00223 {
00224     $db->query( "ALTER TABLE $tableFrom RENAME $tableTo" );
00225 }
00226 
00227 function copyTable( $db, $tableFrom, $tableTo )
00228 {
00229     $db->query( "INSERT INTO $tableTo SELECT * FROM $tableFrom" );
00230 }
00231 
00232 function createTableStructure( $db, $tableFrom, $tableTo, $newType )
00233 {
00234     $res = $db->arrayQuery( "SHOW CREATE TABLE `$tableFrom`" );
00235 
00236     $pattern = array( "/(TYPE|ENGINE)=(\w*)/", "/TABLE `$tableFrom`/" );
00237     $replacement = array( "ENGINE=$newType", "TABLE `$tableTo`" );
00238     $structure = preg_replace( $pattern, $replacement, $res[0]["Create Table"] );
00239 
00240     $db->query( $structure );
00241 }
00242 
00243 function dropTable( $db, $tableName )
00244 {
00245     $db->query( "DROP TABLE $tableName" );
00246 }
00247 
00248 function setNewType( $cli, $db, $newType, $usecopy )
00249 {
00250     $tables = $db->arrayQuery( "show tables" );
00251 
00252     foreach ( $tables as $table )
00253     {
00254         $tableName = current( $table );
00255 
00256         // Checking if it is necessary to convert the table.
00257         if ( strncmp( $tableName, "ez", 2 ) != 0 )
00258         {
00259             $cli->notice( "Skipping table $tableName because it is not an eZ Publish table" );
00260         }
00261         else if ( strcasecmp( getTableType( $db, $tableName ), $newType ) == 0 )
00262         {
00263             $cli->notice( "Skipping table $tableName because it has already the $newType type" );
00264         }
00265         else
00266         {
00267             // Yes, convert.
00268             $cli->notice( "Converting table $tableName ... " );
00269 
00270             if ( !$usecopy )
00271             {
00272                 // The simple one
00273                 alterType( $db, $tableName, $newType );
00274             }
00275             else
00276             {
00277                 renameTable( $db, $tableName, "eztemp__$tableName" );
00278                 createTableStructure( $db, "eztemp__$tableName", $tableName, $newType );
00279                 copyTable( $db, "eztemp__$tableName", $tableName );
00280                 dropTable( $db, "eztemp__$tableName" );
00281             }
00282         }
00283     }
00284 }
00285 
00286 $script->shutdown();
00287 ?>