EDIT:
I changed the hard coded query to be:
query.setParameter("desc", "%unplug //your// server... enjoy the freedom%" ESCAPE '//')
and now I am getting an com.sun.jdi.InvocationException occurred invoking method.
There's no stacktrace produced either.
I have a description column in my PostgreSQL database and I am trying to query it with a 'LIKE' clause, however I am unable to get any results. Here's an example:
Query query = em.createQuery("from MyClass c WHERE c.description LIKE :desc");
query.setParameter("desc", "%unplug /your/ server... enjoy the freedom%");
In the database I have many descriptions containing a substring of the above text. I've done a lot of research and looked into escaping special chars etc, but nothing has worked.
I am missing something, I just cannot figure out what that is.
Most likely the slash / is messing up the parsing in PG. Turn the parameter into a quoted literal. Unless you are certain that no special characters go into string arguments (i.e. you control the strings), this is always a good idea to avoid SQL injection.
query.setParameter("desc", "quote_literal('%unplug /your/ server... enjoy the freedom%')");
Related
How to compose SQL(MySQL) like PreparedStatement, such as escaping, to avoid SQL injection and genearte safe SQL statement.
Is there any present JavaCode to do this?
Real scenario:
Frontend input as column value to compose a safe SQL (the "where" part), the specified in the backend are table name and column name.
There are some SQL builders, and in general they keep track of all parameters and build a PreparedStatement. It might even be an idea to not only provide parameter values, but parameter names, so one may use it as a real PreparedStatement.
You may create a JdbcTemplate from Spring. Or Criteria API.
If you want to build your own, as research, you might explore escaping too.
Then (research) also consider barring Unicode bidi hacking with LTR (\u200E) and RTL (\u200F): by using a Right-To-Left control one can obfuscate the SQL looking seemingly okay in the editor, but doing something maliciously different. You could require that the characters may not appear in a string but must be escaped too: \\u200F. (However it is something for nerds or insiders, and your SQL must already be at a sensitive spot.)
The SQL dialect is important; backtick (MySQL) or double quotes (Standard) for names etcetera.
There is Apache's commonlang escapeSql.
I am getting the following error after running the jsp report.
Query Tag:doAfterBody(),0,Non supported SQL92 token at position: 3477: S
I know that the following snippet causing the problem ‘{S}’:
…….. AND (L.Applicable_Location_Region_ID IN (N'PARIS2', N'{S}Paris2'))
As per my investigation, I came to know following:
Oracle parses the SQL and treats the text of "'{S}Paris2" as a string literal then finds {S} which it is treating as a SQL Escape Sequence which it doesn't recognize.
The following link explains well about “Escape Characters”:
http://docs.oracle.com/cd/F49540_01/DOC/inter.815/a67843/cqspcl.htm
we must use {S} followed by name.
The above AND statement works fine with SQL Server and MySQL, but causes problem with Oracle as “When you use braces to escape a single character, the escaped character becomes a separate token in the query.”
Due to above reason the application treats {S}, as the escaped a single character with braces becomes a separate token in the query.
So please could you help me how can I escape single character with braces in oracle or any suggestion please.
Try
AND (L.Applicable_Location_Region_ID IN (N'PARIS2', N'\{S\}Paris2'))
EDIT:
Running this query from Toad
select (N'{S}test2') from dual where ((N'{S}test2') IN (N'test2', N'{S}test2'))
does work for me.
Are you sure that the problem is in Oracle database and not in the class/driver accessing it ?
Is there a built-in method to escape a string for SQL? I would use setString, but it happens I am using setString multiple times in the same combined SQL statement and it would be better performance (I think) if the escape happened only once instead of each time I say setString. If I had the escaped string in a variable, I could re-use it.
Is there no way to do this in Java?
Current method, multi-source search. In reality they are three entirely different where statements including joins, but for this example I will just show the same where for each table.
String q = '%' + request.getParameter("search") + '%';
PreparedStatement s = s("SELECT a,b,c FROM table1 where a = ? UNION select a,b,c from table2 where a = ? UNION select a,b,c FROM table3 where a = ?");
s.setString(1, q);
s.setString(2, q);
s.setString(3, q);
ResultSet r = s.executeQuery();
I know this is not a big deal, but I like to make things efficient and also there are situations where it is more readable to use " + quote(s) + " instead of ? and then somewhere down the line you find setString.
If you use setString for a parameter (e.g. PreparedStatement.setString), there may well be no actual escaping required - it's likely that the data will be passed separately from the SQL itself, in a way that doesn't require escaping.
Do you have any concrete indication that this really is a performance bottleneck? It seems very unlikely that within a database query, the expensive part is setting the parameters locally...
Short answer: I wouldn't bother. It's best to do escaping at the last popssible moment. When you try to escape a string early and keep it around, it becomes much more difficult to verify that all strings have been escaped exactly once. (Escaping a string twice is almost as bad as not escaping it at all!) I've seen plenty of programs that try to escape strings early and then run into trouble because they need to update the string and then the programmer forgets to re-do the escape, or they update the escaped version of the string, or they have four strings and they escape three of them, etc. (I was just working on a bug where a programmer did HTML escapes on a string early, then decided he had to truncate the string to fit on a form, and ended up trying to output a string that ended with "&am". That is, he truncated his escape sequence so it was no longer valid.)
The CPU time to escape a string should be trivial. Unless you have a very large number of records or very big strings that are re-used, I doubt the savings would be worth worrying about. You'd probably be better off spending your time optimizing queries: saving a read of one record would probably be worth far more than eliminating 1000 trips through the string escape logic.
Longer answer: There's no built-in function. You could write one easily enough: Most flavors of SQL just need you to double any single quotes. You may need to also double backslashes or one or two other special characters. The fact that this can be different between SQL engines is one of the big arguments for using PreparedStatements and letting JDBC worry about it. (Personally I think there should be a JDbC function to do escaping that could then know any requirements specific to the DB engine. But there isn't so that's how it is.)
In any case, it's not clear how it would work with a PreparedStatement. There'd have to be some way to tell the PreparedStatement not to escape this string because it's already been escaped. And who really knows what's happening under the table in the conversation between JDBC and the DB engine: Maybe it never really escapes it at all, but passes it separately from the query. I suppose there could be an extra parameter on the setString that says "this string was pre-escaped", but that would add complexity and potential errors for very little gain.
Do not use org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);
It does not escape characters like \
You can use StringEscapeUtils from Apache commons:
org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);
Is there a Java library for escaping special characters from a string that is going to be inserted into an SQL query.
I keep writing code to escape various things, but I keep finding some new issue trips me up. So a library that takes care of all or most of the possibilities would be very handy.
EDIT: I am using MySQL (if that makes any difference).
Well... jdbc. Pass the strings as parameters, and don't append them to the query string
A little bit more research points me to this:
http://devwar.blogspot.com/2010/06/how-to-escape-special-characters-in.html
Which suggests to use apache.commons.lang.StringEscapeUtils, I will try this out
I know this is a long time thread, but using the commonslang library there is a method called escapeSql(String). Also using prepared statement automatically escape the offending SQL character.
I am using Lucene in my portal (J2EE based) for indexing and search services.
The problem is about the keywords of Lucene. When you use one of them in the search query, you'll get an error.
For example:
searchTerms = "ik OR jij"
This works fine, because it will search for "ik" or "jij"
searchTerms = "ik AND jij"
This works fine, it searches for "ik" and "jij"
But when you search:
searchTerms = "OR"
searchTerms = "AND"
searchTerms = "ik OR"
searchTerms = "OR ik"
Etc., it will fail with an error:
Component Name: STSE_RESULTS Class: org.apache.lucene.queryParser.ParseException Message: Cannot parse 'OR jij': Encountered "OR" at line 1, column 0.
Was expecting one of:
...
It makes sense, because these words are keywords for Lucene are probably reserved and will act as keywords.
In Dutch, the word "OR" is important because it has a meaning for "Ondernemings Raad". It is used in many texts, and it needs to be found. For example "or" does work, but does not return texts matching the term "OR". How can I make it searchable?
How can I escape the keyword "or"? Or How can I tell Lucene to treat "or" as a search term NOT as a keyword.
I suppose you have tried putting the "OR" into double quotes?
If that doesn't work I think you might have to go so far as to change the Lucene source and then recompile the whole thing, as the operator "OR" is buried deep inside the code. Actually, compiling probably isn't even enough: you'll have to change the file QueryParser.jj in the source package that serves as input for JavaCC, then run JavaCC, then recompile the whole thing.
The good news, however, is that there's only one line to change:
| <OR: ("OR" | "||") >
becomes
| <OR: ("||") >
That way, you'll have only "||" as logical OR operator. There is a build.xml that also contains the invocation of JavaCC, but you have to download that tool yourself. I can't try it myself right now, I'm afraid.
This is perhaps a good question for the Lucene developer mailing list, but please let us know if you do that and they come up with a simpler solution ;-)
OR, NOT and AND are reserved keywords. I solved this problem just 2 days ago by lower-casing those 3 words in the user's search term before feeding it into the lucene query parser. Note that if you search and replace for these keywords make sure you use word boundaries (\b) so you don't end up changing words such as ANDROID and ORDER.
I then let the user specify NOT and AND by using - and +, just like Google does.
Escaping OR and AND with double quotes works for me. So try with a Java string like
String query = "field:\"AND\"";
I have read your question many times! =[
please look at these suggestions
How is your index stored?
Document containing Fields stored can be stored as
1)Stored 2)Tokenized 3)Indexed 4)Vector
it can make a significant difference
please use Luke, it can tell you how your indexes are stored(actually)
Luke is a must have if you are working with lucene, as it gives you a real idea of how indexes are stored,it also offers search, try it let us know with your update!
You're probably doing something wrong when you're building the query. I'll second Narayan's suggestion on getting Luke (as posted in the comments) and try running your queries with that. It has been a little while since I used Lucene, but I don't remember ever having issues with OR and AND.
Other than that, you can try escaping the input strings using QueryParser.escape(userQuery)
More On Escaping
You can escape the "OR" when it's a search term, or write your own query parser for a different syntax. Lucene offers an extensive query API in addition to the parser, with which you support your own query syntax quite easily.