What's Squeryl syntax for exclusion (i.e. != )? - scala

Doing a simple Squeryl database lookup, but trying to exclude a value. I've tried:
j.id not jobExclude and j.id != jobExclude
however the first triggers a compiler error and the second triggers a runtime error.
The whole transaction:
from(DB.jobs)(j =>
where((j.startTime >= todayStart)
and (j.startTime <= todayEnd)
and (j.userId === userId)
and (j.teamId === teamId)
and (j.startOrder >= index)
and (j.id not jobExclude))
select (j)).toList
Thanks!

Courtesy of the Squeryl Groups:
Not equals is <>
so in the bigger picture:
(job.id <> jobExclude)
See http://squeryl.org/functions.html
Credit https://groups.google.com/forum/?fromgroups#!topic/squeryl/Hw7iVyvLLNM

Related

Issue with JPA statement "translation"

I have a JPA statement which is like this
select p from Proposal p where p.creationTime > :startDate AND p.creationTime < :stopDate AND ((p.owner = :owner) OR (:member MEMBER OF p.sharedWithTeam.members)) ORDER BY p.creationTime DESC
But it never generates any result. I use EclipseLink.
After digging a bit into the generated SQL, I found out that it translates the query into something that can never be true!
SELECT XXX FROM userteam_users t3, USERTEAM t2, USERS t1, PROPOSAL t0 WHERE ((((t0.CREATIONTIME > ?) AND (t0.CREATIONTIME < ?)) AND ((t0.OWNER_username = ?) OR (? = t1.username))) AND ((t2.ID = t0.SHAREDWITHTEAM_ID) AND ((t3.teams_ID = t2.ID) AND (t1.username = t3.members_username)))) ORDER BY t0.CREATIONTIME DESC LIMIT ? OFFSET ?
(I only included the from and where clause to make it shorter...)
I can't see what is wrong with my JPQL query. Could it be my use of "OR"? or my "bold" use of the member of condition?
EDIT: in fact, the statement can be true, I misread it. BUT I have proposals with NO shared user team, so the first condition is always false in this case, and it should be true (in my view)
Thanks!

Linq to Entity Framework with Informix generates useless CAST

I have the following Linq query:
var asnPacApoRepository = repoFactory.GetRepository<asn_pac_apo>();
var query = asnPacApoRepository.Table
.Where(_ => positionList.Contains(_.pzn) && _.gueltig_von <= date &&
(date <= _.gueltig_bis || _.gueltig_bis == null));
This generates the SQL query:
SELECT *
FROM informix.asn_pac_apo AS Extent1
WHERE ((((CAST('06460518' AS nvarchar(8)) = Extent1.pzn) OR (CAST('10710808' AS nvarchar(8)) = Extent1.pzn)) OR ((CAST('00584142' AS nvarchar(8)) = Extent1.pzn) OR (CAST('03728156' AS nvarchar(8)) = Extent1.pzn))) AND (Extent1.gueltig_von <= '2016-04-24')) AND (('2016-04-24' <= Extent1.gueltig_bis) OR (Extent1.gueltig_bis IS NULL))
The issue with the generated query is performance, because the pzn column is of type:
and it is indexed, but the statement: CAST('06460518' AS nvarchar(8)) makes the index not to be used.
I was expecting Linq to generate the following query:
SELECT *
FROM informix.asn_pac_apo AS Extent1
WHERE (Extent1.pzn IN ('06460518','10710808','00584142','03728156') AND (Extent1.gueltig_von <= '2016-04-24')) AND (('2016-04-24' <= Extent1.gueltig_bis) OR (Extent1.gueltig_bis IS NULL));
If I create a linq query with Equals instead of Contains, the cast does not appear, and the SQL generated query is as expected.
How can I get rid of this useless CAST statement?
I set in .edmx the property Unicode=True:
but this doesn't seem to affect in any way the generated model, nor the generated query.
As a note, I use the old ObjectContext for my EF model and the database type is INFORMIX.

Calculating Average Timespan between two dates in Entity Framework

