I have a problem with an empty result set, which are throwing some errors. But it is working fine as long as it is not empty.
String sql = "SELECT M2.fromProfileId, profiles.profileMiniature, profiles.firstName, profiles.lastName, profiles.timeFormat, lastMessages.message, lastMessages.timeStamp " +
"FROM (" +
" SELECT M1.fromProfileId, " +
" max(M1.timeStamp) AS lastMessageTime " +
" FROM messages AS M1 " +
" WHERE M1.toProfileId = ? " +
" GROUP BY M1.fromProfileId " +
" ORDER BY max(M1.timeStamp) DESC " +
" LIMIT 10 " +//line 60
" ) AS M2 " +
"INNER JOIN messages AS lastMessages " +
"ON (" +
" lastMessages.timeStamp = M2.lastMessageTime " +
"AND lastMessages.fromProfileId = M2.fromProfileId" +
" )" +
"INNER JOIN profiles " +
"ON M2.fromProfileId = profiles.profileId ";
PreparedStatement statement = con.prepareStatement(sql);
statement.setString(1, profileId);
ResultSet result = statement.executeQuery();
JSONArray messages = new JSONArray();
while(result.next()){
JSONObject message = new JSONObject();
message.put("fromProfileId", result.getString("fromProfileId"));
message.put("profileMiniature", result.getString("profileMiniature"));
message.put("firstName", result.getString("firstName"));
message.put("lastName", result.getString("lastName"));
message.put("lastMessage", result.getString("message"));
message.put("lastMessageTime", result.getString("timeStamp"));
message.put("timeFormat", result.getString("timeFormat"));
messages.put(message);
}
and the error is Illegal operation on empty result set. How shall I fix this?
StackTrace:
Illegal operation on empty result set.
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at
com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:841)
at
com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5656)
at
com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5576)
at
com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5616)
at
messages.GetMessages.doGet(GetMessages.java:60)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:534)
etc..
I found many bugs in MySQL JDBC driver which seem to cause this exception.
Related
If i insert a quote symbol " in the codContract parameter I receive the following error.
Error querying database. Cause: java.sql.SQLSyntaxErrorException:
ORA-00972: identifier too long
The error may exist in mappers/existence.xml The error may involve
com.iv.queryinterface.AssistenzaMapper.getTitlesFromCodContratct-Inline
The error occurred while setting parameters
SQL:
SELECT t.id_title,
c.des_lastname,
c.des_firstname,
to_char(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW,
DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE
FROM Ivf_Policy p,
Ivf_Title t,
Ivg_Client c,
Ivf_Price pr
WHERE Cod_Contract = TEST
AND p.id_policy = t.id_policy
AND t.cod_type_title IN(2, 3, 13)
AND t.cod_statustitle IN(1, 2)
AND t.cod_client = c.cod_client
AND t.id_price = pr.id_price;
Cause: java.sql.SQLSyntaxErrorException: ORA-00972: identifier too
long
In this example, i set " TEST as value for the codContract parameter. My questions are:
Is this an exploitable SQL injection or a false positive that just prints an sql error into the stack trace?
The code is susceptible to SQL injection, and does no escaping. All that is avoidable by the use of PreparedStatement. Where the query string is not composed dynamically.
Now "TEST is the first part of an SQL identifier till a closing double quote.
I do not want to instruct readers on hacking, but think what something like
"'' OR 1=1 "
+ "UNION SELECT u.login, u.password, '', '', '', '' "
+ "FROM users"
+ "\u0000-- ";
might reveal on data.
Use java.sql.PreparedStatement for avoiding SQL injection.
String query =
"SELECT " +
" t.id_title , " +
" c.des_lastname , " +
" c.des_firstname , " +
" TO_CHAR(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW, " +
" DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE " +
"FROM " +
" Ivf_Policy p, " +
" Ivf_Title t, " +
" Ivg_Client c, " +
" Ivf_Price pr " +
"WHERE " +
"1 = 1 AND " +
" Cod_Contract = ? " +
"AND p.id_policy = t.id_policy " +
"AND t.cod_type_title IN(2, " +
" 3, " +
" 13) " +
"AND t.cod_statustitle IN(1, " +
" 2) " +
"AND t.cod_client = c.cod_client " +
"AND t.id_price = pr.id_price;";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, 'TEST');
ResultSet rs = stmt.executeQuery();
To avoid SQL injection, do not append parameter values directly to SQL queries.
Use bind variables instead.
Thanks.
I wanted to execute this query, but it gave me an error without using variables but it gave me an error ORA-00905: missing keyword.
I tested the query in SQL Developer and it ran with no errors. I'm probably think it's a driver issue or a syntax issue with JDBC. But I have no idea here's the code:
public List<ReimbBean> getAllReimb() {
String sql = "select reim.reimb_id, reim.reimb_amount,"
+ "reim.reimb_submitted, reim.reimb_resolved, "
+ "CONCAT(CONCAT(u.user_first_name,' '),"
+ " u.user_last_name) AS \"REIMB_AUTHOR\", "
+ "reim.REIMB_RESCRIPTION, rst.REIMB_STATUS, "
+ "rtype.REIMB_TYPE, CONCAT(CONCAT(urs.user_first_name,' '), "
+ "urs.user_last_name) AS \"REIMB_RESOLVER\""
+ "FROM ERS_REIMBURSTMENT reim"
+ "LEFT JOIN ERS_USERS u"
+ "ON u.ERS_USERS_ID = reim.REIMB_AUTHOR"
+ "LEFT JOIN ERS_REIMBURSTMENT_STATUS rst"
+ "ON rst.REIMB_STATUS_ID = reim.REIMB_STATUS_ID"
+ "LEFT JOIN ERS_REIMBURSTMENT_TYPE rtype"
+ "ON rtype.reimb_type_id = reim.REIMB_TYPE_ID"
+ "LEFT JOIN ERS_USERS urs"
+ "ON urs.ERS_USERS_ID = reim.REIMB_RESOLVER"
+ "ORDER BY reim.reimb_id";
List<ReimbBean> reimbAllList = new ArrayList<>();
ReimbBean reimb = new ReimbBean();
try {
PreparedStatement preparedStatement = conn6.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()){
reimb.setReimbAmount(rs.getDouble("reimb_Amount"));
reimb.setReimbDescript(rs.getString("reimb_Description"));
reimb.setReimbSubmitted(rs.getTimestamp("reimb_Submitted"));
reimb.setReimbAuthor(rs.getInt("reimb_Author"));
reimb.setReimbResolved(rs.getTimestamp("reimb_Resolved"));
reimb.setReimbResolver(rs.getInt("reimb_Resolver"));
reimb.setReimbStatusID(rs.getInt("reimb_Status_ID"));
reimb.setReimbTypeID(rs.getInt("reimb_Type_ID"));
reimbAllList.add(reimb);
}
I read online that the preapareStatement is unable to bind objects only variables, so the alternative was to define them explicitly, so I created a part for declarations and substituted the fields with String variables, but the error continues to persist.
You are missing whitespaces at the end of a lot of those strings:
String sql = "select reim.reimb_id, reim.reimb_amount,"
+ "reim.reimb_submitted, reim.reimb_resolved, "
+ "CONCAT(CONCAT(u.user_first_name,' '),"
+ " u.user_last_name) AS \"REIMB_AUTHOR\", "
+ "reim.REIMB_RESCRIPTION, rst.REIMB_STATUS, "
+ "rtype.REIMB_TYPE, CONCAT(CONCAT(urs.user_first_name,' '), "
+ "urs.user_last_name) AS \"REIMB_RESOLVER\" " // Here
+ "FROM ERS_REIMBURSTMENT reim " // and here
+ "LEFT JOIN ERS_USERS u " // and here
+ "ON u.ERS_USERS_ID = reim.REIMB_AUTHOR " // and here
+ "LEFT JOIN ERS_REIMBURSTMENT_STATUS rst " // and here
+ "ON rst.REIMB_STATUS_ID = reim.REIMB_STATUS_ID " // and here
+ "LEFT JOIN ERS_REIMBURSTMENT_TYPE rtype " // and here
+ "ON rtype.reimb_type_id = reim.REIMB_TYPE_ID " // and here
+ "LEFT JOIN ERS_USERS urs " // and here
+ "ON urs.ERS_USERS_ID = reim.REIMB_RESOLVER " // and here
+ "ORDER BY reim.reimb_id";
Good day. I have a query in my Java code that deletes duplicate rows in a table. Initially it worked and for a while i didn't touch the project. But on running the file a few days ago, my code was throwing exceptions. This is my code:
String query = "DELETE error_log FROM error_log INNER JOIN "
+ "(SELECT min(id) minid, service_source, channel,transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date FROM error_log "
+ "GROUP BY service_source, channel, transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date "
+ "HAVING COUNT(1) > 1 AS duplicates ON "
+ "(duplicates.service_source = error_log.service_source AND duplicates.channel = error_log.channel "
+ "AND duplicates.transaction_type = error_log.transaction_type AND duplicates.provider_name = error_log.provider_name "
+ "AND duplicates.pido_account = error_log.pido_account AND duplicates.beneficiary_id = error_log.beneficiary_id "
+ "AND duplicates.error_description = error_log.error_description AND duplicates.error_date = error_log.error_date "
+ "AND duplicates.minid <> error_log.id"
+ ")"
+ ")";
int deploy = duplicate.executeUpdate(query);
I get this afterwards:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'AS duplicates ON (duplicates.service_source = error_log.service_source AND dupli' at line 1.
How do i correct this and have the duplicates deleted from the table?
You have a missing ) on line + "HAVING COUNT(1) > 1 AS duplicates ON " and have an extra ) at the end.
String query = "DELETE error_log FROM error_log INNER JOIN "
+ "(SELECT min(id) minid, service_source, channel,transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date FROM error_log "
+ "GROUP BY service_source, channel, transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date "
+ "HAVING COUNT(1) > 1 ) AS duplicates ON "
+ "(duplicates.service_source = error_log.service_source AND duplicates.channel = error_log.channel "
+ "AND duplicates.transaction_type = error_log.transaction_type AND duplicates.provider_name = error_log.provider_name "
+ "AND duplicates.pido_account = error_log.pido_account AND duplicates.beneficiary_id = error_log.beneficiary_id "
+ "AND duplicates.error_description = error_log.error_description AND duplicates.error_date = error_log.error_date "
+ "AND duplicates.minid <> error_log.id"
+ ")";
int deploy = duplicate.executeUpdate(query);
If you haven't made any changes and it stopped working, 1) are you sure you tested this code? and 2) has anyone else made any changes without your knowledge?
I keep getting the following error: "could not locate named parameter [articleCommentId]" but it doesn't make sense to me because to me the named parameter is very much in place.
public ArticleCommentForDisplay getCommentByArticleCommentId(BigInteger articleCommentId) {
String queryString = "select c.article_comment_id, "
+ " c.article_id, "
+ " c.parent_comment_id, "
+ " p.nickname, "
+ " c.title, "
+ " c.comment, "
+ " c.person_id, "
+ " c.confirmed_user, "
+ " c.comment_depth, "
+ " c.moderation_rank, "
+ " c.moderation_reason, "
+ " c.hide, "
+ " c.hide_reason, "
+ " c.session_id, "
+ " c.confirmation_uuid, "
+ " c.created_timestamp, "
+ " c.created_by_id, "
+ " c.updated_timestamp, "
+ " c.updated_by_id, "
+ " c.update_action, "
+ " null as comment_path "
+ "from article_comment c "
+ " join person p "
+ " on p.person_id = c.person_id "
+ "where c.article_comment_id = :articleCommentId; ";
Query query = em.createNativeQuery(queryString, "ArticleCommentMap");
query.setParameter("articleCommentId", articleCommentId);
List <ArticleCommentForDisplay> articleComments = new ArrayList<>();
articleComments = query.getResultList();
ArticleCommentForDisplay theComment = articleComments.get(0);
return (theComment);
}
Here is an extract of the stack trace with the relevant error:
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryParameterException: could not locate named parameter [articleCommentId]
at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:379)
at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:72)
at com.extremelatitudesoftware.content.ArticleCommentFacade.getCommentByArticleCommentId(ArticleCommentFacade.java:293)
I bet it is due to the extra ; in your query string.
SQL/HQL does not need to be terminated by semicolon
The named parameters is not defined for native queries in JPA Specification.
Replace
where c.article_comment_id = :articleCommentId;
with
where c.article_comment_id = ?1;
....
query.setParameter(1, articleCommentId)
Mine was an extra ' in the sql query. Oh my gosh, kept looking until my eyes nearly pooooopped out `-)
So, ensure that you don't have anything "extra" in your query, make sure that your (, ", ' etc...have matching pairs, because the error message in that case is not relevant and has nothing to do with your named parameter! JPA is right as it could not locate it, but that's because something else in your query is messing up...
You can also use it like this
where c.article_comment_id = ?,
and c.any_other_field = ?;
....
query.setParameter(1, articleCommentId)
query.setParameter(2, anyOtherValue)
it will take it by sequence.
And you can also give numbers like
where c.article_comment_id = ?1,
and c.any_other_field = ?2;
....
query.setParameter(1, articleCommentId)
query.setParameter(2, anyOtherValue)
If you are using named parameter at end of your query the remove the ; from your query
In my case, I didn't add the extra space after the named parameter.
example:
+ "WHERE\n" + " s.something = 'SOME'\n" + "START WITH\n"
+ " s.country_type = :countryName" + "CONNECT BY\n"
changed to (notice the space after named parameter :countryName
+ "WHERE\n" + " s.something = 'SOME'\n" + "START WITH\n"
+ " s.country_type = :countryName " + "CONNECT BY\n"
I have a follow up to complicated mysql question that I recently asked: Show the ten first contacts that I have recieved message
Now I know that it is missing something, my last question was:
I want to create Sql statement that
show the ten first contacts that I
have recieved message from along with
their latest sent message and time.
The table columns is messageId,
message, fromProfileId, toProfileId,
timeStamp and table is called
messages. The database is Mysql and
Java is the language. But I want this
to happen in one single sql statement.
What's missing is that I want to show the message I've sent also, but it should be grouped with the messages that I've recieved from the user I've sent to:
ten first contacts that I have
received message from or sent to along
with their latest sent message and
time.
Little complicated to understand? Ok. think like this. the quoted first sql statement above only show messages that I reveived from. but what if I send a message? That message will never show up.
This is my code, but I failed to succed(look at where I marked the comment):
"SELECT M2.messageProfileId, profiles.profileMiniature, profiles.firstName, profiles.lastName, profiles.timeFormat, lastMessages.message, lastMessages.timeStamp " +
"FROM (" +
" SELECT IF(M1.fromProfileId = ?, M1.toProfileId, M1.fromProfileId) AS messageProfileId, " +
" max(M1.timeStamp) AS lastMessageTime " +
" FROM messages AS M1 " +
" WHERE M1.toProfileId = ? " +
" OR M1.fromProfileId = ? " +
" GROUP BY IF(M1.fromProfileId = ?, M1.toProfileId, M1.fromProfileId) " +
" ORDER BY max(M1.timeStamp) DESC " +
" LIMIT 10 " +
" ) AS M2 " +
"INNER JOIN messages AS lastMessages " +
"ON (" +
" lastMessages.timeStamp = M2.lastMessageTime " +
"AND lastMessages.fromProfileId = M2.messageProfileId" +//This to be like the if statements above, but how?
" )" +
"INNER JOIN profiles " +
"ON M2.messageProfileId = profiles.profileId ";
UPDATE:
All question marks in the above code will be replaced with a a same id, for example 27.
UPDATE:
You just have to solve one line now. Look at the commented line above. I dont know how to make if statement in where clause?
Ok figured it out myself
"SELECT M2.messageProfileId, profiles.profileMiniature, profiles.firstName, profiles.lastName, profiles.timeFormat, lastMessages.message, lastMessages.timeStamp " +
"FROM (" +
" SELECT IF(M1.fromProfileId = ?, M1.toProfileId, M1.fromProfileId) AS messageProfileId, " +
" max(M1.timeStamp) AS lastMessageTime " +
" FROM messages AS M1 " +
" WHERE (M1.toProfileId = ? " +
" OR M1.fromProfileId = ?) " +
" GROUP BY IF(M1.fromProfileId = ?, M1.toProfileId, M1.fromProfileId) " +
" ORDER BY max(M1.timeStamp) DESC " +
" LIMIT 10 " +
" ) AS M2 " +
"INNER JOIN messages AS lastMessages " +
"ON (" +
" lastMessages.timeStamp = M2.lastMessageTime " +
"AND (" +
" lastMessages.fromProfileId = M2.messageProfileId " +
"OR lastMessages.toProfileId = M2.messageProfileId " +
" )" +
" )" +
"INNER JOIN profiles " +
"ON M2.messageProfileId = profiles.profileId ";