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) { if($alteredFields) {
foreach($alteredFields as $k => $v) { foreach($alteredFields as $k => $v) {
$val=$this->alterTableAlterColumn($tableName, $k, $v, $indexList); $val=$this->alterTableAlterColumn($tableName, $k, $v, $indexList);
if($val!='') if($val!='')
$alterList[] .= $val; $alterList[] .= $val;
@ -405,6 +404,21 @@ class MSSQLDatabase extends Database {
return $constraint; 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: * Get the actual enum fields from the constraint value:
*/ */
@ -450,34 +464,20 @@ class MSSQLDatabase extends Database {
} }
$prefix="ALTER TABLE \"" . $tableName . "\" "; $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])) { 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 // SET null / not null
if(!empty($matches[2])) $alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1] $matches[2]"; if(!empty($matches[2])) $alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1] $matches[2]";
// SET default (we drop it first, for reasons of precaution) // Add a default back
//TODO: changing default values not implemented yet: if(!empty($matches[3])) $alterCol .= ";\n$prefix ADD $matches[3] FOR \"$colName\"";
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";*/
}
// SET check constraint (The constraint HAS to be dropped) // SET check constraint (The constraint HAS to be dropped)
if(!empty($matches[4])) { if(!empty($matches[4])) {
@ -554,11 +554,52 @@ class MSSQLDatabase extends Database {
public function fieldList($table) { public function fieldList($table) {
//This gets us more information than we need, but I've included it all for the moment.... //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(); $output = array();
if($fields) foreach($fields as $field) { 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']){ 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': case 'varchar':
//Check to see if there's a constraint attached to this column: //Check to see if there's a constraint attached to this column:
$constraint=$this->ColumnConstraints($table, $field['column_name']); $constraint=$this->ColumnConstraints($table, $field['column_name']);
@ -566,14 +607,28 @@ class MSSQLDatabase extends Database {
$constraints=$this->EnumValuesFromConstraint($constraint['CHECK_CLAUSE']); $constraints=$this->EnumValuesFromConstraint($constraint['CHECK_CLAUSE']);
$default=substr($field['column_default'], 2, -2); $default=substr($field['column_default'], 2, -2);
$field['data_type']=$this->enum(Array('default'=>$default, 'name'=>$field['column_name'], 'enums'=>$constraints, 'table'=>$table)); $field['data_type']=$this->enum(Array('default'=>$default, 'name'=>$field['column_name'], 'enums'=>$constraints, 'table'=>$table));
break;
} }
$output[$field['column_name']]=$field;
break;
default: 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; return $output;
@ -780,11 +835,15 @@ class MSSQLDatabase extends Database {
//Annoyingly, we need to do a good ol' fashioned switch here: //Annoyingly, we need to do a good ol' fashioned switch here:
($values['default']) ? $default='1' : $default='0'; ($values['default']) ? $default='1' : $default='0';
if($asDbValue) if($asDbValue) {
return 'bit'; return array(
else 'data_type'=>'bit',
'default' => $default
);
} else {
return 'bit not null default ' . $default; return 'bit not null default ' . $default;
} }
}
/** /**
* Return a date type-formatted string. * Return a date type-formatted string.
@ -793,11 +852,14 @@ class MSSQLDatabase extends Database {
* @return string * @return string
*/ */
public function date($values, $asDbValue=false){ public function date($values, $asDbValue=false){
if($asDbValue) if($asDbValue) {
return 'datetime'; return array(
else 'data_type' => 'decimal',
);
} else {
return 'datetime null'; return 'datetime null';
} }
}
/** /**
* Return a decimal type-formatted string * 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 * @params array $values Contains a tokenised list of info about this data type
* @return string * @return string
*/ */
public function enum($values){ 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. // Enums are a bit different. We'll be creating a varchar(255) with a constraint of all the
//NOTE: In this one instance, we are including the table name in the values array // 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']) . "'))"; $maxLength = max(array_map('strlen', $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'] . "\"";
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 * @return string
*/ */
public function text($values, $asDbValue=false){ public function text($values, $asDbValue=false){
if($asDbValue) if($asDbValue) {
return Array('data_type'=>'varchar(max)'); return array(
else 'data_type'=>'varchar',
'character_maximum_length' => -1,
);
} else {
return 'varchar(max) null'; return 'varchar(max) null';
} }
}
/** /**
* Return a time type-formatted string. * Return a time type-formatted string.
@ -904,7 +981,7 @@ class MSSQLDatabase extends Database {
*/ */
public function varchar($values, $asDbValue=false){ public function varchar($values, $asDbValue=false){
if($asDbValue) if($asDbValue)
return Array('data_type'=>'varchar', 'character_maximum_length'=>'255'); return Array('data_type'=>'varchar', 'character_maximum_length'=>$values['precision']);
else else
return 'varchar(' . $values['precision'] . ') null'; return 'varchar(' . $values['precision'] . ') null';
} }
@ -950,11 +1027,11 @@ class MSSQLDatabase extends Database {
function IdColumn($asDbValue=false, $hasAutoIncPK=true){ function IdColumn($asDbValue=false, $hasAutoIncPK=true){
if($asDbValue) if($asDbValue)
return 'bigint'; return 'bigint(19) not null';
else { else {
if($hasAutoIncPK) if($hasAutoIncPK)
return 'bigint identity(1,1)'; return 'bigint(19) identity(1,1)';
else return 'bigint'; else return 'bigint(19) not null';
} }
} }