Skip to content
New issue

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

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

Already on GitHub? # to your account

[Core: Candidate] Fix getFirstVisit method #4075

Merged
merged 17 commits into from
Jan 28, 2019

Conversation

davidblader
Copy link
Contributor

@davidblader davidblader commented Nov 7, 2018

Brief summary of changes

ran into this while trying to run assign_missing_instruments
got:
PHP Fatal error: Uncaught DomainException: Attempt to use pselectRow on a query that returns multiple rows in /var/www/loris/php/libraries/Database.class.inc:764 Stack trace: #0 /var/www/loris/php/libraries/Database.class.inc(892): Database->pselectRow('SELECT Visit_la...', Array) #1 /var/www/loris/php/libraries/Candidate.class.inc(630): Database->pselectOne('SELECT Visit_la...', Array) #2 /var/www/loris/tools/assign_missing_instruments.php(93): Candidate->getFirstVisit() #3 /var/www/loris/tools/assign_missing_instruments.php(148): populateVisitLabel(Array, 'Initial_Assessm...')
this updates the query to ensure a singular result is returned

To test this change...

  • try running assign_missing_instruments.php, also try creating & starting a visit

@davidblader davidblader added Bug PR or issue introducing/requiring bug fixes (not mutually exclusive with the Feature label) [branch] major labels Nov 7, 2018
@johnsaigle
Copy link
Contributor

johnsaigle commented Nov 7, 2018

I just did some testing of your error and I was able to reproduce it. It's definitely a problem.

I don't think I like the approach of hamstringing pselectOne in this way. The limit clause is there to tell developers that they're using the function correctly -- in this case it's doing exactly what it's supposed to do.

My opinion would be to attempt a rewrite of the query. Even if it becomes fairly unreadable, that's what code comments are for.

Another possible approach would be to change the signature of getFirstVisit to return an array instead of a string. This way it will typically return a one-element array. In the case where two results appear (i.e. when a candidate does two visits on the same day), the calling code can determine which or both of the visit labels is appropriate to use.

What do you think?

In any case the real issue here is in the Candidate class and not in the Database class , so I don't think we should change the Database.

@christinerogers
Copy link
Contributor

I'd agree, leaning towards fixing getFirstVisit() - including the function description (and maybe even name?) -- given we're now plausibly allowing for multiple first visits to be returned.

php/libraries/Candidate.class.inc Outdated Show resolved Hide resolved
php/libraries/Database.class.inc Outdated Show resolved Hide resolved
php/libraries/Database.class.inc Outdated Show resolved Hide resolved
Copy link
Collaborator

@driusan driusan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @johnsaigle. I don't like this change. If you're calling pselectRow you should be providing a query that only returns one row. The right solution is to fix the places that are providing non-unique queries to pselectRow/One.

@johnsaigle johnsaigle added Needs Work PR awaiting additional changes by the author or contains issues that the author needs to fix Discussion Required PR or issue awaiting the resolution of a discussion between all involved parties and removed Needs Work PR awaiting additional changes by the author or contains issues that the author needs to fix labels Nov 14, 2018
@davidblader davidblader changed the title [Core: Database / Candidate] Add third param to pselectOne & pselectRow [Core: Candidate] Fix getFirstVisit method Nov 19, 2018
@johnsaigle johnsaigle added the Passed Manual Tests PR has undergone proper testing by at least one peer label Nov 19, 2018
@johnsaigle
Copy link
Contributor

assign_missing_instruments.php no longer throws the error that it did before.

@johnsaigle johnsaigle dismissed driusan’s stale review November 19, 2018 17:26

Addressed by David

johnsaigle
johnsaigle previously approved these changes Nov 19, 2018
Copy link
Contributor

@johnsaigle johnsaigle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me and fixes the error. Someone else should probably review the query because I don't know enough to tell if it's optimal.

PapillonMcGill
PapillonMcGill previously approved these changes Nov 20, 2018
@johnsaigle johnsaigle added the Needs Work PR awaiting additional changes by the author or contains issues that the author needs to fix label Nov 27, 2018
@johnsaigle
Copy link
Contributor

Adding Needs Work based on the discussion in Dave's review.

@davidblader davidblader removed the Discussion Required PR or issue awaiting the resolution of a discussion between all involved parties label Dec 14, 2018
johnsaigle
johnsaigle previously approved these changes Jan 21, 2019
@johnsaigle
Copy link
Contributor

Looks like the unit tests needs to be updated.

@zaliqarosli
Copy link
Contributor

