Details
-
Type:
Bug
-
Status:
Resolved
-
Priority:
Blocker
-
Resolution: Fixed
-
Affects Version/s: 1.9
-
Fix Version/s: 1.9.1
-
Component/s: Module: Questionnaire
-
Labels:None
-
Environment:PostgreSQL 8.1.9 on Red Hat
-
Database:PostgreSQL
-
Affected Branches:MOODLE_19_STABLE
-
Fixed Branches:MOODLE_19_STABLE
Description
I have encountered some bugs which appear to be postgres-specific when upgrading to the latest version of Questionnaire.
I was attempting to upgrade to the latest version of Questionnaire downloaded from the MOODLE_19_STABLE branch on cvs.moodle.org. Our previous version of this plugin would have been based on approximately version 1.20.2.1
There appear to be two issues: please see attachment for more complete error messages.
Warning: pg_query() [function.pg-query]: Query failed: ERROR: value too long for type character varying(20) in /var/www/html/gcm77/moodle23/lib/adodb/drivers/adodb-postgres7.inc.php on line 115
-1: ERROR: value too long for type character varying(20)
This appears to be due to conversion of the field "changed" in the questionnaire_survey table from a timestamp into an integer via the intermediate format of a character(20) field - however, the default value of this field in postgres was now(), which results in a high-precision timestamp such as '2008-01-09 15:22:24.728441' which will not fit into a 20-char field.
Therefore, I propose changing this to a character(30) to allow a bit of leeway.
The second one, "Query failed: ERROR: check constraint "mdl23_quesques_req_ck" is violated by some row in
/var/www/html/gcm77/moodle23/lib/adodb/drivers/adodb-postgres7.inc.php on line 115"
This appears to be due to the part of the upgrade script that attempts to change the enumeration on the field "required" on <prefix>_questionnaire_question to lowercase 'y'/'n'. It was originally upper case 'Y'/'N'. It does not appear actually to convert the value, only attempt to apply the new constraint. It also does not appear to delete the old constraint.
I'm told that a likely reason is that MySQL is case-insensitive with regard to enums, although I don't have enough MySQL experience to verify this, but it would be good if the upgrade script could be modified to remove the old constraint, change the existing Y/N values to lower case, and then put the new constraint in place, when dealing with Postgres databases.
One possibility might be to amend the method getModifyEnumSQL or one of the methods that that calls, to perform the extra steps according to database type. I have been advised to speak to Eloy Lafuente about this.
I will keep this Tracker entry posted as to any discussion that I have, and its outcomes.
Attachments
Issue Links
| This issue blocks: | ||||
| CONTRIB-106 | Upgrade Questionnaire module for Roles and Capabilities |
|
|
|
| This issue will be resolved by: | ||||
| CONTRIB-343 | Module: Questionnaire - Installation error with changed field default value during creation of questionnaire_survey table |
|
|
|
While looking to sort out a proper solution, I coded a work-around for this problem and then encountered another related one: (I had to put an error_reporting(E_ALL) into the code to get the actual error message)
--------------------------------------------------------------------------------
FROM mdl25b_questionnaire_survey
(postgres7): ALTER TABLE mdl25b_questionnaire_response_single_id_seq RENAME TO mdl25b_questionnaire_resp_single_id_seq
--------------------------------------------------------------------------------
Success
--------------------------------------------------------------------------------
(postgres7): SELECT COUNT
--------------------------------------------------------------------------------
Notice: Undefined variable: field in /var/www/html/gcm77/moodle25/mod/questionnaire/db/upgrade.php on line 179
Fatal error: Call to a member function setAttributes() on a non-object in /var/www/html/gcm77/moodle25/mod/questionnaire/db/upgrade.php on line 179
The problem seems to be these lines of code beginning at line 101 of upgrade.php - basically, it only creates the $table and $field objects within the conditional code, but it then attempts to use them after the end of that condition. This probably works if there are records in the 'questionnaire_survey' table, but I was doing an upgrade of a newly-installed environment and there weren't any.
/// Upgrade the questionnaire_survey table to use integer timestamps.
if (($numrecs = count_records('questionnaire_survey')) > 0) {
$table = new XMLDBTable('questionnaire_survey');
$field = new XMLDBField('changed');
$field->setAttributes(XMLDB_TYPE_CHAR, '20');
$status &= change_field_type($table, $field);
$status &= change_field_precision($table, $field);
$recstart = 0;
$recstoget = 100;
while ($recstart < $numrecs) {
if ($records = get_records('questionnaire_survey', '', '', '', '*', $recstart, $recstoget)) {
foreach ($records as $record) { $tstampparts = explode(' ', $record->changed); $dateparts = explode('-', $tstampparts[0]); $timeparts = explode(':', $tstampparts[1]); $time = mktime($timeparts[0], $timeparts[1], $timeparts[2], $dateparts[1], $dateparts[2], $dateparts[0]); $status &= set_field('questionnaire_survey', 'changed', $time, 'id', $record->id); }
}
$recstart += $recstoget;
}
}
$field->setAttributes(XMLDB_TYPE_INTEGER, '10');
$status &= change_field_type($table, $field);
$status &= change_field_precision($table, $field);
/// Upgrade the questionnaire_question_type table to use typeid.
unset($table);
unset($field);
What I've tried is moving the following 5 lines from just inside the IF statement to instead be just before it, and this seems to allow the upgrade to work:
$table = new XMLDBTable('questionnaire_survey');
$field = new XMLDBField('changed');
$field->setAttributes(XMLDB_TYPE_CHAR, '20');
$status &= change_field_type($table, $field);
$status &= change_field_precision($table, $field);