-
Notifications
You must be signed in to change notification settings - Fork 225
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
Translate hstore access to SQL #212
Comments
It's definitely possible to perform this kind of translation to SQL, but this isn't currently supported. Since the translation doesn't exist at the moment, the above code will trigger client evaluation - EF Core will select everything and perform the Where() client-side. I did something similar for translating basic .NET Regex functionality to PostgreSQL regex operators (see #6), also see #4 which would translate JSON operators. I'll keep this open as a feature request. |
Would this be difficult to implement ? I have never done anything like this but I would like to look into it. Could you point me in some direction ? |
@DavizOWNS while translating expressions to SQL is usually simple (and even fun), unfortunately this case doesn't involve simple method call translation (like, say, regular expressions) but the indexing operator. A while back I did some work in a branch on #120, which involves something similar but for an array. Let me bring that branch up to date and see if I can even merge it (or some of it) for 2.0.0. After that I'll come back here and try to give some guidance. |
@DavizOWNS you may want to take a look at dotnet/efcore#9183, which is me asking for a review from the EF Core team on work I did to translate array operations (including subscripting). You would probably do something not too far off, so you may want to look at my work, and let's wait for their feedback. |
FYI the array operation translation work has been merged for 2.0.0. You may wish to take a look at b79fd0c to see how that was done and start working from there. |
Created PR #240 with my first attempt at this. |
Just dropping by my solution in case anyone else is struggling with this. CREATE OR REPLACE FUNCTION public.hstore_has_key_value(IN "@hstore" hstore, IN "@key" text, IN "@operator" text, IN "@value" text)
RETURNS boolean
AS $func$
SELECT
CASE
WHEN "@operator" = '=' THEN "@hstore" -> "@key" = "@value"
WHEN "@operator" = '<>' THEN "@hstore" -> "@key" <> "@value"
WHEN "@operator" = '>' THEN "@hstore" -> "@key" > "@value"
WHEN "@operator" = '>=' THEN "@hstore" -> "@key" >= "@value"
WHEN "@operator" = '<' THEN "@hstore" -> "@key" < "@value"
WHEN "@operator" = '<=' THEN "@hstore" -> "@key" <= "@value"
WHEN "@operator" = 'LIKE' THEN "@hstore" -> "@key" LIKE "@value"
ELSE "@hstore" -> "@key" = "@value"
END
$func$ LANGUAGE sql; Then a dummy DbFunction on my C# code: public static class DbFunctionsExtensions
{
public static bool HasKeyValue(Dictionary<string, string> dic, string key, string @operator, string value)
{
throw new NotImplementedException("For use only as an EF core Db function");
}
} Configured the mapping between the functions on the DbContext: protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//other stuff
modelBuilder.HasDbFunction(typeof(DbFunctionsExtensions).GetMethods()
.Where(m =>
{
return m.Name == "HasKeyValue";
})
.SingleOrDefault())
.HasName("public.hstore_has_key_value");
} Use it and be happy: var result = dbContext.Entites.AsNoTracking().Where(r => DbFunctionsExtensions.HasKeyValue(r.Dictionary, "someKey", "=", "someValue")).FirstOrDefault(); |
I have implemented full support for You can now do all the above queries you've suggested as well as the following methods are all supported:
If you're going to use the |
Is there a way to query hstore columns using LINQ ?
I would expect something like this to work:
However that WHERE statement is evaluated at client and I want it to be evaluated in db server.
I expect something like this to be generated
select * from "Products" where "Tags" -> 'Variant' = 'SD'
This works so everything is configured correctly.
var prods = db.Products.FromSql("select * from \"Products\" where \"Tags\" -> 'Variant' = 'SD'").ToList();
The text was updated successfully, but these errors were encountered: