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