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;
11     var $links;
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         $dbini = 'ini_'. basename($this->dburl['path']);
36         
37         
38         $iniCache = $ff->DB_DataObject[$dbini];
39         
40         $this->schema = parse_ini_file($iniCache, true);
41         $this->links = parse_ini_file(preg_replace('/\.ini$/', '.links.ini', $iniCache), true);
42         
43
44         
45     }
46    
47     function updateCharacterSet()
48     {
49         $db = DB_DataObject::factory('core_enum')->getDatabaseConnection();
50         $views = $db->getListOf(  'views');
51         
52         
53         foreach (array_keys($this->schema) as $tbl){
54             
55             if(strpos($tbl, '__keys') !== false ){
56                 continue;
57             }
58             
59             if(in_array($tbl , $views)) {
60                 continue;
61             }
62             
63             $ce = DB_DataObject::factory('core_enum');
64             
65             $ce->query("
66                 SELECT
67                         CCSA.character_set_name csname,
68                         CCSA.collation_name collatename
69                 FROM
70                         information_schema.`TABLES` T,
71                         information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
72                 WHERE
73                         CCSA.collation_name = T.table_collation
74                     AND
75                         T.table_schema = '{$ce->database()}' -- COLLATE utf8_general_ci
76                     AND
77                         T.table_name = '{$tbl}' -- COLLATE utf8_general_ci
78             ");
79                      
80             if (!$ce->fetch()) {
81                 continue;
82             }
83             
84             if($ce->csname == 'utf8' && $ce->collatename == 'utf8_general_ci'){
85                 echo "utf8: SKIP $tbl\n";
86                 continue;
87             }
88             // this used to be utf8_unicode_ci
89             //as the default collation for stored procedure parameters is utf8_general_ci and you can't mix collations.
90             
91             $ce = DB_DataObject::factory('core_enum');
92             // not sure why, but convert to does not actually change the 'charset=' bit..
93             $ce->query("ALTER TABLE $tbl CHARSET=utf8");
94             $ce->query("ALTER TABLE {$tbl} CONVERT TO CHARACTER SET  utf8 COLLATE utf8_general_ci");
95             echo "utf8: FIXED {$tbl}\n";
96             
97         }
98     }
99     function updateEngine()
100     {
101         $db = DB_DataObject::factory('core_enum');
102         $db->query("show variables like 'innodb_file_per_table'");
103         $db->fetch();
104         if ($db->Value == 'OFF') {
105             die("Error: set innodb_file_per_table = 1 in my.cnf\n\n");
106         }
107         
108         // get a list of table views...
109         // innodb in single files is far more efficient that MYD or one big innodb file.
110         // first check if database is using this format.
111         
112         
113         
114         $db = DB_DataObject::factory('core_enum')->getDatabaseConnection();
115         $views = $db->getListOf(  'views');
116         
117         
118         
119         
120         foreach (array_keys($this->schema) as $tbl){
121             
122             if(strpos($tbl, '__keys') !== false ){
123                 continue;
124             }
125             if(in_array($tbl , $views)) {
126                 continue;
127             }
128             
129             $ce = DB_DataObject::factory('core_enum');
130             
131             $ce->query("
132                 select
133                     engine
134                 from
135                     information_schema.tables
136                 where
137                     table_schema='{$ce->database()}'
138                     and
139                     table_name = '{$tbl}'
140             ");
141
142             if (!$ce->fetch()) {
143                 continue;
144             }
145             
146             if($ce->engine == 'InnoDB' ){
147                 echo "InnoDB: SKIP $tbl\n";
148                 continue;
149             }
150             // this used to be utf8_unicode_ci
151             //as the default collation for stored procedure parameters is utf8_general_ci and you can't mix collations.
152             
153             $ce = DB_DataObject::factory('core_enum');
154             $ce->query("ALTER TABLE $tbl ENGINE=InnoDB");
155             echo "InnoDB: FIXED {$tbl}\n";
156             
157         }
158     }
159     
160 }
161