Added stub for database query profiling.
[fa-stable.git] / sql / alter2.4.php
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 class fa2_4 {
13         var $version = '2.4.0'; // version installed
14         var $description;
15         var $sql = 'alter2.4.sql';
16         var $preconf = true;
17         
18         function fa2_4() {
19                 $this->description = _('Upgrade from version 2.3 to 2.4');
20         }
21         
22         //
23         //      Install procedure. All additional changes 
24         //      not included in sql file should go here.
25         //
26         function install($company, $force=false) 
27         {
28                 global $db_version, $db_connections;
29
30                 $pref = $db_connections[$company]['tbpref'];
31
32                 if (get_company_pref('grn_clearing_act') === null) { // available form 2.3.1, can be not defined on pre-2.4 installations
33                         set_company_pref('grn_clearing_act', 'glsetup.purchase', 'varchar', 15, 0);
34                 }
35                 if (get_company_pref('default_quote_valid_days') === null) { // new in 2.3.23 installations
36                         set_company_pref('default_quote_valid_days', 'glsetup.sales', 'smallint', 6, 30);
37                 }
38                 if (get_company_pref('bcc_email') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
39                         set_company_pref('bcc_email', 'setup.company', 'varchar', 100, '');
40                 }
41                 if (get_company_pref('alternative_tax_include_on_docs') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
42                         set_company_pref('alternative_tax_include_on_docs', 'setup.company', 'tinyint', 1, '0');
43                 }
44                 if (get_company_pref('suppress_tax_rates') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
45                         set_company_pref('suppress_tax_rates', 'setup.company', 'tinyint', 1, '0');
46                 }
47
48                 $result = $this->update_workorders()  && $this->update_grn_rates() && $this->switch_database_to_utf($pref);
49
50                 if ($result)
51                         $result = $this->do_cleanup();
52
53                 //remove obsolete and temporary columns.
54                 // this have to be done here as db_import rearranges alter query order
55                 $dropcol = array(
56                                 'cust_branch' => array('contact_name', 'disable_trans'),
57                 );
58
59                 foreach($dropcol as $table => $columns)
60                         foreach($columns as $col) {
61                                 if (db_query("ALTER TABLE `".TB_PREF."{$table}` DROP `$col`")==false) {
62                                         display_error("Cannot drop {$table}.{$col} column:<br>".db_error_msg($db));
63                                         return false;
64                                 }
65                         }
66
67                 return  update_company_prefs(array('version_id'=>$db_version));
68         }
69         //
70         //      Checking before install
71         //
72         function pre_check($pref, $force)
73         {
74                 return true;
75         }
76
77         //
78         // optional procedure done after upgrade fail, before backup is restored
79         //
80         function post_fail($pref)
81         {
82                 db_query("DROP TABLE IF EXISTS " . $pref . 'wo_costing');
83         }
84         //
85         //      Test if patch was applied before.
86         //
87         function installed($pref)
88         {
89                 $n = 2; // number of patches to be installed
90                 $patchcnt = 0;
91
92                 if (!check_table($pref, 'suppliers', 'tax_algorithm')) $patchcnt++;
93                 if (!check_table($pref, 'wo_costing')) $patchcnt++;
94                 return $n == $patchcnt ? true : ($patchcnt ? ($patchcnt.'/'. $n) : 0);
95         }
96
97         function update_workorders()
98         {
99                 global $db;
100
101                 $sql = "SELECT DISTINCT type, type_no, tran_date, person_id FROM ".TB_PREF."gl_trans WHERE `type`=".ST_WORKORDER
102                 ." AND person_type_id=1";
103                 $res = db_query($sql);
104                 if (!$res)
105                 {
106                         display_error("Cannot update work orders costs"
107                                 .':<br>'. db_error_msg($db));
108                         return false;
109                 }
110                 while ($row = db_fetch($res))
111                 {
112                         $journal_id = get_next_trans_no(ST_JOURNAL);
113
114                         $sql1 = "UPDATE ".TB_PREF."gl_trans SET `type`=".ST_JOURNAL.", type_no={$journal_id},
115                                 person_type_id=NULL, person_id=0
116                                 WHERE `type`=".ST_WORKORDER." AND type_no={$row['type_no']} AND tran_date='{$row['tran_date']}'
117                                 AND person_id='{$row['person_id']}'";
118                         if (!db_query($sql1)) return false;
119                         
120                         $sql2 = "INSERT INTO ".TB_PREF."wo_costing (workorder_id, cost_type, trans_no) 
121                                 VALUES ({$row['type_no']}, {$row['person_id']}, {$journal_id})";
122                         if (!db_query($sql2)) return false;
123                 }
124                 return true;
125         }
126
127 /*
128         In previous versions FA ignored encoding settings on database/tables, so it depended on server settings,
129         but data stored is encoded in user language encoding. Now we switch to utf8 internal database encoding, while
130         user encoding can be selected independently.
131
132         To perform safe FA database switch to utf-8 encoding we have to first ensure that all text/char columns 
133         have properly set encoding (the same as its content), so the algorithm performed on every table is as follows:
134         . set default table encoding for the table to currently used on client side;
135         . for all text/char column:
136          - suppress autorecoding by change of the type to related binary/blob type
137          - change column to utf8 encodding and selected collation.
138         . change default table encoding to utf8
139 */
140         function switch_database_to_utf($pref, $test = false) {
141
142                 global $installed_languages, $dflt_lang;
143
144                 $old_encoding = 'latin1'; // default client encoding
145
146                  // site default encoding is presumed as encoding for all databases!
147                 $lang = array_search_value($dflt_lang, $installed_languages, 'code');
148                 $new_encoding = get_mysql_encoding_name(strtoupper($lang['encoding']));
149
150                 if ($test)
151                         error_log('Switching database to utf8 encoding from '.$old_encoding);
152                 $collation = get_mysql_collation();
153                 $tsql = "SHOW TABLES LIKE '".($pref=='' ? '' : substr($pref, 0, -1).'\\_')."%'";
154                 $tresult = db_query($tsql, "Cannot select all tables with prefix '$pref'");
155                 while($tbl = db_fetch($tresult)) {
156                         $table = $tbl[0];
157
158                         db_query("ALTER TABLE `$table` CONVERT TO CHARACTER SET $old_encoding"); // convert encoding on utf-8 tables
159
160                         // set proper default table encoding for current user language (used on binary->text conversion)
161                         db_query("ALTER TABLE `$table` CHARSET $new_encoding");
162                         $csql = "SHOW COLUMNS FROM $table";
163                         $cresult = db_query($csql, "Cannot select column names for table '$table'");
164                         $convert = false;
165
166                         $to_binary = $to_default = $to_utf = array();
167                         while($col = db_fetch($cresult)) {
168
169                                 $bintype = strtr($col['Type'], array('varchar' => 'varbinary', 'char'=>'varbinary', 'text'=>'blob', 'tinytext'=>'tinyblob'));
170
171                                 if ($bintype != $col['Type'])
172                                 { // this is char/text column, so change encoding to proper encoding
173                                         if ($test)
174                                                 error_log($table.'.'.$col['Field']);
175
176                                         $null = $col['Null'] === 'YES' ? ' NULL ' : ' NOT NULL ';
177                                         $default = $col['Null'] !== 'YES' && isset($col['Default']) ? ' DEFAULT '.db_escape($col['Default']) : '';
178
179                                         // to avoid column width multiplication x3 we old->binary->ui->utf column type change instead of column CONVERT
180
181                                         $to_binary[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$bintype;
182                                         $to_default[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$col['Type'].$null.$default;
183                                         $to_utf[] = "MODIFY COLUMN `".$col['Field']."` ".$col['Type']." COLLATE ".$collation.$null.$default;
184                                         $convert = true;
185                                 }
186                         }
187                         if(count($to_binary))
188                         {
189                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_binary);
190                                 db_query($sql);
191                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_default);
192                                 db_query($sql);
193                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_utf);
194                                 db_query($sql);
195                         }
196                         db_query("ALTER TABLE `$table` COLLATE $collation");
197                 }
198                 db_query("ALTER DATABASE COLLATE $collation");
199                 if ($test)
200                         error_log('Convertion to utf8 done.');
201
202                 return true;
203         }
204
205         function update_grn_rates()
206         {
207                 $sql = "SELECT grn.id, grn.delivery_date, supp.curr_code 
208                         FROM ".TB_PREF."grn_batch grn, ".TB_PREF."suppliers supp
209                         WHERE supp.supplier_id=grn.supplier_id AND supp.curr_code!='".get_company_pref('curr_default')."'";
210                 $result = db_query($sql);
211
212                 if (!$result)
213                         return false;
214
215                 $sql = "UPDATE ".TB_PREF."grn_batch SET rate=%s WHERE id=%d";
216                 while ($grn = db_fetch($result))
217                         db_query(sprintf($sql, get_exchange_rate_from_home_currency($grn['curr_code'], sql2date($grn['delivery_date'])), $grn['id']));
218
219                 return true;
220         }
221
222         function do_cleanup()
223         {
224                 $dropcol = array(
225                                 'tax_group_items' => array('rate'),
226                                 'budget_trans' => array('type', 'type_no', 'person_id', 'person_type_id', 'memo_'),
227                 );
228
229                 foreach($dropcol as $table => $columns)
230                         foreach($columns as $col) {
231                                 if (db_query("ALTER TABLE `".TB_PREF."{$table}` DROP `$col`") == false) {
232                                         display_error("Cannot drop {$table}.{$col} column:<br>".db_error_msg($db));
233                                         return false;
234                                 }
235                         }
236         }
237 }
238
239 $install = new fa2_4;