Spring Boot throws an SQL Syntax exception - mysql

I am testing new endpoints on my API and getting an error that confuses me a bit.
2022-08-24 11:51:54.283 WARN 9836 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1064, SQLState: 42000
2022-08-24 11:51:54.283 ERROR 9836 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE) FROM rates WHERE (date BETWEEN '2022-01-01' AND '2022-03-01') AND ((null ' at line 1
2022-08-24 11:51:54.292 ERROR 9836 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/api/v1] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE) FROM rates WHERE (date BETWEEN '2022-01-01' AND '2022-03-01') AND ((null ' at line 1
The confusing part for me is that I don't understand where it gets the first part of the query WHERE) in the error message.
Repo
#Query("SELECT * FROM rates WHERE (date BETWEEN :startDate AND :endDate) AND ((:code IS NULL OR rate_code = :code) AND rate > 0)", nativeQuery = true)
fun getByDateRange(startDate: Date, endDate: Date, code: String?, pageable: Pageable): Page<RateEntity>
Controller
#GetMapping("/historic")
fun ratesForDateRange(
#RequestParam startDate: Optional<Date>,
#RequestParam endDate: Optional<Date>,
#RequestParam(required = false) code: String?,
#RequestParam(required = false) pageNumber: Int?
): Page<RateEntity> {
val lastDate = Date.valueOf(START_DATE)
val page = pageNumber ?: 0
println(code)
return repo.getByDateRange(
startDate.orElse(lastDate),
endDate.orElse(UtilFunctions.getCurrentSQLDate()),
code,
PageRequest.of(page, 50)
)
}
When I use the wrong code in request URL /api/v1/historic?startDate=2022-1-1&endDate=2022-3-1&code=abc I get an empty page as expected.
When I use the right code in request URL /api/v1/historic?startDate=2022-1-1&endDate=2022-3-1&code=suv and there are records between specified dates, I get the page with results as expected.
However, when I don't specify the code in request URL /api/v1/historic?startDate=2022-1-1&endDate=2022-3-1 I get this exception.
I use MySQL for Database and if use this query directly in CLI it works as expected.
For example this query
SELECT * FROM rates WHERE (date BETWEEN '2022-01-01' AND '2022-03-01') AND ((null IS NULL OR rate_code = null) AND rate > 0);
returns all results for specified date range as expected.

I think it is the problem with date_and_time in spring boot.
You are comparing two dates whereas the actual values saved are dateAndTime, which spring can not compare. Therefore, you should cast the date field as follow:
CAST(date as DATE)
Complete Query:
#Query("SELECT * FROM rates WHERE (CAST(date as DATE) BETWEEN :startDate AND :endDate) AND ((:code IS NULL OR rate_code = :code) AND rate > 0)", nativeQuery = true)

Ok so I've already found where the problem lies and fixed it. Probably posted too soon.
After some more testing I found out that the exception occurs when amount of results is >= page size (50 in my case).
So after displaying hibernate queries with:
spring.jpa.show-sql = true
I found this:
Hibernate: SELECT count(WHERE) FROM rates WHERE (date BETWEEN ? AND ?) AND ((? IS NULL OR rate_code = ?) AND rate > 0)
That's where WHERE) comes from, which is obviously a syntax error.
The fix was to add custom count query like this:
#Query(
value = "SELECT * FROM rates WHERE (date BETWEEN :startDate AND :endDate) AND ((:code IS NULL OR currency_code = :code) AND rate > 0)",
countQuery = "SELECT count(*) FROM rates WHERE (date BETWEEN :startDate AND :endDate) AND ((:code IS NULL OR currency_code = :code) AND rate > 0)",
nativeQuery = true
)
fun getByDateRange(startDate: Date, endDate: Date, code: String?, pageable: Pageable): Page<RateEntity>

Related

how to alias(AS) a table in raw SQL with knex.js

I am using knex.js with MySql DB. I have a migration where I have to use raw SQL. My migration looks like this :
import * as Knex from "knex";
const brokersTable = "OriginationAdmin.Brokers";
const brokerIndividualTable = "OriginationAdmin.BrokerIndividuals";
exports.up = async (knex: Knex) => {
await knex.schema.raw(
`UPDATE ${brokersTable}
JOIN(
SELECT CompanyName, MIN(Id) AS Id
FROM ${brokersTable}
GROUP BY CompanyName )
AS x
ON x.CompanyName = ${brokersTable}.CompanyName
AND isDeleted IS NULL
SET isDeleted = CASE WHEN (x.Id <> ${brokersTable}.Id) THEN 1 END`
);
when I run migrate up I get an error message:RequestError: Incorrect syntax near the keyword 'AS'. I know the SQL Query is syntactically correct but why am I getting an error with the aliasing keyword and how do I fix it?
Edit: This most(relevant part) of the error message
migration file "20210822190619_de-duplicate-brokers-and-associate-individuals.ts" failed
migration failed with error: UPDATE OriginationAdmin.Brokers
JOIN (
SELECT CompanyName, MIN(Id) AS Id
FROM OriginationAdmin.Brokers
GROUP BY CompanyName
) AS x
ON x.CompanyName = OriginationAdmin.Brokers.CompanyName
AND isDeleted IS NULL
SET isDeleted = CASE WHEN (x.Id <> OriginationAdmin.Brokers.Id) THEN 1 END
- Incorrect syntax near the keyword 'AS'.
RequestError: Incorrect syntax near the keyword 'AS'.
at handleError (/Users/haroonAzhar/Desktop/FAL/omni-api/node_modules/mssql/lib/tedious/request.js:366:15)
The error message isn't very helpful to what the problem is.

Conversion failed when converting the nvarchar value '7575932.' to data type int

I have this legacy code that started failing…
UPDATE B2C
SET B2C.dborderid = A.order_number__c
FROM b2csf B2C
JOIN Alemania A ON B2C.actualid = A.salesforce_id
I get this error:
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value '7201799-' to data type int.
I went ahead and changed it to:
UPDATE B2C
SET B2C.dborderid = (CASE
WHEN Isnumeric (a.order_number__c) = 1
THEN CAST(a.order_number__c AS INT)
END)
FROM b2csf B2C
JOIN Alemania A ON B2C.actualid = A.salesforce_id
And now I get
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value '7575932.' to data type int.
My questions now are:
how can I avoid this error? I don’t mind for example losing '7575932.' value.(Ideally I would like to discard '7575932.' value)
I am trying my best to follow best practices... is changing the column DBorderid to nvarchar the only "best practice" alternative?
(I am using SQL Server 2008)
Instead of ... WHEN Isnumeric (a.order_number__c) = 1 ... use ... WHEN Isnumeric (a.order_number__c + '.0e0') = 1 ...

Hibernate query for employee with date

This is my code.. Query working when i search with mysql query(find it in screenshot).But failed with hiberbate query.
EmployeeAttendanceMaster masterEmployeeFromRepository = masterEmployeeRepository.findById(employee, date);
if (masterEmployeeFromRepository == null) {
System.out.println("SignIn Successfully");
}else System.out.println("You are already Logged In");
masterEmployeeRepository:
#Query("select me from EmployeeAttendanceMaster me where me.employee = ?1 and Date(me.date) = ?2 order by me.date desc")
EmployeeAttendanceMaster findById(Employee employee,Date date);
mysql db screenshot in with same query
Data with same date there in db..So it shoudnot go through if condition.It should follow else condition.But as long as i tried this it prints "SignIn Successfully"
Thanks advance
You are using the Spring Data JPA #Query annotation (as discerned from the full data type you have provided in the comments to your question). The query you specify with #Query (select me from EmployeeAttendanceMaster me ...) must be a valid JPA Query Language (JPQL) statement. From what I know and remember, JPQL does not have a Date() function. So, your query is invalid because it contains Date(me.date) which refers to a non-existent JPQL Date() function, even if you can run it directly on MySQL.
You can change your query declaration to:
#Query(value = "select * from EmployeeAttendanceMaster where employee_id = ?1 and Date(date) = ?2 order by date desc", nativeQuery = true)
This will force the JPA provider (Hibernate in your case) to treat the query as a native SQL query and will be executed on the underlying database without any translation. You will lose database independence though.

Query that searches between two dates

Hi guys i have a search query that should display all the results between a set date range
the query :
public List<Appointment> appointmentRangeSearch(Date startdatetime, Date endDate) {
Query q = em.createQuery("SELECT u FROM Appointment U WHERE u.startDatetime BETWEEN : date1 AND : date2 ");
q.setParameter("date1", startdatetime, TemporalType.TIMESTAMP);
q.setParameter("date2", endDate, TemporalType.TIMESTAMP);
return q.getResultList();
}
it is returning the errror :
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing [SELECT u FROM Appointment U WHERE u.startDatetime BETWEEN : date1 AND : date2 ].
[34, 77] The expression is not a valid conditional expression.
the data in the table is stored :
2013-12-15 00:00:00.0
how can i complete this search ?
thanks guys
Remove the space between : and date1 from : date1. So your query should be like this:
SELECT u FROM Appointment U WHERE u.startDatetime BETWEEN :date1 AND :date2
Your syntax error has been solved but you might have a logic problem not related to your question. If your datatype is datetime, and the data includes a time portion, then this:
where myField between '2013-12-01' and '2013-12-05'
will not pick up records with values like 2013-12-05 01:00
The solution is to do this
where myField >= '2013-12-01'
and myField < '2013-12-06' -- note that this is one day later

Orbeon 3.9.0 remote/network Mysql server

I'm using Orbeon 3.9.0 PE RC1 with liferay-portal-6.0.5. When using Localhost Mysql persistence layer, its works.
but when try to use remote (Local Network) Mysql database, then Form builder can't publish any form and no data shown.
Properties-local.xml configaretion
`
Error Log sample.
2011-04-07 12:37:18,118 INFO ProcessorService - /fr/service/mysql/search/orbeon/builder - Received request
2011-04-07 12:37:20,853 ERROR SQLProcessor - PreparedStatement:
select
(
select count(*) from orbeon_form_data
where
(app, form, document_id, last_modified) in (
select app, form, document_id, max(last_modified) last_modified
from orbeon_form_data
where
app = ?
and form = ?
group by app, form, document_id)
and deleted = 'N'
) total,
(
select count(*) from (
select
data.created, data.last_modified, data.document_id
, extractValue(data.xml, '/*/xhtml:head/xforms:model[#id = ''fr-form-model'']/xforms:instance[#id = ''fr-form-metadata'']/*/application-name') detail_1
, extractValue(data.xml, '/*/xhtml:head/xforms:model[#id = ''fr-form-model'']/xforms:instance[#id = ''fr-form-metadata'']/*/form-name') detail_2
, extractValue(data.xml, '/*/xhtml:head/xforms:model[#id = ''fr-form-model'']/xforms:instance[#id = ''fr-form-metadata'']/*/title[#xml:lang = ''en'']') detail_3
, extractValue(data.xml, '/*/xhtml:head/xforms:model[#id = ''fr-form-model'']/xforms:instance[#id = ''fr-form-metadata'']/*/description[#xml:lang = ''en'']') detail_4
from orbeon_form_data data,
(
select max(last_modified) last_modified, app, form, document_id
from orbeon_form_data
where
app = ?
and form = ?
group by app, form, document_id
) latest
where
data.last_modified = latest.last_modified
and data.app = latest.app
and data.form = latest.form
and data.document_id = latest.document_id
and data.deleted = 'N'
order by created desc
)a
) search_total
2011-04-07 12:37:20,868 INFO DatabaseContext - Rolling back JDBC connection for datasource: jdbc/mysql.
2011-04-07 12:37:20,868 ERROR ProcessorService - Exception at oxf:/apps/fr/persistence/mysql/search.xpl (executing XSLT transformation)
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: FUNCTION orbeon.extractValue does not exist
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:874)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:169)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:169)
at org.orbeon.oxf.processor.sql.interpreters.QueryInterpreter.end(QueryInterpreter.java:600)
at org.orbeon.oxf.processor.sql.SQLProcessor$InterpreterContentHandler.endElement(SQLProcessor.java:540)
at org.orbeon.oxf.processor.sql.SQLProcessor$ForwardingContentHandler.endElement(SQLProcessor.java:635)
at org.orbeon.oxf.processor.sql.SQLProcessor$InterpreterContentHandler.endElement(SQLProcessor.java:542)
at org.orbeon.oxf.processor.sql.SQLProcessor$ForwardingContentHandler.endElement(SQLProcessor.java:635)
at org.orbeon.oxf.processor.sql.SQLProcessor$InterpreterContentHandler.endElement(SQLProcessor.java:542)
at org.orbeon.oxf.processor.sql.SQLProcessor$ForwardingContentHandler.endElement(SQLProcessor.java:635)
at org.orbeon.oxf.processor.sql.SQLProcessor$InterpreterContentHandler.endElement(SQLProcessor.java:542)
at org.orbeon.oxf.processor.sql.SQLProcessor$RootInterpreter.endElement(SQLProcessor.java:290)
at org.orbeon.oxf.xml.SAXStore.replay(SAXStore.java:288)
at org.orbeon.oxf.xml.SAXStore.replay(SAXStore.java:202)
at org.orbeon.oxf.processor.sql.SQLProcessor.execute(SQLProcessor.java:251)
at org.orbeon.oxf.processor.sql.SQLProcessor$1.readImpl(SQLProcessor.java:89)
at org.orbeon.oxf.processor.impl.ProcessorOutputImpl$TopLevelOutputFilter.read(ProcessorOutputImpl.java:263)
at org.orbeon.oxf.processor.impl.ProcessorOutputImpl.read(ProcessorOutputImpl.java:406)
at `
Since the error you're getting is FUNCTION orbeon.extractValue does not exist, I suspect this is because the other (remote) version of MySQL is an older version which doesn't support extractValue(). The MySQL persistence layer relies on XML functions that have been introduced in MySQL 5.1, so you need to be using the MySQL 5.1 (which was released in November 2008) or newer.