~ubuntu-branches/ubuntu/maverick/mahara/maverick-updates

« back to all changes in this revision

Viewing changes to htdocs/lib/ddl.php

  • Committer: Bazaar Package Importer
  • Author(s): Nigel McNie
  • Date: 2008-04-29 11:15:39 UTC
  • Revision ID: james.westby@ubuntu.com-20080429111539-b28eqkagavaub2zr
Tags: upstream-1.0.2
ImportĀ upstreamĀ versionĀ 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php // $Id: ddllib.php,v 1.42 2006/10/09 22:28:22 stronk7 Exp $
 
2
/**
 
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
 
4
 * Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
 
5
 *
 
6
 * This program is free software: you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation, either version 3 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 *
 
19
 * @package mahara
 
20
 * @subpackage core
 
21
 * @copyright  (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
 
22
 *
 
23
 * This file incorporates work covered by the following copyright and
 
24
 * permission notice:
 
25
 *
 
26
 *    Moodle - Modular Object-Oriented Dynamic Learning Environment
 
27
 *             http://moodle.com
 
28
 *
 
29
 *    Copyright (C) 2001-3001 Martin Dougiamas        http://dougiamas.com
 
30
 *              (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com
 
31
 *
 
32
 *    This program is free software; you can redistribute it and/or modify
 
33
 *    it under the terms of the GNU General Public License as published by
 
34
 *    the Free Software Foundation; either version 2 of the License, or
 
35
 *    (at your option) any later version.
 
36
 *
 
37
 *    This program is distributed in the hope that it will be useful,
 
38
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
39
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
40
 *    GNU General Public License for more details:
 
41
 *
 
42
 *             http://www.gnu.org/copyleft/gpl.html
 
43
 */
 
44
 
 
45
// Mahara hacks
 
46
$CFG->libdir = get_config('libroot');
 
47
$CFG->prefix = (isset($CFG->dbprefix)) ? $CFG->dbprefix : '';
 
48
if (is_postgres()) {
 
49
    $CFG->dbtype = 'postgres7';
 
50
}
 
51
else if (is_mysql()) {
 
52
    $CFG->dbtype = 'mysql';
 
53
}
 
54
// Mahara hacks end
 
55
 
 
56
 
 
57
// This library includes all the required functions used to handle the DB
 
58
// structure (DDL) independently of the underlying RDBMS in use. All the functions
 
59
// rely on the XMLDBDriver classes to be able to generate the correct SQL
 
60
// syntax needed by each DB.
 
61
//
 
62
// To define any structure to be created we'll use the schema defined
 
63
// by the XMLDB classes, for tables, fields, indexes, keys and other
 
64
// statements instead of direct handling of SQL sentences.
 
65
//
 
66
// This library should be used, exclusively, by the installation and
 
67
// upgrade process of Moodle.
 
68
//
 
69
// For further documentation, visit http://docs.moodle.org/en/DDL_functions
 
70
 
 
71
/// Add required XMLDB constants
 
72
    require_once($CFG->libdir . '/xmldb/classes/XMLDBConstants.php');
 
73
 
 
74
/// Add main XMLDB Generator
 
75
    require_once($CFG->libdir . '/xmldb/classes/generators/XMLDBGenerator.class.php');
 
76
 
 
77
/// Add required XMLDB DB classes
 
78
    require_once($CFG->libdir . '/xmldb/classes/XMLDBObject.class.php');
 
79
    require_once($CFG->libdir . '/xmldb/classes/XMLDBFile.class.php');
 
80
    require_once($CFG->libdir . '/xmldb/classes/XMLDBStructure.class.php');
 
81
    require_once($CFG->libdir . '/xmldb/classes/XMLDBTable.class.php');
 
82
    require_once($CFG->libdir . '/xmldb/classes/XMLDBField.class.php');
 
83
    require_once($CFG->libdir . '/xmldb/classes/XMLDBKey.class.php');
 
84
    require_once($CFG->libdir . '/xmldb/classes/XMLDBIndex.class.php');
 
85
    require_once($CFG->libdir . '/xmldb/classes/XMLDBStatement.class.php');
 
86
 
 
87
/// Based on $CFG->dbtype, add the proper generator class
 
88
    if (!file_exists($CFG->libdir . '/xmldb/classes/generators/' . $CFG->dbtype . '/' . $CFG->dbtype . '.class.php')) {
 
89
        error ('DB Type: ' . $CFG->dbtype . ' not supported by XMLDDB');
 
90
    }
 
91
    require_once($CFG->libdir . '/xmldb/classes/generators/' . $CFG->dbtype . '/' . $CFG->dbtype . '.class.php');
 
92
 
 
93
 
 
94
/// Add other libraries
 
95
    require_once($CFG->libdir . '/xmlize.php');
 
96
/**
 
97
 * Add a new field to a table, or modify an existing one (if oldfield is defined).
 
98
 * Warning: Please be careful on primary keys, as this function will eat auto_increments
 
99
 *
 
100
 * @uses $CFG
 
101
 * @uses $db
 
102
 * @param string $table the name of the table to modify. (Without the prefix.)
 
103
 * @param string $oldfield If changing an existing column, the name of that column.
 
104
 * @param string $field The name of the column at the end of the operation.
 
105
 * @param string $type The type of the column at the end of the operation. TEXT, VARCHAR, CHAR, INTEGER, REAL, or TINYINT
 
106
 * @param string $size The size of that column type. As in VARCHAR($size), or INTEGER($size).
 
107
 * @param string $signed For numeric column types, whether that column is 'signed' or 'unsigned'.
 
108
 * @param string $default The new default value for the column.
 
109
 * @param string $null 'not null', or '' to allow nulls.
 
110
 * @param string $after Which column to insert this one after. Not supported on Postgres.
 
111
 *
 
112
 * @return boolean Wheter the operation succeeded.
 
113
 */
 
