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

Fall back to non-RETURNING updates with old Sqlite #28911

Merged
merged 1 commit into from
Aug 29, 2022

Conversation

roji
Copy link
Member

@roji roji commented Aug 28, 2022

@bricelam I ended up using SQLitePCL.raw.sqlite3_libversion_number() to find out which Sqlite version we're using, since the UpdateSqlGenerator is set up in a singleton context and it's a bit of a hassle to get a SqliteConnection etc. Are we aware of a situation where different versions of Sqlite could be used based on the connection string (seems unlikely)? If so and you think it's important, I can look into using SqliteConnection.ServerVersion instead.

Test-wise, I've verified manually that the old SQL gets properly generated on Windows (where the version is 3034001, using SQLitePCLRaw.bundle_winsqlite3); there's also a new legacy test suite which I've verified artifically by hard-coding an old version. But since all our tests pass in CI, I'm assuming we always run with the bundled version which is new; we could do the extra legwork to e.g. use the system Windows version for tests, but that seems low-value to me...

Fixes #28776

@roji roji requested a review from a team August 28, 2022 10:24
@roji
Copy link
Member Author

roji commented Aug 28, 2022

@bricelam could you take a look at the test failure? CSharpRuntimeModelCodeGeneratorTest.Sqlite fails because of:

You need to call SQLitePCL.raw.SetProvider().  If you are using a bundle package, this is done by calling SQLitePCL.Batteries.Init().

(because only the core package is referenced and we now call SQLitePCL.raw.sqlite3_libversion_number).

Trying to reference EFCore.Sqlite from EFCore.Design.Tests fails with:

Metadata file '/home/roji/projects/efcore/artifacts/obj/EFCore.Sqlite/Debug/net6.0/ref/EFCore.Sqlite.dll' could not be found

@ErikEJ
Copy link
Contributor

ErikEJ commented Aug 28, 2022

Maybe a quirk switch in addition to the version test?

@roji
Copy link
Member Author

roji commented Aug 28, 2022

A quirk is easy enough to do, but any particular reason in mind? We usually do quirks for patches, and I'm not sure this Sqlite change is particularly risky.

@ErikEJ
Copy link
Contributor

ErikEJ commented Aug 29, 2022

@roji Only if some depending on winsqlite would like a predictable behaviour (if it ever gets updated) ?

@smitpatel
Copy link
Member

smitpatel commented Aug 29, 2022

I think we can add quirk to allow user to opt-in in particular behavior for whatever reason they want to differ in case our check is not accurate enough for them. Not necessarily the change is risky, just a user configurable behavior.

We should discuss with team though as we have never added such switch in framework before. (Patch quirks only live for that major release).

@roji
Copy link
Member Author

roji commented Aug 29, 2022

Only if some depending on winsqlite would like a predictable behaviour (if it ever gets updated) ?

@ErikEJ hopefully the visible end-user behavior is predictable and the same across both versions, with only the SQL (and performance) varying; otherwise that would mean there's some sort of bug/issue 😅

But sure, we'll discuss and I have no problem adding this if needed.

Copy link
Contributor

@bricelam bricelam left a comment

Choose a reason for hiding this comment

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

Are we aware of a situation where different versions of Sqlite could be used?

No. It's very difficult and error-prone to load multiple versions of SQLite into a process.

add a quirk to allow user to opt-in in particular behavior

No need for a quirk. Just use ReplaceService to get the behavior you want.

// Detect which version we're using, and fall back to the older INSERT/UPDATE+SELECT behavior on legacy versions.
var dependencies = sp.GetRequiredService<UpdateSqlGeneratorDependencies>();

return SQLitePCL.raw.sqlite3_libversion_number() < 3035000
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, configuring services is a bit early for calling this. Use new SqliteConnection().ServerVersion instead to ensure the SQLitePCLRaw provider is set.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, that makes it look better - but CSharpRuntimeModelCodeGeneratorTest.Sqlite is still failing in the same way for me...

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, so that wasn't the reason it was failing. It really is just because that project doesn't reference a provider.

Hmm, I really hate how early in the stack (configuring services) we need to make this check. Is it possible to push this decision down into the actual service?

Copy link
Contributor

Choose a reason for hiding this comment

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

You can revert the change to use SqliteConnection if you want.

If we can't defer the check until later, you can just reference SQLitePCLRaw.bundle_e_sqlite3 from EFCore.Design.Tests to fix the failure.

Copy link
Member Author

Choose a reason for hiding this comment

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

No I think using SqliteConnection is better.

I think it's nice to have the behavior switch happen at the wiring up of services, and among other things it makes it very simple to swap the services around as you suggested... Referencing SQLitePCLRaw.bundle_e_sqlite3 seems simple enough (and we do it in many other test projects), so I'll do that.

Copy link
Member Author

@roji roji Aug 29, 2022

Choose a reason for hiding this comment

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

BTW will centralize the version to SqlitePCLRawVersion in Versions.props

Copy link
Contributor

Choose a reason for hiding this comment

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

BTW will centralize the version to SqlitePCLRawVersion in Versions.props

Not sure Dependabot will like that, but I’ll revert it if it has trouble.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh OK, sorry about that.

BTW hopefully we'll move to nuget's centralized package management at some point, it works well with dependabot.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I filed an issue on Arcade the day it finally released.

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.

EF7 should work with SQLite version that is included in Windows and older Ubuntu LTS
4 participants