Aleksander Machniak
2013-03-26 1d4c84f4d74217a6639b143c14c99e3473fc539a
commit | author | age
b7e7c8 1 #!/usr/bin/env php
AM 2 <?php
3 /*
4  +-----------------------------------------------------------------------+
5  | bin/updatedb.sh                                                       |
6  |                                                                       |
7  | This file is part of the Roundcube Webmail client                     |
8  | Copyright (C) 2010-2012, The Roundcube Dev Team                       |
9  | Copyright (C) 2010-2012, Kolab Systems AG                             |
10  |                                                                       |
11  | Licensed under the GNU General Public License version 3 or            |
12  | any later version with exceptions for skins & plugins.                |
13  | See the README file for a full license statement.                     |
14  |                                                                       |
15  | PURPOSE:                                                              |
16  |   Update database schema                                              |
17  +-----------------------------------------------------------------------+
18  | Author: Aleksander Machniak <alec@alec.pl>                            |
19  +-----------------------------------------------------------------------+
20 */
21
22 define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
23
24 require_once INSTALL_PATH . 'program/include/clisetup.php';
25
26 // get arguments
27 $opts = rcube_utils::get_opt(array(
28     'v' => 'version',
29     'd' => 'dir',
9e329c 30     'p' => 'package',
b7e7c8 31 ));
AM 32
33 if (empty($opts['dir'])) {
34   echo "ERROR: Database schema directory not specified (--dir).\n";
35   exit(1);
36 }
9e329c 37 if (empty($opts['package'])) {
AM 38   echo "ERROR: Database schema package name not specified (--package).\n";
b7e7c8 39   exit(1);
AM 40 }
41
42 // Check if directory exists
43 if (!file_exists($opts['dir'])) {
44   echo "ERROR: Specified database schema directory doesn't exist.\n";
45   exit(1);
46 }
47
7e7431 48 $RC = rcube::get_instance();
AM 49 $DB = rcube_db::factory($RC->config->get('db_dsnw'));
50
51 // Connect to database
52 $DB->db_connect('w');
53 if (!$DB->is_connected()) {
54     echo "Error connecting to database: " . $DB->is_error() . ".\n";
55     exit(1);
56 }
57
c10187 58 // Read DB schema version from database (if 'system' table exists)
15e4c8 59 if (in_array($DB->table_name('system'), (array)$DB->list_tables())) {
9be085 60     $DB->query("SELECT " . $DB->quote_identifier('value')
c10187 61         ." FROM " . $DB->quote_identifier($DB->table_name('system'))
9be085 62         ." WHERE " . $DB->quote_identifier('name') ." = ?",
9e329c 63         $opts['package'] . '-version');
7e7431 64
9be085 65     $row     = $DB->fetch_array();
9e46fb 66     $version = preg_replace('/[^0-9]/', '', $row[0]);
9be085 67 }
7e7431 68
9be085 69 // DB version not found, but release version is specified
7e7431 70 if (!$version && $opts['version']) {
b7e7c8 71     // Map old release version string to DB schema version
AM 72     // Note: This is for backward compat. only, do not need to be updated
73     $map = array(
74         '0.1-stable' => 1,
75         '0.1.1'      => 2008030300,
76         '0.2-alpha'  => 2008040500,
77         '0.2-beta'   => 2008060900,
78         '0.2-stable' => 2008092100,
79         '0.3-stable' => 2008092100,
80         '0.3.1'      => 2009090400,
81         '0.4-beta'   => 2009103100,
82         '0.4.2'      => 2010042300,
83         '0.5-beta'   => 2010100600,
84         '0.5'        => 2010100600,
85         '0.5.1'      => 2010100600,
86         '0.6-beta'   => 2011011200,
87         '0.6'        => 2011011200,
88         '0.7-beta'   => 2011092800,
89         '0.7'        => 2011111600,
90         '0.7.1'      => 2011111600,
91         '0.7.2'      => 2011111600,
92         '0.7.3'      => 2011111600,
93         '0.8-beta'   => 2011121400,
94         '0.8-rc'     => 2011121400,
95         '0.8.0'      => 2011121400,
96         '0.8.1'      => 2011121400,
97         '0.8.2'      => 2011121400,
98         '0.8.3'      => 2011121400,
99         '0.8.4'      => 2011121400,
100         '0.9-beta'   => 2012080700,
101     );
102
103     $version = $map[$opts['version']];
104 }
105
c10187 106 // Assume last version before the 'system' table was added
b7e7c8 107 if (empty($version)) {
AM 108     $version = 2012080700;
109 }
110
111 $dir = $opts['dir'] . DIRECTORY_SEPARATOR . $DB->db_provider;
112 if (!file_exists($dir)) {
113     echo "DDL Upgrade files for " . $DB->db_provider . " driver not found.\n";
114     exit(1);
115 }
116
117 $dh     = opendir($dir);
118 $result = array();
119
120 while ($file = readdir($dh)) {
121     if (preg_match('/^([0-9]+)\.sql$/', $file, $m) && $m[1] > $version) {
122         $result[] = $m[1];
123     }
124 }
125 sort($result, SORT_NUMERIC);
126
127 foreach ($result as $v) {
128     echo "Updating database schema ($v)... ";
9e329c 129     $error = update_db_schema($opts['package'], $v, $dir . DIRECTORY_SEPARATOR . "$v.sql");
b7e7c8 130
AM 131     if ($error) {
132         echo "\nError in DDL upgrade $v: $error\n";
133         exit(1);
134     }
135     echo "[OK]\n";
136 }
137
138 exit(0);
139
9e329c 140 function update_db_schema($package, $version, $file)
b7e7c8 141 {
AM 142     global $DB;
143
144     // read DDL file
145     if ($lines = file($file)) {
146         $sql = '';
147         foreach ($lines as $line) {
148             if (preg_match('/^--/', $line) || trim($line) == '')
149                 continue;
150
151             $sql .= $line . "\n";
152             if (preg_match('/(;|^GO)$/', trim($line))) {
15e4c8 153                 @$DB->query(fix_table_names($sql));
b7e7c8 154                 $sql = '';
AM 155                 if ($error = $DB->is_error()) {
156                     return $error;
157                 }
158             }
159         }
160     }
161
c3d061 162     // escape if 'system' table does not exist
AM 163     if ($version < 2013011000) {
164         return;
165     }
166
c10187 167     $system_table = $DB->quote_identifier($DB->table_name('system'));
AM 168
169     $DB->query("UPDATE " . $system_table
b7e7c8 170         ." SET " . $DB->quote_identifier('value') . " = ?"
AM 171         ." WHERE " . $DB->quote_identifier('name') . " = ?",
9e329c 172         $version, $package . '-version');
b7e7c8 173
AM 174     if (!$DB->is_error() && !$DB->affected_rows()) {
c10187 175         $DB->query("INSERT INTO " . $system_table
b7e7c8 176             ." (" . $DB->quote_identifier('name') . ", " . $DB->quote_identifier('value') . ")"
AM 177             ." VALUES (?, ?)",
9e329c 178             $package . '-version', $version);
b7e7c8 179     }
AM 180
181     return $DB->is_error();
182 }
183
15e4c8 184 function fix_table_names($sql)
TB 185 {
186     global $DB;
187
188     foreach (array('users','identities','contacts','contactgroups','contactgroupmembers','session','cache','cache_index','cache_index','cache_messages','dictionary','searches','system') as $table) {
189         $real_table = $DB->table_name($table);
190         if ($real_table != $table) {
191             $sql = preg_replace("/([^a-z0-9_])$table([^a-z0-9_])/i", "\\1$real_table\\2", $sql);
192         }
193     }
194
195     return $sql;
196 }
197
b7e7c8 198 ?>