114
function table_column($table, $oldfield, $field, $type='integer', $size='10',
 
115
                      $signed='unsigned', $default='0', $null='not null', $after='') {
 
116
    global $CFG, $db, $empty_rs_cache;
 
117
 
 
118
    if (!empty($empty_rs_cache[$table])) {  // Clear the recordset cache because it's out of date
 
119
        unset($empty_rs_cache[$table]);
 
120
    }
 
121
 
 
122
    switch (strtolower($CFG->dbtype)) {
 
123
 
 
124
        case 'mysql':
 
125
        case 'mysqlt':
 
126
 
 
127
            switch (strtolower($type)) {
 
128
                case 'text':
 
129
                    $type = 'TEXT';
 
130
                    $signed = '';
 
131
                    break;
 
132
                case 'integer':
 
133
                    $type = 'INTEGER('. $size .')';
 
134
                    break;
 
135
                case 'varchar':
 
136
                    $type = 'VARCHAR('. $size .')';
 
137
                    $signed = '';
 
138
                    break;
 
139
                case 'char':
 
140
                    $type = 'CHAR('. $size .')';
 
141
                    $signed = '';
 
142
                    break;
 
143
            }
 
144
 
 
145
            if (!empty($oldfield)) {
 
146
                $operation = 'CHANGE '. $oldfield .' '. $field;
 
147
            } else {
 
148
                $operation = 'ADD '. $field;
 
149
            }
 
150
 
 
151
            $default = 'DEFAULT \''. $default .'\'';
 
152
 
 
153
            if (!empty($after)) {
 
154
                $after = 'AFTER `'. $after .'`';
 
155
            }
 
156
 
 
157
            return execute_sql('ALTER TABLE '. $CFG->prefix . $table .' '. $operation .' '. $type .' '. $signed .' '. $default .' '. $null .' '. $after);
 
158
 
 
159
        case 'postgres7':        // From Petri Asikainen
 
160
            //Check db-version
 
161
            $dbinfo = $db->ServerInfo();
 
162
            $dbver = substr($dbinfo['version'],0,3);
 
163
 
 
164
            //to prevent conflicts with reserved words
 
165
            $realfield = '"'. $field .'"';
 
166
            $field = '"'. $field .'_alter_column_tmp"';
 
167
            $oldfield = '"'. $oldfield .'"';
 
168
 
 
169
            switch (strtolower($type)) {
 
170
                case 'tinyint':
 
171
                case 'integer':
 
172
                    if ($size <= 4) {
 
173
                        $type = 'INT2';
 
174
                    }
 
175
                    if ($size <= 10) {
 
176
                        $type = 'INT';
 
177
                    }
 
178
                    if  ($size > 10) {
 
179
                        $type = 'INT8';
 
180
                    }
 
181
                    break;
 
182
                case 'varchar':
 
183
                    $type = 'VARCHAR('. $size .')';
 
184
                    break;
 
185
                case 'char':
 
186
                    $type = 'CHAR('. $size .')';
 
187
                    $signed = '';
 
188
                    break;
 
189
            }
 
190
 
 
191
            $default = '\''. $default .'\'';
 
192
 
 
193
            //After is not implemented in postgesql
 
194
            //if (!empty($after)) {
 
195
            //    $after = "AFTER '$after'";
 
196
            //}
 
197
 
 
198
            //Use transactions
 
199
            db_begin();
 
200
 
 
201
            //Always use temporary column
 
202
            execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ADD COLUMN '. $field .' '. $type);
 
203
            //Add default values
 
204
            execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .'='. $default);
 
205
 
 
206
 
 
207
            if ($dbver >= '7.3') {
 
208
                // modifying 'not null' is posible before 7.3
 
209
                //update default values to table
 
210
                if (strtoupper($null) == 'NOT NULL') {
 
211
                    execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .'='. $default .' WHERE '. $field .' IS NULL');
 
212
                    execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET '. $null);
 
213
                } else {
 
214
                    execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' DROP NOT NULL');
 
215
                }
 
216
            }
 
217
 
 
218
            execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET DEFAULT '. $default);
 
219
 
 
220
            if ( $oldfield != '""' ) {
 
221
 
 
222
                // We are changing the type of a column. This may require doing some casts...
 
223
                $casting = '';
 
224
                $oldtype = column_type($table, $oldfield);
 
225
                $newtype = column_type($table, $field);
 
226
 
 
227
                // Do we need a cast?
 
228
                if($newtype == 'N' && $oldtype == 'C') {
 
229
                    $casting = 'CAST(CAST('.$oldfield.' AS TEXT) AS REAL)';
 
230
                }
 
231
                else if($newtype == 'I' && $oldtype == 'C') {
 
232
                    $casting = 'CAST(CAST('.$oldfield.' AS TEXT) AS INTEGER)';
 
233
                }
 
234
                else {
 
235
                    $casting = $oldfield;
 
236
                }
 
237
 
 
238
                // Run the update query, casting as necessary
 
239
                execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .' = '. $casting);
 
240
                execute_sql('ALTER TABLE  '. $CFG->prefix . $table .' DROP COLUMN '. $oldfield);
 
241
            }
 
242
 
 
243
            execute_sql('ALTER TABLE '. $CFG->prefix . $table .' RENAME COLUMN '. $field .' TO '. $realfield);
 
244
 
 
245
            return db_commit();
 
246
 
 
247
        default:
 
248
            switch (strtolower($type)) {
 
249
                case 'integer':
 
250
                    $type = 'INTEGER';
 
251
                    break;
 
252
                case 'varchar':
 
253
                    $type = 'VARCHAR';
 
254
                    break;
 
255
            }
 
256
 
 
257
            $default = 'DEFAULT \''. $default .'\'';
 
258
 
 
259
            if (!empty($after)) {
 
260
                $after = 'AFTER '. $after;
 
261
            }
 
262
 
 
263
            if (!empty($oldfield)) {
 
264
                execute_sql('ALTER TABLE '. $CFG->prefix . $table .' RENAME COLUMN '. $oldfield .' '. $field);
 
265
            } else {
 
266
                execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ADD COLUMN '. $field .' '. $type);
 
267
            }
 
