| 1 |
lars |
1 |
<?php
|
|
|
2 |
// +----------------------------------------------------------------------+
|
|
|
3 |
// | PHP Version 4 |
|
|
|
4 |
// +----------------------------------------------------------------------+
|
|
|
5 |
// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox, |
|
|
|
6 |
// | Stig. S. Bakken, Lukas Smith |
|
|
|
7 |
// | All rights reserved. |
|
|
|
8 |
// +----------------------------------------------------------------------+
|
|
|
9 |
// | MDB is a merge of PEAR DB and Metabases that provides a unified DB |
|
|
|
10 |
// | API as well as database abstraction for PHP applications. |
|
|
|
11 |
// | This LICENSE is in the BSD license style. |
|
|
|
12 |
// | |
|
|
|
13 |
// | Redistribution and use in source and binary forms, with or without |
|
|
|
14 |
// | modification, are permitted provided that the following conditions |
|
|
|
15 |
// | are met: |
|
|
|
16 |
// | |
|
|
|
17 |
// | Redistributions of source code must retain the above copyright |
|
|
|
18 |
// | notice, this list of conditions and the following disclaimer. |
|
|
|
19 |
// | |
|
|
|
20 |
// | Redistributions in binary form must reproduce the above copyright |
|
|
|
21 |
// | notice, this list of conditions and the following disclaimer in the |
|
|
|
22 |
// | documentation and/or other materials provided with the distribution. |
|
|
|
23 |
// | |
|
|
|
24 |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
|
|
|
25 |
// | Lukas Smith nor the names of his contributors may be used to endorse |
|
|
|
26 |
// | or promote products derived from this software without specific prior|
|
|
|
27 |
// | written permission. |
|
|
|
28 |
// | |
|
|
|
29 |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
|
|
30 |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
|
|
31 |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|
|
|
32 |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
|
|
33 |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
|
|
34 |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
|
|
35 |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
|
|
|
36 |
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
|
|
37 |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
|
|
38 |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
|
|
|
39 |
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
|
|
40 |
// | POSSIBILITY OF SUCH DAMAGE. |
|
|
|
41 |
// +----------------------------------------------------------------------+
|
|
|
42 |
// | Author: Lukas Smith <smith@backendmedia.com> |
|
|
|
43 |
// +----------------------------------------------------------------------+
|
|
|
44 |
//
|
|
|
45 |
// $Id: Manager.php,v 1.75.4.4 2004/03/10 14:42:59 lsmith Exp $
|
|
|
46 |
//
|
|
|
47 |
|
|
|
48 |
require_once('MDB/Parser.php');
|
|
|
49 |
|
|
|
50 |
define('MDB_MANAGER_DUMP_ALL', 0);
|
|
|
51 |
define('MDB_MANAGER_DUMP_STRUCTURE', 1);
|
|
|
52 |
define('MDB_MANAGER_DUMP_CONTENT', 2);
|
|
|
53 |
|
|
|
54 |
/**
|
|
|
55 |
* The database manager is a class that provides a set of database
|
|
|
56 |
* management services like installing, altering and dumping the data
|
|
|
57 |
* structures of databases.
|
|
|
58 |
*
|
|
|
59 |
* @package MDB
|
|
|
60 |
* @category Database
|
|
|
61 |
* @author Lukas Smith <smith@backendmedia.com>
|
|
|
62 |
*/
|
|
|
63 |
class MDB_Manager extends PEAR
|
|
|
64 |
{
|
|
|
65 |
// {{{ properties
|
|
|
66 |
|
|
|
67 |
var $database;
|
|
|
68 |
|
|
|
69 |
var $options = array(
|
|
|
70 |
'fail_on_invalid_names' => 1,
|
|
|
71 |
'debug' => 0
|
|
|
72 |
);
|
|
|
73 |
var $invalid_names = array(
|
|
|
74 |
'user' => array(),
|
|
|
75 |
'is' => array(),
|
|
|
76 |
'file' => array(
|
|
|
77 |
'oci' => array(),
|
|
|
78 |
'oracle' => array()
|
|
|
79 |
),
|
|
|
80 |
'notify' => array(
|
|
|
81 |
'pgsql' => array()
|
|
|
82 |
),
|
|
|
83 |
'restrict' => array(
|
|
|
84 |
'mysql' => array()
|
|
|
85 |
),
|
|
|
86 |
'password' => array(
|
|
|
87 |
'ibase' => array()
|
|
|
88 |
)
|
|
|
89 |
);
|
|
|
90 |
var $default_values = array(
|
|
|
91 |
'integer' => 0,
|
|
|
92 |
'float' => 0,
|
|
|
93 |
'decimal' => 0,
|
|
|
94 |
'text' => '',
|
|
|
95 |
'timestamp' => '0001-01-01 00:00:00',
|
|
|
96 |
'date' => '0001-01-01',
|
|
|
97 |
'time' => '00:00:00'
|
|
|
98 |
);
|
|
|
99 |
|
|
|
100 |
var $warnings = array();
|
|
|
101 |
|
|
|
102 |
var $database_definition = array(
|
|
|
103 |
'name' => '',
|
|
|
104 |
'create' => 0,
|
|
|
105 |
'TABLES' => array()
|
|
|
106 |
);
|
|
|
107 |
|
|
|
108 |
// }}}
|
|
|
109 |
// {{{ raiseError()
|
|
|
110 |
|
|
|
111 |
/**
|
|
|
112 |
* This method is used to communicate an error and invoke error
|
|
|
113 |
* callbacks etc. Basically a wrapper for PEAR::raiseError
|
|
|
114 |
* without the message string.
|
|
|
115 |
*
|
|
|
116 |
* @param mixed $code integer error code, or a PEAR error object (all
|
|
|
117 |
* other parameters are ignored if this parameter is an object
|
|
|
118 |
* @param int $mode error mode, see PEAR_Error docs
|
|
|
119 |
* @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
|
|
|
120 |
* error level (E_USER_NOTICE etc). If error mode is
|
|
|
121 |
* PEAR_ERROR_CALLBACK, this is the callback function, either as a
|
|
|
122 |
* function name, or as an array of an object and method name. For
|
|
|
123 |
* other error modes this parameter is ignored.
|
|
|
124 |
* @param string $userinfo Extra debug information. Defaults to the last
|
|
|
125 |
* query and native error code.
|
|
|
126 |
* @param mixed $nativecode Native error code, integer or string depending
|
|
|
127 |
* the backend.
|
|
|
128 |
* @return object a PEAR error object
|
|
|
129 |
* @access public
|
|
|
130 |
* @see PEAR_Error
|
|
|
131 |
*/
|
|
|
132 |
function &raiseError($code = MDB_MANAGER_ERROR, $mode = NULL, $options = NULL,
|
|
|
133 |
$userinfo = NULL, $nativecode = NULL)
|
|
|
134 |
{
|
|
|
135 |
// The error is yet a MDB error object
|
|
|
136 |
if(is_object($code)) {
|
|
|
137 |
$err = PEAR::raiseError($code, NULL, NULL, NULL, NULL, NULL, TRUE);
|
|
|
138 |
return($err);
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
$err = PEAR::raiseError(NULL, $code, $mode, $options, $userinfo,
|
|
|
142 |
'MDB_Error', TRUE);
|
|
|
143 |
return($err);
|
|
|
144 |
}
|
|
|
145 |
|
|
|
146 |
// }}}
|
|
|
147 |
// {{{ captureDebugOutput()
|
|
|
148 |
|
|
|
149 |
/**
|
|
|
150 |
* set a debug handler
|
|
|
151 |
*
|
|
|
152 |
* @param string $capture name of the function that should be used in
|
|
|
153 |
* debug()
|
|
|
154 |
* @access public
|
|
|
155 |
* @see debug()
|
|
|
156 |
*/
|
|
|
157 |
function captureDebugOutput($capture)
|
|
|
158 |
{
|
|
|
159 |
$this->options['debug'] = $capture;
|
|
|
160 |
$this->database->captureDebugOutput(1);
|
|
|
161 |
}
|
|
|
162 |
|
|
|
163 |
// }}}
|
|
|
164 |
// {{{ debugOutput()
|
|
|
165 |
|
|
|
166 |
/**
|
|
|
167 |
* output debug info
|
|
|
168 |
*
|
|
|
169 |
* @return string content of the debug_output class variable
|
|
|
170 |
* @access public
|
|
|
171 |
*/
|
|
|
172 |
function debugOutput()
|
|
|
173 |
{
|
|
|
174 |
return($this->database->debugOutput());
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
// }}}
|
|
|
178 |
// {{{ resetWarnings()
|
|
|
179 |
|
|
|
180 |
/**
|
|
|
181 |
* reset the warning array
|
|
|
182 |
*
|
|
|
183 |
* @access public
|
|
|
184 |
*/
|
|
|
185 |
function resetWarnings()
|
|
|
186 |
{
|
|
|
187 |
$this->warnings = array();
|
|
|
188 |
}
|
|
|
189 |
|
|
|
190 |
// }}}
|
|
|
191 |
// {{{ getWarnings()
|
|
|
192 |
|
|
|
193 |
/**
|
|
|
194 |
* get all warnings in reverse order.
|
|
|
195 |
* This means that the last warning is the first element in the array
|
|
|
196 |
*
|
|
|
197 |
* @return array with warnings
|
|
|
198 |
* @access public
|
|
|
199 |
* @see resetWarnings()
|
|
|
200 |
*/
|
|
|
201 |
function getWarnings()
|
|
|
202 |
{
|
|
|
203 |
return array_reverse($this->warnings);
|
|
|
204 |
}
|
|
|
205 |
|
|
|
206 |
// }}}
|
|
|
207 |
// {{{ setOption()
|
|
|
208 |
|
|
|
209 |
/**
|
|
|
210 |
* set the option for the db class
|
|
|
211 |
*
|
|
|
212 |
* @param string $option option name
|
|
|
213 |
* @param mixed $value value for the option
|
|
|
214 |
* @return mixed MDB_OK or MDB_Error
|
|
|
215 |
* @access public
|
|
|
216 |
*/
|
|
|
217 |
function setOption($option, $value)
|
|
|
218 |
{
|
|
|
219 |
if(isset($this->options[$option])) {
|
|
|
220 |
$this->options[$option] = $value;
|
|
|
221 |
return(MDB_OK);
|
|
|
222 |
}
|
|
|
223 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
|
|
|
224 |
}
|
|
|
225 |
|
|
|
226 |
// }}}
|
|
|
227 |
// {{{ getOption()
|
|
|
228 |
|
|
|
229 |
/**
|
|
|
230 |
* returns the value of an option
|
|
|
231 |
*
|
|
|
232 |
* @param string $option option name
|
|
|
233 |
* @return mixed the option value or error object
|
|
|
234 |
* @access public
|
|
|
235 |
*/
|
|
|
236 |
function getOption($option)
|
|
|
237 |
{
|
|
|
238 |
if(isset($this->options[$option])) {
|
|
|
239 |
return($this->options[$option]);
|
|
|
240 |
}
|
|
|
241 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
|
|
|
242 |
}
|
|
|
243 |
|
|
|
244 |
// }}}
|
|
|
245 |
// {{{ connect()
|
|
|
246 |
|
|
|
247 |
/**
|
|
|
248 |
* Create a new MDB connection object and connect to the specified
|
|
|
249 |
* database
|
|
|
250 |
*
|
|
|
251 |
* @param mixed $dbinfo 'data source name', see the MDB::parseDSN
|
|
|
252 |
* method for a description of the dsn format.
|
|
|
253 |
* Can also be specified as an array of the
|
|
|
254 |
* format returned by MDB::parseDSN.
|
|
|
255 |
* Finally you can also pass an existing db
|
|
|
256 |
* object to be used.
|
|
|
257 |
* @param mixed $options An associative array of option names and
|
|
|
258 |
* their values.
|
|
|
259 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
260 |
* @access public
|
|
|
261 |
* @see MDB::parseDSN
|
|
|
262 |
*/
|
|
|
263 |
function &connect(&$dbinfo, $options = FALSE)
|
|
|
264 |
{
|
|
|
265 |
if(is_object($this->database) && !MDB::isError($this->database)) {
|
|
|
266 |
$this->disconnect();
|
|
|
267 |
}
|
|
|
268 |
if(is_object($dbinfo)) {
|
|
|
269 |
$this->database =& $dbinfo;
|
|
|
270 |
} else {
|
|
|
271 |
$this->database =& MDB::connect($dbinfo, $options);
|
|
|
272 |
if(MDB::isError($this->database)) {
|
|
|
273 |
return($this->database);
|
|
|
274 |
}
|
|
|
275 |
}
|
|
|
276 |
if(is_array($options)) {
|
|
|
277 |
$this->options = array_merge($options, $this->options);
|
|
|
278 |
}
|
|
|
279 |
return(MDB_OK);
|
|
|
280 |
}
|
|
|
281 |
|
|
|
282 |
// }}}
|
|
|
283 |
// {{{ disconnect()
|
|
|
284 |
|
|
|
285 |
/**
|
|
|
286 |
* Log out and disconnect from the database.
|
|
|
287 |
*
|
|
|
288 |
* @access public
|
|
|
289 |
*/
|
|
|
290 |
function disconnect()
|
|
|
291 |
{
|
|
|
292 |
if(is_object($this->database) && !MDB::isError($this->database)) {
|
|
|
293 |
$this->database->disconnect();
|
|
|
294 |
unset($this->database);
|
|
|
295 |
}
|
|
|
296 |
}
|
|
|
297 |
|
|
|
298 |
// }}}
|
|
|
299 |
// {{{ setDatabase()
|
|
|
300 |
|
|
|
301 |
/**
|
|
|
302 |
* Select a different database
|
|
|
303 |
*
|
|
|
304 |
* @param string $name name of the database that should be selected
|
|
|
305 |
* @return string name of the database previously connected to
|
|
|
306 |
* @access public
|
|
|
307 |
*/
|
|
|
308 |
function setDatabase($name)
|
|
|
309 |
{
|
|
|
310 |
return($this->database->setDatabase($name));
|
|
|
311 |
}
|
|
|
312 |
|
|
|
313 |
// }}}
|
|
|
314 |
// {{{ _createTable()
|
|
|
315 |
|
|
|
316 |
/**
|
|
|
317 |
* create a table and inititialize the table if data is available
|
|
|
318 |
*
|
|
|
319 |
* @param string $table_name name of the table to be created
|
|
|
320 |
* @param array $table multi dimensional array that containts the
|
|
|
321 |
* structure and optional data of the table
|
|
|
322 |
* @param boolean $overwrite determine if the table/index should be
|
|
|
323 |
overwritten if it already exists
|
|
|
324 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
325 |
* @access private
|
|
|
326 |
*/
|
|
|
327 |
function _createTable($table_name, $table, $overwrite = FALSE)
|
|
|
328 |
{
|
|
|
329 |
$this->expectError(MDB_ERROR_ALREADY_EXISTS);
|
|
|
330 |
$result = $this->database->createTable($table_name, $table['FIELDS']);
|
|
|
331 |
$this->popExpect();
|
|
|
332 |
if(MDB::isError($result)) {
|
|
|
333 |
if($result->getCode() === MDB_ERROR_ALREADY_EXISTS) {
|
|
|
334 |
$this->warnings[] = 'Table already exists: '.$table_name;
|
|
|
335 |
if($overwrite) {
|
|
|
336 |
$this->database->debug('Overwritting Table');
|
|
|
337 |
$result = $this->database->dropTable($table_name);
|
|
|
338 |
if(MDB::isError($result)) {
|
|
|
339 |
return($result);
|
|
|
340 |
}
|
|
|
341 |
$result = $this->database->createTable($table_name, $table['FIELDS']);
|
|
|
342 |
if(MDB::isError($result)) {
|
|
|
343 |
return($result);
|
|
|
344 |
}
|
|
|
345 |
} else {
|
|
|
346 |
$result = MDB_OK;
|
|
|
347 |
}
|
|
|
348 |
} else {
|
|
|
349 |
$this->database->debug('Create table error: '.$table_name);
|
|
|
350 |
return($result);
|
|
|
351 |
}
|
|
|
352 |
}
|
|
|
353 |
if(isset($table['initialization']) && is_array($table['initialization'])) {
|
|
|
354 |
foreach($table['initialization'] as $instruction) {
|
|
|
355 |
switch($instruction['type']) {
|
|
|
356 |
case 'insert':
|
|
|
357 |
$query_fields = $query_values = array();
|
|
|
358 |
if(isset($instruction['FIELDS']) && is_array($instruction['FIELDS'])) {
|
|
|
359 |
foreach($instruction['FIELDS'] as $field_name => $field) {
|
|
|
360 |
$query_fields[] = $field_name;
|
|
|
361 |
$query_values[] = '?';
|
|
|
362 |
}
|
|
|
363 |
$query_fields = implode(',',$query_fields);
|
|
|
364 |
$query_values = implode(',',$query_values);
|
|
|
365 |
$result = $prepared_query = $this->database->prepareQuery(
|
|
|
366 |
"INSERT INTO $table_name ($query_fields) VALUES ($query_values)");
|
|
|
367 |
}
|
|
|
368 |
if(!MDB::isError($prepared_query)) {
|
|
|
369 |
if(isset($instruction['FIELDS']) && is_array($instruction['FIELDS'])) {
|
|
|
370 |
$lobs = array();
|
|
|
371 |
$field_number = 0;
|
|
|
372 |
foreach($instruction['FIELDS'] as $field_name => $field) {
|
|
|
373 |
$field_number++;
|
|
|
374 |
$query = $field_name;
|
|
|
375 |
switch($table['FIELDS'][$field_name]['type']) {
|
|
|
376 |
case 'integer':
|
|
|
377 |
$result = $this->database->setParamInteger($prepared_query,
|
|
|
378 |
$field_number, intval($field));
|
|
|
379 |
break;
|
|
|
380 |
case 'text':
|
|
|
381 |
$result = $this->database->setParamText($prepared_query,
|
|
|
382 |
$field_number, $field);
|
|
|
383 |
break;
|
|
|
384 |
case 'clob':
|
|
|
385 |
$lob_definition = array(
|
|
|
386 |
'Database' => $this->database,
|
|
|
387 |
'Error' => '',
|
|
|
388 |
'Data' => $field
|
|
|
389 |
);
|
|
|
390 |
if(MDB::isError($result = $this->database->createLob($lob_definition)))
|
|
|
391 |
{
|
|
|
392 |
break;
|
|
|
393 |
}
|
|
|
394 |
$lob = count($lobs);
|
|
|
395 |
$lobs[$lob] = $result;
|
|
|
396 |
$result = $this->database->setParamClob($prepared_query,
|
|
|
397 |
$field_number, $lobs[$lob], $field_name);
|
|
|
398 |
break;
|
|
|
399 |
case 'blob':
|
|
|
400 |
$lob_definition = array(
|
|
|
401 |
'Database' => $this->database,
|
|
|
402 |
'Error' => '',
|
|
|
403 |
'Data' => $field
|
|
|
404 |
);
|
|
|
405 |
if(MDB::isError($result = $this->database->createLob($lob_definition))) {
|
|
|
406 |
break;
|
|
|
407 |
}
|
|
|
408 |
$lob = count($lobs);
|
|
|
409 |
$lobs[$lob] = $result;
|
|
|
410 |
$result = $this->database->setParamBlob($prepared_query,
|
|
|
411 |
$field_number, $lobs[$lob], $field_name);
|
|
|
412 |
break;
|
|
|
413 |
case 'boolean':
|
|
|
414 |
$result = $this->database->setParamBoolean($prepared_query,
|
|
|
415 |
$field_number, intval($field));
|
|
|
416 |
break;
|
|
|
417 |
case 'date':
|
|
|
418 |
$result = $this->database->setParamDate($prepared_query,
|
|
|
419 |
$field_number, $field);
|
|
|
420 |
break;
|
|
|
421 |
case 'timestamp':
|
|
|
422 |
$result = $this->database->setParamTimestamp($prepared_query,
|
|
|
423 |
$field_number, $field);
|
|
|
424 |
break;
|
|
|
425 |
case 'time':
|
|
|
426 |
$result = $this->database->setParamTime($prepared_query,
|
|
|
427 |
$field_number, $field);
|
|
|
428 |
break;
|
|
|
429 |
case 'float':
|
|
|
430 |
$result = $this->database->setParamFloat($prepared_query,
|
|
|
431 |
$field_number, doubleval($field));
|
|
|
432 |
break;
|
|
|
433 |
case 'decimal':
|
|
|
434 |
$result = $this->database->setParamDecimal($prepared_query,
|
|
|
435 |
$field_number, $field);
|
|
|
436 |
break;
|
|
|
437 |
default:
|
|
|
438 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
439 |
'type "'.$field['type'].'" is not yet supported');
|
|
|
440 |
break;
|
|
|
441 |
}
|
|
|
442 |
if(MDB::isError($result)) {
|
|
|
443 |
break;
|
|
|
444 |
}
|
|
|
445 |
}
|
|
|
446 |
}
|
|
|
447 |
if(!MDB::isError($result)) {
|
|
|
448 |
$result = $this->database->executeQuery($prepared_query);
|
|
|
449 |
}
|
|
|
450 |
for($lob = 0; $lob < count($lobs); $lob++) {
|
|
|
451 |
$this->database->destroyLOB($lobs[$lob]);
|
|
|
452 |
}
|
|
|
453 |
$this->database->freePreparedQuery($prepared_query);
|
|
|
454 |
}
|
|
|
455 |
break;
|
|
|
456 |
}
|
|
|
457 |
}
|
|
|
458 |
};
|
|
|
459 |
if(!MDB::isError($result) && isset($table['INDEXES']) && is_array($table['INDEXES'])) {
|
|
|
460 |
if(!$this->database->support('Indexes')) {
|
|
|
461 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
462 |
'indexes are not supported'));
|
|
|
463 |
}
|
|
|
464 |
foreach($table['INDEXES'] as $index_name => $index) {
|
|
|
465 |
$this->expectError(MDB_ERROR_ALREADY_EXISTS);
|
|
|
466 |
$result = $this->database->createIndex($table_name, $index_name, $index);
|
|
|
467 |
$this->popExpect();
|
|
|
468 |
if(MDB::isError($result)) {
|
|
|
469 |
if($result->getCode() === MDB_ERROR_ALREADY_EXISTS) {
|
|
|
470 |
$this->warnings[] = 'Index already exists: '.$index_name;
|
|
|
471 |
if($overwrite) {
|
|
|
472 |
$this->database->debug('Overwritting Index');
|
|
|
473 |
$result = $this->database->dropIndex($table_name, $index_name);
|
|
|
474 |
if(MDB::isError($result)) {
|
|
|
475 |
break;
|
|
|
476 |
}
|
|
|
477 |
$result = $this->database->createIndex($table_name, $index_name, $index);
|
|
|
478 |
if(MDB::isError($result)) {
|
|
|
479 |
break;
|
|
|
480 |
}
|
|
|
481 |
} else {
|
|
|
482 |
$result = MDB_OK;
|
|
|
483 |
}
|
|
|
484 |
} else {
|
|
|
485 |
$this->database->debug('Create index error: '.$table_name);
|
|
|
486 |
break;
|
|
|
487 |
}
|
|
|
488 |
}
|
|
|
489 |
}
|
|
|
490 |
}
|
|
|
491 |
if(MDB::isError($result)) {
|
|
|
492 |
$result = $this->database->dropTable($table_name);
|
|
|
493 |
if(MDB::isError($result)) {
|
|
|
494 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
495 |
'could not drop the table ('
|
|
|
496 |
.$result->getMessage().' ('.$result->getUserinfo(),'))',
|
|
|
497 |
'MDB_Error', TRUE);
|
|
|
498 |
}
|
|
|
499 |
return($result);
|
|
|
500 |
}
|
|
|
501 |
return(MDB_OK);
|
|
|
502 |
}
|
|
|
503 |
|
|
|
504 |
// }}}
|
|
|
505 |
// {{{ _dropTable()
|
|
|
506 |
|
|
|
507 |
/**
|
|
|
508 |
* drop a table
|
|
|
509 |
*
|
|
|
510 |
* @param string $table_name name of the table to be dropped
|
|
|
511 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
512 |
* @access private
|
|
|
513 |
*/
|
|
|
514 |
function _dropTable($table_name)
|
|
|
515 |
{
|
|
|
516 |
return($this->database->dropTable($table_name));
|
|
|
517 |
}
|
|
|
518 |
|
|
|
519 |
// }}}
|
|
|
520 |
// {{{ _createSequence()
|
|
|
521 |
|
|
|
522 |
/**
|
|
|
523 |
* create a sequence
|
|
|
524 |
*
|
|
|
525 |
* @param string $sequence_name name of the sequence to be created
|
|
|
526 |
* @param array $sequence multi dimensional array that containts the
|
|
|
527 |
* structure and optional data of the table
|
|
|
528 |
* @param string $created_on_table
|
|
|
529 |
* @param boolean $overwrite determine if the sequence should be overwritten
|
|
|
530 |
if it already exists
|
|
|
531 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
532 |
* @access private
|
|
|
533 |
*/
|
|
|
534 |
function _createSequence($sequence_name, $sequence, $created_on_table, $overwrite = FALSE)
|
|
|
535 |
{
|
|
|
536 |
if(!$this->database->support('Sequences')) {
|
|
|
537 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
538 |
'sequences are not supported'));
|
|
|
539 |
}
|
|
|
540 |
if(!isset($sequence_name) || !strcmp($sequence_name, '')) {
|
|
|
541 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
542 |
'no valid sequence name specified'));
|
|
|
543 |
}
|
|
|
544 |
$this->database->debug('Create sequence: '.$sequence_name);
|
|
|
545 |
if(isset($sequence['start']) && $sequence['start'] != '') {
|
|
|
546 |
$start = $sequence['start'];
|
|
|
547 |
} else if(isset($sequence['on']) && !$created_on_table) {
|
|
|
548 |
$table = $sequence['on']['table'];
|
|
|
549 |
$field = $sequence['on']['field'];
|
|
|
550 |
if($this->database->support('Summaryfunctions')) {
|
|
|
551 |
$field = "MAX($field)";
|
|
|
552 |
}
|
|
|
553 |
$start = $this->database->queryOne("SELECT $field FROM $table");
|
|
|
554 |
if(MDB::isError($start)) {
|
|
|
555 |
return($start);
|
|
|
556 |
}
|
|
|
557 |
} else {
|
|
|
558 |
$start = 1;
|
|
|
559 |
}
|
|
|
560 |
|
|
|
561 |
$this->expectError(MDB_ERROR_ALREADY_EXISTS);
|
|
|
562 |
$result = $this->database->createSequence($sequence_name, $start);
|
|
|
563 |
$this->popExpect();
|
|
|
564 |
if(MDB::isError($result)) {
|
|
|
565 |
if($result->getCode() === MDB_ERROR_ALREADY_EXISTS) {
|
|
|
566 |
$this->warnings[] = 'Sequence already exists: '.$sequence_name;
|
|
|
567 |
if($overwrite) {
|
|
|
568 |
$this->database->debug('Overwritting Sequence');
|
|
|
569 |
$result = $this->database->dropSequence($sequence_name);
|
|
|
570 |
if(MDB::isError($result)) {
|
|
|
571 |
return($result);
|
|
|
572 |
}
|
|
|
573 |
$result = $this->database->createSequence($sequence_name, $start);
|
|
|
574 |
if(MDB::isError($result)) {
|
|
|
575 |
return($result);
|
|
|
576 |
}
|
|
|
577 |
} else {
|
|
|
578 |
return(MDB_OK);
|
|
|
579 |
}
|
|
|
580 |
} else {
|
|
|
581 |
$this->database->debug('Create sequence error: '.$sequence_name);
|
|
|
582 |
return($result);
|
|
|
583 |
}
|
|
|
584 |
}
|
|
|
585 |
}
|
|
|
586 |
|
|
|
587 |
// }}}
|
|
|
588 |
// {{{ _dropSequence()
|
|
|
589 |
|
|
|
590 |
/**
|
|
|
591 |
* drop a table
|
|
|
592 |
*
|
|
|
593 |
* @param string $sequence_name name of the sequence to be dropped
|
|
|
594 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
595 |
* @access private
|
|
|
596 |
*/
|
|
|
597 |
function _dropSequence($sequence_name)
|
|
|
598 |
{
|
|
|
599 |
if(!$this->database->support('Sequences')) {
|
|
|
600 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
601 |
'sequences are not supported'));
|
|
|
602 |
}
|
|
|
603 |
$this->database->debug('Dropping sequence: '.$sequence_name);
|
|
|
604 |
if(!isset($sequence_name) || !strcmp($sequence_name, '')) {
|
|
|
605 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
606 |
'no valid sequence name specified'));
|
|
|
607 |
}
|
|
|
608 |
return($this->database->dropSequence($sequence_name));
|
|
|
609 |
}
|
|
|
610 |
|
|
|
611 |
// }}}
|
|
|
612 |
// {{{ _createDatabase()
|
|
|
613 |
|
|
|
614 |
/**
|
|
|
615 |
* Create a database space within which may be created database objects
|
|
|
616 |
* like tables, indexes and sequences. The implementation of this function
|
|
|
617 |
* is highly DBMS specific and may require special permissions to run
|
|
|
618 |
* successfully. Consult the documentation or the DBMS drivers that you
|
|
|
619 |
* use to be aware of eventual configuration requirements.
|
|
|
620 |
*
|
|
|
621 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
622 |
* @access private
|
|
|
623 |
*/
|
|
|
624 |
function _createDatabase()
|
|
|
625 |
{
|
|
|
626 |
if(!isset($this->database_definition['name'])
|
|
|
627 |
|| !strcmp($this->database_definition['name'], '')
|
|
|
628 |
) {
|
|
|
629 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
630 |
'no valid database name specified'));
|
|
|
631 |
}
|
|
|
632 |
$create = (isset($this->database_definition['create']) && $this->database_definition['create']);
|
|
|
633 |
$overwrite = (isset($this->database_definition['overwrite']) && $this->database_definition['overwrite']);
|
|
|
634 |
if($create) {
|
|
|
635 |
$this->database->debug('Create database: '.$this->database_definition['name']);
|
|
|
636 |
$this->expectError(MDB_ERROR_ALREADY_EXISTS);
|
|
|
637 |
$result = $this->database->createDatabase($this->database_definition['name']);
|
|
|
638 |
$this->popExpect();
|
|
|
639 |
if(MDB::isError($result)) {
|
|
|
640 |
if($result->getCode() === MDB_ERROR_ALREADY_EXISTS) {
|
|
|
641 |
$this->warnings[] = 'Database already exists: '.$this->database_definition['name'];
|
|
|
642 |
if($overwrite) {
|
|
|
643 |
$this->database->debug('Overwritting Database');
|
|
|
644 |
$result = $this->database->dropDatabase($this->database_definition['name']);
|
|
|
645 |
if(MDB::isError($result)) {
|
|
|
646 |
return($result);
|
|
|
647 |
}
|
|
|
648 |
$result = $this->database->createDatabase($this->database_definition['name']);
|
|
|
649 |
if(MDB::isError($result)) {
|
|
|
650 |
return($result);
|
|
|
651 |
}
|
|
|
652 |
} else {
|
|
|
653 |
$result = MDB_OK;
|
|
|
654 |
}
|
|
|
655 |
} else {
|
|
|
656 |
$this->database->debug('Create database error.');
|
|
|
657 |
return($result);
|
|
|
658 |
}
|
|
|
659 |
}
|
|
|
660 |
}
|
|
|
661 |
$previous_database_name = $this->database->setDatabase($this->database_definition['name']);
|
|
|
662 |
if(($support_transactions = $this->database->support('Transactions'))
|
|
|
663 |
&& MDB::isError($result = $this->database->autoCommit(FALSE))
|
|
|
664 |
) {
|
|
|
665 |
return($result);
|
|
|
666 |
}
|
|
|
667 |
|
|
|
668 |
$created_objects = 0;
|
|
|
669 |
if(isset($this->database_definition['TABLES'])
|
|
|
670 |
&& is_array($this->database_definition['TABLES'])
|
|
|
671 |
) {
|
|
|
672 |
foreach($this->database_definition['TABLES'] as $table_name => $table) {
|
|
|
673 |
$result = $this->_createTable($table_name, $table, $overwrite);
|
|
|
674 |
if(MDB::isError($result)) {
|
|
|
675 |
break;
|
|
|
676 |
}
|
|
|
677 |
$created_objects++;
|
|
|
678 |
}
|
|
|
679 |
}
|
|
|
680 |
if(!MDB::isError($result)
|
|
|
681 |
&& isset($this->database_definition['SEQUENCES'])
|
|
|
682 |
&& is_array($this->database_definition['SEQUENCES'])
|
|
|
683 |
) {
|
|
|
684 |
foreach($this->database_definition['SEQUENCES'] as $sequence_name => $sequence) {
|
|
|
685 |
$result = $this->_createSequence($sequence_name, $sequence, 0, $overwrite);
|
|
|
686 |
|
|
|
687 |
if(MDB::isError($result)) {
|
|
|
688 |
break;
|
|
|
689 |
}
|
|
|
690 |
$created_objects++;
|
|
|
691 |
}
|
|
|
692 |
}
|
|
|
693 |
|
|
|
694 |
if(MDB::isError($result)) {
|
|
|
695 |
if($created_objects) {
|
|
|
696 |
if($support_transactions) {
|
|
|
697 |
$res = $this->database->rollback();
|
|
|
698 |
if(MDB::isError($res))
|
|
|
699 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
700 |
'Could not rollback the partially created database alterations ('
|
|
|
701 |
.$result->getMessage().' ('.$result->getUserinfo(),'))',
|
|
|
702 |
'MDB_Error', TRUE);
|
|
|
703 |
} else {
|
|
|
704 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
705 |
'the database was only partially created ('
|
|
|
706 |
.$result->getMessage().' ('.$result->getUserinfo(),'))',
|
|
|
707 |
'MDB_Error', TRUE);
|
|
|
708 |
}
|
|
|
709 |
}
|
|
|
710 |
} else {
|
|
|
711 |
if($support_transactions) {
|
|
|
712 |
$res = $this->database->autoCommit(TRUE);
|
|
|
713 |
if(MDB::isError($res))
|
|
|
714 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
715 |
'Could not end transaction after successfully created the database ('
|
|
|
716 |
.$res->getMessage().' ('.$res->getUserinfo(),'))',
|
|
|
717 |
'MDB_Error', TRUE);
|
|
|
718 |
}
|
|
|
719 |
}
|
|
|
720 |
|
|
|
721 |
$this->database->setDatabase($previous_database_name);
|
|
|
722 |
|
|
|
723 |
if(MDB::isError($result)
|
|
|
724 |
&& $create
|
|
|
725 |
&& MDB::isError($res = $this->database->dropDatabase($this->database_definition['name']))
|
|
|
726 |
) {
|
|
|
727 |
return($this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
728 |
'Could not drop the created database after unsuccessful creation attempt ('
|
|
|
729 |
.$res->getMessage().' ('.$res->getUserinfo(),'))',
|
|
|
730 |
'MDB_Error', TRUE));
|
|
|
731 |
}
|
|
|
732 |
|
|
|
733 |
if(MDB::isError($result)) {
|
|
|
734 |
return($result);
|
|
|
735 |
}
|
|
|
736 |
|
|
|
737 |
return(MDB_OK);
|
|
|
738 |
}
|
|
|
739 |
|
|
|
740 |
// }}}
|
|
|
741 |
// {{{ _addDefinitionChange()
|
|
|
742 |
|
|
|
743 |
/**
|
|
|
744 |
* add change to an array of multiple changes
|
|
|
745 |
*
|
|
|
746 |
* @param array &$changes
|
|
|
747 |
* @param string $definition
|
|
|
748 |
* @param string $item
|
|
|
749 |
* @param array $change
|
|
|
750 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
751 |
* @access private
|
|
|
752 |
*/
|
|
|
753 |
function _addDefinitionChange(&$changes, $definition, $item, $change)
|
|
|
754 |
{
|
|
|
755 |
if(!isset($changes[$definition][$item])) {
|
|
|
756 |
$changes[$definition][$item] = array();
|
|
|
757 |
}
|
|
|
758 |
foreach($change as $change_data_name => $change_data) {
|
|
|
759 |
if(isset($change_data) && is_array($change_data)) {
|
|
|
760 |
if(!isset($changes[$definition][$item][$change_data_name])) {
|
|
|
761 |
$changes[$definition][$item][$change_data_name] = array();
|
|
|
762 |
}
|
|
|
763 |
foreach($change_data as $change_part_name => $change_part) {
|
|
|
764 |
$changes[$definition][$item][$change_data_name][$change_part_name] = $change_part;
|
|
|
765 |
}
|
|
|
766 |
} else {
|
|
|
767 |
$changes[$definition][$item][$change_data_name] = $change_data;
|
|
|
768 |
}
|
|
|
769 |
}
|
|
|
770 |
return(MDB_OK);
|
|
|
771 |
}
|
|
|
772 |
|
|
|
773 |
// }}}
|
|
|
774 |
// {{{ _compareDefinitions()
|
|
|
775 |
|
|
|
776 |
/**
|
|
|
777 |
* compare a previous definition with the currenlty parsed definition
|
|
|
778 |
*
|
|
|
779 |
* @param array multi dimensional array that contains the previous definition
|
|
|
780 |
* @return mixed array of changes on success, or a MDB error object
|
|
|
781 |
* @access private
|
|
|
782 |
*/
|
|
|
783 |
function _compareDefinitions($previous_definition)
|
|
|
784 |
{
|
|
|
785 |
$defined_tables = $changes = array();
|
|
|
786 |
if(isset($this->database_definition['TABLES']) && is_array($this->database_definition['TABLES'])) {
|
|
|
787 |
foreach($this->database_definition['TABLES'] as $table_name => $table) {
|
|
|
788 |
$was_table_name = $table['was'];
|
|
|
789 |
if(isset($previous_definition['TABLES'][$table_name])
|
|
|
790 |
&& isset($previous_definition['TABLES'][$table_name]['was'])
|
|
|
791 |
&& !strcmp($previous_definition['TABLES'][$table_name]['was'], $was_table_name)
|
|
|
792 |
) {
|
|
|
793 |
$was_table_name = $table_name;
|
|
|
794 |
}
|
|
|
795 |
if(isset($previous_definition['TABLES'][$was_table_name])) {
|
|
|
796 |
if(strcmp($was_table_name, $table_name)) {
|
|
|
797 |
$this->_addDefinitionChange($changes, 'TABLES', $was_table_name, array('name' => $table_name));
|
|
|
798 |
$this->database->debug("Renamed table '$was_table_name' to '$table_name'");
|
|
|
799 |
}
|
|
|
800 |
if(isset($defined_tables[$was_table_name])) {
|
|
|
801 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
802 |
'the table "'.$was_table_name.'" was specified as base of more than of table of the database',
|
|
|
803 |
'MDB_Error', TRUE));
|
|
|
804 |
}
|
|
|
805 |
$defined_tables[$was_table_name] = 1;
|
|
|
806 |
|
|
|
807 |
$previous_fields = $previous_definition['TABLES'][$was_table_name]['FIELDS'];
|
|
|
808 |
$defined_fields = array();
|
|
|
809 |
if(isset($table['FIELDS']) && is_array($table['FIELDS'])) {
|
|
|
810 |
foreach($table['FIELDS'] as $field_name => $field) {
|
|
|
811 |
$was_field_name = $field['was'];
|
|
|
812 |
if(isset($previous_fields[$field_name])
|
|
|
813 |
&& isset($previous_fields[$field_name]['was'])
|
|
|
814 |
&& !strcmp($previous_fields[$field_name]['was'], $was_field_name)
|
|
|
815 |
) {
|
|
|
816 |
$was_field_name = $field_name;
|
|
|
817 |
}
|
|
|
818 |
if(isset($previous_fields[$was_field_name])) {
|
|
|
819 |
if(strcmp($was_field_name, $field_name)) {
|
|
|
820 |
$query = $this->database->getFieldDeclaration($field_name, $field);
|
|
|
821 |
if(MDB::isError($query)) {
|
|
|
822 |
return($query);
|
|
|
823 |
}
|
|
|
824 |
$this->_addDefinitionChange($changes, 'TABLES', $was_table_name,
|
|
|
825 |
array(
|
|
|
826 |
'RenamedFields' => array(
|
|
|
827 |
$was_field_name => array(
|
|
|
828 |
'name' => $field_name,
|
|
|
829 |
'Declaration' => $query
|
|
|
830 |
)
|
|
|
831 |
)
|
|
|
832 |
)
|
|
|
833 |
);
|
|
|
834 |
$this->database->debug("Renamed field '$was_field_name' to '$field_name' in table '$table_name'");
|
|
|
835 |
}
|
|
|
836 |
if(isset($defined_fields[$was_field_name])) {
|
|
|
837 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
838 |
'the field "'.$was_table_name.'" was specified as base of more than one field of table',
|
|
|
839 |
'MDB_Error', TRUE));
|
|
|
840 |
}
|
|
|
841 |
$defined_fields[$was_field_name] = 1;
|
|
|
842 |
$change = array();
|
|
|
843 |
if($field['type'] == $previous_fields[$was_field_name]['type']) {
|
|
|
844 |
switch($field['type']) {
|
|
|
845 |
case 'integer':
|
|
|
846 |
$previous_unsigned = isset($previous_fields[$was_field_name]['unsigned']);
|
|
|
847 |
$unsigned = isset($fields[$field_name]['unsigned']);
|
|
|
848 |
if(strcmp($previous_unsigned, $unsigned)) {
|
|
|
849 |
$change['unsigned'] = $unsigned;
|
|
|
850 |
$this->database->debug("Changed field '$field_name' type from '".($previous_unsigned ? 'unsigned ' : '').$previous_fields[$was_field_name]['type']."' to '".($unsigned ? 'unsigned ' : '').$field['type']."' in table '$table_name'");
|
|
|
851 |
}
|
|
|
852 |
break;
|
|
|
853 |
case 'text':
|
|
|
854 |
case 'clob':
|
|
|
855 |
case 'blob':
|
|
|
856 |
$previous_length = (isset($previous_fields[$was_field_name]['length']) ? $previous_fields[$was_field_name]['length'] : 0);
|
|
|
857 |
$length = (isset($field['length']) ? $field['length'] : 0);
|
|
|
858 |
if(strcmp($previous_length, $length)) {
|
|
|
859 |
$change['length'] = $length;
|
|
|
860 |
$this->database->debug("Changed field '$field_name' length from '".$previous_fields[$was_field_name]['type'].($previous_length == 0 ? ' no length' : "($previous_length)")."' to '".$field['type'].($length == 0 ? ' no length' : "($length)")."' in table '$table_name'");
|
|
|
861 |
}
|
|
|
862 |
break;
|
|
|
863 |
case 'date':
|
|
|
864 |
case 'timestamp':
|
|
|
865 |
case 'time':
|
|
|
866 |
case 'boolean':
|
|
|
867 |
case 'float':
|
|
|
868 |
case 'decimal':
|
|
|
869 |
break;
|
|
|
870 |
default:
|
|
|
871 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
872 |
'type "'.$field['type'].'" is not yet supported',
|
|
|
873 |
'MDB_Error', TRUE));
|
|
|
874 |
}
|
|
|
875 |
|
|
|
876 |
$previous_notnull = isset($previous_fields[$was_field_name]['notnull']);
|
|
|
877 |
$notnull = isset($field['notnull']);
|
|
|
878 |
if($previous_notnull != $notnull) {
|
|
|
879 |
$change['ChangedNotNull'] = 1;
|
|
|
880 |
if($notnull) {
|
|
|
881 |
$change['notnull'] = isset($field['notnull']);
|
|
|
882 |
}
|
|
|
883 |
$this->database->debug("Changed field '$field_name' notnull from $previous_notnull to $notnull in table '$table_name'");
|
|
|
884 |
}
|
|
|
885 |
|
|
|
886 |
$previous_default = isset($previous_fields[$was_field_name]['default']);
|
|
|
887 |
$default = isset($field['default']);
|
|
|
888 |
if(strcmp($previous_default, $default)) {
|
|
|
889 |
$change['ChangedDefault'] = 1;
|
|
|
890 |
if($default) {
|
|
|
891 |
$change['default'] = $field['default'];
|
|
|
892 |
}
|
|
|
893 |
$this->database->debug("Changed field '$field_name' default from ".($previous_default ? "'".$previous_fields[$was_field_name]['default']."'" : 'NULL').' TO '.($default ? "'".$fields[$field_name]['default']."'" : 'NULL')." IN TABLE '$table_name'");
|
|
|
894 |
} else {
|
|
|
895 |
if($default
|
|
|
896 |
&& strcmp($previous_fields[$was_field_name]['default'], $field['default'])
|
|
|
897 |
) {
|
|
|
898 |
$change['ChangedDefault'] = 1;
|
|
|
899 |
$change['default'] = $field['default'];
|
|
|
900 |
$this->database->debug("Changed field '$field_name' default from '".$previous_fields[$was_field_name]['default']."' to '".$fields[$field_name]['default']."' in table '$table_name'");
|
|
|
901 |
}
|
|
|
902 |
}
|
|
|
903 |
} else {
|
|
|
904 |
$change['type'] = $field['type'];
|
|
|
905 |
$this->database->debug("Changed field '$field_name' type from '".$previous_fields[$was_field_name]['type']."' to '".$fields[$field_name]['type']."' in table '$table_name'");
|
|
|
906 |
}
|
|
|
907 |
if(count($change)) {
|
|
|
908 |
$query = $this->database->getFieldDeclaration($field_name, $field);
|
|
|
909 |
if(MDB::isError($query)) {
|
|
|
910 |
return($query);
|
|
|
911 |
}
|
|
|
912 |
$change['Declaration'] = $query;
|
|
|
913 |
$change['Definition'] = $field;
|
|
|
914 |
$this->_addDefinitionChange($changes, 'TABLES', $was_table_name, array('ChangedFields' => array($field_name => $change)));
|
|
|
915 |
}
|
|
|
916 |
} else {
|
|
|
917 |
if(strcmp($field_name, $was_field_name)) {
|
|
|
918 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
919 |
'it was specified a previous field name ("'
|
|
|
920 |
.$was_field_name.'") for field "'.$field_name.'" of table "'
|
|
|
921 |
.$table_name.'" that does not exist',
|
|
|
922 |
'MDB_Error', TRUE));
|
|
|
923 |
}
|
|
|
924 |
$query = $this->database->getFieldDeclaration($field_name, $field);
|
|
|
925 |
if(MDB::isError($query)) {
|
|
|
926 |
return($query);
|
|
|
927 |
}
|
|
|
928 |
$change['Declaration'] = $query;
|
|
|
929 |
$this->_addDefinitionChange($changes, 'TABLES', $table_name, array('AddedFields' => array($field_name => $change)));
|
|
|
930 |
$this->database->debug("Added field '$field_name' to table '$table_name'");
|
|
|
931 |
}
|
|
|
932 |
}
|
|
|
933 |
}
|
|
|
934 |
if(isset($previous_fields) && is_array($previous_fields)) {
|
|
|
935 |
foreach ($previous_fields as $field_previous_name => $field_previous) {
|
|
|
936 |
if(!isset($defined_fields[$field_previous_name])) {
|
|
|
937 |
$this->_addDefinitionChange($changes, 'TABLES', $table_name, array('RemovedFields' => array($field_previous_name => array())));
|
|
|
938 |
$this->database->debug("Removed field '$field_name' from table '$table_name'");
|
|
|
939 |
}
|
|
|
940 |
}
|
|
|
941 |
}
|
|
|
942 |
$indexes = array();
|
|
|
943 |
if(isset($this->database_definition['TABLES'][$table_name]['INDEXES'])
|
|
|
944 |
&& is_array($this->database_definition['TABLES'][$table_name]['INDEXES'])
|
|
|
945 |
) {
|
|
|
946 |
$indexes = $this->database_definition['TABLES'][$table_name]['INDEXES'];
|
|
|
947 |
}
|
|
|
948 |
$previous_indexes = array();
|
|
|
949 |
if(isset($previous_definition['TABLES'][$was_table_name]['INDEXES'])
|
|
|
950 |
&& is_array($previous_definition['TABLES'][$was_table_name]['INDEXES'])
|
|
|
951 |
) {
|
|
|
952 |
$previous_indexes = $previous_definition['TABLES'][$was_table_name]['INDEXES'];
|
|
|
953 |
}
|
|
|
954 |
$defined_indexes = array();
|
|
|
955 |
foreach($indexes as $index_name => $index) {
|
|
|
956 |
$was_index_name = $index['was'];
|
|
|
957 |
if(isset($previous_indexes[$index_name])
|
|
|
958 |
&& isset($previous_indexes[$index_name]['was'])
|
|
|
959 |
&& !strcmp($previous_indexes[$index_name]['was'], $was_index_name)
|
|
|
960 |
) {
|
|
|
961 |
$was_index_name = $index_name;
|
|
|
962 |
}
|
|
|
963 |
if(isset($previous_indexes[$was_index_name])) {
|
|
|
964 |
$change = array();
|
|
|
965 |
|
|
|
966 |
if(strcmp($was_index_name, $index_name)) {
|
|
|
967 |
$change['name'] = $was_index_name;
|
|
|
968 |
$this->database->debug("Changed index '$was_index_name' name to '$index_name' in table '$table_name'");
|
|
|
969 |
}
|
|
|
970 |
if(isset($defined_indexes[$was_index_name])) {
|
|
|
971 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
972 |
'the index "'.$was_index_name.'" was specified as base of'
|
|
|
973 |
.' more than one index of table "'.$table_name.'"',
|
|
|
974 |
'MDB_Error', TRUE));
|
|
|
975 |
}
|
|
|
976 |
$defined_indexes[$was_index_name] = 1;
|
|
|
977 |
|
|
|
978 |
$previous_unique = isset($previous_indexes[$was_index_name]['unique']);
|
|
|
979 |
$unique = isset($index['unique']);
|
|
|
980 |
if($previous_unique != $unique) {
|
|
|
981 |
$change['ChangedUnique'] = 1;
|
|
|
982 |
if($unique) {
|
|
|
983 |
$change['unique'] = $unique;
|
|
|
984 |
}
|
|
|
985 |
$this->database->debug("Changed index '$index_name' unique from $previous_unique to $unique in table '$table_name'");
|
|
|
986 |
}
|
|
|
987 |
$defined_fields = array();
|
|
|
988 |
$previous_fields = $previous_indexes[$was_index_name]['FIELDS'];
|
|
|
989 |
if(isset($index['FIELDS']) && is_array($index['FIELDS'])) {
|
|
|
990 |
foreach($index['FIELDS'] as $field_name => $field) {
|
|
|
991 |
if(isset($previous_fields[$field_name])) {
|
|
|
992 |
$defined_fields[$field_name] = 1;
|
|
|
993 |
$sorting = (isset($field['sorting']) ? $field['sorting'] : '');
|
|
|
994 |
$previous_sorting = (isset($previous_fields[$field_name]['sorting']) ? $previous_fields[$field_name]['sorting'] : '');
|
|
|
995 |
if(strcmp($sorting, $previous_sorting)) {
|
|
|
996 |
$this->database->debug("Changed index field '$field_name' sorting default from '$previous_sorting' to '$sorting' in table '$table_name'");
|
|
|
997 |
$change['ChangedFields'] = 1;
|
|
|
998 |
}
|
|
|
999 |
} else {
|
|
|
1000 |
$change['ChangedFields'] = 1;
|
|
|
1001 |
$this->database->debug("Added field '$field_name' to index '$index_name' of table '$table_name'");
|
|
|
1002 |
}
|
|
|
1003 |
}
|
|
|
1004 |
}
|
|
|
1005 |
if(isset($previous_fields) && is_array($previous_fields)) {
|
|
|
1006 |
foreach($previous_fields as $field_name => $field) {
|
|
|
1007 |
if(!isset($defined_fields[$field_name])) {
|
|
|
1008 |
$change['ChangedFields'] = 1;
|
|
|
1009 |
$this->database->debug("Removed field '$field_name' from index '$index_name' of table '$table_name'");
|
|
|
1010 |
}
|
|
|
1011 |
}
|
|
|
1012 |
}
|
|
|
1013 |
|
|
|
1014 |
if(count($change)) {
|
|
|
1015 |
$this->_addDefinitionChange($changes, 'INDEXES', $table_name,array('ChangedIndexes' => array($index_name => $change)));
|
|
|
1016 |
}
|
|
|
1017 |
} else {
|
|
|
1018 |
if(strcmp($index_name, $was_index_name)) {
|
|
|
1019 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
1020 |
'it was specified a previous index name ("'.$was_index_name
|
|
|
1021 |
.') for index "'.$index_name.'" of table "'.$table_name.'" that does not exist',
|
|
|
1022 |
'MDB_Error', TRUE));
|
|
|
1023 |
}
|
|
|
1024 |
$this->_addDefinitionChange($changes, 'INDEXES', $table_name,array('AddedIndexes' => array($index_name => $indexes[$index_name])));
|
|
|
1025 |
$this->database->debug("Added index '$index_name' to table '$table_name'");
|
|
|
1026 |
}
|
|
|
1027 |
}
|
|
|
1028 |
foreach($previous_indexes as $index_previous_name => $index_previous) {
|
|
|
1029 |
if(!isset($defined_indexes[$index_previous_name])) {
|
|
|
1030 |
$this->_addDefinitionChange($changes, 'INDEXES', $table_name, array('RemovedIndexes' => array($index_previous_name => $was_table_name)));
|
|
|
1031 |
$this->database->debug("Removed index '$index_name' from table '$table_name'");
|
|
|
1032 |
}
|
|
|
1033 |
}
|
|
|
1034 |
} else {
|
|
|
1035 |
if(strcmp($table_name, $was_table_name)) {
|
|
|
1036 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
1037 |
'it was specified a previous table name ("'
|
|
|
1038 |
.$was_table_name.'") for table "'.$table_name.'" that does not exist',
|
|
|
1039 |
'MDB_Error', TRUE));
|
|
|
1040 |
}
|
|
|
1041 |
$this->_addDefinitionChange($changes, 'TABLES', $table_name,array('Add' => 1));
|
|
|
1042 |
$this->database->debug("Added table '$table_name'");
|
|
|
1043 |
}
|
|
|
1044 |
}
|
|
|
1045 |
if(isset($previous_definition['TABLES']) && is_array($previous_definition['TABLES'])) {
|
|
|
1046 |
foreach ($previous_definition['TABLES'] as $table_name => $table) {
|
|
|
1047 |
if(!isset($defined_tables[$table_name])) {
|
|
|
1048 |
$this->_addDefinitionChange($changes, 'TABLES', $table_name, array('Remove' => 1));
|
|
|
1049 |
$this->database->debug("Removed table '$table_name'");
|
|
|
1050 |
}
|
|
|
1051 |
}
|
|
|
1052 |
}
|
|
|
1053 |
if(isset($this->database_definition['SEQUENCES']) && is_array($this->database_definition['SEQUENCES'])) {
|
|
|
1054 |
foreach ($this->database_definition['SEQUENCES'] as $sequence_name => $sequence) {
|
|
|
1055 |
$was_sequence_name = $sequence['was'];
|
|
|
1056 |
if(isset($previous_definition['SEQUENCES'][$sequence_name])
|
|
|
1057 |
&& isset($previous_definition['SEQUENCES'][$sequence_name]['was'])
|
|
|
1058 |
&& !strcmp($previous_definition['SEQUENCES'][$sequence_name]['was'], $was_sequence_name)
|
|
|
1059 |
) {
|
|
|
1060 |
$was_sequence_name = $sequence_name;
|
|
|
1061 |
}
|
|
|
1062 |
if(isset($previous_definition['SEQUENCES'][$was_sequence_name])) {
|
|
|
1063 |
if(strcmp($was_sequence_name, $sequence_name)) {
|
|
|
1064 |
$this->_addDefinitionChange($changes, 'SEQUENCES', $was_sequence_name,array('name' => $sequence_name));
|
|
|
1065 |
$this->database->debug("Renamed sequence '$was_sequence_name' to '$sequence_name'");
|
|
|
1066 |
}
|
|
|
1067 |
if(isset($defined_sequences[$was_sequence_name])) {
|
|
|
1068 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
1069 |
'the sequence "'.$was_sequence_name.'" was specified as base'
|
|
|
1070 |
.' of more than of sequence of the database',
|
|
|
1071 |
'MDB_Error', TRUE));
|
|
|
1072 |
}
|
|
|
1073 |
$defined_sequences[$was_sequence_name] = 1;
|
|
|
1074 |
$change = array();
|
|
|
1075 |
if(strcmp($sequence['start'], $previous_definition['SEQUENCES'][$was_sequence_name]['start'])) {
|
|
|
1076 |
$change['start'] = $this->database_definition['SEQUENCES'][$sequence_name]['start'];
|
|
|
1077 |
$this->database->debug("Changed sequence '$sequence_name' start from '".$previous_definition['SEQUENCES'][$was_sequence_name]['start']."' to '".$this->database_definition['SEQUENCES'][$sequence_name]['start']."'");
|
|
|
1078 |
}
|
|
|
1079 |
if(strcmp($sequence['on']['table'], $previous_definition['SEQUENCES'][$was_sequence_name]['on']['table'])
|
|
|
1080 |
|| strcmp($sequence['on']['field'], $previous_definition['SEQUENCES'][$was_sequence_name]['on']['field'])
|
|
|
1081 |
) {
|
|
|
1082 |
$change['on'] = $sequence['on'];
|
|
|
1083 |
$this->database->debug("Changed sequence '$sequence_name' on table field from '".$previous_definition['SEQUENCES'][$was_sequence_name]['on']['table'].'.'.$previous_definition['SEQUENCES'][$was_sequence_name]['on']['field']."' to '".$this->database_definition['SEQUENCES'][$sequence_name]['on']['table'].'.'.$this->database_definition['SEQUENCES'][$sequence_name]['on']['field']."'");
|
|
|
1084 |
}
|
|
|
1085 |
if(count($change)) {
|
|
|
1086 |
$this->_addDefinitionChange($changes, 'SEQUENCES', $was_sequence_name,array('Change' => array($sequence_name => array($change))));
|
|
|
1087 |
}
|
|
|
1088 |
} else {
|
|
|
1089 |
if(strcmp($sequence_name, $was_sequence_name)) {
|
|
|
1090 |
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
|
|
|
1091 |
'it was specified a previous sequence name ("'.$was_sequence_name
|
|
|
1092 |
.'") for sequence "'.$sequence_name.'" that does not exist',
|
|
|
1093 |
'MDB_Error', TRUE));
|
|
|
1094 |
}
|
|
|
1095 |
$this->_addDefinitionChange($changes, 'SEQUENCES', $sequence_name, array('Add' => 1));
|
|
|
1096 |
$this->database->debug("Added sequence '$sequence_name'");
|
|
|
1097 |
}
|
|
|
1098 |
}
|
|
|
1099 |
}
|
|
|
1100 |
if(isset($previous_definition['SEQUENCES']) && is_array($previous_definition['SEQUENCES'])) {
|
|
|
1101 |
foreach ($previous_definition['SEQUENCES'] as $sequence_name => $sequence) {
|
|
|
1102 |
if(!isset($defined_sequences[$sequence_name])) {
|
|
|
1103 |
$this->_addDefinitionChange($changes, 'SEQUENCES', $sequence_name, array('Remove' => 1));
|
|
|
1104 |
$this->database->debug("Removed sequence '$sequence_name'");
|
|
|
1105 |
}
|
|
|
1106 |
}
|
|
|
1107 |
}
|
|
|
1108 |
}
|
|
|
1109 |
return($changes);
|
|
|
1110 |
}
|
|
|
1111 |
|
|
|
1112 |
// }}}
|
|
|
1113 |
// {{{ _alterDatabase()
|
|
|
1114 |
|
|
|
1115 |
/**
|
|
|
1116 |
* Execute the necessary actions to implement the requested changes
|
|
|
1117 |
* in a database structure.
|
|
|
1118 |
*
|
|
|
1119 |
* @param array $previous_definition an associative array that contains
|
|
|
1120 |
* the definition of the database structure before applying the requested
|
|
|
1121 |
* changes. The definition of this array may be built separately, but
|
|
|
1122 |
* usually it is built by the Parse method the Metabase parser class.
|
|
|
1123 |
* @param array $changes an associative array that contains the definition of
|
|
|
1124 |
* the changes that are meant to be applied to the database structure.
|
|
|
1125 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
1126 |
* @access private
|
|
|
1127 |
*/
|
|
|
1128 |
function _alterDatabase($previous_definition, $changes)
|
|
|
1129 |
{
|
|
|
1130 |
$result = '';
|
|
|
1131 |
if(isset($changes['TABLES']) && is_array($changes['TABLES'])) {
|
|
|
1132 |
foreach($changes['TABLES'] as $table_name => $table) {
|
|
|
1133 |
if(isset($table['Add']) || isset($table['Remove'])) {
|
|
|
1134 |
continue;
|
|
|
1135 |
}
|
|
|
1136 |
$result = $this->database->alterTable($table_name, $table, 1);
|
|
|
1137 |
if(MDB::isError($result)) {
|
|
|
1138 |
return($result);
|
|
|
1139 |
}
|
|
|
1140 |
}
|
|
|
1141 |
}
|
|
|
1142 |
if(isset($changes['SEQUENCES']) && is_array($changes['SEQUENCES'])) {
|
|
|
1143 |
if(!$this->database->support('Sequences')) {
|
|
|
1144 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
1145 |
'sequences are not supported'));
|
|
|
1146 |
}
|
|
|
1147 |
foreach($changes['SEQUENCES'] as $sequence) {
|
|
|
1148 |
if(isset($sequence['Add'])
|
|
|
1149 |
|| isset($sequence['Remove'])
|
|
|
1150 |
|| isset($sequence['Change'])
|
|
|
1151 |
) {
|
|
|
1152 |
continue;
|
|
|
1153 |
}
|
|
|
1154 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
1155 |
'some sequences changes are not yet supported'));
|
|
|
1156 |
}
|
|
|
1157 |
}
|
|
|
1158 |
if(isset($changes['INDEXES']) && is_array($changes['INDEXES'])) {
|
|
|
1159 |
if(!$this->database->support('Indexes')) {
|
|
|
1160 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
1161 |
'indexes are not supported'));
|
|
|
1162 |
}
|
|
|
1163 |
foreach($changes['INDEXES'] as $index) {
|
|
|
1164 |
$table_changes = count($index);
|
|
|
1165 |
if(isset($index['AddedIndexes'])) {
|
|
|
1166 |
$table_changes--;
|
|
|
1167 |
}
|
|
|
1168 |
if(isset($index['RemovedIndexes'])) {
|
|
|
1169 |
$table_changes--;
|
|
|
1170 |
}
|
|
|
1171 |
if(isset($index['ChangedIndexes'])) {
|
|
|
1172 |
$table_changes--;
|
|
|
1173 |
}
|
|
|
1174 |
if($table_changes) {
|
|
|
1175 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
1176 |
'index alteration not yet supported'));
|
|
|
1177 |
}
|
|
|
1178 |
}
|
|
|
1179 |
}
|
|
|
1180 |
|
|
|
1181 |
$previous_database_name = $this->database->setDatabase($this->database_definition['name']);
|
|
|
1182 |
if(($support_transactions = $this->database->support('Transactions'))
|
|
|
1183 |
&& MDB::isError($result = $this->database->autoCommit(FALSE))
|
|
|
1184 |
) {
|
|
|
1185 |
return($result);
|
|
|
1186 |
}
|
|
|
1187 |
$error = '';
|
|
|
1188 |
$alterations = 0;
|
|
|
1189 |
if(isset($changes['INDEXES']) && is_array($changes['INDEXES'])) {
|
|
|
1190 |
foreach($changes['INDEXES'] as $index_name => $index) {
|
|
|
1191 |
if(isset($index['RemovedIndexes']) && is_array($index['RemovedIndexes'])) {
|
|
|
1192 |
foreach($index['RemovedIndexes'] as $index_remove_name => $index_remove) {
|
|
|
1193 |
$result = $this->database->dropIndex($index_name,$index_remove_name);
|
|
|
1194 |
if(MDB::isError($result)) {
|
|
|
1195 |
break;
|
|
|
1196 |
}
|
|
|
1197 |
$alterations++;
|
|
|
1198 |
}
|
|
|
1199 |
}
|
|
|
1200 |
if(!MDB::isError($result)
|
|
|
1201 |
&& is_array($index['ChangedIndexes'])
|
|
|
1202 |
) {
|
|
|
1203 |
foreach($index['ChangedIndexes'] as $index_changed_name => $index_changed) {
|
|
|
1204 |
$was_name = (isset($indexes[$name]['name']) ? $indexes[$index_changed_name]['name'] : $index_changed_name);
|
|
|
1205 |
$result = $this->database->dropIndex($index_name, $was_name);
|
|
|
1206 |
if(MDB::isError($result)) {
|
|
|
1207 |
break;
|
|
|
1208 |
}
|
|
|
1209 |
$alterations++;
|
|
|
1210 |
}
|
|
|
1211 |
}
|
|
|
1212 |
if(MDB::isError($result)) {
|
|
|
1213 |
break;
|
|
|
1214 |
}
|
|
|
1215 |
}
|
|
|
1216 |
}
|
|
|
1217 |
if(!MDB::isError($result) && isset($changes['TABLES'])
|
|
|
1218 |
&& is_array($changes['TABLES'])
|
|
|
1219 |
) {
|
|
|
1220 |
foreach($changes['TABLES'] as $table_name => $table) {
|
|
|
1221 |
if(isset($table['Remove'])) {
|
|
|
1222 |
$result = $this->_dropTable($table_name);
|
|
|
1223 |
if(!MDB::isError($result)) {
|
|
|
1224 |
$alterations++;
|
|
|
1225 |
}
|
|
|
1226 |
} else {
|
|
|
1227 |
if(!isset($table['Add'])) {
|
|
|
1228 |
$result = $this->database->alterTable($table_name, $changes['TABLES'][$table_name], 0);
|
|
|
1229 |
if(!MDB::isError($result)) {
|
|
|
1230 |
$alterations++;
|
|
|
1231 |
}
|
|
|
1232 |
}
|
|
|
1233 |
}
|
|
|
1234 |
if(MDB::isError($result)) {
|
|
|
1235 |
break;
|
|
|
1236 |
}
|
|
|
1237 |
}
|
|
|
1238 |
foreach($changes['TABLES'] as $table_name => $table) {
|
|
|
1239 |
if(isset($table['Add'])) {
|
|
|
1240 |
$result = $this->_createTable($table_name, $this->database_definition['TABLES'][$table_name]);
|
|
|
1241 |
if(!MDB::isError($result)) {
|
|
|
1242 |
$alterations++;
|
|
|
1243 |
}
|
|
|
1244 |
}
|
|
|
1245 |
if(MDB::isError($result)) {
|
|
|
1246 |
break;
|
|
|
1247 |
}
|
|
|
1248 |
}
|
|
|
1249 |
}
|
|
|
1250 |
if(!MDB::isError($result) && isset($changes['SEQUENCES']) && is_array($changes['SEQUENCES'])) {
|
|
|
1251 |
foreach($changes['SEQUENCES'] as $sequence_name => $sequence) {
|
|
|
1252 |
if(isset($sequence['Add'])) {
|
|
|
1253 |
$created_on_table = 0;
|
|
|
1254 |
if(isset($this->database_definition['SEQUENCES'][$sequence_name]['on'])) {
|
|
|
1255 |
$table = $this->database_definition['SEQUENCES'][$sequence_name]['on']['table'];
|
|
|
1256 |
if(isset($changes['TABLES'])
|
|
|
1257 |
&& isset($changes['TABLES'][$table_name])
|
|
|
1258 |
&& isset($changes['TABLES'][$table_name]['Add'])
|
|
|
1259 |
) {
|
|
|
1260 |
$created_on_table = 1;
|
|
|
1261 |
}
|
|
|
1262 |
}
|
|
|
1263 |
|
|
|
1264 |
$result = $this->_createSequence($sequence_name,
|
|
|
1265 |
$this->database_definition['SEQUENCES'][$sequence_name], $created_on_table);
|
|
|
1266 |
if(!MDB::isError($result)) {
|
|
|
1267 |
$alterations++;
|
|
|
1268 |
}
|
|
|
1269 |
} else {
|
|
|
1270 |
if(isset($sequence['Remove'])) {
|
|
|
1271 |
if(!strcmp($error = $this->_dropSequence($sequence_name), '')) {
|
|
|
1272 |
$alterations++;
|
|
|
1273 |
}
|
|
|
1274 |
} else {
|
|
|
1275 |
if(isset($sequence['Change'])) {
|
|
|
1276 |
$created_on_table = 0;
|
|
|
1277 |
if(isset($this->database_definition['SEQUENCES'][$sequence_name]['on'])) {
|
|
|
1278 |
$table = $this->database_definition['SEQUENCES'][$sequence_name]['on']['table'];
|
|
|
1279 |
if(isset($changes['TABLES'])
|
|
|
1280 |
&& isset($changes['TABLES'][$table_name])
|
|
|
1281 |
&& isset($changes['TABLES'][$table_name]['Add'])
|
|
|
1282 |
) {
|
|
|
1283 |
$created_on_table = 1;
|
|
|
1284 |
}
|
|
|
1285 |
}
|
|
|
1286 |
if(!MDB::isError($result = $this->_dropSequence(
|
|
|
1287 |
$this->database_definition['SEQUENCES'][$sequence_name]['was']), '')
|
|
|
1288 |
&& !MDB::isError($result = $this->_createSequence(
|
|
|
1289 |
$sequence_name, $this->database_definition['SEQUENCES'][$sequence_name], $created_on_table), '')
|
|
|
1290 |
) {
|
|
|
1291 |
$alterations++;
|
|
|
1292 |
}
|
|
|
1293 |
} else {
|
|
|
1294 |
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
|
|
|
1295 |
'changing sequences is not yet supported'));
|
|
|
1296 |
}
|
|
|
1297 |
}
|
|
|
1298 |
}
|
|
|
1299 |
if(MDB::isError($result)) {
|
|
|
1300 |
break;
|
|
|
1301 |
}
|
|
|
1302 |
}
|
|
|
1303 |
}
|
|
|
1304 |
if(!MDB::isError($result) && isset($changes['INDEXES']) && is_array($changes['INDEXES'])) {
|
|
|
1305 |
foreach($changes['INDEXES'] as $table_name => $indexes) {
|
|
|
1306 |
if(isset($indexes['ChangedIndexes'])) {
|
|
|
1307 |
$changedindexes = $indexes['ChangedIndexes'];
|
|
|
1308 |
foreach($changedindexes as $index_name => $index) {
|
|
|
1309 |
$result = $this->database->createIndex($table_name, $index_name,
|
|
|
1310 |
$this->database_definition['TABLES'][$table_name]['INDEXES'][$index_name]);
|
|
|
1311 |
if(MDB::isError($result)) {
|
|
|
1312 |
break;
|
|
|
1313 |
}
|
|
|
1314 |
$alterations++;
|
|
|
1315 |
}
|
|
|
1316 |
}
|
|
|
1317 |
if(!MDB::isError($result)
|
|
|
1318 |
&& isset($indexes['AddedIndexes'])
|
|
|
1319 |
) {
|
|
|
1320 |
$addedindexes = $indexes['AddedIndexes'];
|
|
|
1321 |
foreach($addedindexes as $index_name => $index) {
|
|
|
1322 |
$result = $this->database->createIndex($table_name, $index_name,
|
|
|
1323 |
$this->database_definition['TABLES'][$table_name]['INDEXES'][$index_name]);
|
|
|
1324 |
if(MDB::isError($result)) {
|
|
|
1325 |
break;
|
|
|
1326 |
}
|
|
|
1327 |
$alterations++;
|
|
|
1328 |
}
|
|
|
1329 |
}
|
|
|
1330 |
if(MDB::isError($result)) {
|
|
|
1331 |
break;
|
|
|
1332 |
}
|
|
|
1333 |
}
|
|
|
1334 |
}
|
|
|
1335 |
if($alterations && MDB::isError($result)) {
|
|
|
1336 |
if($support_transactions) {
|
|
|
1337 |
$res = $this->database->rollback();
|
|
|
1338 |
if(MDB::isError($res))
|
|
|
1339 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
1340 |
'Could not rollback the partially created database alterations ('
|
|
|
1341 |
.$result->getMessage().' ('.$result->getUserinfo(),'))',
|
|
|
1342 |
'MDB_Error', TRUE);
|
|
|
1343 |
} else {
|
|
|
1344 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
1345 |
'the requested database alterations were only partially implemented ('
|
|
|
1346 |
.$result->getMessage().' ('.$result->getUserinfo(),'))',
|
|
|
1347 |
'MDB_Error', TRUE);
|
|
|
1348 |
}
|
|
|
1349 |
}
|
|
|
1350 |
if($support_transactions) {
|
|
|
1351 |
$result = $this->database->autoCommit(TRUE);
|
|
|
1352 |
if(MDB::isError($result)) {
|
|
|
1353 |
$result = $this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
1354 |
'Could not end transaction after successfully implemented the requested database alterations ('
|
|
|
1355 |
.$result->getMessage().' ('.$result->getUserinfo(),'))',
|
|
|
1356 |
'MDB_Error', TRUE);
|
|
|
1357 |
}
|
|
|
1358 |
}
|
|
|
1359 |
$this->database->setDatabase($previous_database_name);
|
|
|
1360 |
return($result);
|
|
|
1361 |
}
|
|
|
1362 |
|
|
|
1363 |
// }}}
|
|
|
1364 |
// {{{ _escapeSpecialCharacters()
|
|
|
1365 |
|
|
|
1366 |
/**
|
|
|
1367 |
* add escapecharacters to all special characters in a string
|
|
|
1368 |
*
|
|
|
1369 |
* @param string $string string that should be escaped
|
|
|
1370 |
* @return string escaped string
|
|
|
1371 |
* @access private
|
|
|
1372 |
*/
|
|
|
1373 |
function _escapeSpecialCharacters($string)
|
|
|
1374 |
{
|
|
|
1375 |
if(gettype($string) != 'string') {
|
|
|
1376 |
$string = strval($string);
|
|
|
1377 |
}
|
|
|
1378 |
for($escaped = '', $character = 0;
|
|
|
1379 |
$character < strlen($string);
|
|
|
1380 |
$character++)
|
|
|
1381 |
{
|
|
|
1382 |
switch($string[$character]) {
|
|
|
1383 |
case '\"':
|
|
|
1384 |
case '>':
|
|
|
1385 |
case '<':
|
|
|
1386 |
case '&':
|
|
|
1387 |
$code = ord($string[$character]);
|
|
|
1388 |
break;
|
|
|
1389 |
default:
|
|
|
1390 |
$code = ord($string[$character]);
|
|
|
1391 |
if($code < 32 || $code>127) {
|
|
|
1392 |
break;
|
|
|
1393 |
}
|
|
|
1394 |
$escaped .= $string[$character];
|
|
|
1395 |
continue 2;
|
|
|
1396 |
}
|
|
|
1397 |
$escaped .= "&#$code;";
|
|
|
1398 |
}
|
|
|
1399 |
return($escaped);
|
|
|
1400 |
}
|
|
|
1401 |
|
|
|
1402 |
// }}}
|
|
|
1403 |
// {{{ _dumpSequence()
|
|
|
1404 |
|
|
|
1405 |
/**
|
|
|
1406 |
* dump the structure of a sequence
|
|
|
1407 |
*
|
|
|
1408 |
* @param string $sequence_name
|
|
|
1409 |
* @param string $eol
|
|
|
1410 |
* @return mixed string with xml seqeunce definition on success, or a MDB error object
|
|
|
1411 |
* @access private
|
|
|
1412 |
*/
|
|
|
1413 |
function _dumpSequence($sequence_name, $eol, $dump = MDB_MANAGER_DUMP_ALL)
|
|
|
1414 |
{
|
|
|
1415 |
$sequence_definition = $this->database_definition['SEQUENCES'][$sequence_name];
|
|
|
1416 |
$buffer = "$eol <sequence>$eol <name>$sequence_name</name>$eol";
|
|
|
1417 |
if($dump == MDB_MANAGER_DUMP_ALL || $dump == MDB_MANAGER_DUMP_CONTENT) {
|
|
|
1418 |
if(isset($sequence_definition['start'])) {
|
|
|
1419 |
$start = $sequence_definition['start'];
|
|
|
1420 |
$buffer .= " <start>$start</start>$eol";
|
|
|
1421 |
}
|
|
|
1422 |
}
|
|
|
1423 |
if(isset($sequence_definition['on'])) {
|
|
|
1424 |
$buffer .= " <on>$eol <table>".$sequence_definition['on']['table']."</table>$eol <field>".$sequence_definition['on']['field']."</field>$eol </on>$eol";
|
|
|
1425 |
}
|
|
|
1426 |
$buffer .= " </sequence>$eol";
|
|
|
1427 |
return($buffer);
|
|
|
1428 |
}
|
|
|
1429 |
|
|
|
1430 |
// }}}
|
|
|
1431 |
// {{{ parseDatabaseDefinitionFile()
|
|
|
1432 |
|
|
|
1433 |
/**
|
|
|
1434 |
* Parse a database definition file by creating a Metabase schema format
|
|
|
1435 |
* parser object and passing the file contents as parser input data stream.
|
|
|
1436 |
*
|
|
|
1437 |
* @param string $input_file the path of the database schema file.
|
|
|
1438 |
* @param array $variables an associative array that the defines the text
|
|
|
1439 |
* string values that are meant to be used to replace the variables that are
|
|
|
1440 |
* used in the schema description.
|
|
|
1441 |
* @param bool $fail_on_invalid_names (optional) make function fail on invalid
|
|
|
1442 |
* names
|
|
|
1443 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
1444 |
* @access public
|
|
|
1445 |
*/
|
|
|
1446 |
function parseDatabaseDefinitionFile($input_file, $variables, $fail_on_invalid_names = 1)
|
|
|
1447 |
{
|
|
|
1448 |
$parser =& new MDB_Parser($variables, $fail_on_invalid_names);
|
|
|
1449 |
$result = $parser->setInputFile($input_file);
|
|
|
1450 |
if(MDB::isError($result)) {
|
|
|
1451 |
return($result);
|
|
|
1452 |
};
|
|
|
1453 |
$result = $parser->parse();
|
|
|
1454 |
if(MDB::isError($result)) {
|
|
|
1455 |
return($result);
|
|
|
1456 |
};
|
|
|
1457 |
if(MDB::isError($parser->error)) {
|
|
|
1458 |
return($parser->error);
|
|
|
1459 |
}
|
|
|
1460 |
return($parser->database_definition);
|
|
|
1461 |
}
|
|
|
1462 |
|
|
|
1463 |
// }}}
|
|
|
1464 |
// {{{ _debugDatabaseChanges()
|
|
|
1465 |
|
|
|
1466 |
/**
|
|
|
1467 |
* Dump the changes between two database definitions.
|
|
|
1468 |
*
|
|
|
1469 |
* @param array $changes an associative array that specifies the list
|
|
|
1470 |
* of database definitions changes as returned by the _compareDefinitions
|
|
|
1471 |
* manager class function.
|
|
|
1472 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
1473 |
* @access private
|
|
|
1474 |
*/
|
|
|
1475 |
function _debugDatabaseChanges($changes)
|
|
|
1476 |
{
|
|
|
1477 |
if(isset($changes['TABLES'])) {
|
|
|
1478 |
foreach($changes['TABLES'] as $table_name => $table)
|
|
|
1479 |
{
|
|
|
1480 |
$this->database->debug("$table_name:");
|
|
|
1481 |
if(isset($table['Add'])) {
|
|
|
1482 |
$this->database->debug("\tAdded table '$table_name'");
|
|
|
1483 |
} elseif(isset($table['Remove'])) {
|
|
|
1484 |
$this->database->debug("\tRemoved table '$table_name'");
|
|
|
1485 |
} else {
|
|
|
1486 |
if(isset($table['name'])) {
|
|
|
1487 |
$this->database->debug("\tRenamed table '$table_name' to '".$table['name']."'");
|
|
|
1488 |
}
|
|
|
1489 |
if(isset($table['AddedFields'])) {
|
|
|
1490 |
foreach($table['AddedFields'] as $field_name => $field) {
|
|
|
1491 |
$this->database->debug("\tAdded field '".$field_name."'");
|
|
|
1492 |
}
|
|
|
1493 |
}
|
|
|
1494 |
if(isset($table['RemovedFields'])) {
|
|
|
1495 |
foreach($table['RemovedFields'] as $field_name => $field) {
|
|
|
1496 |
$this->database->debug("\tRemoved field '".$field_name."'");
|
|
|
1497 |
}
|
|
|
1498 |
}
|
|
|
1499 |
if(isset($table['RenamedFields'])) {
|
|
|
1500 |
foreach($table['RenamedFields'] as $field_name => $field) {
|
|
|
1501 |
$this->database->debug("\tRenamed field '".$field_name."' to '".$field['name']."'");
|
|
|
1502 |
}
|
|
|
1503 |
}
|
|
|
1504 |
if(isset($table['ChangedFields'])) {
|
|
|
1505 |
foreach($table['ChangedFields'] as $field_name => $field) {
|
|
|
1506 |
if(isset($field['type'])) {
|
|
|
1507 |
$this->database->debug(
|
|
|
1508 |
"\tChanged field '$field_name' type to '".$field['type']."'");
|
|
|
1509 |
}
|
|
|
1510 |
if(isset($field['unsigned'])) {
|
|
|
1511 |
$this->database->debug(
|
|
|
1512 |
"\tChanged field '$field_name' type to '".
|
|
|
1513 |
($field['unsigned'] ? '' : 'not ')."unsigned'");
|
|
|
1514 |
}
|
|
|
1515 |
if(isset($field['length'])) {
|
|
|
1516 |
$this->database->debug(
|
|
|
1517 |
"\tChanged field '$field_name' length to '".
|
|
|
1518 |
($field['length'] == 0 ? 'no length' : $field['length'])."'");
|
|
|
1519 |
}
|
|
|
1520 |
if(isset($field['ChangedDefault'])) {
|
|
|
1521 |
$this->database->debug(
|
|
|
1522 |
"\tChanged field '$field_name' default to ".
|
|
|
1523 |
(isset($field['default']) ? "'".$field['default']."'" : 'NULL'));
|
|
|
1524 |
}
|
|
|
1525 |
if(isset($field['ChangedNotNull'])) {
|
|
|
1526 |
$this->database->debug(
|
|
|
1527 |
"\tChanged field '$field_name' notnull to ".(isset($field['notnull']) ? "'1'" : '0'));
|
|
|
1528 |
}
|
|
|
1529 |
}
|
|
|
1530 |
}
|
|
|
1531 |
}
|
|
|
1532 |
}
|
|
|
1533 |
}
|
|
|
1534 |
if(isset($changes['SEQUENCES'])) {
|
|
|
1535 |
foreach($changes['SEQUENCES'] as $sequence_name => $sequence)
|
|
|
1536 |
{
|
|
|
1537 |
$this->database->debug("$sequence_name:");
|
|
|
1538 |
if(isset($sequence['Add'])) {
|
|
|
1539 |
$this->database->debug("\tAdded sequence '$sequence_name'");
|
|
|
1540 |
} elseif(isset($sequence['Remove'])) {
|
|
|
1541 |
$this->database->debug("\tRemoved sequence '$sequence_name'");
|
|
|
1542 |
} else {
|
|
|
1543 |
if(isset($sequence['name'])) {
|
|
|
1544 |
$this->database->debug("\tRenamed sequence '$sequence_name' to '".$sequence['name']."'");
|
|
|
1545 |
}
|
|
|
1546 |
if(isset($sequence['Change'])) {
|
|
|
1547 |
foreach($sequence['Change'] as $sequence_name => $sequence) {
|
|
|
1548 |
if(isset($sequence['start'])) {
|
|
|
1549 |
$this->database->debug(
|
|
|
1550 |
"\tChanged sequence '$sequence_name' start to '".$sequence['start']."'");
|
|
|
1551 |
}
|
|
|
1552 |
}
|
|
|
1553 |
}
|
|
|
1554 |
}
|
|
|
1555 |
}
|
|
|
1556 |
}
|
|
|
1557 |
if(isset($changes['INDEXES'])) {
|
|
|
1558 |
foreach($changes['INDEXES'] as $table_name => $table)
|
|
|
1559 |
{
|
|
|
1560 |
$this->database->debug("$table_name:");
|
|
|
1561 |
if(isset($table['AddedIndexes'])) {
|
|
|
1562 |
foreach($table['AddedIndexes'] as $index_name => $index) {
|
|
|
1563 |
$this->database->debug("\tAdded index '".$index_name."' of table '$table_name'");
|
|
|
1564 |
}
|
|
|
1565 |
}
|
|
|
1566 |
if(isset($table['RemovedIndexes'])) {
|
|
|
1567 |
foreach($table['RemovedIndexes'] as $index_name => $index) {
|
|
|
1568 |
$this->database->debug("\tRemoved index '".$index_name."' of table '$table_name'");
|
|
|
1569 |
}
|
|
|
1570 |
}
|
|
|
1571 |
if(isset($table['ChangedIndexes'])) {
|
|
|
1572 |
foreach($table['ChangedIndexes'] as $index_name => $index) {
|
|
|
1573 |
if(isset($index['name'])) {
|
|
|
1574 |
$this->database->debug(
|
|
|
1575 |
"\tRenamed index '".$index_name."' to '".$index['name']."' on table '$table_name'");
|
|
|
1576 |
}
|
|
|
1577 |
if(isset($index['ChangedUnique'])) {
|
|
|
1578 |
$this->database->debug(
|
|
|
1579 |
"\tChanged index '".$index_name."' unique to '".
|
|
|
1580 |
isset($index['unique'])."' on table '$table_name'");
|
|
|
1581 |
}
|
|
|
1582 |
if(isset($index['ChangedFields'])) {
|
|
|
1583 |
$this->database->debug("\tChanged index '".$index_name."' on table '$table_name'");
|
|
|
1584 |
}
|
|
|
1585 |
}
|
|
|
1586 |
}
|
|
|
1587 |
}
|
|
|
1588 |
}
|
|
|
1589 |
return(MDB_OK);
|
|
|
1590 |
}
|
|
|
1591 |
|
|
|
1592 |
// }}}
|
|
|
1593 |
// {{{ _dumpDatabaseContents()
|
|
|
1594 |
|
|
|
1595 |
/**
|
|
|
1596 |
* Parse a database schema definition file and dump the respective structure
|
|
|
1597 |
* and contents.
|
|
|
1598 |
*
|
|
|
1599 |
* @param string $schema_file path of the database schema file.
|
|
|
1600 |
* @param mixed $setup_arguments an associative array that takes pairs of tag names and values
|
|
|
1601 |
* that define the setup arguments that are passed to the
|
|
|
1602 |
* MDB_Manager::connect function.
|
|
|
1603 |
* @param array $dump_arguments an associative array that takes pairs of tag names and values
|
|
|
1604 |
* that define dump options as defined for the MDB_Manager::DumpDatabase
|
|
|
1605 |
* function.
|
|
|
1606 |
* @param array $variables an associative array that the defines the text string values
|
|
|
1607 |
* that are meant to be used to replace the variables that are used in the
|
|
|
1608 |
* schema description as defined for the
|
|
|
1609 |
* MDB_Manager::parseDatabaseDefinitionFile function.
|
|
|
1610 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
1611 |
* @access private
|
|
|
1612 |
*/
|
|
|
1613 |
function _dumpDatabaseContents($schema_file, $setup_arguments, $dump_arguments, $variables)
|
|
|
1614 |
{
|
|
|
1615 |
$database_definition = $this->parseDatabaseDefinitionFile($schema_file,
|
|
|
1616 |
$variables, $this->options['fail_on_invalid_names']);
|
|
|
1617 |
if(MDB::isError($database_definition)) {
|
|
|
1618 |
return($database_definition);
|
|
|
1619 |
}
|
|
|
1620 |
|
|
|
1621 |
$this->database_definition = $database_definition;
|
|
|
1622 |
|
|
|
1623 |
$result = $this->connect($setup_arguments);
|
|
|
1624 |
if(MDB::isError($result)) {
|
|
|
1625 |
return($result);
|
|
|
1626 |
}
|
|
|
1627 |
|
|
|
1628 |
return($this->dumpDatabase($dump_arguments));
|
|
|
1629 |
}
|
|
|
1630 |
|
|
|
1631 |
// }}}
|
|
|
1632 |
// {{{ getDefinitionFromDatabase()
|
|
|
1633 |
|
|
|
1634 |
/**
|
|
|
1635 |
* Attempt to reverse engineer a schema structure from an existing MDB
|
|
|
1636 |
* This method can be used if no xml schema file exists yet.
|
|
|
1637 |
* The resulting xml schema file may need some manual adjustments.
|
|
|
1638 |
*
|
|
|
1639 |
* @return mixed MDB_OK or array with all ambiguities on success, or a MDB error object
|
|
|
1640 |
* @access public
|
|
|
1641 |
*/
|
|
|
1642 |
function getDefinitionFromDatabase()
|
|
|
1643 |
{
|
|
|
1644 |
$database = $this->database->database_name;
|
|
|
1645 |
if(strlen($database) == 0) {
|
|
|
1646 |
return('it was not specified a valid database name');
|
|
|
1647 |
}
|
|
|
1648 |
$this->database_definition = array(
|
|
|
1649 |
'name' => $database,
|
|
|
1650 |
'create' => 1,
|
|
|
1651 |
'TABLES' => array()
|
|
|
1652 |
);
|
|
|
1653 |
$tables = $this->database->listTables();
|
|
|
1654 |
if(MDB::isError($tables)) {
|
|
|
1655 |
return($tables);
|
|
|
1656 |
}
|
|
|
1657 |
for($table = 0; $table < count($tables); $table++) {
|
|
|
1658 |
$table_name = $tables[$table];
|
|
|
1659 |
$fields = $this->database->listTableFields($table_name);
|
|
|
1660 |
if(MDB::isError($fields)) {
|
|
|
1661 |
return($fields);
|
|
|
1662 |
}
|
|
|
1663 |
$this->database_definition['TABLES'][$table_name] = array('FIELDS' => array());
|
|
|
1664 |
for($field = 0; $field < count($fields); $field++)
|
|
|
1665 |
{
|
|
|
1666 |
$field_name = $fields[$field];
|
|
|
1667 |
$definition = $this->database->getTableFieldDefinition($table_name, $field_name);
|
|
|
1668 |
if(MDB::isError($definition)) {
|
|
|
1669 |
return($definition);
|
|
|
1670 |
}
|
|
|
1671 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_name] = $definition[0][0];
|
|
|
1672 |
$field_choices = count($definition[0]);
|
|
|
1673 |
if($field_choices > 1) {
|
|
|
1674 |
$warning = "There are $field_choices type choices in the table $table_name field $field_name (#1 is the default): ";
|
|
|
1675 |
$field_choice_cnt = 1;
|
|
|
1676 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_name]['CHOICES'] = array();
|
|
|
1677 |
foreach($definition[0] as $field_choice) {
|
|
|
1678 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_name]['CHOICES'][] = $field_choice;
|
|
|
1679 |
$warning .= 'choice #'.($field_choice_cnt).': '.serialize($field_choice);
|
|
|
1680 |
$field_choice_cnt++;
|
|
|
1681 |
}
|
|
|
1682 |
$this->warnings[] = $warning;
|
|
|
1683 |
}
|
|
|
1684 |
if(isset($definition[1])) {
|
|
|
1685 |
$sequence = $definition[1]['definition'];
|
|
|
1686 |
$sequence_name = $definition[1]['name'];
|
|
|
1687 |
$this->database->debug('Implicitly defining sequence: '.$sequence_name);
|
|
|
1688 |
if(!isset($this->database_definition['SEQUENCES'])) {
|
|
|
1689 |
$this->database_definition['SEQUENCES'] = array();
|
|
|
1690 |
}
|
|
|
1691 |
$this->database_definition['SEQUENCES'][$sequence_name] = $sequence;
|
|
|
1692 |
}
|
|
|
1693 |
if(isset($definition[2])) {
|
|
|
1694 |
$index = $definition[2]['definition'];
|
|
|
1695 |
$index_name = $definition[2]['name'];
|
|
|
1696 |
$this->database->debug('Implicitly defining index: '.$index_name);
|
|
|
1697 |
if(!isset($this->database_definition['TABLES'][$table_name]['INDEXES'])) {
|
|
|
1698 |
$this->database_definition['TABLES'][$table_name]['INDEXES'] = array();
|
|
|
1699 |
}
|
|
|
1700 |
$this->database_definition['TABLES'][$table_name]['INDEXES'][$index_name] = $index;
|
|
|
1701 |
}
|
|
|
1702 |
}
|
|
|
1703 |
$indexes = $this->database->listTableIndexes($table_name);
|
|
|
1704 |
if(MDB::isError($indexes)) {
|
|
|
1705 |
return($indexes);
|
|
|
1706 |
}
|
|
|
1707 |
if(is_array($indexes) && count($indexes) > 0 && !isset($this->database_definition['TABLES'][$table_name]['INDEXES'])) {
|
|
|
1708 |
$this->database_definition['TABLES'][$table_name]['INDEXES'] = array();
|
|
|
1709 |
}
|
|
|
1710 |
for($index = 0, $index_cnt = count($indexes); $index < $index_cnt; $index++)
|
|
|
1711 |
{
|
|
|
1712 |
$index_name = $indexes[$index];
|
|
|
1713 |
$definition = $this->database->getTableIndexDefinition($table_name, $index_name);
|
|
|
1714 |
if(MDB::isError($definition)) {
|
|
|
1715 |
return($definition);
|
|
|
1716 |
}
|
|
|
1717 |
$this->database_definition['TABLES'][$table_name]['INDEXES'][$index_name] = $definition;
|
|
|
1718 |
}
|
|
|
1719 |
// ensure that all fields that have an index on them are set to not null
|
|
|
1720 |
if(isset($this->database_definition['TABLES'][$table_name]['INDEXES'])
|
|
|
1721 |
&& is_array($this->database_definition['TABLES'][$table_name]['INDEXES'])
|
|
|
1722 |
&& count($this->database_definition['TABLES'][$table_name]['INDEXES']) > 0
|
|
|
1723 |
) {
|
|
|
1724 |
foreach($this->database_definition['TABLES'][$table_name]['INDEXES'] as $index_check_null) {
|
|
|
1725 |
foreach($index_check_null['FIELDS'] as $field_name_check_null => $field_check_null) {
|
|
|
1726 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_name_check_null]['notnull'] = 1;
|
|
|
1727 |
}
|
|
|
1728 |
}
|
|
|
1729 |
}
|
|
|
1730 |
// ensure that all fields that are set to not null also have a default value
|
|
|
1731 |
if(is_array($this->database_definition['TABLES'][$table_name]['FIELDS'])
|
|
|
1732 |
&& count($this->database_definition['TABLES'][$table_name]['FIELDS']) > 0
|
|
|
1733 |
) {
|
|
|
1734 |
foreach($this->database_definition['TABLES'][$table_name]['FIELDS'] as $field_set_default_name => $field_set_default) {
|
|
|
1735 |
if(isset($field_set_default['notnull']) && $field_set_default['notnull']
|
|
|
1736 |
&& !isset($field_set_default['default'])
|
|
|
1737 |
) {
|
|
|
1738 |
if(isset($this->default_values[$field_set_default['type']])) {
|
|
|
1739 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_set_default_name]['default'] = $this->default_values[$field_set_default['type']];
|
|
|
1740 |
} else {
|
|
|
1741 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_set_default_name]['default'] = 0;
|
|
|
1742 |
}
|
|
|
1743 |
}
|
|
|
1744 |
if(isset($field_set_default['CHOICES']) && is_array($field_set_default['CHOICES'])) {
|
|
|
1745 |
foreach($field_set_default['CHOICES'] as $field_choices_set_default_name => $field_choices_set_default) {
|
|
|
1746 |
if(isset($field_choices_set_default['notnull'])
|
|
|
1747 |
&& $field_choices_set_default['notnull']
|
|
|
1748 |
&& !isset($field_choices_set_default['default'])
|
|
|
1749 |
) {
|
|
|
1750 |
if(isset($this->default_values[$field_choices_set_default['type']])) {
|
|
|
1751 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_set_default_name]['CHOICES']
|
|
|
1752 |
[$field_choices_set_default_name]['default'] = $this->default_values[$field_choices_set_default['type']];
|
|
|
1753 |
} else {
|
|
|
1754 |
$this->database_definition['TABLES'][$table_name]['FIELDS'][$field_set_default_name]['CHOICES']
|
|
|
1755 |
[$field_choices_set_default_name]['default'] = 0;
|
|
|
1756 |
}
|
|
|
1757 |
}
|
|
|
1758 |
}
|
|
|
1759 |
}
|
|
|
1760 |
}
|
|
|
1761 |
}
|
|
|
1762 |
}
|
|
|
1763 |
$sequences = $this->database->listSequences();
|
|
|
1764 |
if(MDB::isError($sequences)) {
|
|
|
1765 |
return($sequences);
|
|
|
1766 |
}
|
|
|
1767 |
if(is_array($sequences) && count($sequences) > 0 && !isset($this->database_definition['SEQUENCES'])) {
|
|
|
1768 |
$this->database_definition['SEQUENCES'] = array();
|
|
|
1769 |
}
|
|
|
1770 |
for($sequence = 0; $sequence < count($sequences); $sequence++) {
|
|
|
1771 |
$sequence_name = $sequences[$sequence];
|
|
|
1772 |
$definition = $this->database->getSequenceDefinition($sequence_name);
|
|
|
1773 |
if(MDB::isError($definition)) {
|
|
|
1774 |
return($definition);
|
|
|
1775 |
}
|
|
|
1776 |
$this->database_definition['SEQUENCES'][$sequence_name] = $definition;
|
|
|
1777 |
}
|
|
|
1778 |
return(MDB_OK);
|
|
|
1779 |
}
|
|
|
1780 |
|
|
|
1781 |
// }}}
|
|
|
1782 |
// {{{ dumpDatabase()
|
|
|
1783 |
|
|
|
1784 |
/**
|
|
|
1785 |
* Dump a previously parsed database structure in the Metabase schema
|
|
|
1786 |
* XML based format suitable for the Metabase parser. This function
|
|
|
1787 |
* may optionally dump the database definition with initialization
|
|
|
1788 |
* commands that specify the data that is currently present in the tables.
|
|
|
1789 |
*
|
|
|
1790 |
* @param array $arguments an associative array that takes pairs of tag
|
|
|
1791 |
* names and values that define dump options.
|
|
|
1792 |
* array (
|
|
|
1793 |
* 'Definition' => Boolean
|
|
|
1794 |
* TRUE : dump currently parsed definition
|
|
|
1795 |
* default: dump currently connected database
|
|
|
1796 |
* 'Output_Mode' => String
|
|
|
1797 |
* 'file' : dump into a file
|
|
|
1798 |
* default: dump using a function
|
|
|
1799 |
* 'Output' => String
|
|
|
1800 |
* depending on the 'Output_Mode'
|
|
|
1801 |
* name of the file
|
|
|
1802 |
* name of the function
|
|
|
1803 |
* 'EndOfLine' => String
|
|
|
1804 |
* end of line delimiter that should be used
|
|
|
1805 |
* default: "\n"
|
|
|
1806 |
* );
|
|
|
1807 |
* @param integer $dump constant that determines what data to dump
|
|
|
1808 |
* MDB_MANAGER_DUMP_ALL : the entire db
|
|
|
1809 |
* MDB_MANAGER_DUMP_STRUCTURE : only the structure of the db
|
|
|
1810 |
* MDB_MANAGER_DUMP_CONTENT : only the content of the db
|
|
|
1811 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
1812 |
* @access public
|
|
|
1813 |
*/
|
|
|
1814 |
function dumpDatabase($arguments, $dump = MDB_MANAGER_DUMP_ALL)
|
|
|
1815 |
{
|
|
|
1816 |
if(isset($arguments['Definition']) && $arguments['Definition']) {
|
|
|
1817 |
$dump_definition = TRUE;
|
|
|
1818 |
} else {
|
|
|
1819 |
if(!$this->database) {
|
|
|
1820 |
return($this->raiseError(MDB_ERROR_NODBSELECTED,
|
|
|
1821 |
NULL, NULL, 'please connect to a RDBMS first'));
|
|
|
1822 |
}
|
|
|
1823 |
$error = $this->getDefinitionFromDatabase();
|
|
|
1824 |
if(MDB::isError($error)) {
|
|
|
1825 |
return($error);
|
|
|
1826 |
}
|
|
|
1827 |
$dump_definition = FALSE;
|
|
|
1828 |
}
|
|
|
1829 |
if(isset($arguments['Output'])) {
|
|
|
1830 |
if(isset($arguments['Output_Mode']) && $arguments['Output_Mode'] == 'file') {
|
|
|
1831 |
$fp = fopen($arguments['Output'], 'w');
|
|
|
1832 |
$output = FALSE;
|
|
|
1833 |
} elseif(function_exists($arguments['Output'])) {
|
|
|
1834 |
$output = $arguments['Output'];
|
|
|
1835 |
} else {
|
|
|
1836 |
return($this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
1837 |
'no valid output function specified'));
|
|
|
1838 |
}
|
|
|
1839 |
} else {
|
|
|
1840 |
return($this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
1841 |
'no output method specified'));
|
|
|
1842 |
}
|
|
|
1843 |
if(isset($arguments['EndOfLine'])) {
|
|
|
1844 |
$eol = $arguments['EndOfLine'];
|
|
|
1845 |
} else {
|
|
|
1846 |
$eol = "\n";
|
|
|
1847 |
}
|
|
|
1848 |
|
|
|
1849 |
$sequences = array();
|
|
|
1850 |
if(isset($this->database_definition['SEQUENCES'])
|
|
|
1851 |
&& is_array($this->database_definition['SEQUENCES'])
|
|
|
1852 |
) {
|
|
|
1853 |
foreach($this->database_definition['SEQUENCES'] as $sequence_name => $sequence) {
|
|
|
1854 |
if(isset($sequence['on'])) {
|
|
|
1855 |
$table = $sequence['on']['table'];
|
|
|
1856 |
} else {
|
|
|
1857 |
$table = '';
|
|
|
1858 |
}
|
|
|
1859 |
$sequences[$table][] = $sequence_name;
|
|
|
1860 |
}
|
|
|
1861 |
}
|
|
|
1862 |
$previous_database_name = (strcmp($this->database_definition['name'], '') ? $this->database->setDatabase($this->database_definition['name']) : '');
|
|
|
1863 |
$buffer = ('<?xml version="1.0" encoding="ISO-8859-1" ?>'.$eol);
|
|
|
1864 |
$buffer .= ("<database>$eol$eol <name>".$this->database_definition['name']."</name>$eol <create>".$this->database_definition['create']."</create>$eol");
|
|
|
1865 |
|
|
|
1866 |
if($output) {
|
|
|
1867 |
$output($buffer);
|
|
|
1868 |
} else {
|
|
|
1869 |
fwrite($fp, $buffer);
|
|
|
1870 |
}
|
|
|
1871 |
$buffer = '';
|
|
|
1872 |
if(isset($this->database_definition['TABLES']) && is_array($this->database_definition['TABLES'])) {
|
|
|
1873 |
foreach($this->database_definition['TABLES'] as $table_name => $table) {
|
|
|
1874 |
$buffer = ("$eol <table>$eol$eol <name>$table_name</name>$eol");
|
|
|
1875 |
if($dump == MDB_MANAGER_DUMP_ALL || $dump == MDB_MANAGER_DUMP_STRUCTURE) {
|
|
|
1876 |
$buffer .= ("$eol <declaration>$eol");
|
|
|
1877 |
if(isset($table['FIELDS']) && is_array($table['FIELDS'])) {
|
|
|
1878 |
foreach($table['FIELDS'] as $field_name => $field) {
|
|
|
1879 |
if(!isset($field['type'])) {
|
|
|
1880 |
return($this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
1881 |
'it was not specified the type of the field "'.$field_name.'" of the table "'.$table_name));
|
|
|
1882 |
}
|
|
|
1883 |
$buffer .=("$eol <field>$eol <name>$field_name</name>$eol <type>".$field['type']."</type>$eol");
|
|
|
1884 |
if(in_array($field_name, array_keys($this->invalid_names))) {
|
|
|
1885 |
$this->warnings[] = "invalid field name: $field_name. You will need to set the class var \$fail_on_invalid_names to FALSE or change the field name.";
|
|
|
1886 |
}
|
|
|
1887 |
switch($field['type']) {
|
|
|
1888 |
case 'integer':
|
|
|
1889 |
if(isset($field['unsigned'])) {
|
|
|
1890 |
$buffer .=(" <unsigned>1</unsigned>$eol");
|
|
|
1891 |
}
|
|
|
1892 |
break;
|
|
|
1893 |
case 'text':
|
|
|
1894 |
case 'clob':
|
|
|
1895 |
case 'blob':
|
|
|
1896 |
if(isset($field['length'])) {
|
|
|
1897 |
$buffer .=(' <length>'.$field['length']."</length>$eol");
|
|
|
1898 |
}
|
|
|
1899 |
break;
|
|
|
1900 |
case 'boolean':
|
|
|
1901 |
case 'date':
|
|
|
1902 |
case 'timestamp':
|
|
|
1903 |
case 'time':
|
|
|
1904 |
case 'float':
|
|
|
1905 |
case 'decimal':
|
|
|
1906 |
break;
|
|
|
1907 |
default:
|
|
|
1908 |
return('type "'.$field['type'].'" is not yet supported');
|
|
|
1909 |
}
|
|
|
1910 |
if(isset($field['notnull'])) {
|
|
|
1911 |
$buffer .=(" <notnull>1</notnull>$eol");
|
|
|
1912 |
}
|
|
|
1913 |
if(isset($field['default'])) {
|
|
|
1914 |
$buffer .=(' <default>'.$this->_escapeSpecialCharacters($field['default'])."</default>$eol");
|
|
|
1915 |
}
|
|
|
1916 |
$buffer .=(" </field>$eol");
|
|
|
1917 |
}
|
|
|
1918 |
}
|
|
|
1919 |
if(isset($table['INDEXES']) && is_array($table['INDEXES'])) {
|
|
|
1920 |
foreach($table['INDEXES'] as $index_name => $index) {
|
|
|
1921 |
$buffer .=("$eol <index>$eol <name>$index_name</name>$eol");
|
|
|
1922 |
if(isset($index['unique'])) {
|
|
|
1923 |
$buffer .=(" <unique>1</unique>$eol");
|
|
|
1924 |
}
|
|
|
1925 |
foreach($index['FIELDS'] as $field_name => $field) {
|
|
|
1926 |
$buffer .=(" <field>$eol <name>$field_name</name>$eol");
|
|
|
1927 |
if(is_array($field) && isset($field['sorting'])) {
|
|
|
1928 |
$buffer .=(' <sorting>'.$field['sorting']."</sorting>$eol");
|
|
|
1929 |
}
|
|
|
1930 |
$buffer .=(" </field>$eol");
|
|
|
1931 |
}
|
|
|
1932 |
$buffer .=(" </index>$eol");
|
|
|
1933 |
}
|
|
|
1934 |
}
|
|
|
1935 |
$buffer .= ("$eol </declaration>$eol");
|
|
|
1936 |
}
|
|
|
1937 |
if($output) {
|
|
|
1938 |
$output($buffer);
|
|
|
1939 |
} else {
|
|
|
1940 |
fwrite($fp, $buffer);
|
|
|
1941 |
}
|
|
|
1942 |
$buffer = '';
|
|
|
1943 |
if($dump == MDB_MANAGER_DUMP_ALL || $dump == MDB_MANAGER_DUMP_CONTENT) {
|
|
|
1944 |
if($dump_definition) {
|
|
|
1945 |
if(isset($table['initialization']) && is_array($table['initialization'])) {
|
|
|
1946 |
$buffer = ("$eol <initialization>$eol");
|
|
|
1947 |
foreach($table['initialization'] as $instruction_name => $instruction) {
|
|
|
1948 |
switch($instruction['type']) {
|
|
|
1949 |
case 'insert':
|
|
|
1950 |
$buffer .= ("$eol <insert>$eol");
|
|
|
1951 |
foreach($instruction['FIELDS'] as $field_name => $field) {
|
|
|
1952 |
$buffer .= ("$eol <field>$eol <name>$field_name</name>$eol <value>".$this->_escapeSpecialCharacters($field)."</value>$eol </field>$eol");
|
|
|
1953 |
}
|
|
|
1954 |
$buffer .= ("$eol </insert>$eol");
|
|
|
1955 |
break;
|
|
|
1956 |
}
|
|
|
1957 |
}
|
|
|
1958 |
$buffer .= ("$eol </initialization>$eol");
|
|
|
1959 |
}
|
|
|
1960 |
} else {
|
|
|
1961 |
$types = array();
|
|
|
1962 |
foreach($table['FIELDS'] as $field) {
|
|
|
1963 |
$types[] = $field['type'];
|
|
|
1964 |
}
|
|
|
1965 |
$query = 'SELECT '.implode(',',array_keys($table['FIELDS']))." FROM $table_name";
|
|
|
1966 |
$result = $this->database->queryAll($query, $types, MDB_FETCHMODE_ASSOC);
|
|
|
1967 |
if(MDB::isError($result)) {
|
|
|
1968 |
return($result);
|
|
|
1969 |
}
|
|
|
1970 |
$rows = count($result);
|
|
|
1971 |
if($rows > 0) {
|
|
|
1972 |
$buffer = ("$eol <initialization>$eol");
|
|
|
1973 |
if($output) {
|
|
|
1974 |
$output($buffer);
|
|
|
1975 |
} else {
|
|
|
1976 |
fwrite($fp, $buffer);
|
|
|
1977 |
}
|
|
|
1978 |
|
|
|
1979 |
for($row = 0; $row < $rows; $row++) {
|
|
|
1980 |
$buffer = ("$eol <insert>$eol");
|
|
|
1981 |
$values = $result[$row];
|
|
|
1982 |
if(!is_array($values)) {
|
|
|
1983 |
break;
|
|
|
1984 |
} else {
|
|
|
1985 |
foreach($values as $field_name => $field) {
|
|
|
1986 |
$buffer .= ("$eol <field>$eol <name>$field_name</name>$eol <value>");
|
|
|
1987 |
$buffer .= $this->_escapeSpecialCharacters($values[$field_name]);
|
|
|
1988 |
$buffer .= ("</value>$eol </field>$eol");
|
|
|
1989 |
}
|
|
|
1990 |
}
|
|
|
1991 |
$buffer .= ("$eol </insert>$eol");
|
|
|
1992 |
if($output) {
|
|
|
1993 |
$output($buffer);
|
|
|
1994 |
} else {
|
|
|
1995 |
fwrite($fp, $buffer);
|
|
|
1996 |
}
|
|
|
1997 |
$buffer = '';
|
|
|
1998 |
}
|
|
|
1999 |
$buffer = ("$eol </initialization>$eol");
|
|
|
2000 |
if($output) {
|
|
|
2001 |
$output($buffer);
|
|
|
2002 |
} else {
|
|
|
2003 |
fwrite($fp, $buffer);
|
|
|
2004 |
}
|
|
|
2005 |
$buffer = '';
|
|
|
2006 |
}
|
|
|
2007 |
}
|
|
|
2008 |
}
|
|
|
2009 |
$buffer .= ("$eol </table>$eol");
|
|
|
2010 |
if($output) {
|
|
|
2011 |
$output($buffer);
|
|
|
2012 |
} else {
|
|
|
2013 |
fwrite($fp, $buffer);
|
|
|
2014 |
}
|
|
|
2015 |
if(isset($sequences[$table_name])) {
|
|
|
2016 |
for($sequence = 0, $j = count($sequences[$table_name]);
|
|
|
2017 |
$sequence < $j;
|
|
|
2018 |
$sequence++)
|
|
|
2019 |
{
|
|
|
2020 |
$result = $this->_dumpSequence($sequences[$table_name][$sequence], $eol, $dump);
|
|
|
2021 |
if(MDB::isError($result)) {
|
|
|
2022 |
return($result);
|
|
|
2023 |
}
|
|
|
2024 |
if($output) {
|
|
|
2025 |
$output($result);
|
|
|
2026 |
} else {
|
|
|
2027 |
fwrite($fp, $result);
|
|
|
2028 |
}
|
|
|
2029 |
}
|
|
|
2030 |
}
|
|
|
2031 |
}
|
|
|
2032 |
}
|
|
|
2033 |
if(isset($sequences[''])) {
|
|
|
2034 |
for($sequence = 0;
|
|
|
2035 |
$sequence < count($sequences['']);
|
|
|
2036 |
$sequence++)
|
|
|
2037 |
{
|
|
|
2038 |
$result = $this->_dumpSequence($sequences[''][$sequence], $eol, $dump);
|
|
|
2039 |
if(MDB::isError($result)) {
|
|
|
2040 |
return($result);
|
|
|
2041 |
}
|
|
|
2042 |
if($output) {
|
|
|
2043 |
$output($result);
|
|
|
2044 |
} else {
|
|
|
2045 |
fwrite($fp, $result);
|
|
|
2046 |
}
|
|
|
2047 |
}
|
|
|
2048 |
}
|
|
|
2049 |
|
|
|
2050 |
$buffer = ("$eol</database>$eol");
|
|
|
2051 |
if($output) {
|
|
|
2052 |
$output($buffer);
|
|
|
2053 |
} else {
|
|
|
2054 |
fwrite($fp, $buffer);
|
|
|
2055 |
fclose($fp);
|
|
|
2056 |
}
|
|
|
2057 |
|
|
|
2058 |
if(strcmp($previous_database_name, '')) {
|
|
|
2059 |
$this->database->setDatabase($previous_database_name);
|
|
|
2060 |
}
|
|
|
2061 |
return(MDB_OK);
|
|
|
2062 |
}
|
|
|
2063 |
|
|
|
2064 |
// }}}
|
|
|
2065 |
// {{{ updateDatabase()
|
|
|
2066 |
|
|
|
2067 |
/**
|
|
|
2068 |
* Compare the correspondent files of two versions of a database schema
|
|
|
2069 |
* definition: the previously installed and the one that defines the schema
|
|
|
2070 |
* that is meant to update the database.
|
|
|
2071 |
* If the specified previous definition file does not exist, this function
|
|
|
2072 |
* will create the database from the definition specified in the current
|
|
|
2073 |
* schema file.
|
|
|
2074 |
* If both files exist, the function assumes that the database was previously
|
|
|
2075 |
* installed based on the previous schema file and will update it by just
|
|
|
2076 |
* applying the changes.
|
|
|
2077 |
* If this function succeeds, the contents of the current schema file are
|
|
|
2078 |
* copied to replace the previous schema file contents. Any subsequent schema
|
|
|
2079 |
* changes should only be done on the file specified by the $current_schema_file
|
|
|
2080 |
* to let this function make a consistent evaluation of the exact changes that
|
|
|
2081 |
* need to be applied.
|
|
|
2082 |
*
|
|
|
2083 |
* @param string $current_schema_file name of the updated database schema
|
|
|
2084 |
* definition file.
|
|
|
2085 |
* @param string $previous_schema_file name the previously installed database
|
|
|
2086 |
* schema definition file.
|
|
|
2087 |
* @param array $variables an associative array that is passed to the argument
|
|
|
2088 |
* of the same name to the parseDatabaseDefinitionFile function. (there third
|
|
|
2089 |
* param)
|
|
|
2090 |
* @return mixed MDB_OK on success, or a MDB error object
|
|
|
2091 |
* @access public
|
|
|
2092 |
*/
|
|
|
2093 |
function updateDatabase($current_schema_file, $previous_schema_file = FALSE, $variables = array())
|
|
|
2094 |
{
|
|
|
2095 |
$database_definition = $this->parseDatabaseDefinitionFile($current_schema_file,
|
|
|
2096 |
$variables, $this->options['fail_on_invalid_names']);
|
|
|
2097 |
if(MDB::isError($database_definition)) {
|
|
|
2098 |
return($database_definition);
|
|
|
2099 |
}
|
|
|
2100 |
$this->database_definition = $database_definition;
|
|
|
2101 |
$copy = 0;
|
|
|
2102 |
/*
|
|
|
2103 |
$this->expectError(MDB_ERROR_UNSUPPORTED);
|
|
|
2104 |
$databases = $this->database->listDatabases();
|
|
|
2105 |
$this->popExpect();
|
|
|
2106 |
if((MDB::isError($databases) || (is_array($databases) && in_array($this->database_definition['name'], $databases)))
|
|
|
2107 |
&& $previous_schema_file && file_exists($previous_schema_file))
|
|
|
2108 |
{
|
|
|
2109 |
*/
|
|
|
2110 |
if($previous_schema_file && file_exists($previous_schema_file)) {
|
|
|
2111 |
$previous_definition = $this->parseDatabaseDefinitionFile($previous_schema_file, $variables, 0);
|
|
|
2112 |
if(MDB::isError($previous_definition)) {
|
|
|
2113 |
return($previous_definition);
|
|
|
2114 |
}
|
|
|
2115 |
$changes = $this->_compareDefinitions($previous_definition);
|
|
|
2116 |
if(MDB::isError($changes)) {
|
|
|
2117 |
return($changes);
|
|
|
2118 |
}
|
|
|
2119 |
if(isset($changes) && is_array($changes)) {
|
|
|
2120 |
$result = $this->_alterDatabase($previous_definition, $changes);
|
|
|
2121 |
if(MDB::isError($result)) {
|
|
|
2122 |
return($result);
|
|
|
2123 |
}
|
|
|
2124 |
$copy = 1;
|
|
|
2125 |
if($this->options['debug']) {
|
|
|
2126 |
$result = $this->_debugDatabaseChanges($changes);
|
|
|
2127 |
if(MDB::isError($result)) {
|
|
|
2128 |
return($result);
|
|
|
2129 |
}
|
|
|
2130 |
}
|
|
|
2131 |
}
|
|
|
2132 |
} else {
|
|
|
2133 |
$result = $this->_createDatabase();
|
|
|
2134 |
if(MDB::isError($result)) {
|
|
|
2135 |
return($result);
|
|
|
2136 |
}
|
|
|
2137 |
$copy = 1;
|
|
|
2138 |
}
|
|
|
2139 |
if($copy && $previous_schema_file && !copy($current_schema_file, $previous_schema_file)) {
|
|
|
2140 |
return($this->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
|
|
|
2141 |
'Could not copy the new database definition file to the current file'));
|
|
|
2142 |
}
|
|
|
2143 |
return(MDB_OK);
|
|
|
2144 |
}
|
|
|
2145 |
|
|
|
2146 |
// }}}
|
|
|
2147 |
}
|
|
|
2148 |
?>
|