i'm trying to use this fix to the script and i'm still getting this type error
PHP Fatal error: Uncaught TypeError: Return value of Candidate::getFirstVisit() must be of the type string, null returned in /var/www/loris/php/libraries/Candidate.class.inc:647 Stack trace: #0 /var/www/loris/tools/assign_missing_instruments.php(93): Candidate->getFirstVisit() #1 /var/www/loris/tools/assign_missing_instruments.php(148): populateVisitLabel(Array, 'V3') #2 {main} thrown in /var/www/loris/php/libraries/Candidate.class.inc on line 647
i'm not quite sure why the empty string still isn't returning 😕

@zaliqarosli
Copy link
Contributor

@davidblader i just figured out that if pselectCol returns an empty array, getFirstVisit returns null. you need an empty() check!

@zaliqarosli zaliqarosli removed the Passed Manual Tests PR has undergone proper testing by at least one peer label Jan 23, 2019
Co-Authored-By: davidblader <dblader.mcin@gmail.com>
@zaliqarosli
Copy link
Contributor

you're also going to have to add return $ProjectList[$this->getProjectID()] ?? ''; to line 412

@zaliqarosli zaliqarosli added the Passed Manual Tests PR has undergone proper testing by at least one peer label Jan 25, 2019
zaliqarosli
zaliqarosli previously approved these changes Jan 25, 2019
Copy link
Contributor

@zaliqarosli zaliqarosli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passed testing and approved! will approve again once passes travis 👍

@zaliqarosli zaliqarosli added "Help! I don't understand Travis!" PR is having a beef with TRAVIS. Someone needs to help and removed Needs Work PR awaiting additional changes by the author or contains issues that the author needs to fix labels Jan 25, 2019
@PapillonMcGill
Copy link
Contributor

@zaliqarosli @davidblader
line 4232+ of Travis report (PHP 7.2)
There was 1 failure:

  1. CandidateTest::testGetFirstVisitReturnsFirstVisitLabel
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    -'V01'
    +''
    /app/test/unittests/CandidateTest.php:362

the test at line 362 of CandidateTest expected to have 'V01' as result but received and empty string.
Hope it help

@xlecours
Copy link
Contributor

Note on Travis error.
My guess is that the test is failing because it is says that the second call of pselectOne should return V01; but there is no second call to that function since pselectCol is called instead.
The test should say something like

$this->_dbMock->expects($this->at(1))
            ->method('pselectCol')
            ->willReturn('V01');

My review of the PR
Considering that:

  1. We should be able to write a query that is returning a single value. The use of pselectCol seems to be a hack to circumvent poor database structure.
  2. The function is use at two places and in both cases there is already a Timepoint in the calling code block where the purpose of the call is to compare the returned visit label with the timepoint's visit label.
  3. There is a VisitNo column that SHOULD be reliable.

Can we remove that function and either have a isFirstVisit function in the Timepoint class or simply check if $timepoint->getVisitNo() === 1 ?

Copy link
Contributor

@zaliqarosli zaliqarosli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, i like this solution 👍

@davidblader davidblader removed the "Help! I don't understand Travis!" PR is having a beef with TRAVIS. Someone needs to help label Jan 28, 2019
@zaliqarosli zaliqarosli removed the Passed Manual Tests PR has undergone proper testing by at least one peer label Jan 28, 2019
@zaliqarosli
Copy link
Contributor

zaliqarosli commented Jan 28, 2019

@davidblader i had a lot of candidates in my RaisinBread with multiple timepoints of VisitNo=1, but i'm passing manual test on this assuming that the real data on projects are clean. Might be nice to add a try catch block in getFirstVisit() or assign_missing_instruments.php that catches the DomainException Attempt to use pselectRow on a query that returns multiple rows if the pselectOne call fails and throws a new error Candidate $candID has two first visits where we expect one. Please clean the data or something like that to the console. but i won't block this PR on that request

@zaliqarosli zaliqarosli added the Passed Manual Tests PR has undergone proper testing by at least one peer label Jan 28, 2019
@driusan driusan merged commit 6f92f69 into aces:major Jan 28, 2019
@ridz1208 ridz1208 added this to the 21.0.0 milestone Feb 11, 2019
driusan pushed a commit that referenced this pull request Feb 13, 2020
Follows up on suggestion made in #4075 to catch error

Attempt to use pselectRow on a query that returns multiple rows thrown in Database.class.inc, when calling function Candidate->getFirstVisit() in assign_missing_instruments.php, when multiple first visits are returned, and throw new LorisException with more meaningful message within the function getFirstVisit().
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Bug PR or issue introducing/requiring bug fixes (not mutually exclusive with the Feature label) Passed Manual Tests PR has undergone proper testing by at least one peer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants