BUGFIX: Fix the generation of fields to be more accurate, and detection of existing fields to be more accurate, so as not to run unnecessary field type change operations.

This commit is contained in:
Sam Minnee 2009-07-27 22:39:57 +00:00
parent f555c3518f
commit 8e7516e537

View File

@ -351,7 +351,6 @@ class MSSQLDatabase extends Database {
if($alteredFields) {
foreach($alteredFields as $k => $v) {
$val=$this->alterTableAlterColumn($tableName, $k, $v, $indexList);
if($val!='')
$alterList[] .= $val;
@ -405,6 +404,21 @@ class MSSQLDatabase extends Database {
return $constraint;
}
/**
* Return the name of the default constraint applied to $tableName.$colName.
* Will return null if no such constraint exists
*/
private function defaultConstraintName($tableName, $colName) {
return $this->query("SELECT s.name --default name
FROM sys.sysobjects s
join sys.syscolumns c ON s.parent_obj = c.id
WHERE s.xtype = 'd'
and c.cdefault = s.id
and parent_obj= OBJECT_ID('$tableName')
and c.name = '$colName'")->value();
}
/**
* Get the actual enum fields from the constraint value:
*/
@ -450,34 +464,20 @@ class MSSQLDatabase extends Database {
}
$prefix="ALTER TABLE \"" . $tableName . "\" ";
// Remove the old default prior to adjusting the column.
if($defaultConstraintName = $this->defaultConstraintName($tableName, $colName)) {
$alterCol .= ";\n$prefix DROP CONSTRAINT \"$defaultConstraintName\"";
}
if(isset($matches[1])) {
$alterCol .= "\n$prefix ALTER COLUMN \"$colName\" $matches[1]\n";
$alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1]";
// SET null / not null
if(!empty($matches[2])) $alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1] $matches[2]";
// SET default (we drop it first, for reasons of precaution)
//TODO: changing default values not implemented yet:
if(!empty($matches[3])) {
$constraint_name="{$tableName}_{$colName}_default";
//$alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" DROP DEFAULT";
//$alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" SET $matches[3]";
/*$constraint_query="
SELECT OBJECT_NAME(OBJECT_ID) AS NameofConstraint,
SCHEMA_NAME(schema_id) AS SchemaName,
OBJECT_NAME(parent_object_id) AS TableName,
type_desc AS ConstraintType
FROM sys.objects
WHERE type_desc LIKE '%CONSTRAINT' AND OBJECT_NAME(parent_object_id)='{$tableName}' AND type_desc='DEFAULT_CONSTRAINT' AND OBJECT_NAME(OBJECT_ID)='$constraint_name'";
$constraint_result=$this->query($constraint_query)->first();
if($constraint_result){
//$alterCol.= ";\n$prefix DROP DEFAULT";
$alterCol .= ";\n$prefix DROP CONSTRAINT $constraint_name";
}
$alterCol .= ";\n$prefix ADD CONSTRAINT \"$constraint_name\" {$matches[3]} FOR $colName";*/
}
// Add a default back
if(!empty($matches[3])) $alterCol .= ";\n$prefix ADD $matches[3] FOR \"$colName\"";
// SET check constraint (The constraint HAS to be dropped)
if(!empty($matches[4])) {
@ -554,11 +554,52 @@ class MSSQLDatabase extends Database {
public function fieldList($table) {
//This gets us more information than we need, but I've included it all for the moment....
$fields = $this->query("SELECT ordinal_position, column_name, data_type, column_default, is_nullable, character_maximum_length, numeric_precision FROM information_schema.columns WHERE table_name = '$table' ORDER BY ordinal_position;");
$fields = $this->query("SELECT ordinal_position, column_name, data_type, column_default,
is_nullable, character_maximum_length, numeric_precision, numeric_scale
FROM information_schema.columns WHERE table_name = '$table'
ORDER BY ordinal_position;");
$output = array();
if($fields) foreach($fields as $field) {
// Update the data_type field to be a complete column definition string for use by
// Database::requireField()
switch($field['data_type']){
case 'bigint':
case 'numeric':
case 'float':
case 'bit':
if($sizeSuffix = $field['numeric_precision']) {
$field['data_type'] .= "($sizeSuffix)";
}
if($field['is_nullable'] == 'YES') {
$field['data_type'] .= ' null';
} else {
$field['data_type'] .= ' not null';
}
if($field['column_default']) {
$default=substr($field['column_default'], 2, -2);
$field['data_type'] .= " default $default";
}
break;
case 'decimal':
if($field['numeric_precision']) {
$sizeSuffix = $field['numeric_precision'] . ',' . $field['numeric_scale'];
$field['data_type'] .= "($sizeSuffix)";
}
if($field['is_nullable'] == 'YES') {
$field['data_type'] .= ' null';
} else {
$field['data_type'] .= ' not null';
}
if($field['column_default']) {
$default=substr($field['column_default'], 2, -2);
$field['data_type'] .= " default $default";
}
break;
case 'varchar':
//Check to see if there's a constraint attached to this column:
$constraint=$this->ColumnConstraints($table, $field['column_name']);
@ -566,14 +607,28 @@ class MSSQLDatabase extends Database {
$constraints=$this->EnumValuesFromConstraint($constraint['CHECK_CLAUSE']);
$default=substr($field['column_default'], 2, -2);
$field['data_type']=$this->enum(Array('default'=>$default, 'name'=>$field['column_name'], 'enums'=>$constraints, 'table'=>$table));
break;
}
$output[$field['column_name']]=$field;
break;
default:
$output[$field['column_name']] = $field;
$sizeSuffix = $field['character_maximum_length'];
if($sizeSuffix == '-1') $sizeSuffix = 'max';
if($sizeSuffix) {
$field['data_type'] .= "($sizeSuffix)";
}
if($field['is_nullable'] == 'YES') {
$field['data_type'] .= ' null';
} else {
$field['data_type'] .= ' not null';
}
if($field['column_default']) {
$default=substr($field['column_default'], 2, -2);
$field['data_type'] .= " default '$default'";
}
}
$output[$field['column_name']]=$field;
}
return $output;
@ -780,11 +835,15 @@ class MSSQLDatabase extends Database {
//Annoyingly, we need to do a good ol' fashioned switch here:
($values['default']) ? $default='1' : $default='0';
if($asDbValue)
return 'bit';
else
if($asDbValue) {
return array(
'data_type'=>'bit',
'default' => $default
);
} else {
return 'bit not null default ' . $default;
}
}
/**
* Return a date type-formatted string.
@ -793,11 +852,14 @@ class MSSQLDatabase extends Database {
* @return string
*/
public function date($values, $asDbValue=false){
if($asDbValue)
return 'datetime';
else
if($asDbValue) {
return array(
'data_type' => 'decimal',
);
} else {
return 'datetime null';
}
}
/**
* Return a decimal type-formatted string
@ -824,13 +886,24 @@ class MSSQLDatabase extends Database {
* @params array $values Contains a tokenised list of info about this data type
* @return string
*/
public function enum($values){
//Enums are a bit different. We'll be creating a varchar(255) with a constraint of all the usual enum options.
//NOTE: In this one instance, we are including the table name in the values array
public function enum($values, $asDbValue=false){
// Enums are a bit different. We'll be creating a varchar(255) with a constraint of all the
// usual enum options.
// NOTE: In this one instance, we are including the table name in the values array
return "varchar(255) not null default '" . $values['default'] . "' check(\"" . $values['name'] . "\" in ('" . implode('\', \'', $values['enums']) . "'))";
//return "varchar(255) not null check(\"" . $values['name'] . "\" in ('" . implode('\', \'', $values['enums']) . "')); add constraint \"" . $values['table'] . '_' . $values['name'] . "_default\" default '" . $values['default'] . "' for \"" . $values['name'] . "\"";
$maxLength = max(array_map('strlen', $values['enums']));
if($asDbValue) {
return array(
'data_type'=>'varchar',
'default' => $values['default'],
'character_maximum_length'=>$maxLength,
);
} else {
return "varchar($maxLength) not null default '" . $values['default']
. "' check(\"" . $values['name'] . "\" in ('" . implode("','", $values['enums'])
. "'))";
}
}
/**
@ -880,11 +953,15 @@ class MSSQLDatabase extends Database {
* @return string
*/
public function text($values, $asDbValue=false){
if($asDbValue)
return Array('data_type'=>'varchar(max)');
else
if($asDbValue) {
return array(
'data_type'=>'varchar',
'character_maximum_length' => -1,
);
} else {
return 'varchar(max) null';
}
}
/**
* Return a time type-formatted string.
@ -904,7 +981,7 @@ class MSSQLDatabase extends Database {
*/
public function varchar($values, $asDbValue=false){
if($asDbValue)
return Array('data_type'=>'varchar', 'character_maximum_length'=>'255');
return Array('data_type'=>'varchar', 'character_maximum_length'=>$values['precision']);
else
return 'varchar(' . $values['precision'] . ') null';
}
@ -950,11 +1027,11 @@ class MSSQLDatabase extends Database {
function IdColumn($asDbValue=false, $hasAutoIncPK=true){
if($asDbValue)
return 'bigint';
return 'bigint(19) not null';
else {
if($hasAutoIncPK)
return 'bigint identity(1,1)';
else return 'bigint';
return 'bigint(19) identity(1,1)';
else return 'bigint(19) not null';
}
}