Fixing MSSQLDatabase to conform to dev/build change detection

This involves changing a few things around so that it's closer to
how the MySQLDatabase adapter works. indexList() should return an
array in the same format instead of using arbitrary "indexname"
and "spec". indexNames() has also been introduced to MSSQLDatabase
so that we can drop all indexes (except for fulltext and primary key
indexes) on a table when altering the table columns, this helps when
constraints not directly related to a modified column refuse to allow changes.
This commit is contained in:
Sean Harvey 2013-01-07 16:25:31 +13:00
parent 91548f76be
commit d6a075f9c7

View File

@ -613,8 +613,11 @@ class MSSQLDatabase extends SS_Database {
// drop the index if it exists
$alterCol='';
$indexName = isset($indexList[$colName]['indexname']) ? $indexList[$colName]['indexname'] : null;
if($indexName && $colName != 'ID') {
// drop *ALL* indexes on a table before proceeding
// this won't drop primary keys, though
$indexes = $this->indexNames($tableName);
foreach($indexes as $indexName) {
$alterCol = "\nDROP INDEX \"$indexName\" ON \"$tableName\";";
}
@ -815,10 +818,10 @@ class MSSQLDatabase extends SS_Database {
* Some indexes may be arrays, such as fulltext and unique indexes, and this allows database-specific
* arrays to be created.
*/
public function convertIndexSpec($indexSpec){
if(is_array($indexSpec)){
public function convertIndexSpec($indexSpec) {
if(is_array($indexSpec)) {
//Here we create a db-specific version of whatever index we need to create.
switch($indexSpec['type']){
switch($indexSpec['type']) {
case 'fulltext':
$indexSpec='fulltext (' . str_replace(' ', '', $indexSpec['value']) . ')';
break;
@ -906,34 +909,50 @@ class MSSQLDatabase extends SS_Database {
foreach($indexes as $index) {
if(strpos($index['index_description'], 'unique') !== false) {
$prefix='unique ';
$prefix = 'unique ';
}
$key = str_replace(', ', ',', $index['index_keys']);
$indexList[$key]['indexname'] = $index['index_name'];
$indexList[$key]['spec'] = $prefix . '(' . $key . ')';
$name = str_replace(', ', ',', $index['index_keys']);
// ensure each piece of the index name is quoted, e.g. RecordID,Version
// should be "RecordID","Version"
$fields = explode(',', $name);
if(!$fields) $fields = array($name);
ksort($fields);
$indexList[$name] = $prefix . '("' . implode('","', $fields) . '")';
}
// Now we need to check to see if we have any fulltext indexes attached to this table:
// separately build up a list of the fulltext indexes for this table
// as MSSQL doesn't return fulltext indexes in sp_helpindex
if($this->fullTextEnabled()) {
$result = DB::query('EXEC sp_help_fulltext_columns;');
$columns = '';
$columns = array();
foreach($result as $row) {
if($row['TABLE_NAME'] == $table) {
$columns .= $row['FULLTEXT_COLUMN_NAME'] . ',';
$columns[] = $row['FULLTEXT_COLUMN_NAME'];
}
}
if($columns!=''){
$columns=trim($columns, ',');
$indexList['SearchFields']['indexname'] = 'SearchFields';
$indexList['SearchFields']['spec'] = 'fulltext (' . $columns . ')';
}
$indexList['SearchFields'] = 'fulltext ("' . implode('","', $columns) . '")';
}
return $indexList;
}
/**
* For a given table name, get all the internal index names,
* except for those that are primary keys and fulltext indexes.
*
* @return array
*/
public function indexNames($tableName) {
return $this->query(sprintf('SELECT ind.name FROM sys.indexes ind
INNER JOIN sys.tables t ON ind.object_id = t.object_id
WHERE is_primary_key = 0 AND t.name = \'%s\'', $tableName))->column();
}
/**
* Returns a list of all the tables in the database.
* Table names will all be in lowercase.