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
[SE-3220] Add support for multiple statements in the XBlock #12
[SE-3220] Add support for multiple statements in the XBlock #12
Conversation
Thanks for the pull request, @mavidser! I've created OSPR-5080 to keep track of it in JIRA, where we prioritize reviews. Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
a151caf
to
149f9c4
Compare
@mavidser Thank you for your contribution. Please let me know once it is ready for our review. |
625c0cd
to
63774d0
Compare
Allowing multiple statements in @mavidser Please add to the description the summary of the solution when it's final. |
1cbd3bb
to
3915f01
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mavidser Great work!
I requested a few changes. Some of them are about error handling which you can do next sprint.
Other comments (positive 👍), and what I tested:
Code
- the descriptions (e.g. modification_query) are good and concise and include everything (e.g. the fact that modification_query is optional)
- the code isn't too complex (it is because there are many paths, but it didn't grow too much in complexity)
- the code updates the requirements
- I could install it in my devstack (in LMS. My Studio is broken but I tested Studio in the sandbox)
Tests
- the code adds unit tests (there weren't any previously)
- the old tests don't need to be modified
- the new tests are very good and they're complete, including modification_query (with multiple statements) and multiple statements in answer_query
- they use an in-memory database
- they test clever things, like triggers, or combinations of insert+update+select (test_multiple_statements)
- they also test
is_ordered
(to enforce ordering) - and wrong queries
- they pass in my devstack, including quality tests, unit tests, coverage tests
- I read through them (though I didn't have time to check every little detail) and tried modifying them
Usage
- I could submit answers at the sandbox
- It took some time to get feedback about my submission! like 25 seconds… It may be just in our sandboxes. It's not very intuitive to the student
- I saw in the sandbox logs how it runs:
2020-11-01 23:52:52,967 INFO 27057 [codejail] [user 20] subproc.py:47 - Executed jailed code sql_grader in /tmp/codejail-gy8khxdc, with PID 2690
- and I saw feedback about the expected results and my results
- the
To check your data modification statement, we ran the following query after your modification:
text now includes the modification_query too, if present - I didn't test many cases since I'd have to design the problems, which takes time; and I already reviewed the scenarios in the unit tests
- I „solved“ a complex problem that Sid prepared, that has multiple statements in student and modification queries. When I wrote the right trigger (trigger1 from answer_query), it passed
- I found that error handling isn't good yet: if the student writes CRIATE, the query still runs and says „Incorrect“. But we have another task to improve it
Next steps: do the minor fixes. And I think it makes sense to leave the PR open until we add the error handling. Instead of having 2 open PRs that depend on each other. So please keep the WIP tag until all code is ready.
97e54df
to
91f2c1b
Compare
@mavidser Thanks! This is in addition to my previous review. Here I tested the end-user behaviour for student and staff. When the student answer with errors:
When the staff creates a query with errors
So for this new part and for the whole PR: 👍, the code is ready.
@mavidser Some requests:
|
9927fb7
to
a7fa166
Compare
@natabene This is ready for edx's review now 👍 |
Hey @mavidser ; thanks for the PR! I'll take a look soon. Do you mind rebasing when you get a chance? (Looks like it's just a re-run of make upgrade) |
c832566
to
f3196df
Compare
@kdmccormick I've rebased the PR on master 👍 |
Hey @stvstnfrd! Thanks for the detailed review! Just updating that I'll get to resuming work on this sometime next week :) |
Sounds good @mavidser . Let me know when to take another look! |
@stvstnfrd Hi, sorry that we couldn't review earlier. We've had reduced capacity issues and nobody available to continue last week. Next 2 sprints it seems tight too. I'll continue looking for who can review and apply the changes you proposed. CC @mavidser |
I continued this review from @mavidser @stvstnfrd Thanks, I applied your changes by doing more commits (didn't squash). But there's one missing, about doing error detection earlier (in Studio). I'd need more time to check. Since we're close to the estimated budget we'll also need to coordinate whether to do this fix or any other, otherwise we'll go over the estimate. The rest of the comments are ready for a review. This can wait for Mike's comments if you prefer. I'll also write an e-mail. I also updated the sandbox. |
sql_grader/problem.py
Outdated
@@ -132,9 +132,11 @@ def run(database, query, is_single_query): | |||
|
|||
database = cls.clone_database(source) | |||
|
|||
# `query` should be a single select statement if no verify_query is | |||
# present in the problem | |||
result, error = run(database, query, is_single_query=not verify_query) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
sql_grader/tests/test_problem.py
Outdated
""" | ||
# Verify that errors are displayed when problem itself contains errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙇
insert into Movie values(105, 'Titanic', 1997, 'James Cameron'); | ||
insert into Movie values(106, 'Snow White', 1937, null); | ||
insert into Movie values(107, 'Avatar', 2009, 'James Cameron'); | ||
insert into Movie values(108, 'Raiders of the Lost Ark', 1981, 'Steven Spielberg'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. If the "live" dataset doesn't break the tests or substantially slow them down, I think we might still want to just load the live version.
As is, I don't think anything actually ensures that real dataset is valid, so we might not catch an error until it gets to production and breaks every problem in every course (the failure mode here).
Making the tests use the same data would catch invalid syntax before hitting production, by failing the test suite.
This is a significant benefit; the .sql
files are code; we should at least test the syntax.
The more I think about this, the more I think we should do it; is there reason we can't/shouldn't?
It should be as easy as loading the fixture from a different path, right? 🤞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, I hit "publish" too soon...
Anyway, this looks great, thanks @clemente
I'll spin this up in my devstack today to smoke-check, but the code looks good.
The only suggested change is the mention of using the "live" dataset (.sql file) instead of a fixture
one; I made a "PR Suggestion" with the change; I'll see if I can run this locally too.
sql_grader/tests/test_problem.py
Outdated
""" | ||
def setUp(self): | ||
current_folder = os.path.dirname(__file__) | ||
sql_file = "{0}/fixtures/rating.sql".format(current_folder) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sql_file = "{0}/fixtures/rating.sql".format(current_folder) | |
sql_file = "{0}/../datasets/rating.sql".format(current_folder) |
@stvstnfrd Thanks, I applied your comment.
I did that. I used a new commit instead of the GitHub suggestion, since I also had to delete the fixtures file. I answered here about the proposal to do earlier validation (in Studio instead of when running the problem). But for now we'd have to wait for Mike's answer about budget (I just e-mailed him), or just consider the project done. Let me know if you want me to squash commits (1 commit? OEP-51 conventional commits?). |
@clemente Looks good! Go ahead and squash and use a conventional commit message to describe the changes. Let me know when that's pushed and I'll merge this then cut a release! |
- Add modification_query field, which allows running multiple statements before the submited answer is checked with verify_query - Improve error handling to allow multiple staments in answer_query - Add tests for the above two changes - Bump up version number
ccd1583
to
8e6843b
Compare
@stvstnfrd Done, I squashed everything into 1 commit. |
@mavidser 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
@stvstnfrd Thanks! It was great working on this project, and the review process was very good. |
This PR adds support for multiple statements in the XBlock, and improves error handling for failed queries. It also updates the XBlock version to 0.2
Adding that functionality in
answer_query
was a rather simple change - executing the query withexecutescript()
instead ofexecute()
(we actually try execute first, due to a caveat mentioned below).executescript()
in Python's sqlite library doesn't return any result back, hence anySELECT
statements which are a part ofexecutescript()
are in-effect ignored. This does makes sense as multiple queries are often meant to perform updates only (no result returned), whereas multipleSELECT
statements rarely makes sense.So, if
verify_query
is being used and it's expecting multiple statements (eg - for testing triggers), then such queries need to be broken up into two parts (as done in this PR):modification_query
is a newly added parameter - and it will contain all modification statements to be performed after executinganswer_query
or the user's queriesverify_query
will just contain a single SQL query, and returns a resultJIRA tickets: OSPR-5080, Opencraft/SE-3218
Sandbox URL:
Executing SQL queries might seem slow in the resource-limited sandbox, which is a pre-existing condition, due to the use of codejail. There has been no significantly increase in execution time as a result of this PR.
Testing instructions:
/edx/src
, and runningpip install -e .
in the repomake test
inside the repoReviewers