Merge branch 'MDL-83153-main-option1-2' of https://github.com/junpataleta/moodle

This commit is contained in:
Sara Arjona 2024-09-18 16:39:35 +02:00
commit 3c712cbea3
No known key found for this signature in database
5 changed files with 192 additions and 4 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20240912" COMMENT="XMLDB file for core Moodle tables"
<XMLDB PATH="lib/db" VERSION="20240916" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
@ -4891,7 +4891,7 @@
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="actionname" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false" COMMENT="Name of the action"/>
<FIELD NAME="actionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID in related action table with more details about the action"/>
<FIELD NAME="success" TYPE="binary" NOTNULL="true" SEQUENCE="false" COMMENT="Was the action successful when run"/>
<FIELD NAME="success" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Was the action successful when run"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user who made the request to run the action"/>
<FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The id of the context the action request was made in"/>
<FIELD NAME="provider" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false" COMMENT="The provider plugin name that processed the action"/>

View File

@ -1297,7 +1297,7 @@ function xmldb_main_upgrade($oldversion) {
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('actionname', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
$table->add_field('actionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('success', XMLDB_TYPE_BINARY, null, null, XMLDB_NOTNULL, null, null);
$table->add_field('success', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
$table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('provider', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
@ -1365,5 +1365,13 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2024091000.01);
}
if ($oldversion < 2024091700.01) {
// Convert the ai_action_register.success column to an integer, if necessary.
upgrade_change_binary_column_to_int('ai_action_register', 'success', XMLDB_NOTNULL, 'actionid');
// Main savepoint reached.
upgrade_main_savepoint(true, 2024091700.01);
}
return true;
}

View File

@ -1821,3 +1821,88 @@ function upgrade_add_foreign_key_and_indexes() {
// Launch add key contextid.
$dbman->add_key($table, $key);
}
/**
* Upgrade helper to change a binary column to an integer column with a length of 1 in a consistent manner across databases.
*
* This function will
* - rename the existing column to a temporary name,
* - add a new column with the integer type,
* - copy the values from the old column to the new column,
* - and finally, drop the old column.
*
* This function will do nothing if the field is already an integer.
*
* The new column with the integer type will need to have a default value of 0.
* This is to avoid breaking the not null constraint, if it's set, especially if there are existing records.
* Please make sure that the column definition in install.xml also has the `DEFAULT` attribute value set to 0.
*
* @param string $tablename The name of the table.
* @param string $fieldname The name of the field to be converted.
* @param bool|null $notnull {@see XMLDB_NOTNULL} or null.
* @param string|null $previous The name of the field that this field should come after.
* @return bool
*/
function upgrade_change_binary_column_to_int(
string $tablename,
string $fieldname,
?bool $notnull = null,
?string $previous = null,
): bool {
global $DB;
// Get the information about the field to be converted.
$columns = $DB->get_columns($tablename);
$toconvert = $columns[$fieldname];
// Check if the field to be converted is already an integer-type column (`meta_type` property of 'I').
if ($toconvert->meta_type === 'I') {
// Nothing to do if the field is already an integer-type.
return false;
} else if (!$toconvert->binary) {
throw new \core\exception\coding_exception(
'This function is only used to convert XMLDB_TYPE_BINARY fields to XMLDB_TYPE_INTEGER fields. '
. 'For other field types, please check out \database_manager::change_field_type()'
);
}
$dbman = $DB->get_manager();
$table = new xmldb_table($tablename);
// Temporary rename the field. We'll drop this later.
$tmpfieldname = "tmp$fieldname";
$field = new xmldb_field($fieldname, XMLDB_TYPE_BINARY);
$dbman->rename_field($table, $field, $tmpfieldname);
// Add the new field wih the integer type.
$field = new xmldb_field($fieldname, XMLDB_TYPE_INTEGER, '1', null, $notnull, null, '0', $previous);
$dbman->add_field($table, $field);
// Copy the 'true' values from the old field to the new field.
if ($DB->get_dbfamily() === 'oracle') {
// It's tricky to use the binary column in the WHERE clause in Oracle DBs.
// Let's go updating the records one by one. It's nasty, but it's only done for instances with Oracle DBs.
// The normal SQL UPDATE statement will be used for other DBs.
$columns = implode(', ', ['id', $tmpfieldname, $fieldname]);
$records = $DB->get_recordset($tablename, null, '', $columns);
if ($records->valid()) {
foreach ($records as $record) {
if (!$record->$tmpfieldname) {
continue;
}
$DB->set_field($tablename, $fieldname, 1, ['id' => $record->id]);
}
}
$records->close();
} else {
$sql = 'UPDATE {' . $tablename . '}
SET ' . $fieldname . ' = 1
WHERE ' . $tmpfieldname . ' = ?';
$DB->execute($sql, [1]);
}
// Drop the old field.
$oldfield = new xmldb_field($tmpfieldname);
$dbman->drop_field($table, $oldfield);
return true;
}

View File

@ -1640,4 +1640,99 @@ calendar,core_calendar|/calendar/view.php?view=month',
$upgrade = get_config('core', 'upgraderunning');
$this->assertFalse($upgrade);
}
/**
* Data provider for {@see test_upgrade_change_binary_column_to_int()}.
*
* @return array[]
*/
public static function upgrade_change_binary_column_to_int_provider(): array {
return [
'Binary column' => [
XMLDB_TYPE_BINARY,
null,
true,
false,
],
'Integer column' => [
XMLDB_TYPE_INTEGER,
'1',
false,
false,
],
'Non-binary and non-integer column' => [
XMLDB_TYPE_TEXT,
null,
false,
true,
],
];
}
/**
* Unit test for {@see upgrade_change_binary_column_to_int()}.
*
* @dataProvider upgrade_change_binary_column_to_int_provider
* @covers ::upgrade_change_binary_column_to_int()
* @param int $type The field type.
* @param string|null $length The field length.
* @param bool $expectedresult Whether the conversion succeeded.
* @param bool $expecexception Whether to expect an exception.
* @return void
*/
public function test_upgrade_change_binary_column_to_int(
int $type,
?string $length,
bool $expectedresult,
bool $expecexception,
): void {
global $DB;
$this->resetAfterTest();
$dbman = $DB->get_manager();
$tmptablename = 'test_convert_table';
$fieldname = 'success';
$table = new xmldb_table($tmptablename);
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE);
$table->add_field($fieldname, $type, $length, null, XMLDB_NOTNULL);
$table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
$dbman->create_table($table);
// Insert sample data.
$ones = [];
$truerecord = (object)[$fieldname => 1];
$falserecord = (object)[$fieldname => 0];
$ones[] = $DB->insert_record($tmptablename, $truerecord);
$DB->insert_record($tmptablename, $falserecord);
$ones[] = $DB->insert_record($tmptablename, $truerecord);
$DB->insert_record($tmptablename, $falserecord);
$ones[] = $DB->insert_record($tmptablename, $truerecord);
$ones[] = $DB->insert_record($tmptablename, $truerecord);
if ($expecexception) {
$this->expectException(coding_exception::class);
}
$result = upgrade_change_binary_column_to_int($tmptablename, $fieldname);
$this->assertEquals($expectedresult, $result);
// Verify converted column and data.
if ($result) {
$columns = $DB->get_columns($tmptablename);
// Verify the new field has been created and is no longer a binary field.
$this->assertArrayHasKey($fieldname, $columns);
$field = $columns[$fieldname];
$this->assertFalse($field->binary);
// Verify that the renamed old field has now been removed.
$this->assertArrayNotHasKey("tmp$fieldname", $columns);
// Confirm that the values for the converted column are the same.
$records = $DB->get_fieldset($tmptablename, 'id', [$fieldname => 1]);
$this->assertEqualsCanonicalizing($ones, $records);
}
// Cleanup.
$dbman->drop_table($table);
}
}

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2024091700.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2024091700.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.5dev+ (Build: 20240917)'; // Human-friendly version name