268
 
 
269
            execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET '. $null);
 
270
            return execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET '. $default);
 
271
    }
 
272
}
 
273
 
 
274
/**
 
275
 * Given one XMLDBTable, check if it exists in DB (true/false)
 
276
 *
 
277
 * @param XMLDBTable table to be searched for
 
278
 * @return boolean true/false
 
279
 */
 
280
function table_exists($table) {
 
281
 
 
282
    global $CFG, $db;
 
283
 
 
284
    $exists = true;
 
285
 
 
286
/// Do this function silenty (to avoid output in install/upgrade process)
 
287
    $olddbdebug = $db->debug;
 
288
    $db->debug = false;
 
289
 
 
290
/// Load the needed generator
 
291
    $classname = 'XMLDB' . $CFG->dbtype;
 
292
    $generator = new $classname();
 
293
    $generator->setPrefix($CFG->prefix);
 
294
/// Calculate the name of the table
 
295
    $tablename = $generator->getTableName($table, false);
 
296
 
 
297
/// Search such tablename in DB
 
298
    $metatables = $db->MetaTables();
 
299
    $metatables = array_flip($metatables);
 
300
    $metatables = array_change_key_case($metatables, CASE_LOWER);
 
301
    if (!array_key_exists($tablename,  $metatables)) {
 
302
        $exists = false;
 
303
    }
 
304
 
 
305
/// Re-set original debug 
 
306
    $db->debug = $olddbdebug;
 
307
 
 
308
    return $exists;
 
309
}
 
310
 
 
311
/**
 
312
 * Given one XMLDBField, check if it exists in DB (true/false)
 
313
 *
 
314
 * @uses, $db
 
315
 * @param XMLDBTable the table
 
316
 * @param XMLDBField the field to be searched for
 
317
 * @return boolean true/false
 
318
 */
 
319
function field_exists($table, $field) {
 
320
 
 
321
    global $CFG, $db;
 
322
 
 
323
    $exists = true;
 
324
 
 
325
/// Do this function silenty (to avoid output in install/upgrade process)
 
326
    $olddbdebug = $db->debug;
 
327
    $db->debug = false;
 
328
 
 
329
/// Check the table exists
 
330
    if (!table_exists($table)) {
 
331
        $db->debug = $olddbdebug; //Re-set original $db->debug
 
332
        return false;
 
333
    }
 
334
 
 
335
/// Load the needed generator
 
336
    $classname = 'XMLDB' . $CFG->dbtype;
 
337
    $generator = new $classname();
 
338
    $generator->setPrefix($CFG->prefix);
 
339
/// Calculate the name of the table
 
340
    $tablename = $generator->getTableName($table, false);
 
341
 
 
342
/// Get list of fields in table
 
343
    $fields = null;
 
344
    if ($fields = $db->MetaColumns($tablename)) {
 
345
        $fields = array_change_key_case($fields, CASE_LOWER);
 
346
    }
 
347
 
 
348
    if (!array_key_exists($field->getName(),  $fields)) {
 
349
        $exists = false;
 
350
    }
 
351
 
 
352
/// Re-set original debug 
 
353
    $db->debug = $olddbdebug;
 
354
 
 
355
    return $exists;
 
356
}
 
357
 
 
358
/**
 
359
 * Given one XMLDBIndex, check if it exists in DB (true/false)
 
360
 *
 
361
 * @uses, $db
 
362
 * @param XMLDBTable the table
 
363
 * @param XMLDBIndex the index to be searched for
 
364
 * @return boolean true/false
 
365
 */
 
366
function index_exists($table, $index) {
 
367
 
 
368
    global $CFG, $db;
 
369
 
 
370
    $exists = true;
 
371
 
 
372
/// Do this function silenty (to avoid output in install/upgrade process)
 
373
    $olddbdebug = $db->debug;
 
374
    $db->debug = false;
 
375
 
 
376
/// Wrap over find_index_name to see if the index exists
 
377
    if (!find_index_name($table, $index)) {
 
378
        $exists = false;
 
379
    }
 
380
 
 
381
/// Re-set original debug 
 
382
    $db->debug = $olddbdebug;
 
383
 
 
384
    return $exists;
 
385
}
 
386
 
 
387
/**
 
388
 * This function IS NOT IMPLEMENTED. ONCE WE'LL BE USING RELATIONAL
 
389
 * INTEGRITY IT WILL BECOME MORE USEFUL. FOR NOW, JUST CALCULATE "OFFICIAL"
 
390
 * KEY NAMES WITHOUT ACCESSING TO DB AT ALL.
 
391
 * Given one XMLDBKey, the function returns the name of the key in DB (if exists)
 
392
 * of false if it doesn't exist
 
393
 *
 
394
 * @uses, $db
 
395
 * @param XMLDBTable the table to be searched
 
396
 * @param XMLDBKey the key to be searched
 
397
 * @return string key name of false
 
398
 */
 
