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