-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Support specifying collations on columns and databases #20602
Conversation
* Added metadata and migration support for column- and database- level collations. * Scaffolding implemented for SQL Server. Sqlite seems to not be reporting the collation in pragma_table_info (need newer version?) Closes dotnet#19275 Closes dotnet#6577
55bd7e2
to
d2b8650
Compare
src/EFCore.Relational/Extensions/RelationalModelBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
What about table level collations? |
…ons.cs Co-Authored-By: Andriy Svyryd <[email protected]>
…nsions.cs Co-Authored-By: Andriy Svyryd <[email protected]>
I looked into this - table-level collations is a MySQL-only extension, whereas database and column collations seem to be near-universal. So I think it makes total sense to do the same metadata and migrations changes for table-leve collations in your provider (using the same annotation etc.), but it doesn't seem to belong in Relational. Makes sense? |
Interesting. Makes sense then. |
Grrr, I'm sure I hit squash... 😠 |
I don't know if this is useful, but I did a study of Sqlite case-sensitivity via EF Core. Here are the answers, with the SQL that EF Core 5.0.0-preview.2.20159.4 produced. As you will see, the default case-sensitivity varies for different string comparison, and some of that is due to the way the LINQ is converted to SQL.
|
Thanks for this valuable info @JonPSmith! @bricelam was just mentioning the pecularities of Sqlite case-sensitivity... The basic thing here seems to be that LIKE is case-insensitive by default, and is not sensitive to collations in any way (see these docs). There's a I'm not sure there's anything we can actually do here, except provide guidance to users... I'll also take this into account when working about #19402 - we should avoid different pattern types (constant, parameter, column) producing different case-sensitivity behavior on Sqlite because of LIKE vs. INSTR. Some tests to show this weird behaviorSELECT sqlite_version(); -- 3.25.1
CREATE TABLE data
(
name TEXT,
name_cs TEXT COLLATE BINARY
);
INSERT INTO data (name, name_cs) VALUES ('foo', 'foo');
-- Equality operator is sensitive to collation
SELECT COUNT(*) FROM data WHERE name = 'foo'; -- 1
SELECT COUNT(*) FROM data WHERE name = 'FOO'; -- 0
SELECT COUNT(*) FROM data WHERE name = 'FOO' COLLATE NOCASE; -- 1
-- LIKE is case-insensitive, regardless of collation
SELECT COUNT(*) FROM data WHERE name LIKE 'f%'; -- 1
SELECT COUNT(*) FROM data WHERE name LIKE 'F%'; -- 1
SELECT COUNT(*) FROM data WHERE name LIKE 'F%' COLLATE BINARY; -- 1
SELECT COUNT(*) FROM data WHERE name COLLATE BINARY LIKE 'F%'; -- 1
-- Same if the collation is defined on the column
SELECT COUNT(*) FROM data WHERE name_cs LIKE 'f%'; -- 1
SELECT COUNT(*) FROM data WHERE name_cs LIKE 'F%'; -- 1
SELECT COUNT(*) FROM data WHERE name_cs LIKE 'F%' COLLATE BINARY; -- 1
SELECT COUNT(*) FROM data WHERE name_cs COLLATE BINARY LIKE 'F%'; -- 1
-- There's a pragma to make LIKE case-sensitive pragma
PRAGMA case_sensitive_like=ON;
SELECT COUNT(*) FROM data WHERE name LIKE 'f%'; -- 1
SELECT COUNT(*) FROM data WHERE name LIKE 'F%'; -- 0
SELECT COUNT(*) FROM data WHERE name LIKE 'F%' COLLATE BINARY; -- 0
SELECT COUNT(*) FROM data WHERE name LIKE 'F%' COLLATE NOCASE; -- 0
SELECT COUNT(*) FROM data WHERE name COLLATE BINARY LIKE 'F%'; -- 0
SELECT COUNT(*) FROM data WHERE name COLLATE NOCASE LIKE 'F%'; -- 0 |
Hi @roji,
Sorry, my edits managed to muck things up. |
Hey @JonPSmith,
I don't recall making any changes for IndexOf, and definitely didn't change the general SQLite database setup to make equality insensitive... Your SQL for IndexOf is a bit odd too - we should be translating it to the SQLite
The exception message seems to be coming from SqlClient, are you sure you haven't gotten your providers crossed? :) |
Doh! Sorry about that. I have edited my last entry and remove that rubbish - big refactoring of unit tests needs more care by me. The results for SQLite are:
I think SQLite is always going to be less 'standard' than the other relational database. Cosmos DB will also be different, although they have added the ability to turn case-insensitive search on the case-sensitively in some API commands I doubt that will be added to EF Core. I feel like I have the information to update my book - sorry for bothering you. |
No problem @JonPSmith, thanks for the additional information on SQLite. At the end of the day, EF Core exposes the mechanism to specify the collation at various levels, but what the database actually does with it is going to be database-dependent... Re Cosmos, I strongly suspect that the API around collations/case-sensitivity is going to look quite different there - note that all of the new support we brought into EF 5.0 is in Relational only (so does not apply to Cosmos). Would you mind opening an issue for our backlog to look at Cosmos collations/case-sensitivity? |
You are very kind - I should I seen that. I did ask about Cosmos DB a while ago and it wasn't being used much so it was on the back burner. I think there are many other issues that come before collation, like aggregates so I'll let someone else ask for Cosmos collations/case-sensitivity when they need it. |
Sure thing. It never hurts to have an issue in the backlog, but as you prefer. |
Closes #19275
Closes #6577
Some notes:
UseCollation
, notHasCollation
. This is because collations are are logically separate thing which a column or database can use, but which can (at least in some cases) be managed separately. For example, PostgreSQL allows creating and dropping collations just like tables or sequences, so I'd useHasCollation
on the database there.