399
function find_key_name($table, $xmldb_key) {
 
400
 
 
401
    global $CFG, $db;
 
402
 
 
403
/// Extract key columns
 
404
    $keycolumns = $xmldb_key->getFields();
 
405
 
 
406
/// Get list of keys in table
 
407
/// first primaries (we aren't going to use this now, because the MetaPrimaryKeys is awful)
 
408
    ///TODO: To implement when we advance in relational integrity
 
409
/// then uniques (note that Moodle, for now, shouldn't have any UNIQUE KEY for now, but unique indexes)
 
410
    ///TODO: To implement when we advance in relational integrity (note that AdoDB hasn't any MetaXXX for this.
 
411
/// then foreign (note that Moodle, for now, shouldn't have any FOREIGN KEY for now, but indexes)
 
412
    ///TODO: To implement when we advance in relational integrity (note that AdoDB has one MetaForeignKeys()
 
413
    ///but it's far from perfect.
 
414
/// TODO: To create the proper functions inside each generator to retrieve all the needed KEY info (name
 
415
///       columns, reftable and refcolumns
 
416
 
 
417
/// So all we do is to return the official name of the requested key without any confirmation!)
 
418
    $classname = 'XMLDB' . $CFG->dbtype;
 
419
    $generator = new $classname();
 
420
    $generator->setPrefix($CFG->prefix);
 
421
/// One exception, harcoded primary constraint names
 
422
    if ($generator->primary_key_name && $xmldb_key->getType() == XMLDB_KEY_PRIMARY) {
 
423
        return $generator->primary_key_name;
 
424
    } else {
 
425
    /// Calculate the name suffix
 
426
        switch ($xmldb_key->getType()) {
 
427
            case XMLDB_KEY_PRIMARY:
 
428
                $suffix = 'pk';
 
429
                break;
 
430
            case XMLDB_KEY_UNIQUE:
 
431
                $suffix = 'uk';
 
432
                break;
 
433
            case XMLDB_KEY_FOREIGN_UNIQUE:
 
434
            case XMLDB_KEY_FOREIGN:
 
435
                $suffix = 'fk';
 
436
                break;
 
437
        }
 
438
    /// And simply, return the oficial name
 
439
        return $generator->getNameForObject($table->getName(), implode(', ', $xmldb_key->getFields()), $suffix);
 
440
    }
 
441
}
 
442
 
 
443
/**
 
444
 * Given one XMLDBIndex, the function returns the name of the index in DB (if exists)
 
445
 * of false if it doesn't exist
 
446
 *
 
447
 * @uses, $db
 
448
 * @param XMLDBTable the table to be searched
 
449
 * @param XMLDBIndex the index to be searched
 
450
 * @return string index name of false
 
451
 */
 
452
function find_index_name($table, $index) {
 
453
 
 
454
    global $CFG, $db;
 
455
 
 
456
/// Do this function silenty (to avoid output in install/upgrade process)
 
457
    $olddbdebug = $db->debug;
 
458
    $db->debug = false;
 
459
 
 
460
/// Extract index columns
 
461
    $indcolumns = $index->getFields();
 
462
 
 
463
/// Check the table exists
 
464
    if (!table_exists($table)) {
 
465
        $db->debug = $olddbdebug; //Re-set original $db->debug
 
466
        return false;
 
467
    }
 
468
 
 
469
/// Load the needed generator
 
470
    $classname = 'XMLDB' . $CFG->dbtype;
 
471
    $generator = new $classname();
 
472
    $generator->setPrefix($CFG->prefix);
 
473
/// Calculate the name of the table
 
474
    $tablename = $generator->getTableName($table, false);
 
475
 
 
476
/// Get list of indexes in table
 
477
    $indexes = null;
 
478
    if ($indexes = $db->MetaIndexes($tablename)) {
 
479
        $indexes = array_change_key_case($indexes, CASE_LOWER);
 
480
    }
 
481
 
 
482
/// Iterate over them looking for columns coincidence
 
483
    if ($indexes) {
 
484
        foreach ($indexes as $indexname => $index) {
 
485
            $columns = $index['columns'];
 
486
        /// Lower case column names
 
487
            $columns = array_flip($columns);
 
488
            $columns = array_change_key_case($columns, CASE_LOWER);
 
489
            $columns = array_flip($columns);
 
490
        /// Check if index matchs queried index
 
491
            $diferences = array_merge(array_diff($columns, $indcolumns), array_diff($indcolumns, $columns));
 
492
        /// If no diferences, we have find the index
 
493
            if (empty($diferences)) {
 
494
                $db->debug = $olddbdebug; //Re-set original $db->debug
 
495
                return $indexname;
 
496
            }
 
497
        }
 
498
    }
 
499
/// Arriving here, index not found
 
500
    $db->debug = $olddbdebug; //Re-set original $db->debug
 
501
    return false;
 
502
}
 
503
 
 
504
/**
 
505
 * Given one XMLDBTable, the function returns the name of its sequence in DB (if exists)
 
506
 * of false if it doesn't exist
 
507
 *
 
508
 * @param XMLDBTable the table to be searched
 
509
 * @return string sequence name of false
 
510
 */
 
511
function find_sequence_name($table) {
 
512
 
 
513
    global $CFG, $db;
 
514
 
 
515
    $sequencename = false;
 
516
 
 
517
/// Do this function silenty (to avoid output in install/upgrade process)
 
518
    $olddbdebug = $db->debug;
 
519
    $db->debug = false;
 
520
 
 
521
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
522
        $db->debug = $olddbdebug; //Re-set original $db->debug
 
523
        return false;
 
524
    }
 
525
 
 
526
/// Check table exists
 
527
    if (!table_exists($table)) {
 
528
        debugging('Table ' . $table->getName() . ' do not exist. Sequence not found', DEBUG_DEVELOPER);
 
529
        $db->debug = $olddbdebug; //Re-set original $db->debug
 
530
        return false; //Table doesn't exist, nothing to do
 
531
    }
 
532
 
 
533
    $sequencename = $table->getSequenceFromDB($CFG->dbtype, $CFG->prefix);
 
534
 
 
535
    $db->debug = $olddbdebug; //Re-set original $db->debug
 
536
    return $sequencename;
 
537
}
 
538
 
 
539
/**
 
540
 * This function will load one entire XMLDB file, generating all the needed
 
541
 * SQL statements, specific for each RDBMS ($CFG->dbtype) and, finally, it
 
542
 * will execute all those statements against the DB.
 
543
 *
 
544
 * @uses $CFG, $db
 
545
 * @param $file full path to the XML file to be used
 
546
 * @return boolean (true on success, false on error)
 
547
 */
 
