1
<?php // $Id: ddllib.php,v 1.42 2006/10/09 22:28:22 stronk7 Exp $
3
* Mahara: Electronic portfolio, weblog, resume builder and social networking
4
* Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
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.
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.
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/>.
21
* @copyright (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
23
* This file incorporates work covered by the following copyright and
26
* Moodle - Modular Object-Oriented Dynamic Learning Environment
29
* Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com
30
* (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com
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.
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:
42
* http://www.gnu.org/copyleft/gpl.html
46
$CFG->libdir = get_config('libroot');
47
$CFG->prefix = (isset($CFG->dbprefix)) ? $CFG->dbprefix : '';
49
$CFG->dbtype = 'postgres7';
51
else if (is_mysql()) {
52
$CFG->dbtype = 'mysql';
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.
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.
66
// This library should be used, exclusively, by the installation and
67
// upgrade process of Moodle.
69
// For further documentation, visit http://docs.moodle.org/en/DDL_functions
71
/// Add required XMLDB constants
72
require_once($CFG->libdir . '/xmldb/classes/XMLDBConstants.php');
74
/// Add main XMLDB Generator
75
require_once($CFG->libdir . '/xmldb/classes/generators/XMLDBGenerator.class.php');
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');
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');
91
require_once($CFG->libdir . '/xmldb/classes/generators/' . $CFG->dbtype . '/' . $CFG->dbtype . '.class.php');
94
/// Add other libraries
95
require_once($CFG->libdir . '/xmlize.php');
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
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.
112
* @return boolean Wheter the operation succeeded.
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;
118
if (!empty($empty_rs_cache[$table])) { // Clear the recordset cache because it's out of date
119
unset($empty_rs_cache[$table]);
122
switch (strtolower($CFG->dbtype)) {
127
switch (strtolower($type)) {
133
$type = 'INTEGER('. $size .')';
136
$type = 'VARCHAR('. $size .')';
140
$type = 'CHAR('. $size .')';
145
if (!empty($oldfield)) {
146
$operation = 'CHANGE '. $oldfield .' '. $field;
148
$operation = 'ADD '. $field;
151
$default = 'DEFAULT \''. $default .'\'';
153
if (!empty($after)) {
154
$after = 'AFTER `'. $after .'`';
157
return execute_sql('ALTER TABLE '. $CFG->prefix . $table .' '. $operation .' '. $type .' '. $signed .' '. $default .' '. $null .' '. $after);
159
case 'postgres7': // From Petri Asikainen
161
$dbinfo = $db->ServerInfo();
162
$dbver = substr($dbinfo['version'],0,3);
164
//to prevent conflicts with reserved words
165
$realfield = '"'. $field .'"';
166
$field = '"'. $field .'_alter_column_tmp"';
167
$oldfield = '"'. $oldfield .'"';
169
switch (strtolower($type)) {
183
$type = 'VARCHAR('. $size .')';
186
$type = 'CHAR('. $size .')';
191
$default = '\''. $default .'\'';
193
//After is not implemented in postgesql
194
//if (!empty($after)) {
195
// $after = "AFTER '$after'";
201
//Always use temporary column
202
execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ADD COLUMN '. $field .' '. $type);
204
execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .'='. $default);
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);
214
execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' DROP NOT NULL');
218
execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET DEFAULT '. $default);
220
if ( $oldfield != '""' ) {
222
// We are changing the type of a column. This may require doing some casts...
224
$oldtype = column_type($table, $oldfield);
225
$newtype = column_type($table, $field);
227
// Do we need a cast?
228
if($newtype == 'N' && $oldtype == 'C') {
229
$casting = 'CAST(CAST('.$oldfield.' AS TEXT) AS REAL)';
231
else if($newtype == 'I' && $oldtype == 'C') {
232
$casting = 'CAST(CAST('.$oldfield.' AS TEXT) AS INTEGER)';
235
$casting = $oldfield;
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);
243
execute_sql('ALTER TABLE '. $CFG->prefix . $table .' RENAME COLUMN '. $field .' TO '. $realfield);
248
switch (strtolower($type)) {
257
$default = 'DEFAULT \''. $default .'\'';
259
if (!empty($after)) {
260
$after = 'AFTER '. $after;
263
if (!empty($oldfield)) {
264
execute_sql('ALTER TABLE '. $CFG->prefix . $table .' RENAME COLUMN '. $oldfield .' '. $field);
266
execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ADD COLUMN '. $field .' '. $type);
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);
275
* Given one XMLDBTable, check if it exists in DB (true/false)
277
* @param XMLDBTable table to be searched for
278
* @return boolean true/false
280
function table_exists($table) {
286
/// Do this function silenty (to avoid output in install/upgrade process)
287
$olddbdebug = $db->debug;
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);
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)) {
305
/// Re-set original debug
306
$db->debug = $olddbdebug;
312
* Given one XMLDBField, check if it exists in DB (true/false)
315
* @param XMLDBTable the table
316
* @param XMLDBField the field to be searched for
317
* @return boolean true/false
319
function field_exists($table, $field) {
325
/// Do this function silenty (to avoid output in install/upgrade process)
326
$olddbdebug = $db->debug;
329
/// Check the table exists
330
if (!table_exists($table)) {
331
$db->debug = $olddbdebug; //Re-set original $db->debug
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);
342
/// Get list of fields in table
344
if ($fields = $db->MetaColumns($tablename)) {
345
$fields = array_change_key_case($fields, CASE_LOWER);
348
if (!array_key_exists($field->getName(), $fields)) {
352
/// Re-set original debug
353
$db->debug = $olddbdebug;
359
* Given one XMLDBIndex, check if it exists in DB (true/false)
362
* @param XMLDBTable the table
363
* @param XMLDBIndex the index to be searched for
364
* @return boolean true/false
366
function index_exists($table, $index) {
372
/// Do this function silenty (to avoid output in install/upgrade process)
373
$olddbdebug = $db->debug;
376
/// Wrap over find_index_name to see if the index exists
377
if (!find_index_name($table, $index)) {
381
/// Re-set original debug
382
$db->debug = $olddbdebug;
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
395
* @param XMLDBTable the table to be searched
396
* @param XMLDBKey the key to be searched
397
* @return string key name of false
399
function find_key_name($table, $xmldb_key) {
403
/// Extract key columns
404
$keycolumns = $xmldb_key->getFields();
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
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;
425
/// Calculate the name suffix
426
switch ($xmldb_key->getType()) {
427
case XMLDB_KEY_PRIMARY:
430
case XMLDB_KEY_UNIQUE:
433
case XMLDB_KEY_FOREIGN_UNIQUE:
434
case XMLDB_KEY_FOREIGN:
438
/// And simply, return the oficial name
439
return $generator->getNameForObject($table->getName(), implode(', ', $xmldb_key->getFields()), $suffix);
444
* Given one XMLDBIndex, the function returns the name of the index in DB (if exists)
445
* of false if it doesn't exist
448
* @param XMLDBTable the table to be searched
449
* @param XMLDBIndex the index to be searched
450
* @return string index name of false
452
function find_index_name($table, $index) {
456
/// Do this function silenty (to avoid output in install/upgrade process)
457
$olddbdebug = $db->debug;
460
/// Extract index columns
461
$indcolumns = $index->getFields();
463
/// Check the table exists
464
if (!table_exists($table)) {
465
$db->debug = $olddbdebug; //Re-set original $db->debug
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);
476
/// Get list of indexes in table
478
if ($indexes = $db->MetaIndexes($tablename)) {
479
$indexes = array_change_key_case($indexes, CASE_LOWER);
482
/// Iterate over them looking for columns coincidence
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
499
/// Arriving here, index not found
500
$db->debug = $olddbdebug; //Re-set original $db->debug
505
* Given one XMLDBTable, the function returns the name of its sequence in DB (if exists)
506
* of false if it doesn't exist
508
* @param XMLDBTable the table to be searched
509
* @return string sequence name of false
511
function find_sequence_name($table) {
515
$sequencename = false;
517
/// Do this function silenty (to avoid output in install/upgrade process)
518
$olddbdebug = $db->debug;
521
if (strtolower(get_class($table)) != 'xmldbtable') {
522
$db->debug = $olddbdebug; //Re-set original $db->debug
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
533
$sequencename = $table->getSequenceFromDB($CFG->dbtype, $CFG->prefix);
535
$db->debug = $olddbdebug; //Re-set original $db->debug
536
return $sequencename;
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.
545
* @param $file full path to the XML file to be used
546
* @return boolean (true on success, false on error)
548
function install_from_xmldb_file($file) {
553
$xmldb_file = new XMLDBFile($file);
555
if (!$xmldb_file->fileExists()) {
559
$loaded = $xmldb_file->loadXMLStructure();
560
if (!$loaded || !$xmldb_file->isLoaded()) {
564
$structure = $xmldb_file->getStructure();
566
if (!$sqlarr = $structure->getCreateStructureSQL($CFG->dbtype, $CFG->prefix, false)) {
567
return true; //Empty array = nothing to do = no error
570
$status = $status && execute_sql_arr($sqlarr);
575
* This function will create the table passed as argument with all its
576
* fields/keys/indexes/sequences, everything based in the XMLDB object
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
584
function create_table($table, $continue=true, $feedback=true) {
590
if (strtolower(get_class($table)) != 'xmldbtable') {
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
600
if(!$sqlarr = $table->getCreateTableSQL($CFG->dbtype, $CFG->prefix, false)) {
601
return true; //Empty array = nothing to do = no error
604
return execute_sql_arr($sqlarr, $continue, $feedback);
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.
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
618
function drop_table($table, $continue=true, $feedback=true) {
624
if (strtolower(get_class($table)) != 'xmldbtable') {
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
634
if(!$sqlarr = $table->getDropTableSQL($CFG->dbtype, $CFG->prefix, false)) {
635
return true; //Empty array = nothing to do = no error
638
return execute_sql_arr($sqlarr, $continue, $feedback);
642
* This function will rename the table passed as argument
643
* Before renaming the index, the function will check it exists
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
652
function rename_table($table, $newname, $continue=true, $feedback=true) {
658
if (strtolower(get_class($table)) != 'xmldbtable') {
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
668
/// Check newname isn't empty
670
debugging('New name for table ' . $index->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
671
return true; //Table doesn't exist, nothing to do
674
if(!$sqlarr = $table->getRenameTableSQL($CFG->dbtype, $CFG->prefix, $newname, false)) {
675
return true; //Empty array = nothing to do = no error
678
return execute_sql_arr($sqlarr, $continue, $feedback);
682
* This function will add the field to the table passed as arguments
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
691
function add_field($table, $field, $continue=true, $feedback=true) {
697
if (strtolower(get_class($table)) != 'xmldbtable') {
700
if (strtolower(get_class($field)) != 'xmldbfield') {
704
/// Check the field doesn't exist
705
if (field_exists($table, $field)) {
706
debugging('Field ' . $field->getName() . ' exists. Create skipped', DEBUG_DEVELOPER);
710
if(!$sqlarr = $table->getAddFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
711
return true; //Empty array = nothing to do = no error
714
return execute_sql_arr($sqlarr, $continue, $feedback);
718
* This function will drop the field from the table passed as arguments
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
727
function drop_field($table, $field, $continue=true, $feedback=true) {
733
if (strtolower(get_class($table)) != 'xmldbtable') {
736
if (strtolower(get_class($field)) != 'xmldbfield') {
740
/// Check the field exists
741
if (!field_exists($table, $field)) {
742
debugging('Field ' . $field->getName() . ' do not exist. Delete skipped', DEBUG_DEVELOPER);
746
if(!$sqlarr = $table->getDropFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
747
return true; //Empty array = nothing to do = no error
750
return execute_sql_arr($sqlarr, $continue, $feedback);
754
* This function will change the type of the field in the table passed as arguments
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
763
function change_field_type($table, $field, $continue=true, $feedback=true) {
769
if (strtolower(get_class($table)) != 'xmldbtable') {
772
if (strtolower(get_class($field)) != 'xmldbfield') {
776
if(!$sqlarr = $table->getAlterFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
777
return true; //Empty array = nothing to do = no error
780
return execute_sql_arr($sqlarr, $continue, $feedback);
784
* This function will change the precision of the field in the table passed as arguments
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
793
function change_field_precision($table, $field, $continue=true, $feedback=true) {
795
/// Just a wrapper over change_field_type. Does exactly the same processing
796
return change_field_type($table, $field, $continue, $feedback);
800
* This function will change the unsigned/signed of the field in the table passed as arguments
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
809
function change_field_unsigned($table, $field, $continue=true, $feedback=true) {
811
/// Just a wrapper over change_field_type. Does exactly the same processing
812
return change_field_type($table, $field, $continue, $feedback);
816
* This function will change the nullability of the field in the table passed as arguments
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
825
function change_field_notnull($table, $field, $continue=true, $feedback=true) {
827
/// Just a wrapper over change_field_type. Does exactly the same processing
828
return change_field_type($table, $field, $continue, $feedback);
832
* This function will change the enum status of the field in the table passed as arguments
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
841
function change_field_enum($table, $field, $continue=true, $feedback=true) {
847
if (strtolower(get_class($table)) != 'xmldbtable') {
850
if (strtolower(get_class($field)) != 'xmldbfield') {
854
if(!$sqlarr = $table->getModifyEnumSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
855
return true; //Empty array = nothing to do = no error
858
return execute_sql_arr($sqlarr, $continue, $feedback);
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
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
871
function change_field_default($table, $field, $continue=true, $feedback=true) {
877
if (strtolower(get_class($table)) != 'xmldbtable') {
880
if (strtolower(get_class($field)) != 'xmldbfield') {
884
if(!$sqlarr = $table->getModifyDefaultSQL($CFG->dbtype, $CFG->prefix, $field, false)) {
885
return true; //Empty array = nothing to do = no error
888
return execute_sql_arr($sqlarr, $continue, $feedback);
892
* This function will rename the field in the table passed as arguments
893
* Before renaming the field, the function will check it exists
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
903
function rename_field($table, $field, $newname, $continue=true, $feedback=true) {
909
if (strtolower(get_class($table)) != 'xmldbtable') {
912
if (strtolower(get_class($field)) != 'xmldbfield') {
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
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
928
/// Check newname isn't empty
930
debugging('New name for field ' . $field->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
931
return true; //Field doesn't exist, nothing to do
934
if(!$sqlarr = $table->getRenameFieldSQL($CFG->dbtype, $CFG->prefix, $field, $newname, false)) {
935
return true; //Empty array = nothing to do = no error
938
return execute_sql_arr($sqlarr, $continue, $feedback);
942
* This function will create the key in the table passed as arguments
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
951
function add_key($table, $key, $continue=true, $feedback=true) {
957
if (strtolower(get_class($table)) != 'xmldbtable') {
960
if (strtolower(get_class($key)) != 'xmldbkey') {
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);
968
if(!$sqlarr = $table->getAddKeySQL($CFG->dbtype, $CFG->prefix, $key, false)) {
969
return true; //Empty array = nothing to do = no error
972
return execute_sql_arr($sqlarr, $continue, $feedback);
976
* This function will drop the key in the table passed as arguments
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
985
function drop_key($table, $key, $continue=true, $feedback=true) {
991
if (strtolower(get_class($table)) != 'xmldbtable') {
994
if (strtolower(get_class($key)) != 'xmldbkey') {
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);
1002
if(!$sqlarr = $table->getDropKeySQL($CFG->dbtype, $CFG->prefix, $key, false)) {
1003
return true; //Empty array = nothing to do = no error
1006
return execute_sql_arr($sqlarr, $continue, $feedback);
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!
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
1021
function rename_key($table, $key, $newname, $continue=true, $feedback=true) {
1025
debugging('rename_key() is one experimental feature. You must not use it in production!', DEBUG_DEVELOPER);
1029
if (strtolower(get_class($table)) != 'xmldbtable') {
1032
if (strtolower(get_class($key)) != 'xmldbkey') {
1036
/// Check newname isn't empty
1038
debugging('New name for key ' . $key->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
1039
return true; //Key doesn't exist, nothing to do
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
1047
return execute_sql_arr($sqlarr, $continue, $feedback);
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
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
1061
function add_index($table, $index, $continue=true, $feedback=true) {
1067
if (strtolower(get_class($table)) != 'xmldbtable') {
1070
if (strtolower(get_class($index)) != 'xmldbindex') {
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
1080
if(!$sqlarr = $table->getAddIndexSQL($CFG->dbtype, $CFG->prefix, $index, false)) {
1081
return true; //Empty array = nothing to do = no error
1084
return execute_sql_arr($sqlarr, $continue, $feedback);
1088
* This function will drop the index in the table passed as arguments
1089
* Before dropping the index, the function will check it exists
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
1098
function drop_index($table, $index, $continue=true, $feedback=true) {
1104
if (strtolower(get_class($table)) != 'xmldbtable') {
1107
if (strtolower(get_class($index)) != 'xmldbindex') {
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
1117
if(!$sqlarr = $table->getDropIndexSQL($CFG->dbtype, $CFG->prefix, $index, false)) {
1118
return true; //Empty array = nothing to do = no error
1121
return execute_sql_arr($sqlarr, $continue, $feedback);
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!
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
1137
function rename_index($table, $index, $newname, $continue=true, $feedback=true) {
1141
debugging('rename_index() is one experimental feature. You must not use it in production!', DEBUG_DEVELOPER);
1145
if (strtolower(get_class($table)) != 'xmldbtable') {
1148
if (strtolower(get_class($index)) != 'xmldbindex') {
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
1158
/// Check newname isn't empty
1160
debugging('New name for index ' . $index->getName() . ' is empty! Rename skipped', DEBUG_DEVELOPER);
1161
return true; //Index doesn't exist, nothing to do
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
1169
return execute_sql_arr($sqlarr, $continue, $feedback);