Moodle
  1. Moodle
  2. MDL-26981

Restore of random question states sets incorrect question id in question_states (1.9)

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.9.8, 1.9.10, 1.9.11
    • Fix Version/s: 1.9.12
    • Component/s: Backup, Questions
    • Environment:
      Linux x86_64, PHP 5.3.3
    • Database:
      MySQL
    • Testing Instructions:
      Hide

      1. In Moodle 1.9, create a quiz and add a random question to it that selects from a category with two questions in it.

      2. Attempt the quiz as a student.

      3. Backup the course with userdata.

      4. Restore the course.

      5. Look in the database to verify that question_states.question points to the newly restored random question, not the random question from the old course. (I can't think of an easy way to verify this through the Moodle UI.)

      Show
      1. In Moodle 1.9, create a quiz and add a random question to it that selects from a category with two questions in it. 2. Attempt the quiz as a student. 3. Backup the course with userdata. 4. Restore the course. 5. Look in the database to verify that question_states.question points to the newly restored random question, not the random question from the old course. (I can't think of an easy way to verify this through the Moodle UI.)
    • Affected Branches:
      MOODLE_19_STABLE
    • Fixed Branches:
      MOODLE_19_STABLE
    • Pull from Repository:
    • Rank:
      17009

      Description

      When restoring random questions states in 1.9, the question column in the question_states tables gets assigned the wrong value. The defect is in function restore_recode_answer in question/type/random/questiontype.php.

      That function gets an object reference $state parameter from the caller (which is function question_states_restore_mods in question/restorelib.php). The function then assigns the reference to another variable and proceeds to modify the referent, which is the question_state that the caller is about to insert into the database. Here are a couple of lines from restore_recode_answer.

      $newstate = $state;
      $newstate->question = $wrapped->new_id;

      The fix could be as simple as changing the first line to

      $newstate = clone($state);

      Here is what this looks like in databases using fresh installs...

      The source system has the following:

      mysql> select id, name, qtype from mdl_question;
      ------------------------------------------------------------

      id name qtype

      ------------------------------------------------------------

      1 sky color shortanswer
      2 grass color shortanswer
      3 Random Question (Default for Random Question) random

      ------------------------------------------------------------

      mysql> select attempt, question, answer from mdl_question_states where seq_number=2;
      ------------------------------

      attempt question answer

      ------------------------------

      11 3 random2-green

      ------------------------------

      After backing up and restoring in another fresh database, we get this:

      mysql> select id, name, qtype from mdl_question where id in (1,2,3);
      ------------------------------------------------------------

      id name qtype

      ------------------------------------------------------------

      1 sky color shortanswer
      2 grass color shortanswer
      3 Random Question (Default for Random Question) random

      ------------------------------------------------------------

      mysql> select attempt, question, answer from mdl_question_states where seq_number=2 and attempt=2;
      ------------------------------

      attempt question answer

      ------------------------------

      2 2 random2-green

      ------------------------------

      Note that the value of the question column is '2' rather than '3'. The correct question id is '3' because that is the id of the random question on the quiz. The 'random2' in the answer is correct because question 2 was actually question randomly presented to the user. The faulty logic, however, incorrectly results in using the id embedded in the answer as the question value.

      After changing the code to use the clone function, we get something that looks like this, which appears to be correct.

      mysql> select id, name, qtype from mdl_question where id in (28,29,30);
      ------------------------------------------------------------

      id name qtype

      ------------------------------------------------------------

      28 sky color shortanswer
      29 grass color shortanswer
      30 Random Question (Default for Random Question) random

      ------------------------------------------------------------

      mysql> select attempt, question, answer from mdl_question_states where seq_number=2 and attempt=20;
      -------------------------------

      attempt question answer

      -------------------------------

      20 30 random29-green

      -------------------------------

      I don't know all the implications of this defect, but this is how we noticed it. We are migrating courses from 1.9 to 2.0 by
      1) backing up from 1.9 production,
      2) restoring into a 1.9 "migration" instance,
      3) upgrading the migration instance to 2.0,
      4) backing up the course from the 2.0 migration instance, and
      5) restoring the course into 2.0 production.

      On the transitory migration instance, even though we have corrupt data due to this defect, we have not noticed any issues. Our problem appears when we backup and restore the upgraded course to complete the migration. On the production 2.0 system, the quiz review displays the wrong random questions; the questions it displays are typically not even in the pool of questions for that random question. Although some warnings appeared during the 2.0 backup or restore, their significance was unclear because the actual data corruption occurs in the 1.9 restore.

        Activity

        Hide
        Tim Hunt added a comment -

        On a quick superficial look, the analysis looks correct. I am not quite sure whey adding the clone fixes things, but again it seems plausible, and I don't want to think deeply about it now.

        Show
        Tim Hunt added a comment - On a quick superficial look, the analysis looks correct. I am not quite sure whey adding the clone fixes things, but again it seems plausible, and I don't want to think deeply about it now.
        Hide
        Elena Ivanova added a comment -

        p.s. we have applied fix, suggested by Colin above, and run through the backup/restore again.
        Everything worked OK this time

        Show
        Elena Ivanova added a comment - p.s. we have applied fix, suggested by Colin above, and run through the backup/restore again. Everything worked OK this time
        Hide
        Tim Hunt added a comment -

        This issue affects 1.9 only.

        Show
        Tim Hunt added a comment - This issue affects 1.9 only.
        Hide
        Tim Hunt added a comment -

        Reviewed.

        Show
        Tim Hunt added a comment - Reviewed.
        Hide
        Eloy Lafuente (stronk7) added a comment -

        Integrated, thanks!

        Show
        Eloy Lafuente (stronk7) added a comment - Integrated, thanks!
        Hide
        David Mudrak added a comment -

        Tested successfully on PostgreSQL 9.0.3/PHP 5.3.6

        Show
        David Mudrak added a comment - Tested successfully on PostgreSQL 9.0.3/PHP 5.3.6
        Hide
        Eloy Lafuente (stronk7) added a comment -

        Closing as fixed. Many (1.9 exactly) thanks!

        Show
        Eloy Lafuente (stronk7) added a comment - Closing as fixed. Many (1.9 exactly) thanks!

          People

          • Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: