1#!/usr/bin/env php
2<?php
3
4define('INSTALL_PATH', getcwd() . '/' );
5
6require_once INSTALL_PATH . 'program/include/clisetup.php';
7
8// get arguments
9$opts = rcube_utils::get_opt(array(
10    'd' => 'dir',
11    'p' => 'package',
12));
13
14if (empty($opts['dir'])) {
15    rcube::raise_error("Database schema directory not specified (--dir).", false, true);
16}
17if (empty($opts['package'])) {
18    rcube::raise_error("Database schema package name not specified (--package).", false, true);
19}
20
21// Check if directory exists
22if (!file_exists($opts['dir'])) {
23    rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
24}
25
26$RC = rcube::get_instance();
27$DB = rcube_db::factory($RC->config->get('db_dsnw'));
28
29// Connect to database
30$DB->db_connect('w');
31if (!$DB->is_connected()) {
32    rcube::raise_error("Error connecting to database: " . $DB->is_error(), false, true);
33}
34
35$opts['dir'] = rtrim($opts['dir'], DIRECTORY_SEPARATOR);
36$file = $opts['dir'] . DIRECTORY_SEPARATOR . $DB->db_provider . '.initial.sql';
37if (!file_exists($file)) {
38    rcube::raise_error("No DDL file found for " . $DB->db_provider . " driver.", false, true);
39}
40
41$package = $opts['package'];
42$error = false;
43
44// read DDL file
45if ($lines = file($file)) {
46    $sql = '';
47    foreach ($lines as $line) {
48        if (preg_match('/^--/', $line) || trim($line) == '')
49            continue;
50
51        $sql .= $line . "\n";
52        if (preg_match('/(;|^GO)$/', trim($line))) {
53            @$DB->query(fix_table_names($sql));
54            $sql = '';
55            if ($error = $DB->is_error()) {
56                break;
57            }
58        }
59    }
60}
61
62if (!$error) {
63    $version = date('Ymd00');
64    $system_table = $DB->quote_identifier($DB->table_name('system'));
65    $name_col = $DB->quote_identifier('name');
66    $value_col = $DB->quote_identifier('value');
67    $package_version = $package . '-version';
68
69    $DB->query("SELECT * FROM $system_table WHERE $name_col=?",
70        $package_version);
71
72    if ($DB->fetch_assoc()) {
73        $DB->query("UPDATE $system_table SET $value_col=? WHERE $name_col=?",
74            $version, $package_version);
75    }
76    else {
77        $DB->query("INSERT INTO $system_table ($name_col, $value_col) VALUES (?, ?)",
78            $package_version, $version);
79    }
80
81    $error = $DB->is_error();
82}
83
84if ($error) {
85    echo "[FAILED]\n";
86    rcube::raise_error("Error in DDL schema $file: $error", false, true);
87}
88echo "[OK]\n";
89
90
91function fix_table_names($sql)
92{
93    global $DB, $RC;
94
95    $prefix = $RC->config->get('db_prefix');
96    $engine = $DB->db_provider;
97
98    if (empty($prefix)) {
99        return $sql;
100    }
101
102    $tables    = array();
103    $sequences = array();
104
105    // find table names
106    if (preg_match_all('/CREATE TABLE (\[dbo\]\.|IF NOT EXISTS )?[`"\[\]]*([^`"\[\] \r\n]+)/i', $sql, $matches)) {
107        foreach ($matches[2] as $table) {
108            $tables[$table] = $prefix . $table;
109        }
110    }
111    // find sequence names
112    if ($engine == 'postgres' && preg_match_all('/CREATE SEQUENCE (IF NOT EXISTS )?"?([^" \n\r]+)/i', $sql, $matches)) {
113        foreach ($matches[2] as $sequence) {
114            $sequences[$sequence] = $prefix . $sequence;
115        }
116    }
117
118    // replace table names
119    foreach ($tables as $table => $real_table) {
120        $sql = preg_replace("/([^a-zA-Z0-9_])$table([^a-zA-Z0-9_])/", "\\1$real_table\\2", $sql);
121    }
122    // replace sequence names
123    foreach ($sequences as $sequence => $real_sequence) {
124        $sql = preg_replace("/([^a-zA-Z0-9_])$sequence([^a-zA-Z0-9_])/", "\\1$real_sequence\\2", $sql);
125    }
126
127    return $sql;
128}
129
130?>
131