Unable to CAST as TEXT after upgrad to 2.1.212 & 2.1.214 - jpa

After upgrading from 1.4.200 (provided by spring) to H2 2.1.212 and then 2.1.214, I started seeing this error message when attempting to cast as text:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Precision ("2147483647") must be between "1" and "1000000000" inclusive; SQL statement:
select distinct userpermis0_.user_id as col_0_0_ from markings.user_permissions_map userpermis0_ inner join markings.marking marking1_ on (marking1_.name=userpermis0_.marking_name and marking1_.unique_name=REGEXP_REPLACE(lower(?),'[^a-z0-9]+','-','g')) where (cast(? as varchar(2147483647)) is null or userpermis0_.user_id>?) and (cast(? as varchar(2147483647)) is null or lower(userpermis0_.user_id) like ?) order by userpermis0_.user_id asc limit ? [90150-214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:632) ~[h2-2.1.214.jar:2.1.214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) ~[h2-2.1.214.jar:2.1.214]
at org.h2.message.DbException.get(DbException.java:223) ~[h2-2.1.214.jar:2.1.214]
at org.h2.command.Parser.getInvalidPrecisionException(Parser.java:6325) ~[h2-2.1.214.jar:2.1.214]
at org.h2.command.Parser.readIfDataType1(Parser.java:6285) ~[h2-2.1.214.jar:2.1.214]
at org.h2.command.Parser.readIfDataType(Parser.java:6087) ~[h2-2.1.214.jar:2.1.214]
This is the where Query using JPA:
#Query("SELECT DISTINCT u.username"
+ " FROM UserPermissionsMap u"
+ " INNER JOIN Marking m ON m.name = u.markingName AND m.uniqueName = REGEXP_REPLACE(lower(:name), '[^a-z0-9]+', '-', 'g') "
+ " WHERE ( cast(:lastUsernameReturned as text) IS NULL OR u.username > :lastUsernameReturned )"
+ " AND ( cast(:usernameContains as text) IS NULL OR lower(u.username) LIKE %:usernameContains% )")
POM:
...
<h2.version>2.1.214</h2.version>
</properties>
...
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version> << v1.4.200 provided by org.springframework.boot:spring-boot-dependencies:2.5.6
</dependency>

Turns out, I'm able to remove the cast all together, but leave the parenthesis and get the same effect for both H2 & PostgreSQL.
cast(:usernameContains as text) --> (:usernameContains)
They must have fixed the variable replacement when the cast as TEXT was broken.
#Query("SELECT DISTINCT u.username"
+ " FROM UserPermissionsMap u"
+ " INNER JOIN Marking m ON m.name = u.markingName AND m.uniqueName = REGEXP_REPLACE(lower(:name), '[^a-z0-9]+', '-', 'g') "
+ " WHERE ( (:lastUsernameReturned) IS NULL OR u.username > :lastUsernameReturned )"
+ " AND ( (:usernameContains) IS NULL OR lower(u.username) LIKE %:usernameContains% )")

Related

How to make a join with ON in jpa? ( Spring Data Jpa 1.4 )

I have this query, which I have tried in SQL and it goes perfectly
#Query("SELECT new es.abacor.elser.commons.empleado.EmpleadoList("+
"empleado.id,persona.nombre,persona.apellido1,persona.apellido2,persona.dni,persona.email)" +
" FROM rrhh.empleado as empleado" +
" INNER JOIN commons.persona AS persona ON empleado.persona_comun = persona.id" +
" WHERE" +
" empleado.persona_comun is not null" +
" and empleado.borrador = false" +
" and empleado.deleted is null" +
" and empleado.fecha_fin_contrato is null" +
" order by persona.nombre,persona.apellido1,persona.apellido2 asc")
public List<EmpleadoList> allEmpleadosList();
But I get the following error when executing within my project
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON near line 1, column 217 [SELECT new es.abacor.elser.commons.empleado.EmpleadoList(empleado.id,persona.nombre,persona.apellido1,persona.apellido2,persona.dni,persona.email) FROM rrhh.empleado as empleado INNER JOIN commons.persona AS persona ON empleado.persona_comun = persona.id WHERE empleado.persona_comun is not null and empleado.borrador = false and empleado.deleted is null and empleado.fecha_fin_contrato is null order by persona.nombre,persona.apellido1,persona.apellido2 asc]
Someone knows what I'm doing wrong, I do not know what to do anymore.
JPA doesn't work on tables, it works on objects. If you want to use native queries you have to add nativeQuery=true to the Definition:
#Query(nativeQuery=true, <SQL-Statement>)
otherwise the ON clasue will be generated from the annotations in your entities

