/** * This method can update the values in mulitple database rows for a colum with * a unique index, without violating that constraint. * * Suppose we have a table with a unique index on (otherid, sortorder), and * for a particular value of otherid, we want to change all the sort orders. * You have to do this carefully or you will violate the unique index at some time. * This method takes care of the details for you. * * Note that, it is the responsibility of the caller to make sure that the * requested rename is legal. For example, if you ask for [1 => 2, 2 => 2] * then you will get a unique key violation error from the database. * * @param string $table The database table to modify. * @param string $field the field that contains the values we are going to change. * @param array $newvalues oldvalue => newvalue how to change the values. * E.g. [1 => 4, 2 => 1, 3 => 3, 4 => 2]. * @param array $otherconditions array fieldname => requestedvalue extra WHERE clause * conditions to restrict which rows are affected. E.g. array('otherid' => 123). * @param int $unusedvalue (defaults to -1) a value that is never used in $ordercol. */ function update_field_with_unique_index($table, $field, array $newvalues, array $otherconditions, $unusedvalue = -1) { global $DB; $safechanges = decompose_update_into_safe_changes($newvalues, $unusedvalue); $transaction = $DB->start_delegated_transaction(); foreach ($safechanges as $change) { list($from, $to) = $change; $otherconditions[$field] = $from; $DB->set_field($table, $field, $to, $otherconditions); } $transaction->allow_commit(); }
public function test_decompose_update_into_safe_changes_string_values() { // Sometimes this happens when data has been loaded from the database. $this->assertEquals(array(array(1, -1), array(2, 1), array(3, 2), array(4, 3), array(-1, 4)), decompose_update_into_safe_changes(array(1 => '4', 2 => '1', 3 => '2', 4 => '3'), -1)); }