548
function install_from_xmldb_file($file) {
 
549
 
 
550
    global $CFG, $db;
 
551
 
 
552
    $status = true;
 
553
    $xmldb_file = new XMLDBFile($file);
 
554
 
 
555
    if (!$xmldb_file->fileExists()) {
 
556
        return false;
 
557
    }
 
558
 
 
559
    $loaded = $xmldb_file->loadXMLStructure();
 
560
    if (!$loaded || !$xmldb_file->isLoaded()) {
 
561
        return false;
 
562
    }
 
563
 
 
564
    $structure = $xmldb_file->getStructure();
 
565
 
 
566
    if (!$sqlarr = $structure->getCreateStructureSQL($CFG->dbtype, $CFG->prefix, false)) {
 
567
        return true; //Empty array = nothing to do = no error
 
568
    }
 
569
 
 
570
    $status = $status && execute_sql_arr($sqlarr);
 
571
    return $status;
 
572
}
 
573
 
 
574
/**
 
575
 * This function will create the table passed as argument with all its
 
576
 * fields/keys/indexes/sequences, everything based in the XMLDB object
 
577
 *
 
578
 * @uses $CFG, $db
 
579
 * @param XMLDBTable table object (full specs are required)
 
580
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
581
 * @param boolean feedback to specify to show status info (true) or not (false)
 
582
 * @return boolean true on success, false on error
 
583
 */
 
584
function create_table($table, $continue=true, $feedback=true) {
 
585
 
 
586
    global $CFG, $db;
 
587
 
 
588
    $status = true;
 
589
 
 
590
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
591
        return false;
 
592
    }
 
593
 
 
594
/// Check table doesn't exist
 
595
    if (table_exists($table)) {
 
596
        debugging('Table ' . $table->getName() . ' exists. Create skipped', DEBUG_DEVELOPER);
 
597
        return true; //Table exists, nothing to do
 
598
    }
 
599
 
 
600
    if(!$sqlarr = $table->getCreateTableSQL($CFG->dbtype, $CFG->prefix, false)) {
 
601
        return true; //Empty array = nothing to do = no error
 
602
    }
 
603
 
 
604
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
605
}
 
606
 
 
607
/**
 
608
 * This function will drop the table passed as argument
 
609
 * and all the associated objects (keys, indexes, constaints, sequences, triggers)
 
610
 * will be dropped too.
 
611
 *
 
612
 * @uses $CFG, $db
 
613
 * @param XMLDBTable table object (just the name is mandatory)
 
614
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
615
 * @param boolean feedback to specify to show status info (true) or not (false)
 
616
 * @return boolean true on success, false on error
 
617
 */
 
618
function drop_table($table, $continue=true, $feedback=true) {
 
619
 
 
620
    global $CFG, $db;
 
621
 
 
622
    $status = true;
 
623
 
 
624
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
625
        return false;
 
626
    }
 
627
 
 
628
/// Check table exists
 
629
    if (!table_exists($table)) {
 
630
        debugging('Table ' . $table->getName() . ' do not exist. Delete skipped', DEBUG_DEVELOPER);
 
631
        return true; //Table don't exist, nothing to do
 
632
    }
 
633
 
 
634
    if(!$sqlarr = $table->getDropTableSQL($CFG->dbtype, $CFG->prefix, false)) {
 
635
        return true; //Empty array = nothing to do = no error
 
636
    }
 
637
 
 
638
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
639
}
 
640
 
 
641
/**
 
642
 * This function will rename the table passed as argument
 
643
 * Before renaming the index, the function will check it exists
 
644
 *
 
645
 * @uses $CFG, $db
 
646
 * @param XMLDBTable table object (just the name is mandatory)
 
647
 * @param string new name of the index
 
648
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
649
 * @param boolean feedback to specify to show status info (true) or not (false)
 
650
 * @return boolean true on success, false on error
 
651
 */
 
652
function rename_table($table, $newname, $continue=true, $feedback=true) {
 
653
 
 
654
    global $CFG, $db;
 
655
 
 
656
    $status = true;
 
657
 
 
658
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
659
        return false;
 
660
    }
 
661
 
 
662
/// Check table exists
 
663
    if (!table_exists($table)) {
 
664
        debugging('Table ' . $table->getName() . ' do not exist. Rename skipped', DEBUG_DEVELOPER);
 
665
        return true; //Table doesn't exist, nothing to do
 
666
    }
 
667
 
 
668
/// Check newname isn't empty
 
669
    if (!$newname) {
 
670
        debugging('New name for table ' . $index->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
 
671
        return true; //Table doesn't exist, nothing to do
 
672
    }
 
673
 
 
674
    if(!$sqlarr = $table->getRenameTableSQL($CFG->dbtype, $CFG->prefix, $newname, false)) {
 
675
        return true; //Empty array = nothing to do = no error
 
676
    }
 
677
 
 
678
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
679
}
 
680
 
 
681
/**
 
682
 * This function will add the field to the table passed as arguments
 
683
 *
 
684
 * @uses $CFG, $db
 
685
 * @param XMLDBTable table object (just the name is mandatory)
 
686
 * @param XMLDBField field object (full specs are required)
 
687
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
688
 * @param boolean feedback to specify to show status info (true) or not (false)
 
689
 * @return boolean true on success, false on error
 
690
 */
 
691
function add_field($table, $field, $continue=true, $feedback=true) {
 
692
 
 
693
    global $CFG, $db;
 
694
 
 
695
    $status = true;
 
696
 
 
697
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
698
        return false;
 
699
    }
 
700
    if (strtolower(get_class($field)) != 'xmldbfield') {
 
701
        return false;
 
702
    }
 
703
 
 
704
/// Check the field doesn't exist
 
705
    if (field_exists($table, $field)) {
 
706
        debugging('Field ' . $field->getName() . ' exists. Create skipped', DEBUG_DEVELOPER);
 
707
        return true;
 
708
    }
 
709
 
 
710
    if(!$sqlarr = $table->getAddFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
 
711
        return true; //Empty array = nothing to do = no error
 
712
    }
 
713
 
 
714
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
715
}
 
716
 
 
717
/**
 
718
 * This function will drop the field from the table passed as arguments
 
719
 *
 
720
 * @uses $CFG, $db
 
721
 * @param XMLDBTable table object (just the name is mandatory)
 
722
 * @param XMLDBField field object (just the name is mandatory)
 
723
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
724
 * @param boolean feedback to specify to show status info (true) or not (false)
 
725
 * @return boolean true on success, false on error
 
726
 */
 
