MDL-11270 use NVARCHAR(MAX) and VARBINARY(MAX) in SQL Server

This commit is contained in:
Petr Škoda
2013-07-26 09:28:50 +02:00
parent bdd045c5ec
commit 656250de83
7 changed files with 138 additions and 9 deletions
+7
View File
@@ -2306,5 +2306,12 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2013071500.02);
}
if ($oldversion < 2013072600.01) {
upgrade_mssql_nvarcharmax();
upgrade_mssql_varbinarymax();
upgrade_main_savepoint(true, 2013072600.01);
}
return true;
}
+106
View File
@@ -164,3 +164,109 @@ function upgrade_mysql_fix_unsigned_and_lob_columns() {
$pbar->update($i, $tablecount, "Converted unsigned/lob columns in MySQL database - $i/$tablecount.");
}
}
/**
* Migrate NTEXT to NVARCHAR(MAX).
*/
function upgrade_mssql_nvarcharmax() {
global $DB;
if ($DB->get_dbfamily() !== 'mssql') {
return;
}
$pbar = new progress_bar('mssqlconvertntext', 500, true);
$prefix = $DB->get_prefix();
$tables = $DB->get_tables(false);
$tablecount = count($tables);
$i = 0;
foreach ($tables as $table) {
$i++;
$columns = array();
$sql = "SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{{$table}}' AND UPPER(data_type) = 'NTEXT'";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $column) {
$columns[] = $column->column_name;
}
$rs->close();
if ($columns) {
// Set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case.
$count = $DB->count_records($table, array());
$timeout = ($count/1000)*60;
$timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout;
upgrade_set_timeout($timeout);
$updates = array();
foreach ($columns as $column) {
// Change the definition.
$sql = "ALTER TABLE {$prefix}$table ALTER COLUMN $column NVARCHAR(MAX)";
$DB->change_database_structure($sql);
$updates[] = "$column = $column";
}
// Now force the migration of text data to new optimised storage.
$sql = "UPDATE {{$table}} SET ".implode(', ', $updates);
$DB->execute($sql);
}
$pbar->update($i, $tablecount, "Converted NTEXT to NVARCHAR(MAX) columns in MS SQL Server database - $i/$tablecount.");
}
}
/**
* Migrate IMAGE to VARBINARY(MAX).
*/
function upgrade_mssql_varbinarymax() {
global $DB;
if ($DB->get_dbfamily() !== 'mssql') {
return;
}
$pbar = new progress_bar('mssqlconvertimage', 500, true);
$prefix = $DB->get_prefix();
$tables = $DB->get_tables(false);
$tablecount = count($tables);
$i = 0;
foreach ($tables as $table) {
$i++;
$columns = array();
$sql = "SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{{$table}}' AND UPPER(data_type) = 'IMAGE'";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $column) {
$columns[] = $column->column_name;
}
$rs->close();
if ($columns) {
// Set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case.
$count = $DB->count_records($table, array());
$timeout = ($count/1000)*60;
$timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout;
upgrade_set_timeout($timeout);
foreach ($columns as $column) {
// Change the definition.
$sql = "ALTER TABLE {$prefix}$table ALTER COLUMN $column VARBINARY(MAX)";
$DB->change_database_structure($sql);
}
// Binary columns should not be used, do not waste time optimising the storage.
}
$pbar->update($i, $tablecount, "Converted IMAGE to VARBINARY(MAX) columns in MS SQL Server database - $i/$tablecount.");
}
}
+2 -2
View File
@@ -221,10 +221,10 @@ class mssql_sql_generator extends sql_generator {
$dbtype .= '(' . $xmldb_length . ')';
break;
case XMLDB_TYPE_TEXT:
$dbtype = 'NTEXT';
$dbtype = 'NVARCHAR(MAX)';
break;
case XMLDB_TYPE_BINARY:
$dbtype = 'IMAGE';
$dbtype = 'VARBINARY(MAX)';
break;
case XMLDB_TYPE_DATETIME:
$dbtype = 'DATETIME';
+10 -3
View File
@@ -464,9 +464,15 @@ class mssql_native_moodle_database extends moodle_database {
// id columns being auto_incremnt are PK by definition
$info->primary_key = ($info->name == 'id' && $info->meta_type == 'R' && $info->auto_increment);
// Put correct length for character and LOB types
$info->max_length = $info->meta_type == 'C' ? $rawcolumn->char_max_length : $rawcolumn->max_length;
$info->max_length = ($info->meta_type == 'X' || $info->meta_type == 'B') ? -1 : $info->max_length;
if ($info->meta_type === 'C' and $rawcolumn->char_max_length == -1) {
// This is NVARCHAR(MAX), not a normal NVARCHAR.
$info->max_length = -1;
$info->meta_type = 'X';
} else {
// Put correct length for character and LOB types
$info->max_length = $info->meta_type == 'C' ? $rawcolumn->char_max_length : $rawcolumn->max_length;
$info->max_length = ($info->meta_type == 'X' || $info->meta_type == 'B') ? -1 : $info->max_length;
}
// Scale
$info->scale = $rawcolumn->scale ? $rawcolumn->scale : false;
@@ -573,6 +579,7 @@ class mssql_native_moodle_database extends moodle_database {
$type = 'X';
break;
case 'IMAGE':
case 'VARBINARY':
case 'VARBINARY(MAX)':
$type = 'B';
break;
+10 -3
View File
@@ -528,9 +528,15 @@ class sqlsrv_native_moodle_database extends moodle_database {
// id columns being auto_incremnt are PK by definition
$info->primary_key = ($info->name == 'id' && $info->meta_type == 'R' && $info->auto_increment);
// Put correct length for character and LOB types
$info->max_length = $info->meta_type == 'C' ? $rawcolumn->char_max_length : $rawcolumn->max_length;
$info->max_length = ($info->meta_type == 'X' || $info->meta_type == 'B') ? -1 : $info->max_length;
if ($info->meta_type === 'C' and $rawcolumn->char_max_length == -1) {
// This is NVARCHAR(MAX), not a normal NVARCHAR.
$info->max_length = -1;
$info->meta_type = 'X';
} else {
// Put correct length for character and LOB types
$info->max_length = $info->meta_type == 'C' ? $rawcolumn->char_max_length : $rawcolumn->max_length;
$info->max_length = ($info->meta_type == 'X' || $info->meta_type == 'B') ? -1 : $info->max_length;
}
// Scale
$info->scale = $rawcolumn->scale ? $rawcolumn->scale : false;
@@ -645,6 +651,7 @@ class sqlsrv_native_moodle_database extends moodle_database {
break;
case 'IMAGE':
case 'VARBINARY':
case 'VARBINARY(MAX)':
$type = 'B';
break;
+2
View File
@@ -11,6 +11,8 @@ information provided here is intended especially for developers.
* Use core_text::* instead of textlib:: and also core_collator::* instead of collatorlib::*.
* Use new function moodleform::mock_submit() to simulate form submission in unit tests (backported).
* New $CFG->localcachedir setting useful for cluster nodes. Admins have to update X-Sendfile aliases if used.
* MS SQL Server drivers are now using NVARCHAR(MAX) instead of NTEXT and VARBINARY(MAX) instead of IMAGE,
this change should be fully transparent and it should help significantly with add-on compatibility.
DEPRECATIONS:
Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices
+1 -1
View File
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2013072600.00; // YYYYMMDD = weekly release date of this DEV branch
$version = 2013072600.01; // YYYYMMDD = weekly release date of this DEV branch
// RR = release increments - 00 in DEV branches
// .XX = incremental changes