converting sql statement back to lambda expression

I have the query below, and its sql code. It's running really slow, so it was re written in sql, now I'm just not sure how to convert the sql back to a lambda expression.
This is the part of the expression giving me the problems, somewhere in
r.RecordProducts.Any()
records = records
.Include(r => r.Employer)
.Include(r => r.Contractor)
.Include(r => r.RecordProducts)
.ThenInclude(rp => rp.ProductDefendant.Defendant)
.Where(r => EF.Functions.Like(r.Employer.DefendantCode, "%" + input.DefendantCode + "%")
|| EF.Functions.Like(r.Contractor.DefendantCode, "%" + input.DefendantCode + "%")
|| r.RecordProducts.Any(rp => EF.Functions.Like(rp.ProductDefendant.Defendant.DefendantCode, "%" + input.DefendantCode + "%") && rp.IsActive == true));
the any clause does an exist and some funky stuff in the sql where clause below
SELECT [t].[Id], [t].[StartDate], [t].[EndDate], [t].[WitnessName], [t].[SourceCode], [t].[JobsiteName], [t].[ShipName], [t].[EmployerCode]
FROM (
SELECT DISTINCT [r].[RecordID] AS [Id], [r].[StartDate], [r].[EndDate], [r.Witness].[FullName] AS [WitnessName], CASE
WHEN [r].[SourceID] IS NOT NULL
THEN [r.Source].[SourceCode] ELSE N'zzzzz'
END AS [SourceCode], CASE
WHEN [r].[JobsiteID] IS NOT NULL
THEN [r.Jobsite].[JobsiteName] ELSE N'zzzzz'
END AS [JobsiteName], CASE
WHEN [r].[ShipID] IS NOT NULL
THEN [r.Ship].[ShipName] ELSE N'zzzzz'
END AS [ShipName], CASE
WHEN [r].[EmployerID] IS NOT NULL
THEN [r.Employer].[DefendantCode] ELSE N'zzzzz'
END AS [EmployerCode]
FROM [Records] AS [r]
LEFT JOIN [Ships] AS [r.Ship] ON [r].[ShipID] = [r.Ship].[ShipID]
LEFT JOIN [Jobsites] AS [r.Jobsite] ON [r].[JobsiteID] = [r.Jobsite].[JobsiteID]
LEFT JOIN [Sources] AS [r.Source] ON [r].[SourceID] = [r.Source].[SourceID]
LEFT JOIN [Witnesses] AS [r.Witness] ON [r].[WitnessID] = [r.Witness].[WitnessID]
LEFT JOIN [Defendants] AS [r.Contractor] ON [r].[ContractorID] = [r.Contractor].[DefendantID]
LEFT JOIN [Defendants] AS [r.Employer] ON [r].[EmployerID] = [r.Employer].[DefendantID]
WHERE ([r].[IsActive] = 1) AND (([r.Employer].[DefendantCode] LIKE (N'%' + 'cert') + N'%' OR [r.Contractor].[DefendantCode] LIKE (N'%' + 'cert') + N'%') OR EXISTS (
SELECT 1
FROM [Records_Products] AS [rp]
INNER JOIN [Product_Defendant] AS [rp.ProductDefendant] ON [rp].[DefendantProductID] = [rp.ProductDefendant].[DefendantProductID]
INNER JOIN [Defendants] AS [rp.ProductDefendant.Defendant] ON [rp.ProductDefendant].[DefendantID] = [rp.ProductDefendant.Defendant].[DefendantID]
WHERE ([rp.ProductDefendant.Defendant].[DefendantCode] LIKE (N'%' + 'cert') + N'%' AND ([rp].[IsActive] = 1)) AND ([r].[RecordID] = [rp].[RecordID])))
) AS [t]
ORDER BY [t].[SourceCode]
OFFSET 0 ROWS FETCH NEXT 500 ROWS ONLY
Here is the new sql that works better, just not sure how to convert it back to a lambda expression
SELECT [t].[Id]
,[t].[StartDate]
,[t].[EndDate]
,[t].[WitnessName]
,[t].[SourceCode]
,[t].[JobsiteName]
,[t].[ShipName]
,[t].[EmployerCode]
FROM (
SELECT DISTINCT [r].[RecordID] AS [Id]
,[r].[StartDate]
,[r].[EndDate]
,[r.Witness].[FullName] AS [WitnessName]
,CASE
WHEN [r].[SourceID] IS NOT NULL
THEN [r.Source].[SourceCode]
ELSE N'zzzzz'
END AS [SourceCode]
,CASE
WHEN [r].[JobsiteID] IS NOT NULL
THEN [r.Jobsite].[JobsiteName]
ELSE N'zzzzz'
END AS [JobsiteName]
,CASE
WHEN [r].[ShipID] IS NOT NULL
THEN [r.Ship].[ShipName]
ELSE N'zzzzz'
END AS [ShipName]
,CASE
WHEN [r].[EmployerID] IS NOT NULL
THEN [r.Employer].[DefendantCode]
ELSE N'zzzzz'
END AS [EmployerCode]
FROM [Records] AS [r]
LEFT JOIN [Ships] AS [r.Ship] ON [r].[ShipID] = [r.Ship].[ShipID]
LEFT JOIN [Jobsites] AS [r.Jobsite] ON [r].[JobsiteID] = [r.Jobsite].[JobsiteID]
LEFT JOIN [Sources] AS [r.Source] ON [r].[SourceID] = [r.Source].[SourceID]
LEFT JOIN [Witnesses] AS [r.Witness] ON [r].[WitnessID] = [r.Witness].[WitnessID]
LEFT JOIN [Defendants] AS [r.Contractor] ON [r].[ContractorID] = [r.Contractor].[DefendantID]
LEFT JOIN [Defendants] AS [r.Employer] ON [r].[EmployerID] = [r.Employer].[DefendantID]
LEFT JOIN (
SELECT [rp].[RecordID]
FROM [Records_Products] AS [rp]
INNER JOIN [Product_Defendant] AS [rp.ProductDefendant] ON [rp].[DefendantProductID] = [rp.ProductDefendant].[DefendantProductID]
INNER JOIN [Defendants] AS [rp.ProductDefendant.Defendant] ON [rp.ProductDefendant].[DefendantID] = [rp.ProductDefendant.Defendant].[DefendantID]
WHERE (
[rp.ProductDefendant.Defendant].[DefendantCode] LIKE (N'%' + 'cert') + N'%'
AND ([rp].[IsActive] = 1)
)
) AS RecordProduct ON [r].[RecordID] = RecordProduct.[RecordID]
WHERE ([r].[IsActive] = 1)
AND (
(
[r.Employer].[DefendantCode] LIKE (N'%' + 'cert') + N'%'
OR [r.Contractor].[DefendantCode] LIKE (N'%' + 'cert') + N'%'
)
OR RecordProduct.RecordID IS NOT NULL --OR EXISTS ( -- SELECT 1 -- FROM [Records_Products] AS [rp] -- INNER JOIN [Product_Defendant] AS [rp.ProductDefendant] ON [rp].[DefendantProductID] = [rp.ProductDefendant].[DefendantProductID] -- INNER JOIN [Defendants] AS [rp.ProductDefendant.Defendant] ON [rp.ProductDefendant].[DefendantID] = [rp.ProductDefendant.Defendant].[DefendantID] -- WHERE ([rp.ProductDefendant.Defendant].[DefendantCode] LIKE (N'%' + 'cert') + N'%' -- AND ([rp].[IsActive] = 1)) AND ([r].[RecordID] = [rp].[RecordID]) -- ) )) AS [t]ORDER BY [t].[SourceCode]OFFSET 0 ROWS FETCH NEXT 500 ROWS ONLY
)
)
The linq expression you supplied and the SQL generated do not match. For one, the linq expression is performing an Include on the various related tables which would have included all of those entity columns in the top-level SELECT which are not present in your example SQL. I also don't see conditions in the Linq expression for the Take 500 & OrderBy, or IsActive assertion on Record.
To be able to help determine the source of any performance concern we need to see the complete Linq expression and the resulting SQL.
Looking at the basis of the Linq expression you provided:
records = records
.Include(r => r.Employer)
.Include(r => r.Contractor)
.Include(r => r.RecordProducts)
.ThenInclude(rp => rp.ProductDefendant.Defendant)
.Where(r => EF.Functions.Like(r.Employer.DefendantCode, "%" + input.DefendantCode + "%")
|| EF.Functions.Like(r.Contractor.DefendantCode, "%" + input.DefendantCode + "%")
|| r.RecordProducts.Any(rp => EF.Functions.Like(rp.ProductDefendant.Defendant.DefendantCode, "%" + input.DefendantCode + "%") && rp.IsActive == true));
There are a few suggestions I can make:
There is no need for the Functions.Like. You should be able to achieve the same with Contains.
Avoid using Include and instead utilize Select to retrieve the columns from the resulting structure that you actually need. Populate these into ViewModels or consume them in the code. The less data you pull back, the better optimized the SQL can be for indexing, and the less data pulled across the wire. Consuming entities also leads to unexpected lazy-load scenarios as systems mature and someone forgets to Include a new relation.
.
records = records
.Where(r => r.IsActive
&& (r.Employer.DefendantCode.Contains(input.DefendantCode)
|| r.Contractor.DefendantCode.Contains(input.DefendantCode)
|| r.RecordProducts.Any(rp => rp.IsActive
&& rp.ProductDefendant.Defendant.DefendantCode.Contains(input.DefendantCode))
.OrderBy(r => r.SourceCode)
.Select(r => new RecordViewModel
{
// Populate the data you want here.
}).Take(500).ToList();
This also adds the IsActive check, OrderBy, and Take(500) based on your sample SQL.

Syntax error in Postgresql but not mySQL

I'm executing this query
String innerQueryWithProductVersion = "select test_suite_name, max(m.date) as date "
+"from master_table_test_runs m "
+"INNER JOIN processed_jenkins_runs pdup "
+"ON m.id=pdup.test_run_id where m.date < "
+"(select max(date) from master_table_test_runs "
+"where product_version =:productVersion) "
+"and m.test_type!='CLOVER' and m.product = :product "
+"and m.test_suite_name in "+missingSuites
+" and m.branch like "+filters.branch
+" and m.deployment_mode like "+filters.deploymentMode
+" and pdup.jenkins_server like "+filters.jenkinsInstance
+" group by m.test_suite_name";
String queryWithProductVersion = "select t.number_tests, "
+"t.number_failure, t.number_skip, t.number_errors, t.test_type, "
+"t.product_version, t.date, t.test_suite_name, "
+"t.branch, p.job_url "
+"from master_table_test_runs t INNER JOIN "
+"(" +innerQueryWithProductVersion+") as x "
+"INNER JOIN processed_jenkins_runs p ON t.id=p.test_run_id "
+"where t.test_suite_name = x.test_suite_name "
+"and t.date = x.date and t.test_suite_name "
+"in "+missingSuites+" and product = :product "
+"and p.jenkins_server like "+filters.jenkinsInstance
+" and t.branch like "+filters.branch
+" and t.deployment_mode like "+filters.deploymentMode+"";
This query its working fine in mysql, but in PostgreSQL its giving syntax errors at "where" and "and"
syntax error at or near 'and'
Can anyone help me figure out the problem?
one of "+missingSuites, "+filters.branch etc is not defined, look at sample:
t=# select true where 'a' like '' and true;
bool
------
(0 rows)
t=# select true where 'a' like /*missed value*/ and true;
ERROR: syntax error at or near "and"
LINE 1: select true where 'a' like /*missed value*/ and true;

query throwing error in web report writer

I have a query/view that is created to be used in a report. When I run in the SMS and in SSRS it run fine. But when I connect the view to the tool that generates our reports it throws the following error. Incorrect syntax near '.8'. When I contact the support for this product they say it has to do with how we calculate the 8thgradyear . I have placed the code below. Any suggestions.
SELECT
dbo.studemo.suniq,
dbo.studemo.ident,
dbo.studemo.lastname,
dbo.studemo.firstname,
dbo.studemo.emailaddr AS stuemail,
dbo.studemo.birthdate,
dbo.track.schoolc,
dbo.school.schname,
dbo.stustat.graden,
dbo.stustat.edate,
dbo.zstustat.descript AS status,
RTRIM(dbo.facdemo.lastname) + ' ' + dbo.facdemo.firstname AS advisor,
dbo.track.schyear,
SUM(8) - dbo.stustat.graden + dbo.track.schyear AS [8thgradyear],
sf.Email, LOWER(sf.Username) AS [user],
LOWER(RIGHT(SUM(8) - dbo.stustat.graden + dbo.track.schyear, 2) + LEFT(dbo.studemo.firstname, 1) + REPLACE(REPLACE(REPLACE(dbo.studemo.lastname, '-', ''), ' ', ''), '''', '') + RIGHT(dbo.studemo.ident, 3)) AS newuser,
CONVERT(varchar(8), dbo.studemo.birthdate,1) AS password,
'STUDENTS' + '/' + (CASE WHEN track.schoolc IN ('19', '43', '17', '23') THEN 'Middle' ELSE 'Elementary' END) + '/' + dbo.school.schname AS neworg,
sf.OU, sf.LastLoginTime
FROM dbo.studemo INNER JOIN
dbo.stustat ON dbo.studemo.suniq = dbo.stustat.suniq INNER JOIN
dbo.track ON dbo.stustat.trkuniq = dbo.track.trkuniq INNER JOIN
dbo.zstustat ON dbo.stustat.stustatc = dbo.zstustat.stustatc INNER JOIN
dbo.facdemo ON dbo.stustat.funiq = dbo.facdemo.funiq LEFT OUTER JOIN
dbo.vw_google_OU AS sf ON sf.Firstname = dbo.studemo.firstname AND sf.Lastname = dbo.studemo.lastname INNER JOIN
dbo.school ON dbo.school.schoolc = dbo.track.schoolc
WHERE (dbo.stustat.stustatc IN
(SELECT stustatc
FROM dbo.zstustat AS zstustat_1
WHERE (snstatus IN ('A', 'M', 'P')))) AND (dbo.stustat.xdate IS NULL OR
dbo.stustat.xdate < dbo.stustat.edate) AND (dbo.track.schoolc NOT IN ('P34', 'P24', '802', '801'))
GROUP BY dbo.studemo.suniq, dbo.studemo.ident, dbo.studemo.lastname, dbo.studemo.firstname, dbo.studemo.birthdate, RIGHT(dbo.studemo.ident, 3), dbo.track.schoolc,
dbo.stustat.graden, dbo.zstustat.descript, RTRIM(dbo.facdemo.lastname) + ' ' + dbo.facdemo.firstname, dbo.stustat.edate, dbo.studemo.gradyear, dbo.track.schyear,
sf.Email, CONVERT(varchar(8), dbo.studemo.birthdate, 1), sf.Username, dbo.school.schname, sf.OU, dbo.studemo.emailaddr, sf.LastLoginTime
SUM function was introduced in SQL Server 2008 and your tool must be using and older version of SQL Server.

Like and And Or ISNull using Linq to Entity Entity Framework4? How do you do that?

I have a screen in my project " Enquiry" where I user can perform 2 kinds of search.I cannot figure out how to do a "like" or "And or is null" in Linq to entity.
Simple Search ( Search in all fields using "Like" operator)
Advanced Advanced Search (Use "And" Operator)
So lets take these 3 tables and make up a noddy example.
Customer Table (CustomerID,Name,Surname)
Address(AddressID,Street,City)
CustomerOrder (OrderID,OrderName)
Basic search :
this is how I would do it in Sql
SELECT TOP (100) C.Name,C.Surname,CA.Street,CA.City,CO.OrderName
FROM Customer C
LEFT JOIN CustomerAddress CA ON C.CustomerID=CA.CustomerID
LEFT JOIN CustomerOrders CO ON C.CustomerID=CA.CustomerID
WHERE (C.CustomerID LIKE '%' + #SearchText + '%'
OR C.Surname LIKE '%' + #SearchText + '%'
OR C.Name LIKE '%' + #SearchText + '%'
OR CA.Street LIKE '%' + #SearchText + '%'
OR CA.City LIKE '%' + #SearchText + '%'
OR CO.OrderName LIKE '%' + #SearchText + '%') )
Advanced Search
This my sql where clause
WHERE (C.CustomerID =#CustomerID or #CustomerID ISNULL
AND C.Surname =#Surname or #Surname ISNULL
AND C.Name=#Name or #Name ISNULL
AND CA.Street =#Street or #Street ISNULL
AND CA.City =#City or #City ISNULL
AND CO.OrderName =#OrderName or #OrderName ISNULL)
AND ((ModifiedDate BETWEEN ISNULL(convert(varchar,#FromDate,101),'01/01/1901')
AND ISNULL(convert(varchar,#ToDate,101),'12/31/9999'))
How do you do Likes or and or is null in entity framework?
thanks a lot!
For LIKE, you can use Contains, StartsWith, or EndsWith. For IS NULL, use == null.
Example:
var list = from p in Products
where (p.Description.Contains("v") && p.Description.StartsWith("C"))
|| p.MFRCode == "TOYOTA"
|| p.Universal == null
select p;
will cause EF to generate this SQL:
SELECT
[Extent1].[MFRCode] AS [MFRCode],
[Extent1].[MFRProductID] AS [MFRProductID],
[Extent1].[Universal] AS [Universal],
[Extent1].[Description] AS [Description]
FROM [dbo].[Products] AS [Extent1]
WHERE (([Extent1].[Description] LIKE N'%v%') AND ([Extent1].[Description] LIKE N'C%')) OR (N'TOYOTA' = [Extent1].[MFRCode]) OR ([Extent1].[Universal] IS NULL)
and produce these results:
Edit
I used LINQPad to generate these results. It's a great tool, free to use (there's an option to purchase an Intellisense feature), and definitely worth a look if you'd like to experiment with different LINQ queries and see the SQL that EF is generating (it's good for general LINQ experimentation and quickly trying out simple code as well).
int? customerID = null;
string surname = "abc";
var q = from c in oc.Customers
where (customerID == null || c.CustomerID == customerID)
&& (surname == null || c.Surname == surname)
select c;