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

BUG Manually create singleton when building table #9952

Conversation

maxime-rainville
Copy link
Contributor

Because we use singleton to get class references when building table, if you try to inject over a class, it's table will never be created.

Parent issue

@maxime-rainville maxime-rainville changed the base branch from 4 to 4.7 May 25, 2021 23:08
@maxime-rainville
Copy link
Contributor Author

maxime-rainville commented May 25, 2021

This may be a naive fix, but at first glance looks like it's working fine. Not quite sure if this is something that is testable.

@michalkleiner
Copy link
Contributor

I'll give it a crack. I think it is testable.

@maxime-rainville
Copy link
Contributor Author

maxime-rainville commented May 26, 2021

Just clarifying: I meant "testable" as is "can write unit test to cover this use case". I tested it locally with a similar example as the one provided by @dhensby.

@michalkleiner
Copy link
Contributor

Yep, I got what you meant. That's why I wrote two independent sentences :)

I think it's testable as long as we can assert what db tables get built and what columns they contain.

@dhensby
Copy link
Contributor

dhensby commented May 26, 2021

a slight variation on #9951 (which I'll close).

I had targeted 4.2 as it is potentially the lowest supported version of the framework, given it's a fairly high impact bug it deserves to be back-ported as far as reasonable.

@GuySartorelli
Copy link
Member

GuySartorelli commented May 13, 2022

I don't think we can add unit tests for this... When the database is built for tests it doesn't use this code at all - it uses SilverStripe\ORM\Connect\TempDatabase::rebuildTables() which also uses the singleton function.

So any test cases written to test this functionality right now would fail with this PR because the method used for creating test database tables is using singleton() (which I think we should address in this PR so that the way test DB tables are made mirrors the way production ones are made) - but even addressing that, they won't test that the actual production functionality works.

$SNG = singleton($dataClass);

$SNG = singleton($dataClass);

@GuySartorelli GuySartorelli changed the base branch from 4.7 to 4.10 May 13, 2022 01:53
@GuySartorelli GuySartorelli force-pushed the pulls/4.7/allow-class-to-inject-over-parent branch from cdff042 to 6a33725 Compare July 5, 2022 21:54
@GuySartorelli GuySartorelli changed the base branch from 4.10 to 4.11 July 5, 2022 21:54
@GuySartorelli GuySartorelli changed the base branch from 4.11 to 4 July 5, 2022 23:27
@GuySartorelli GuySartorelli force-pushed the pulls/4.7/allow-class-to-inject-over-parent branch from 6a33725 to 1140cb3 Compare July 5, 2022 23:30
@GuySartorelli
Copy link
Member

I've found what I think is a pretty clean solution to be able to test this - I've created a new class to hold the logic that is shared between DatabaseAdmin and TempDatabase as far as building tables is concerned. This way we can write a test for that logic which will be valid, because it's the same logic shared between tests and prod db.

@GuySartorelli
Copy link
Member

Scrutinizer failure is unrelated to this PR

Comment on lines 57 to 66
// If we have additional dataobjects which need schema (i.e. for tests), do so here:
if ($extraDataObjects) {
foreach ($extraDataObjects as $dataClass) {
$SNG = new $dataClass([], DataObject::CREATE_SINGLETON);
if ($SNG instanceof DataObject) {
$SNG->requireTable();
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This runs for each input dataClass whereas previously it was outside of the loop. Should this be moved one level up after the first foreach?

Copy link
Member

Choose a reason for hiding this comment

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

Ahh, yes - my bad. I'll fix that.

@michalkleiner
Copy link
Contributor

Nice work @GuySartorelli!
I didn't get to test this yet as it's on a project we parked for a bit and couldn't spend too much time on, but I'll be able to confirm this works at some point in future.

@GuySartorelli GuySartorelli force-pushed the pulls/4.7/allow-class-to-inject-over-parent branch from 7017431 to 0482444 Compare July 6, 2022 21:49
@GuySartorelli
Copy link
Member

Probably also worth me mentioning that I have confirmed the tests I've added fail before the changes in this PR.

@michalkleiner
Copy link
Contributor

Cool, thanks for hopping in and pushing it over the line.
Do we need want to retarget at minor since it's fixing a bug? Or do we see it as a big enough change in the mechanism that it should be seen as an enhancement? I don't think we know when this stopped working.

@GuySartorelli
Copy link
Member

I targetted 4 specifically because there is increased API surface with this approach - technically this is an API PR even though it's to fix a bug.
But it's also effectively internal API (even though it's a new class with a public method) so I could see an argument for it being a patch release.

@michalkleiner
Copy link
Contributor

I would probably lean towards a patch fix due to the nature of the issue, but it can really be argued for both ways. But since we made several workarounds, if I didn't know about this change and just simply applied a new patch release, the site would stop working since the data would become inconsistent in different tables. But also I'd prefer fixing that and having working MTI — 🤷

@GuySartorelli
Copy link
Member

I'll defer the branch targetting conundrum to whoever wants to merge this - happy to retarget and fix commits to match whatever branch the merger chooses.

@michalkleiner
Copy link
Contributor

@maxime-rainville wanna decide this one for us? :-D I'm happy to merge it as a fix with your blessing.

@sabina-talipova
Copy link
Contributor

Test in local environment. All works.
Approve and merge.

@sabina-talipova sabina-talipova merged commit 2262d84 into silverstripe:4 Jul 12, 2022
@sabina-talipova sabina-talipova deleted the pulls/4.7/allow-class-to-inject-over-parent branch July 12, 2022 03:29
@michalkleiner
Copy link
Contributor

Thanks for jumping in for the merge, @sabina-talipova, though I sort of wanted to know what Max's opinion was.

Since we've now merged this into 4, without @maxime-rainville giving his view, the question now is — should we backport this into 4.11?

@maxime-rainville
Copy link
Contributor Author

It is adding a brand new Class to our API, so it should ship in a minor release.

If this was a major bug and people had been screaming for a fix forever, I'd say maybe it's worth shipping this in a patch release, but as far as I can tell it's always been broken and it took us until last year to notice.

It's a smallish change but it affects some pretty low level methods. I would rather take it through our regular minor release regression test.

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

Successfully merging this pull request may close these issues.

5 participants