727
function drop_field($table, $field, $continue=true, $feedback=true) {
 
728
 
 
729
    global $CFG, $db;
 
730
 
 
731
    $status = true;
 
732
 
 
733
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
734
        return false;
 
735
    }
 
736
    if (strtolower(get_class($field)) != 'xmldbfield') {
 
737
        return false;
 
738
    }
 
739
 
 
740
/// Check the field exists
 
741
    if (!field_exists($table, $field)) {
 
742
        debugging('Field ' . $field->getName() . ' do not exist. Delete skipped', DEBUG_DEVELOPER);
 
743
        return true;
 
744
    }
 
745
 
 
746
    if(!$sqlarr = $table->getDropFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
 
747
        return true; //Empty array = nothing to do = no error
 
748
    }
 
749
 
 
750
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
751
}
 
752
 
 
753
/**
 
754
 * This function will change the type of the field in the table passed as arguments
 
755
 *
 
756
 * @uses $CFG, $db
 
757
 * @param XMLDBTable table object (just the name is mandatory)
 
758
 * @param XMLDBField field object (full specs are required)
 
759
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
760
 * @param boolean feedback to specify to show status info (true) or not (false)
 
761
 * @return boolean true on success, false on error
 
762
 */
 
763
function change_field_type($table, $field, $continue=true, $feedback=true) {
 
764
 
 
765
    global $CFG, $db;
 
766
 
 
767
    $status = true;
 
768
 
 
769
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
770
        return false;
 
771
    }
 
772
    if (strtolower(get_class($field)) != 'xmldbfield') {
 
773
        return false;
 
774
    }
 
775
 
 
776
    if(!$sqlarr = $table->getAlterFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
 
777
        return true; //Empty array = nothing to do = no error
 
778
    }
 
779
 
 
780
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
781
}
 
782
 
 
783
/**
 
784
 * This function will change the precision of the field in the table passed as arguments
 
785
 *
 
786
 * @uses $CFG, $db
 
787
 * @param XMLDBTable table object (just the name is mandatory)
 
788
 * @param XMLDBField field object (full specs are required)
 
789
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
790
 * @param boolean feedback to specify to show status info (true) or not (false)
 
791
 * @return boolean true on success, false on error
 
792
 */
 
793
function change_field_precision($table, $field, $continue=true, $feedback=true) {
 
794
 
 
795
/// Just a wrapper over change_field_type. Does exactly the same processing
 
796
    return change_field_type($table, $field, $continue, $feedback);
 
797
}
 
798
 
 
799
/**
 
800
 * This function will change the unsigned/signed of the field in the table passed as arguments
 
801
 *
 
802
 * @uses $CFG, $db
 
803
 * @param XMLDBTable table object (just the name is mandatory)
 
804
 * @param XMLDBField field object (full specs are required)
 
805
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
806
 * @param boolean feedback to specify to show status info (true) or not (false)
 
807
 * @return boolean true on success, false on error
 
808
 */
 
809
function change_field_unsigned($table, $field, $continue=true, $feedback=true) {
 
810
 
 
811
/// Just a wrapper over change_field_type. Does exactly the same processing
 
812
    return change_field_type($table, $field, $continue, $feedback);
 
813
}
 
814
 
 
815
/**
 
816
 * This function will change the nullability of the field in the table passed as arguments
 
817
 *
 
818
 * @uses $CFG, $db
 
819
 * @param XMLDBTable table object (just the name is mandatory)
 
820
 * @param XMLDBField field object (full specs are required)
 
821
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
822
 * @param boolean feedback to specify to show status info (true) or not (false)
 
823
 * @return boolean true on success, false on error
 
824
 */
 
825
function change_field_notnull($table, $field, $continue=true, $feedback=true) {
 
826
 
 
827
/// Just a wrapper over change_field_type. Does exactly the same processing
 
828
    return change_field_type($table, $field, $continue, $feedback);
 
829
}
 
830
 
 
831
/**
 
832
 * This function will change the enum status of the field in the table passed as arguments
 
833
 *
 
834
 * @uses $CFG, $db
 
835
 * @param XMLDBTable table object (just the name is mandatory)
 
836
 * @param XMLDBField field object (full specs are required)
 
837
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
838
 * @param boolean feedback to specify to show status info (true) or not (false)
 
839
 * @return boolean true on success, false on error
 
840
 */
 
841
function change_field_enum($table, $field, $continue=true, $feedback=true) {
 
842
 
 
843
    global $CFG, $db;
 
844
 
 
845
    $status = true;
 
846
 
 
847
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
848
        return false;
 
849
    }
 
850
    if (strtolower(get_class($field)) != 'xmldbfield') {
 
851
        return false;
 
852
    }
 
853
 
 
854
    if(!$sqlarr = $table->getModifyEnumSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
 
855
        return true; //Empty array = nothing to do = no error
 
856
    }
 
857
 
 
858
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
859
}
 
860
/**
 
861
 * This function will change the default of the field in the table passed as arguments
 
862
 * One null value in the default field means delete the default
 
863
 *
 
864
 * @uses $CFG, $db
 
865
 * @param XMLDBTable table object (just the name is mandatory)
 
866
 * @param XMLDBField field object (full specs are required)
 
867
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
868
 * @param boolean feedback to specify to show status info (true) or not (false)
 
869
 * @return boolean true on success, false on error
 
870
 */
 
871
function change_field_default($table, $field, $continue=true, $feedback=true) {
 
872
 
 
873
    global $CFG, $db;
 
874
 
 
875
    $status = true;
 
876
 
 
877
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
878
        return false;
 
879
    }
 
880
    if (strtolower(get_class($field)) != 'xmldbfield') {
 
881
        return false;
 
882
    }
 
883
 
 
884
    if(!$sqlarr = $table->getModifyDefaultSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
 
885
        return true; //Empty array = nothing to do = no error
 
886
    }
 
