Commit 1e4b0ba5 authored by Penny Leach's avatar Penny Leach
Browse files

new xmldb

parent 3c356463
<?php // $Id: XMLDBTable.class.php,v 1.11 2006/09/28 17:25:00 stronk7 Exp $
<?php // $Id: XMLDBTable.class.php,v 1.16 2006/10/08 09:36:54 stronk7 Exp $
///////////////////////////////////////////////////////////////////////////
// //
......@@ -891,6 +891,24 @@ class XMLDBTable extends XMLDBObject {
return $results;
}
/**
* This function will return the SQL code needed to modify the enum of one field in the table for the specified DB and
* prefix. Just one simple wrapper over generators.
*/
function getModifyEnumSQL ($dbtype, $prefix, $xmldb_field, $statement_end=true) {
$results = array();
$classname = 'XMLDB' . $dbtype;
$generator = new $classname();
$generator->setPrefix($prefix);
$results = $generator->getModifyEnumSQL($this, $xmldb_field);
if ($statement_end) {
$results = $generator->getEndedStatements($results);
}
return $results;
}
/**
* This function will return the SQL code needed to modify the default of one field in the table for the specified DB and
* prefix. Just one simple wrapper over generators.
......@@ -945,6 +963,24 @@ class XMLDBTable extends XMLDBObject {
return $results;
}
/**
* This function will return the SQL code needed to rename one key from the table for the specified DB and
* prefix. Just one simple wrapper over generators.
*/
function getRenameKeySQL ($dbtype, $prefix, $xmldb_key, $newname, $statement_end=true) {
$results = array();
$classname = 'XMLDB' . $dbtype;
$generator = new $classname();
$generator->setPrefix($prefix);
$results = $generator->getRenameKeySQL($this, $xmldb_key, $newname);
if ($statement_end) {
$results = $generator->getEndedStatements($results);
}
return $results;
}
/**
* This function will return the SQL code needed to add one index to the table for the specified DB and
* prefix. Just one simple wrapper over generators.
......@@ -980,6 +1016,38 @@ class XMLDBTable extends XMLDBObject {
}
return $results;
}
/**
* This function will return the SQL code needed to rename one index from the table for the specified DB and
* prefix. Just one simple wrapper over generators.
* Experimental. Shouldn't be used at all!
*/
function getRenameIndexSQL ($dbtype, $prefix, $xmldb_index, $newname, $statement_end=true) {
$results = array();
$classname = 'XMLDB' . $dbtype;
$generator = new $classname();
$generator->setPrefix($prefix);
$results = $generator->getRenameIndexSQL($this, $xmldb_index, $newname);
if ($statement_end) {
$results = $generator->getEndedStatements($results);
}
return $results;
}
/**
* This function will return the name of the sequence created for the pk of the table specified
* Just one simple wrapper over generators. Returns false if not found
* Note that not all DB use sequences (only Oracle and PostgreSQL)
*/
function getSequenceFromDB($dbtype, $prefix) {
$classname = 'XMLDB' . $dbtype;
$generator = new $classname();
$generator->setPrefix($prefix);
return $generator->getSequenceFromDB($this);
}
}
?>
<?php // $Id: mssql.class.php,v 1.20 2006/09/28 18:33:48 stronk7 Exp $
<?php // $Id: mssql.class.php,v 1.30 2006/10/02 17:42:14 stronk7 Exp $
///////////////////////////////////////////////////////////////////////////
// //
......@@ -53,9 +53,25 @@ class XMLDBmssql extends XMLDBgenerator {
var $concat_character = '+'; //Characters to be used as concatenation operator. If not defined
//MySQL CONCAT function will be use
var $rename_table_sql = "sp_rename 'OLDNAME', 'NEWNAME'"; //SQL sentence to rename one table, both
//OLDNAME and NEWNAME are dinamically replaced
var $rename_table_extra_code = true; //Does the generator need to add code after table rename
var $rename_column_extra_code = true; //Does the generator need to add code after field rename
var $rename_column_sql = "sp_rename 'TABLENAME.OLDFIELDNAME', 'NEWFIELDNAME', 'COLUMN'";
///TABLENAME, OLDFIELDNAME and NEWFIELDNAME are dianmically replaced
var $drop_index_sql = 'DROP INDEX TABLENAME.INDEXNAME'; //SQL sentence to drop one index
//TABLENAME, INDEXNAME are dinamically replaced
var $rename_index_sql = "sp_rename 'TABLENAME.OLDINDEXNAME', 'NEWINDEXNAME', 'INDEX'"; //SQL sentence to rename one index
//TABLENAME, OLDINDEXNAME, NEWINDEXNAME are dinamically replaced
var $rename_key_sql = null; //SQL sentence to rename one key
//TABLENAME, OLDKEYNAME, NEWKEYNAME are dinamically replaced
/**
* Creates one new XMLDBmssql
*/
......@@ -147,7 +163,7 @@ class XMLDBmssql extends XMLDBgenerator {
$results = array();
/// Get the quoted name of the table and field
$tablename = $this->getEncQuoted($this->prefix . $xmldb_table->getName());
$tablename = $this->getTableName($xmldb_table);
$fieldname = $this->getEncQuoted($xmldb_field->getName());
$checkconsname = $this->getNameForObject($xmldb_table->getName(), $xmldb_field->getName(), 'ck');
......@@ -170,13 +186,187 @@ class XMLDBmssql extends XMLDBgenerator {
return $results;
}
/**
* Given one correct XMLDBField and the new name, returns the SQL statements
* to rename it (inside one array)
* MSSQL is special, so we overload the function here. It needs to
* drop the constraints BEFORE renaming the field
*/
function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) {
$results = array(); //Array where all the sentences will be stored
/// Although this is checked in ddllib - rename_field() - double check
/// that we aren't trying to rename one "id" field. Although it could be
/// implemented (if adding the necessary code to rename sequences, defaults,
/// triggers... and so on under each getRenameFieldExtraSQL() function, it's
/// better to forbide it, mainly because this field is the default PK and
/// in the future, a lot of FKs can be pointing here. So, this field, more
/// or less, must be considered inmutable!
if ($xmldb_field->getName() == 'id') {
return array();
}
/// Drop the check constraint if exists
if ($xmldb_field->getEnum()) {
$results = array_merge($results, $this->getDropEnumSQL($xmldb_table, $xmldb_field));
}
/// Call to standard (parent) getRenameFieldSQL() function
$results = array_merge($results, parent::getRenameFieldSQL($xmldb_table, $xmldb_field, $newname));
return $results;
}
/**
* Returns the code (array of statements) needed to execute extra statements on field rename
*/
function getRenameFieldExtraSQL ($xmldb_table, $xmldb_field, $newname) {
$results = array();
/// If the field is enum, drop and re-create the check constraint
if ($xmldb_field->getEnum()) {
/// Drop the current enum (not needed, it has been dropped before for msqql (in getRenameFieldSQL)
//$results = array_merge($results, $this->getDropEnumSQL($xmldb_table, $xmldb_field));
/// Change field name
$xmldb_field->setName($newname);
/// Recreate the enum
$results = array_merge($results, $this->getCreateEnumSQL($xmldb_table, $xmldb_field));
}
return $results;
}
/**
* Returns the code (array of statements) needed to execute extra statements on table rename
*/
function getRenameTableExtraSQL ($xmldb_table, $newname) {
$results = array();
$newt = new XMLDBTable($newname); //Temporal table for name calculations
$oldtablename = $this->getTableName($xmldb_table);
$newtablename = $this->getTableName($newt);
/// Rename all the check constraints in the table
$oldconstraintprefix = $this->getNameForObject($xmldb_table->getName(), '');
$newconstraintprefix = $this->getNameForObject($newt->getName(), '', '');
if ($constraints = $this->getCheckConstraintsFromDB($xmldb_table)) {
foreach ($constraints as $constraint) {
/// Drop the old constraint
$results[] = 'ALTER TABLE ' . $newtablename . ' DROP CONSTRAINT ' . $constraint->name;
/// Calculate the new constraint name
$newconstraintname = str_replace($oldconstraintprefix, $newconstraintprefix, $constraint->name);
/// Add the new constraint
$results[] = 'ALTER TABLE ' . $newtablename . ' ADD CONSTRAINT ' . $newconstraintname .
' CHECK ' . $constraint->description;
}
}
return $results;
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to alter the field in the table
*/
function getAlterFieldSQL($xmldb_table, $xmldb_field) {
global $db;
$results = array(); /// To store all the needed SQL commands
/// Get the quoted name of the table and field
$tablename = $this->getTableName($xmldb_table);
$fieldname = $this->getEncQuoted($xmldb_field->getName());
/// Take a look to field metadata
$meta = array_change_key_case($db->MetaColumns($tablename));
$metac = $meta[$fieldname];
$oldtype = strtolower($metac->type);
$oldmetatype = column_type($xmldb_table->getName(), $fieldname);
$oldlength = $metac->max_length;
$olddecimals = empty($metac->scale) ? null : $metac->scale;
$oldnotnull = empty($metac->not_null) ? false : $metac->not_null;
$olddefault = empty($metac->has_default) ? null : strtok($metac->default_value, ':');
$typechanged = true; //By default, assume that the column type has changed
/// Detect if we are changing the type of the column
if (($xmldb_field->getType() == XMLDB_TYPE_INTEGER && substr($oldmetatype, 0, 1) == 'I') ||
($xmldb_field->getType() == XMLDB_TYPE_NUMBER && $oldmetatype == 'N') ||
($xmldb_field->getType() == XMLDB_TYPE_FLOAT && $oldmetatype == 'F') ||
($xmldb_field->getType() == XMLDB_TYPE_CHAR && substr($oldmetatype, 0, 1) == 'C') ||
($xmldb_field->getType() == XMLDB_TYPE_TEXT && substr($oldmetatype, 0, 1) == 'X') ||
($xmldb_field->getType() == XMLDB_TYPE_BINARY && $oldmetatype == 'B')) {
$typechanged = false;
}
/// If type has changed drop the default if exists
if ($typechanged) {
$results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field);
}
/// Just prevent default clauses in this type of sentences for mssql and launch the parent one
$this->alter_column_skip_default = true;
return parent::getAlterFieldSQL($xmldb_table, $xmldb_field);
$results = array_merge($results, parent::getAlterFieldSQL($xmldb_table, $xmldb_field)); // Call parent
/// Finally, process the default clause to add it back if necessary
if ($typechanged) {
$results = array_merge($results, $this->getCreateDefaultSQL($xmldb_table, $xmldb_field));
}
/// Return results
return $results;
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to modify the default of the field in the table
*/
function getModifyDefaultSQL($xmldb_table, $xmldb_field) {
/// MSSQL is a bit special with default constraints because it implements them as external constraints so
/// normal ALTER TABLE ALTER COLUMN don't work to change defaults. Because this, we have this method overloaded here
$results = array();
/// Get the quoted name of the table and field
$tablename = $this->getTableName($xmldb_table);
$fieldname = $this->getEncQuoted($xmldb_field->getName());
/// Decide if we are going to create/modify or to drop the default
if ($xmldb_field->getDefault() === null) {
$results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field); //Drop but, under some circumptances, re-enable
if ($this->getDefaultClause($xmldb_field)) { //If getDefaultClause() it must have one default, create it
$results = array_merge($results, $this->getCreateDefaultSQL($xmldb_table, $xmldb_field)); //Create/modify
}
} else {
$results = $this->getDropDefaultSQL($xmldb_table, $xmldb_field); //Drop (only if exists)
$results = array_merge($results, $this->getCreateDefaultSQL($xmldb_table, $xmldb_field)); //Create/modify
}
return $results;
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its enum
* (usually invoked from getModifyEnumSQL()
*/
function getCreateEnumSQL($xmldb_table, $xmldb_field) {
/// All we have to do is to create the check constraint
return array('ALTER TABLE ' . $this->getTableName($xmldb_table) .
' ADD ' . $this->getEnumExtraSQL($xmldb_table, $xmldb_field));
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its enum
* (usually invoked from getModifyEnumSQL()
*/
function getDropEnumSQL($xmldb_table, $xmldb_field) {
/// All we have to do is to drop the check constraint
return array('ALTER TABLE ' . $this->getTableName($xmldb_table) .
' DROP CONSTRAINT ' . $this->getNameForObject($xmldb_table->getName(), $xmldb_field->getName(), 'ck'));
}
/**
......@@ -184,9 +374,21 @@ class XMLDBmssql extends XMLDBgenerator {
* (usually invoked from getModifyDefaultSQL()
*/
function getCreateDefaultSQL($xmldb_table, $xmldb_field) {
/// This method does exactly the same than getDropDefaultSQL(), first trying to
/// drop the default if it exists and then, regenerating it, so we simply wrap over it
return $this->getDropDefaultSQL($xmldb_table, $xmldb_field);
/// MSSQL is a bit special and it requires the corresponding DEFAULT CONSTRAINT to be dropped
$results = array();
/// Get the quoted name of the table and field
$tablename = $this->getTableName($xmldb_table);
$fieldname = $this->getEncQuoted($xmldb_field->getName());
/// Now, check if, with the current field attributes, we have to build one default
if ($default_clause = $this->getDefaultClause($xmldb_field)) {
/// We need to build the default (Moodle) default, so do it
$results[] = 'ALTER TABLE ' . $tablename . ' ADD' . $default_clause . ' FOR ' . $fieldname;
}
return $results;
}
/**
......@@ -199,19 +401,14 @@ class XMLDBmssql extends XMLDBgenerator {
$results = array();
/// Get the quoted name of the table and field
$tablename = $this->getEncQuoted($this->prefix . $xmldb_table->getName());
$tablename = $this->getTableName($xmldb_table);
$fieldname = $this->getEncQuoted($xmldb_field->getName());
/// Look for the default contraint and, if found, drop it
if ($defaultname = $this->getDefaultConstraintName($xmldb_table, $xmldb_field)) {
$results[] = 'ALTER TABLE ' . $tablename . ' DROP CONSTRAINT ' . $defaultname;
}
}
/// Now, check if, with the current field attributes, we have to build one default
if ($default_clause = $this->getDefaultClause($xmldb_field)) {
/// We need to build the default (Moodle) default, so do it
$results[] = 'ALTER TABLE ' . $tablename . ' ADD' . $default_clause . ' FOR ' . $fieldname;
}
return $results;
}
......@@ -222,10 +419,8 @@ class XMLDBmssql extends XMLDBgenerator {
*/
function getDefaultConstraintName($xmldb_table, $xmldb_field) {
global $db;
/// Get the quoted name of the table and field
$tablename = $this->getEncQuoted($this->prefix . $xmldb_table->getName());
$tablename = $this->getTableName($xmldb_table);
$fieldname = $this->getEncQuoted($xmldb_field->getName());
/// Look for any default constraint in this field and drop it
......@@ -239,6 +434,34 @@ class XMLDBmssql extends XMLDBgenerator {
}
}
/**
* Given one XMLDBTable returns one array with all the check constrainsts
* in the table (fetched from DB)
* Each element contains the name of the constraint and its description
* If no check constraints are found, returns an empty array
*/
function getCheckConstraintsFromDB($xmldb_table) {
$results = array();
$tablename = $this->getTableName($xmldb_table);
if ($constraints = get_records_sql("SELECT o.name, c.text AS description
FROM sysobjects o,
sysobjects p,
syscomments c
WHERE p.id = o.parent_obj
AND o.id = c.id
AND o.xtype = 'C'
AND p.name = '{$tablename}'")) {
foreach ($constraints as $constraint) {
$results[$constraint->name] = $constraint;
}
}
return $results;
}
/**
* Returns an array of reserved words (lowercase) for this DB
*/
......
<?php // $Id: mysql.class.php,v 1.23 2006/09/28 21:48:34 stronk7 Exp $
<?php // $Id: mysql.class.php,v 1.29 2006/10/02 17:02:07 stronk7 Exp $
///////////////////////////////////////////////////////////////////////////
// //
......@@ -65,6 +65,12 @@ class XMLDBmysql extends XMLDBGenerator {
var $drop_index_sql = 'ALTER TABLE TABLENAME DROP INDEX INDEXNAME'; //SQL sentence to drop one index
//TABLENAME, INDEXNAME are dinamically replaced
var $rename_index_sql = null; //SQL sentence to rename one index (MySQL doesn't support this!)
//TABLENAME, OLDINDEXNAME, NEWINDEXNAME are dinamically replaced
var $rename_key_sql = null; //SQL sentence to rename one key (MySQL doesn't support this!)
//TABLENAME, OLDKEYNAME, NEWKEYNAME are dinamically replaced
/**
* Creates one new XMLDBmysql
*/
......@@ -160,6 +166,24 @@ class XMLDBmysql extends XMLDBGenerator {
return $dbtype;
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its enum
* (usually invoked from getModifyEnumSQL()
*/
function getCreateEnumSQL($xmldb_table, $xmldb_field) {
/// For MySQL, just alter the field
return $this->getAlterFieldSQL($xmldb_table, $xmldb_field);
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its enum
* (usually invoked from getModifyEnumSQL()
*/
function getDropEnumSQL($xmldb_table, $xmldb_field) {
/// For MySQL, just alter the field
return $this->getAlterFieldSQL($xmldb_table, $xmldb_field);
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to create its default
* (usually invoked from getModifyDefaultSQL()
......@@ -170,6 +194,24 @@ class XMLDBmysql extends XMLDBGenerator {
return $this->getAlterFieldSQL($xmldb_table, $xmldb_field);
}
/**
* Given one correct XMLDBField and the new name, returns the SQL statements
* to rename it (inside one array)
* MySQL is pretty diferent from the standard to justify this oveloading
*/
function getRenameFieldSQL($xmldb_table, $xmldb_field, $newname) {
$results = array(); //Array where all the sentences will be stored
/// Change the name of the field to perform the change
$xmldb_field->setName($xmldb_field->getName() . ' ' . $newname);
$results[] = 'ALTER TABLE ' . $this->getTableName($xmldb_table) . ' CHANGE ' .
$this->getFieldSQL($xmldb_field);
return $results;
}
/**
* Given one XMLDBTable and one XMLDBField, return the SQL statements needded to drop its default
* (usually invoked from getModifyDefaultSQL()
......@@ -195,12 +237,24 @@ class XMLDBmysql extends XMLDBGenerator {
$comment = '';
if ($xmldb_table->getComment()) {
$comment .= 'ALTER TABLE ' . $this->getEncQuoted($this->prefix . $xmldb_table->getName());
$comment .= 'ALTER TABLE ' . $this->getTableName($xmldb_table);
$comment .= " COMMENT='" . substr($xmldb_table->getComment(), 0, 250) . "'";
}
return array($comment);
}
/**
* Given one XMLDBTable returns one array with all the check constrainsts
* in the table (fetched from DB)
* Each element contains the name of the constraint and its description
* If no check constraints are found, returns an empty array
* MySQL doesn't have check constraints in this implementation
*/
function getCheckConstraintsFromDB($xmldb_table) {
return array();
}
/**
* Returns an array of reserved words (lowercase) for this DB
*/
......
<?php // $Id: oci8po.class.php,v 1.21 2006/09/28 23:06:04 stronk7 Exp $
<?php // $Id: oci8po.class.php,v 1.27 2006/10/08 09:36:33 stronk7 Exp $
///////////////////////////////////////////////////////////////////////////
// //
......@@ -49,14 +49,18 @@ class XMLDBoci8po extends XMLDBgenerator {
var $sequence_extra_code = true; //Does the generator need to add extra code to generate the sequence fields
var $sequence_name = ''; //Particular name for inline sequences in this generator
var $drop_table_extra_code = true; //Does the generatos need to add code after table drop
var $drop_table_extra_code = true; //Does the generator need to add code after table drop
var $rename_table_extra_code = true; //Does the generator need to add code after table rename
var $rename_column_extra_code = true; //Does the generator need to add code after field rename
var $enum_inline_code = false; //Does the generator need to add inline code in the column definition
var $alter_column_sql = 'ALTER TABLE TABLENAME MODIFY (COLUMNSPECS)'; //The SQL template to alter columns
/**
* Creates one new XMLDBpostgres7
* Creates one new XMLDBoci8po
*/
function XMLDBoci8po() {
parent::XMLDBgenerator();
......@@ -129,6 +133,8 @@ class XMLDBoci8po extends XMLDBgenerator {
*/
function getCreateSequenceSQL ($xmldb_table, $xmldb_field) {
$results = array();
$sequence_name = $this->getNameForObject($xmldb_table->getName(), $xmldb_field->getName(), 'seq');
$sequence = "CREATE SEQUENCE " . $sequence_name;
......@@ -136,18 +142,32 @@ class XMLDBoci8po extends XMLDBgenerator {
$sequence.= "\n INCREMENT BY 1";
$sequence.= "\n NOMAXVALUE";
$results[] = $sequence;
$results = array_merge($results, $this->getCreateTriggerSQL ($xmldb_table, $xmldb_field));
return $results;
}
/**
* Returns the code needed to create one trigger for the xmldb_table and xmldb_field passed
*/
function getCreateTriggerSQL ($xmldb_table, $xmldb_field) {
$trigger_name = $this->getNameForObject($xmldb_table->getName(), $xmldb_field->getName(), 'trg');
$sequence_name = $this->getNameForObject($xmldb_table->getName(), $xmldb_field->getName(), 'seq');
$trigger = "CREATE TRIGGER " . $trigger_name;
$trigger.= "\n BEFORE INSERT";
$trigger.= "\nON " . $this->getEncQuoted($this->prefix . $xmldb_table->getName());
$trigger.= "\nON " . $this->getTableName($xmldb_table);
$trigger.= "\n FOR EACH ROW";
$trigger.= "\nBEGIN";
$trigger.= "\n IF :new." . $this->getEncQuoted($xmldb_field->getName()) . ' IS NULL THEN';
$trigger.= "\n SELECT " . $sequence_name . '.nextval INTO :new.' . $this->getEncQuoted($xmldb_field->getName()) . " FROM dual;";
$trigger.= "\n END IF;";
$trigger.= "\nEND;";
return array($sequence, $trigger);
return array($trigger);
}
/**
......@@ -177,12 +197,32 @@ class XMLDBoci8po extends XMLDBgenerator {
*/
function getCommentSQL ($xmldb_table) {
$comment = "COMMENT ON TABLE " . $this->getEncQuoted($this->prefix . $xmldb_table->getName());
$comment = "COMMENT ON TABLE " . $this->getTableName($xmldb_table);
$comment.= " IS '" . substr($xmldb_table->getComment(), 0, 250) . "'";
return array($comment);
}
/**
* Returns the code (array of statements) needed to execute extra statements on field rename
*/
function getRenameFieldExtraSQL ($xmldb_table, $xmldb_field, $newname) {
$results = array();