Skip to content
Snippets Groups Projects
Unverified Commit 2d845385 authored by Michael Terry's avatar Michael Terry Committed by GitHub
Browse files

Merge pull request #23399 from edx/mikix/update-subquery

Avoid subquery on table being updated
parents cfca8ef9 3775fb1d
No related branches found
Tags release-2020-03-16-08.06
No related merge requests found
......@@ -242,29 +242,33 @@ class ResetScheduleTests(SharedModuleStoreTestCase):
self.enrollment = CourseEnrollmentFactory(
course_id=self.course.id,
mode=CourseMode.AUDIT,
is_active=False,
)
self.schedule = self.enrollment.schedule
self.user = self.enrollment.user
def test_schedule_is_reset_after_enrollment_change(self):
""" Test that an update in enrollment causes a schedule reset. """
original_start = self.schedule.start_date
CourseEnrollment.enroll(self.enrollment.user, self.course.id, mode=CourseMode.VERIFIED)
CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.VERIFIED)
self.schedule.refresh_from_db()
self.assertGreater(self.schedule.start_date, original_start) # should have been reset to current time
def test_schedule_is_reset_to_availabilty_date(self):
""" Test that a switch to audit enrollment resets to the availabilty date, not current time. """
def test_schedule_is_reset_to_availability_date(self):
""" Test that a switch to audit enrollment resets to the availability date, not current time. """
original_start = self.schedule.start_date
# Switch to verified, confirm we change start date
CourseEnrollment.enroll(self.enrollment.user, self.course.id, mode=CourseMode.VERIFIED)
CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.VERIFIED)
self.schedule.refresh_from_db()
self.assertNotEqual(self.schedule.start_date, original_start)
CourseEnrollment.unenroll(self.user, self.course.id)
# Switch back to audit, confirm we change back to original availability date
CourseEnrollment.enroll(self.enrollment.user, self.course.id, mode=CourseMode.AUDIT)
CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.AUDIT)
self.schedule.refresh_from_db()
self.assertEqual(self.schedule.start_date, original_start)
......
......@@ -8,6 +8,7 @@ from django.db.models import F, Subquery
from django.db.models.functions import Greatest
from openedx.core.djangoapps.schedules.models import Schedule
from student.models import CourseEnrollment
LOG = logging.getLogger(__name__)
......@@ -54,7 +55,18 @@ def reset_self_paced_schedule(user, course_key, use_availability_date=False):
)
if use_availability_date:
schedule = schedule.annotate(start_of_access=Greatest(F('enrollment__created'), F('enrollment__course__start')))
schedule.update(start_date=Subquery(schedule.values('start_of_access')[:1]))
# Query enrollments to find availability date -- very similar to query above, but we can't reuse that query
# object because mysql doesn't like a subquery of an update to reference the same table being updated.
# Be careful attempting to remove this logic because you can't reproduce a problem locally -- in my own testing,
# I could not reproduce in devstack, but it was happening on prod databases. So implementations vary.
# See https://dev.mysql.com/doc/refman/8.0/en/subquery-restrictions.html
enrollments = CourseEnrollment.objects.filter(
user=user,
course__id=course_key,
course__self_paced=True,
).annotate(
availability=Greatest(F('created'), F('course__start')),
)
schedule.update(start_date=Subquery(enrollments.values('availability')[:1]))
else:
schedule.update(start_date=datetime.datetime.now(pytz.utc))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment