Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foreign key constraint preventing TRUNCATE mdl_grade_grades #154

Open
marxjohnson opened this issue Dec 22, 2022 · 0 comments
Open

Foreign key constraint preventing TRUNCATE mdl_grade_grades #154

marxjohnson opened this issue Dec 22, 2022 · 0 comments

Comments

@marxjohnson
Copy link
Contributor

marxjohnson commented Dec 22, 2022

While testing Moodle 4.1 compatibility, I came across the following issue when running on PostgreSQL 14. I was unable to reproduce it on MySQL. Steps to reproduce:

  • Create a new site and install datacleaner
  • Visit Site Administration > Development > Make test course and create a test course
  • Visit Site Administration > Plugins > Local Plugins > Data cleaner and enable all cleaners. Specifically, I believe you need the course, user and grades cleaners enabled.
  • Satisfy the safeguards and run php admin/local/datacleaner/cli/clean.php --run
  • When running the grades cleaner, the following error is encountered:
== Running grades cleaner ==
 Removing grades         0% (0/2)      
!!! Error writing to database !!!
!! ERROR:  cannot truncate a table referenced in a foreign key constraint
DETAIL:  Table "mdl_competency_usercomp" references "mdl_grade_grades".
HINT:  Truncate table "mdl_competency_usercomp" at the same time, or use TRUNCATE ... CASCADE.
TRUNCATE TABLE mdl_grade_grades
[array (
)]
Error code: dmlwriteexception !!
!! Stack trace: * line 497 of /lib/dml/moodle_database.php: dml_write_exception thrown
* line 293 of /lib/dml/moodle_read_slave_trait.php: call to moodle_database->query_end()
* line 341 of /lib/dml/pgsql_native_moodle_database.php: call to pgsql_native_moodle_database->read_slave_query_end()
* line 846 of /lib/dml/pgsql_native_moodle_database.php: call to pgsql_native_moodle_database->query_end()
* line 2029 of /lib/dml/moodle_database.php: call to pgsql_native_moodle_database->execute()
* line 46 of /local/datacleaner/cleaner/grades/classes/clean.php: call to moodle_database->delete_records()
* line 160 of /local/datacleaner/cli/clean.php: call to cleaner_grades\clean::execute()
 !!

Running with --verbose shows that a foreign key constraint is added from mdl_competency_usercomp.grade to mdl_grade_grades.id. This is also applied to some other competency tables. Because all records are being deleted from the grades table, this is performed with a TRUNCATE which doesn't trigger the ON DELETE CASCADE defined in the foreign key constraint.

It would be possible to avoid this by passing an empty array to the $DB->delete_records() call to force it to use DELETE rather than TRUNCATE. However, I did a test when mdl_competency_usercomp was populated with some data and the constraint was not created, because it correctly detected that this isn't actually a foreign key. The grade field stores an actual grade value, not a reference to a mdl_grade_grades record.

This appears to be a flaw in the logic that decides whether a constraint to be added to a field, as it treats no data as matching data. Perhaps to avoid cases like this we could have a defined list of fields in schema_add_cascade_delete that should never have a constraint added?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant