libdir . '/xmldb/classes/XMLDBConstants.php'); /// Add main XMLDB Generator require_once($CFG->libdir . '/xmldb/classes/generators/XMLDBGenerator.class.php'); /// Add required XMLDB DB classes require_once($CFG->libdir . '/xmldb/classes/XMLDBObject.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBFile.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBStructure.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBTable.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBField.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBKey.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBIndex.class.php'); require_once($CFG->libdir . '/xmldb/classes/XMLDBStatement.class.php'); /// Based on $CFG->dbtype, add the proper generator class require_once($CFG->libdir . '/xmldb/classes/generators/' . $CFG->dbtype . '/' . $CFG->dbtype . '.class.php'); /// Add other libraries require_once($CFG->libdir . '/xmlize.php'); /** * Add a new field to a table, or modify an existing one (if oldfield is defined). * Warning: Please be careful on primary keys, as this function will eat auto_increments * * @uses $CFG * @uses $db * @param string $table the name of the table to modify. (Without the prefix.) * @param string $oldfield If changing an existing column, the name of that column. * @param string $field The name of the column at the end of the operation. * @param string $type The type of the column at the end of the operation. TEXT, VARCHAR, CHAR, INTEGER, REAL, or TINYINT * @param string $size The size of that column type. As in VARCHAR($size), or INTEGER($size). * @param string $signed For numeric column types, whether that column is 'signed' or 'unsigned'. * @param string $default The new default value for the column. * @param string $null 'not null', or '' to allow nulls. * @param string $after Which column to insert this one after. Not supported on Postgres. * * @return boolean Wheter the operation succeeded. */ function table_column($table, $oldfield, $field, $type='integer', $size='10', $signed='unsigned', $default='0', $null='not null', $after='') { global $CFG, $db, $empty_rs_cache; if (!empty($empty_rs_cache[$table])) { // Clear the recordset cache because it's out of date unset($empty_rs_cache[$table]); } switch (strtolower($CFG->dbtype)) { case 'mysql': case 'mysqlt': switch (strtolower($type)) { case 'text': $type = 'TEXT'; $signed = ''; break; case 'integer': $type = 'INTEGER('. $size .')'; break; case 'varchar': $type = 'VARCHAR('. $size .')'; $signed = ''; break; case 'char': $type = 'CHAR('. $size .')'; $signed = ''; break; } if (!empty($oldfield)) { $operation = 'CHANGE '. $oldfield .' '. $field; } else { $operation = 'ADD '. $field; } $default = 'DEFAULT \''. $default .'\''; if (!empty($after)) { $after = 'AFTER `'. $after .'`'; } return execute_sql('ALTER TABLE '. $CFG->prefix . $table .' '. $operation .' '. $type .' '. $signed .' '. $default .' '. $null .' '. $after); case 'postgres7': // From Petri Asikainen //Check db-version $dbinfo = $db->ServerInfo(); $dbver = substr($dbinfo['version'],0,3); //to prevent conflicts with reserved words $realfield = '"'. $field .'"'; $field = '"'. $field .'_alter_column_tmp"'; $oldfield = '"'. $oldfield .'"'; switch (strtolower($type)) { case 'tinyint': case 'integer': if ($size <= 4) { $type = 'INT2'; } if ($size <= 10) { $type = 'INT'; } if ($size > 10) { $type = 'INT8'; } break; case 'varchar': $type = 'VARCHAR('. $size .')'; break; case 'char': $type = 'CHAR('. $size .')'; $signed = ''; break; } $default = '\''. $default .'\''; //After is not implemented in postgesql //if (!empty($after)) { // $after = "AFTER '$after'"; //} //Use transactions execute_sql('BEGIN'); //Always use temporary column execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ADD COLUMN '. $field .' '. $type); //Add default values execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .'='. $default); if ($dbver >= '7.3') { // modifying 'not null' is posible before 7.3 //update default values to table if (strtoupper($null) == 'NOT NULL') { execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .'='. $default .' WHERE '. $field .' IS NULL'); execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET '. $null); } else { execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' DROP NOT NULL'); } } execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET DEFAULT '. $default); if ( $oldfield != '""' ) { // We are changing the type of a column. This may require doing some casts... $casting = ''; $oldtype = column_type($table, $oldfield); $newtype = column_type($table, $field); // Do we need a cast? if($newtype == 'N' && $oldtype == 'C') { $casting = 'CAST(CAST('.$oldfield.' AS TEXT) AS REAL)'; } else if($newtype == 'I' && $oldtype == 'C') { $casting = 'CAST(CAST('.$oldfield.' AS TEXT) AS INTEGER)'; } else { $casting = $oldfield; } // Run the update query, casting as necessary execute_sql('UPDATE '. $CFG->prefix . $table .' SET '. $field .' = '. $casting); execute_sql('ALTER TABLE '. $CFG->prefix . $table .' DROP COLUMN '. $oldfield); } execute_sql('ALTER TABLE '. $CFG->prefix . $table .' RENAME COLUMN '. $field .' TO '. $realfield); return execute_sql('COMMIT'); default: switch (strtolower($type)) { case 'integer': $type = 'INTEGER'; break; case 'varchar': $type = 'VARCHAR'; break; } $default = 'DEFAULT \''. $default .'\''; if (!empty($after)) { $after = 'AFTER '. $after; } if (!empty($oldfield)) { execute_sql('ALTER TABLE '. $CFG->prefix . $table .' RENAME COLUMN '. $oldfield .' '. $field); } else { execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ADD COLUMN '. $field .' '. $type); } execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET '. $null); return execute_sql('ALTER TABLE '. $CFG->prefix . $table .' ALTER COLUMN '. $field .' SET '. $default); } } /** * This function will load one entire XMLDB file, generating all the needed * SQL statements, specific for each RDBMS ($CFG->dbtype) and, finally, it * will execute all those statements against the DB. * * @uses $CFG, $db * @param $file full path to the XML file to be used * @return boolean (true on success, false on error) */ function install_from_xmldb_file($file) { global $CFG, $db; $status = true; $xmldb_file = new XMLDBFile($file); if (!$xmldb_file->fileExists()) { return false; } $loaded = $xmldb_file->loadXMLStructure(); if (!$loaded || !$xmldb_file->isLoaded()) { return false; } $structure = $xmldb_file->getStructure(); if (!$sqlarr = $structure->getCreateStructureSQL($CFG->dbtype, $CFG->prefix, false)) { return false; } return execute_sql_arr($sqlarr); } /** * This function will create the table passed as argument with all its * fields/keys/indexes/sequences, everything based in the XMLDB object * * @uses $CFG, $db * @param XMLDBTable table object (full specs are required) * @param boolean continue to specify if must continue on error (true) or stop (false) * @param boolean feedback to specify to show status info (true) or not (false) * @return boolean true on success, false on error */ function create_table($table, $continue=true, $feedback=true) { global $CFG, $db; $status = true; if (strtolower(get_class($table)) != 'xmldbtable') { return false; } if(!$sqlarr = $table->getCreateTableSQL($CFG->dbtype, $CFG->prefix, false)) { return false; } return execute_sql_arr($sqlarr, $continue, $feedback); } /** * This function will drop the table passed as argument * and all the associated objects (keys, indexes, constaints, sequences, triggers) * will be dropped too. * * @uses $CFG, $db * @param XMLDBTable table object (just the name is mandatory) * @param boolean continue to specify if must continue on error (true) or stop (false) * @param boolean feedback to specify to show status info (true) or not (false) * @return boolean true on success, false on error */ function drop_table($table, $continue=true, $feedback=true) { global $CFG, $db; $status = true; if (strtolower(get_class($table)) != 'xmldbtable') { return false; } if(!$sqlarr = $table->getDropTableSQL($CFG->dbtype, $CFG->prefix, false)) { return false; } return execute_sql_arr($sqlarr, $continue, $feedback); } /** * This function will add the field to the table passed as arguments * * @uses $CFG, $db * @param XMLDBTable table object (just the name is mandatory) * @param XMLDBField field object (full specs are required) * @param boolean continue to specify if must continue on error (true) or stop (false) * @param boolean feedback to specify to show status info (true) or not (false) * @return boolean true on success, false on error */ function add_field($table, $field, $continue=true, $feedback=true) { global $CFG, $db; $status = true; if (strtolower(get_class($table)) != 'xmldbtable') { return false; } if (strtolower(get_class($field)) != 'xmldbfield') { return false; } if(!$sqlarr = $table->getAddFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) { return false; } return execute_sql_arr($sqlarr, $continue, $feedback); } /** * This function will drop the field from the table passed as arguments * * @uses $CFG, $db * @param XMLDBTable table object (just the name is mandatory) * @param XMLDBField field object (just the name is mandatory) * @param boolean continue to specify if must continue on error (true) or stop (false) * @param boolean feedback to specify to show status info (true) or not (false) * @return boolean true on success, false on error */ function drop_field($table, $field, $continue=true, $feedback=true) { global $CFG, $db; $status = true; if (strtolower(get_class($table)) != 'xmldbtable') { return false; } if (strtolower(get_class($field)) != 'xmldbfield') { return false; } if(!$sqlarr = $table->getDropFieldSQL($CFG->dbtype, $CFG->prefix, $field, false)) { return false; } return execute_sql_arr($sqlarr, $continue, $feedback); } ?>