+/*
+ In previous versions FA ignored encoding settings on database/tables, so it depended on server settings,
+ but data stored is encoded in user language encoding. Now we switch to utf8 internal database encoding, while
+ user encoding can be selected independently.
+
+ To perform safe FA database switch to utf-8 encoding we have to first ensure that all text/char columns
+ have properly set encoding (the same as its content), so the algorithm performed on every table is as follows:
+ . set default table encoding for the table to currently used on client side;
+ . for all text/char column:
+ - suppress autorecoding by change of the type to related binary/blob type
+ - change column to utf8 encodding and selected collation.
+ . change default table encoding to utf8 and selected collation
+*/
+ function switch_database_to_utf($pref, $dbg = false) {
+
+ global $installed_languages, $dflt_lang;
+
+ $old_encoding = 'latin1'; // default client encoding
+
+ // uncomment in case of 1071 errors (requires SUPER privileges)
+ // db_query("SET @@global.innodb_large_prefix=1", "Cannot set large prefix");
+
+ // site default encoding is presumed as encoding for all databases!
+ $lang = array_search_value($dflt_lang, $installed_languages, 'code');
+ $new_encoding = get_mysql_encoding_name(strtoupper($lang['encoding']));
+
+ $this->log_error(sprintf('Switching database to utf8 encoding from %s', $old_encoding), 'Info');
+ $collation = get_mysql_collation($this->collation);
+ $tsql = "SHOW TABLES LIKE '".($pref=='' ? '' : substr($pref, 0, -1).'\\_')."%'";
+ $tresult = db_query($tsql, "Cannot select all tables with prefix '$pref'");
+ while($tbl = db_fetch($tresult)) {
+ $table = $tbl[0];
+
+ db_query("ALTER TABLE `$table` CONVERT TO CHARACTER SET $old_encoding"); // convert encoding on utf-8 tables
+
+ // set proper default table encoding for current user language (used on binary->text conversion)
+ db_query("ALTER TABLE `$table` CHARSET $new_encoding");
+ $csql = "SHOW COLUMNS FROM $table";
+ $cresult = db_query($csql, "Cannot select column names for table '$table'");
+ $convert = false;
+
+ $to_binary = $to_default = $to_utf = array();
+ while($col = db_fetch($cresult)) {
+
+ $bintype = strtr($col['Type'], array('varchar' => 'varbinary', 'char'=>'varbinary', 'text'=>'blob', 'tinytext'=>'tinyblob'));
+
+ if ($bintype != $col['Type'])
+ { // this is char/text column, so change encoding to proper encoding
+ if ($dbg)
+ $this->log_error(sprintf('%s switched to uft8.', $table.'.'.$col['Field']), 'Debug');
+
+ $null = $col['Null'] === 'YES' ? ' NULL ' : ' NOT NULL ';
+ $default = $col['Null'] !== 'YES' && isset($col['Default']) ? ' DEFAULT '.db_escape($col['Default']) : '';
+
+ // to avoid column width multiplication x3 we old->binary->ui->utf column type change instead of column CONVERT
+
+ $to_binary[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$bintype;
+ $to_default[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$col['Type'].$null.$default;
+ $to_utf[] = "MODIFY COLUMN `".$col['Field']."` ".$col['Type']." COLLATE ".$collation.$null.$default;
+ $convert = true;
+ }
+ }
+ if(count($to_binary))
+ {
+ $sql = "ALTER TABLE `$table` ".implode(',',$to_binary);
+ db_query($sql);
+ $sql = "ALTER TABLE `$table` ".implode(',',$to_default);
+ db_query($sql);
+ $sql = "ALTER TABLE `$table` ".implode(',',$to_utf);
+ db_query($sql);
+ }
+ db_query("ALTER TABLE `$table` COLLATE $collation");
+ }
+ db_query("ALTER DATABASE COLLATE $collation");
+ $this->log_error(_('Convertion to utf8 done.'), 'Info');
+
+ return true;
+ }
+
+ function update_grn_rates()