887
 
 
888
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
889
}
 
890
 
 
891
/**
 
892
 * This function will rename the field in the table passed as arguments
 
893
 * Before renaming the field, the function will check it exists
 
894
 *
 
895
 * @uses $CFG, $db
 
896
 * @param XMLDBTable table object (just the name is mandatory)
 
897
 * @param XMLDBField index object (full specs are required)
 
898
 * @param string new name of the field
 
899
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
900
 * @param boolean feedback to specify to show status info (true) or not (false)
 
901
 * @return boolean true on success, false on error
 
902
 */
 
903
function rename_field($table, $field, $newname, $continue=true, $feedback=true) {
 
904
 
 
905
    global $CFG, $db;
 
906
 
 
907
    $status = true;
 
908
 
 
909
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
910
        return false;
 
911
    }
 
912
    if (strtolower(get_class($field)) != 'xmldbfield') {
 
913
        return false;
 
914
    }
 
915
 
 
916
/// Check field isn't id. Renaming over that field is not allowed
 
917
    if ($field->getName() == 'id') {
 
918
        debugging('Field ' . $field->getName() . ' cannot be renamed. Rename skipped', DEBUG_DEVELOPER);
 
919
        return true; //Field is "id", nothing to do
 
920
    }
 
921
 
 
922
/// Check field exists
 
923
    if (!field_exists($table, $field)) {
 
924
        debugging('Field ' . $field->getName() . ' do not exist. Rename skipped', DEBUG_DEVELOPER);
 
925
        return true; //Field doesn't exist, nothing to do
 
926
    }
 
927
 
 
928
/// Check newname isn't empty
 
929
    if (!$newname) {
 
930
        debugging('New name for field ' . $field->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
 
931
        return true; //Field doesn't exist, nothing to do
 
932
    }
 
933
 
 
934
    if(!$sqlarr = $table->getRenameFieldSQL($CFG->dbtype, $CFG->prefix, $field, $newname, false)) {
 
935
        return true; //Empty array = nothing to do = no error
 
936
    }
 
937
 
 
938
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
939
}
 
940
 
 
941
/**
 
942
 * This function will create the key in the table passed as arguments
 
943
 *
 
944
 * @uses $CFG, $db
 
945
 * @param XMLDBTable table object (just the name is mandatory)
 
946
 * @param XMLDBKey index object (full specs are required)
 
947
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
948
 * @param boolean feedback to specify to show status info (true) or not (false)
 
949
 * @return boolean true on success, false on error
 
950
 */
 
951
function add_key($table, $key, $continue=true, $feedback=true) {
 
952
 
 
953
    global $CFG, $db;
 
954
 
 
955
    $status = true;
 
956
 
 
957
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
958
        return false;
 
959
    }
 
960
    if (strtolower(get_class($key)) != 'xmldbkey') {
 
961
        return false;
 
962
    }
 
963
    if ($key->getType() == XMLDB_KEY_PRIMARY) { // Prevent PRIMARY to be added (only in create table, being serious  :-P)
 
964
        //debugging('Primary Keys can be added at table create time only', DEBUG_DEVELOPER);
 
965
        //return true;
 
966
    }
 
967
 
 
968
    if(!$sqlarr = $table->getAddKeySQL($CFG->dbtype, $CFG->prefix, $key, false)) {
 
969
        return true; //Empty array = nothing to do = no error
 
970
    }
 
971
 
 
972
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
973
}
 
974
 
 
975
/**
 
976
 * This function will drop the key in the table passed as arguments
 
977
 *
 
978
 * @uses $CFG, $db
 
979
 * @param XMLDBTable table object (just the name is mandatory)
 
980
 * @param XMLDBKey key object (full specs are required)
 
981
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
982
 * @param boolean feedback to specify to show status info (true) or not (false)
 
983
 * @return boolean true on success, false on error
 
984
 */
 
985
function drop_key($table, $key, $continue=true, $feedback=true) {
 
986
 
 
987
    global $CFG, $db;
 
988
 
 
989
    $status = true;
 
990
 
 
991
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
992
        return false;
 
993
    }
 
994
    if (strtolower(get_class($key)) != 'xmldbkey') {
 
995
        return false;
 
996
    }
 
997
    if ($key->getType() == XMLDB_KEY_PRIMARY) { // Prevent PRIMARY to be dropped (only in drop table, being serious  :-P)
 
998
//        debugging('Primary Keys can be deleted at table drop time only', DEBUG_DEVELOPER);
 
999
//        return true;
 
1000
    }
 
1001
 
 
1002
    if(!$sqlarr = $table->getDropKeySQL($CFG->dbtype, $CFG->prefix, $key, false)) {
 
1003
        return true; //Empty array = nothing to do = no error
 
1004
    }
 
1005
 
 
1006
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
1007
}
 
1008
 
 
1009
/**
 
1010
 * This function will rename the key in the table passed as arguments
 
1011
 * Experimental. Shouldn't be used at all in normal installation/upgrade!
 
1012
 *
 
1013
 * @uses $CFG, $db
 
1014
 * @param XMLDBTable table object (just the name is mandatory)
 
1015
 * @param XMLDBKey key object (full specs are required)
 
1016
 * @param string new name of the key
 
1017
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
1018
 * @param boolean feedback to specify to show status info (true) or not (false)
 
1019
 * @return boolean true on success, false on error
 
1020
 */
 
1021
function rename_key($table, $key, $newname, $continue=true, $feedback=true) {
 
1022
 
 
1023
    global $CFG, $db;
 
1024
 
 
1025
    debugging('rename_key() is one experimental feature. You must not use it in production!', DEBUG_DEVELOPER);
 
1026
 
 
1027
    $status = true;
 
1028
 
 
1029
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
1030
        return false;
 
1031
    }
 
1032
    if (strtolower(get_class($key)) != 'xmldbkey') {
 
1033
        return false;
 
1034
    }
 
1035
 
 
1036
/// Check newname isn't empty
 