I have a database table with two columns: StartDateTime and FinishDateTime. both are nullable datetime columns.
I'm wanting to calculate the Average time between both fields per row. ie the average duration of my recorded event.
I'm getting a "DbArithmeticExpression arguments must have a numeric common type."
Example EF code with a touch of simplification for the demo.
from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.Average(p=> (p.FinishDateTime.Value - p.StartDateTime.Value).Ticks)
I'd love an example of the above, as SQL makes this a breeze.
Its depends on your data provider, it may support DbFunctions and you could do something like this:
(from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.Average(x=> DbFunctions.DiffMilliseconds(p.FinishDateTime,p.StartDateTime))
if it doesn't, i think you have to go linq to objects after the select:
(from p in new DbContext()
where p.user_id = 123
&& p.StartDateTime != null
&& p.FinishDateTime != null
select new {p.StartDateTime, p.FinishDateTime})
.ToArray()
.Average(x=> (p.FinishDateTime -p.StartDateTime).Ticks)

Count before order, skip and take

I'm using Entity Framework together with Unit-of-work and repository pattern.
For a function with ordering, pagination, etc. I use the following code:
stammdatenEntityModels =
_unitOfWork.StammdatenRepository.Get()
.Where(
s =>
s.Geloescht == false &&
((s.Auftraggeber != null && s.Auftraggeber.Bezeichnung.ToLower().Contains(keyword)) ||
(s.SerienNummer.Contains(keyword)) ||
(s.Bezeichnung.ToLower().Contains(keyword)) ||
(s.StammdatenKunde != null && s.StammdatenKunde.Name.ToLower().Contains(keyword)) ||
(s.BeginnVos.HasValue && s.BeginnVos == dateTime) ||
(s.VosDauer != null && s.VosDauer.Bezeichnung.ToLower().Contains(keyword)) ||
(s.Geraetewert.HasValue && s.Geraetewert.Value.ToString().Contains(keyword))
))
.OrderBy(orderBy)
.Skip(inputModel.EntriesToDisplay*(inputModel.Page - 1))
.Take(inputModel.EntriesToDisplay)
.ToList();
Now I need to know the numbers of records, but before the skip and take (for pagination) is performed.
Therefore I have the same code again:
totalCount = _unitOfWork.StammdatenRepository.Get()
.Count(
s =>
s.Geloescht == false &&
((s.Auftraggeber != null && s.Auftraggeber.Bezeichnung.ToLower().Contains(keyword)) ||
(s.SerienNummer.Contains(keyword)) ||
(s.Bezeichnung.ToLower().Contains(keyword)) ||
(s.StammdatenKunde != null && s.StammdatenKunde.Name.ToLower().Contains(keyword)) ||
(s.BeginnVos.HasValue && s.BeginnVos == dateTime) ||
(s.VosDauer != null && s.VosDauer.Bezeichnung.ToLower().Contains(keyword)) ||
(s.Geraetewert.HasValue && s.Geraetewert.Value.ToString().Contains(keyword))
));
Unfortunately this leads to a lot of redundance and my query is performed twice. Is there any better solution?
I agree with the redundancy. What you can do is to cache the count result for the specific parameters (keyword, dateTime) a certain amount of time and use it again at subsequent calls to deliver paginated (skip, take) results from the StammDatenRepository.
This way you only have the overall count-call one time for specific parameters.
Found this SO question where a respected member states:
Thinking about it from a SQL point of view, I can't think of a way in
a single normal query to retrieve both the total count and a subset of
the data, so I don't think you will be able to do it in LINQ either.
So, I really think you have to cache some counts results to increase performance. You know best how to do it for your specific situation and if it's worth it at all...

Slick compare table column with null

Can someone please tell me how do we compare a table column against NULL using slick's lifted embedding.
What i want to achieve in mysql:
select * from Users where email = '<some_email_addr>' and ( removed = NULL OR removed <= 1 )
It gives me an errors at x.removed === null when i try:
val q = for {
x <- Users
if x.email === email && ( x.removed === null || x.removed <= 1 )
} yield x.removed
Thanks
Try:
x.removed.isNull
I think that is what you are looking for
As daaatz said and per http://slick.typesafe.com/doc/2.1.0/upgrade.html#isnull-and-isnotnull you should use isEmpty, but it only works on Option columns. A workaround is x.removed.?.isEmpty.
Try
x.removed.isEmpty()
There are no nulls in scala ;-)