UpdateDatabase/MysqlEngineCharset.php
[Pman.Core] / UpdateDatabase / MysqlEngineCharset.php
1 <?php
2 /**
3   fixes character set and engine=InnoDB.. in Mysql
4   more efficent 
5  */
6
7 class Pman_Core_UpdateDatabase_MysqlEngineCharset {
8     
9     var $dburl;
10     var $schema = array();
11     var $links = array();
12     
13     function __construct()
14     {
15           
16         $this->loadIniFiles(); //?? shared???
17         
18         // update the engine first - get's around 1000 character limit on indexes..cd
19         // however - Innodb does not support fulltext indexes, so this may fail...
20         $this->updateEngine(); 
21         
22         $this->updateCharacterSet();
23         
24         
25     }
26     
27     function loadIniFiles()
28     {
29         // will create the combined ini cache file for the running user.
30         
31         $ff = HTML_FlexyFramework::get();
32         $ff->generateDataobjectsCache(true);
33         $this->dburl = parse_url($ff->database);
34         
35          
36         $dbini = 'ini_'. basename($this->dburl['path']);
37         
38         
39         $iniCache = isset( $ff->PDO_DataObject) ?  $ff->DB_DataObject['schema_location'] : $ff->DB_DataObject[$dbini];
40         if (!file_exists($iniCache)) {
41             return;
42         }
43         
44         $this->schema = parse_ini_file($iniCache, true);
45         $this->links = parse_ini_file(preg_replace('/\.ini$/', '.links.ini', $iniCache), true);
46         
47
48         
49     }
50    
51     function updateCharacterSet()
52     {
53         $db = DB_DataObject::factory('core_enum')->getDatabaseConnection();
54         $views = $db->getListOf(  'views');
55         
56         
57         foreach (array_keys($this->schema) as $tbl){
58             
59             if(strpos($tbl, '__keys') !== false ){
60                 continue;
61             }
62             
63             if(in_array($tbl , $views)) {
64                 continue;
65             }
66             
67             $ce = DB_DataObject::factory('core_enum');
68             
69             $ce->query("
70                 SELECT
71                         CCSA.character_set_name csname,
72                         CCSA.collation_name collatename
73                 FROM
74                         information_schema.`TABLES` T,
75                         information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
76                 WHERE
77                         CCSA.collation_name = T.table_collation
78                     AND
79                         T.table_schema = '{$ce->database()}' -- COLLATE utf8_general_ci
80                     AND
81                         T.table_name = '{$tbl}' -- COLLATE utf8_general_ci
82             ");
83                      
84             if (!$ce->fetch()) {
85                 continue;
86             }
87             
88             if($ce->csname == 'utf8' && $ce->collatename == 'utf8_general_ci'){
89                 echo "utf8: SKIP $tbl\n";
90                 continue;
91             }
92             // this used to be utf8_unicode_ci
93             //as the default collation for stored procedure parameters is utf8_general_ci and you can't mix collations.
94             
95             $ce = DB_DataObject::factory('core_enum');
96             // not sure why, but convert to does not actually change the 'charset=' bit..
97             $ce->query("ALTER TABLE $tbl CHARSET=utf8");
98             $ce->query("ALTER TABLE {$tbl} CONVERT TO CHARACTER SET  utf8 COLLATE utf8_general_ci");
99             echo "utf8: FIXED {$tbl}\n";
100             
101         }
102     }
103     function updateEngine()
104     {
105         $db = DB_DataObject::factory('core_enum');
106         $db->query("show variables like 'innodb_file_per_table'");
107         $db->fetch();
108         if ($db->Value == 'OFF') {
109             die("Error: set innodb_file_per_table = 1 in my.cnf\n\n");
110         }
111         
112         // get a list of table views...
113         // innodb in single files is far more efficient that MYD or one big innodb file.
114         // first check if database is using this format.
115         
116         
117         
118         $db = DB_DataObject::factory('core_enum')->getDatabaseConnection();
119         $views = $db->getListOf( 'views');  // needs updated pear... 
120         
121         
122         
123         
124         foreach (array_keys($this->schema) as $tbl){
125             
126             if(strpos($tbl, '__keys') !== false ){
127                 continue;
128             }
129             if(in_array($tbl , $views)) {
130                 continue;
131             }
132             
133             $ce = DB_DataObject::factory('core_enum');
134             
135             $ce->query("
136                 select
137                     engine
138                 from
139                     information_schema.tables
140                 where
141                     table_schema='{$ce->database()}'
142                     and
143                     table_name = '{$tbl}'
144             ");
145
146             if (!$ce->fetch()) {
147                 continue;
148             }
149             
150             if($ce->engine == 'InnoDB' ){
151                 echo "InnoDB: SKIP $tbl\n";
152                 continue;
153             }
154             // this used to be utf8_unicode_ci
155             //as the default collation for stored procedure parameters is utf8_general_ci and you can't mix collations.
156             
157             $ce = DB_DataObject::factory('core_enum');
158             $ce->query("ALTER TABLE $tbl ENGINE=InnoDB");
159             echo "InnoDB: FIXED {$tbl}\n";
160             
161         }
162     }
163     
164 }
165