1037
    if (!$newname) {
 
1038
        debugging('New name for key ' . $key->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
 
1039
        return true; //Key doesn't exist, nothing to do
 
1040
    }
 
1041
 
 
1042
    if(!$sqlarr = $table->getRenameKeySQL($CFG->dbtype, $CFG->prefix, $key, $newname, false)) {
 
1043
        debugging('Some DBs do not support key renaming (MySQL, PostgreSQL, MsSQL). Rename skipped', DEBUG_DEVELOPER);
 
1044
        return true; //Empty array = nothing to do = no error
 
1045
    }
 
1046
 
 
1047
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
1048
}
 
1049
 
 
1050
/**
 
1051
 * This function will create the index in the table passed as arguments
 
1052
 * Before creating the index, the function will check it doesn't exists
 
1053
 *
 
1054
 * @uses $CFG, $db
 
1055
 * @param XMLDBTable table object (just the name is mandatory)
 
1056
 * @param XMLDBIndex index object (full specs are required)
 
1057
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
1058
 * @param boolean feedback to specify to show status info (true) or not (false)
 
1059
 * @return boolean true on success, false on error
 
1060
 */
 
1061
function add_index($table, $index, $continue=true, $feedback=true) {
 
1062
 
 
1063
    global $CFG, $db;
 
1064
 
 
1065
    $status = true;
 
1066
 
 
1067
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
1068
        return false;
 
1069
    }
 
1070
    if (strtolower(get_class($index)) != 'xmldbindex') {
 
1071
        return false;
 
1072
    }
 
1073
 
 
1074
/// Check index doesn't exist
 
1075
    if (index_exists($table, $index)) {
 
1076
        debugging('Index ' . $index->getName() . ' exists. Create skipped', DEBUG_DEVELOPER);
 
1077
        return true; //Index exists, nothing to do
 
1078
    }
 
1079
 
 
1080
    if(!$sqlarr = $table->getAddIndexSQL($CFG->dbtype, $CFG->prefix, $index, false)) {
 
1081
        return true; //Empty array = nothing to do = no error
 
1082
    }
 
1083
 
 
1084
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
1085
}
 
1086
 
 
1087
/**
 
1088
 * This function will drop the index in the table passed as arguments
 
1089
 * Before dropping the index, the function will check it exists
 
1090
 *
 
1091
 * @uses $CFG, $db
 
1092
 * @param XMLDBTable table object (just the name is mandatory)
 
1093
 * @param XMLDBIndex index object (full specs are required)
 
1094
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
1095
 * @param boolean feedback to specify to show status info (true) or not (false)
 
1096
 * @return boolean true on success, false on error
 
1097
 */
 
1098
function drop_index($table, $index, $continue=true, $feedback=true) {
 
1099
 
 
1100
    global $CFG, $db;
 
1101
 
 
1102
    $status = true;
 
1103
 
 
1104
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
1105
        return false;
 
1106
    }
 
1107
    if (strtolower(get_class($index)) != 'xmldbindex') {
 
1108
        return false;
 
1109
    }
 
1110
 
 
1111
/// Check index exists
 
1112
    if (!index_exists($table, $index)) {
 
1113
        debugging('Index ' . $index->getName() . ' do not exist. Delete skipped', DEBUG_DEVELOPER);
 
1114
        return true; //Index doesn't exist, nothing to do
 
1115
    }
 
1116
 
 
1117
    if(!$sqlarr = $table->getDropIndexSQL($CFG->dbtype, $CFG->prefix, $index, false)) {
 
1118
        return true; //Empty array = nothing to do = no error
 
1119
    }
 
1120
 
 
1121
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
1122
}
 
1123
 
 
1124
/**
 
1125
 * This function will rename the index in the table passed as arguments
 
1126
 * Before renaming the index, the function will check it exists
 
1127
 * Experimental. Shouldn't be used at all!
 
1128
 *
 
1129
 * @uses $CFG, $db
 
1130
 * @param XMLDBTable table object (just the name is mandatory)
 
1131
 * @param XMLDBIndex index object (full specs are required)
 
1132
 * @param string new name of the index
 
1133
 * @param boolean continue to specify if must continue on error (true) or stop (false)
 
1134
 * @param boolean feedback to specify to show status info (true) or not (false)
 
1135
 * @return boolean true on success, false on error
 
1136
 */
 
1137
function rename_index($table, $index, $newname, $continue=true, $feedback=true) {
 
1138
 
 
1139
    global $CFG, $db;
 
1140
 
 
1141
    debugging('rename_index() is one experimental feature. You must not use it in production!', DEBUG_DEVELOPER);
 
1142
 
 
1143
    $status = true;
 
1144
 
 
1145
    if (strtolower(get_class($table)) != 'xmldbtable') {
 
1146
        return false;
 
1147
    }
 
1148
    if (strtolower(get_class($index)) != 'xmldbindex') {
 
1149
        return false;
 
1150
    }
 
1151
 
 
1152
/// Check index exists
 
1153
    if (!index_exists($table, $index)) {
 
1154
        debugging('Index ' . $index->getName() . ' do not exist. Rename skipped', DEBUG_DEVELOPER);
 
1155
        return true; //Index doesn't exist, nothing to do
 
1156
    }
 
1157
 
 
1158
/// Check newname isn't empty
 
1159
    if (!$newname) {
 
1160
        debugging('New name for index ' . $index->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
 
1161
        return true; //Index doesn't exist, nothing to do
 
1162
    }
 
1163
 
 
1164
    if(!$sqlarr = $table->getRenameIndexSQL($CFG->dbtype, $CFG->prefix, $index, $newname, false)) {
 
1165
        debugging('Some DBs do not support index renaming (MySQL). Rename skipped', DEBUG_DEVELOPER);
 
1166
        return true; //Empty array = nothing to do = no error
 
1167
    }
 
1168
 
 
1169
    return execute_sql_arr($sqlarr, $continue, $feedback);
 
1170
}
 
1171
 
 
1172
?>