How to replace single quote in Java with Postgres? - java

How to replace single quote in Java with Postgres?
select * from where id in ('<45646300.KDSFJJSKJSDF95'fdgdfgdfgd>', 'fdgdfgdg');
I always use params like
select * from where id = ?;
But in this case i have problem, where i have 'in' statement with string passed to it.
I wish to replace all dangerous chars

It would be better to continue using PreparedStatements rather than to escape characters manually.
In the case of IN clause you can generate a query with appropriate number of ?s dynamically.
String[] input = ...;
StringBuilder b = new StringBuilder();
b.append("select * from where id in (");
b.append("?"); // Assume that input contains at least one element
for (int i = 1; i < input.length; i++) b.append(", ?");
b.append(")");
PreparedStatement s = c.prepareStatement(b.toString());
for (int i = 0; i < input.length; i++) s.setString(i + 1, input[i]);

Apache commons API provides multiples ways to remove dangerous chars for specific languages such as CSS, Javascript SQL, etc...
Take a look at this if it helps : http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/StringEscapeUtils.html

Use the standard SQL quoting for single quotes:
select *
from the_table
where id in ('<45646300.KDSFJJSKJSDF95''fdgdfgdfgd>', 'fdgdfgdg');
So any embedded single quote needs to be written twice.

Did you try?
select * from TABLE_NAME where id in (?);

There's a page explaining the different options over here on the javaranch site

Related

Getting WHERE clause after Update statement

I am required to fetch the where clause after an update statement e.g.
UPDATE user_accounts SET bio='This is my bio' WHERE user_id = 1 OR name = 'Alex';
At the moment, I am able to get everything after the where clause with the following code:
String query = "UPDATE user_accounts SET bio='This is my bio' WHERE user_id = 1 OR name = 'Alex'";
int index = query.toUpperCase().indexOf("WHERE");
if (index != -1) {
System.out.println(query.substring(index));
}
But then I discovered that this was significantly flawed, since these sample queries would fail:
UPDATE user_accounts SET bio='This is where my bio is' WHERE user_id = 1 OR name = 'Alex';
UPDATE user_accounts SET whereColumn='' WHERE user_id = 1 OR name = 'Alex'
UPDATE user_whereabouts SET columnName='' WHERE user_id = 1 OR name = 'Alex'
Essentially, this fails if table name or any column name or column value under SET contains the word 'where' (case insensitive).
My thinking has currently been along the lines of a regex that does the following:
Checks if the word where is in between ' ' or " " (e.g. bio = "This is where my bio is") and skips it to move to the one which isn't inside the quotes. This will help eliminate the where words found in the SET values. Of course the Java quotes surrounding a string do not apply since they aren't part of the string itself.
Checks that the word where is sandwiched between spaces (e.g. ... WHERE ...). This will help eliminate the where words found in either table name or column name (SQL syntax itself can't allow table name or column name to solely be a reserved word).
Finally, returns the index of the wanted WHERE in order to get the substring (The objective of the question).
I am not very conversant with regexes and thus, I am in need of assistance. Please note that any other ways of achieving the objective will be highly appreciated as well.
You need some kind of SQL parser because regexes will fail short in many cases (for instance what if the where clause has a sub-select?)
I've never tried it but JSQLParser seems like a good solution
Using JSqlParser this would look like:
List<String> sqls = Arrays.asList("UPDATE user_accounts SET bio='This is my bio' WHERE user_id = 1 OR name = 'Alex';",
"UPDATE user_accounts SET whereColumn='' WHERE user_id = 1 OR name = 'Alex'",
"UPDATE user_whereabouts SET columnName='' WHERE user_id = 1 OR name = 'Alex'");
for (String sql : sqls) {
Statement stmt = CCJSqlParserUtil.parse(sql);
Update update = (Update)stmt;
System.out.println("sql=" + stmt.toString());
System.out.println(" where=" + update.getWhere());
}
However you could improve your where search by using regular expressions, e.g. for with word boudaries:
\bwhere\b
but again you are right, this version is flawed as well for e.g. set col = ' test where test'.
The right way to do it, is to parse the whole sql via a parser (https://github.com/JSQLParser/JSqlParser).

Apache Calcite to Find Selected Columns in an SQL String

I have a use case where I want to know the columns which have been selected in an SQL string.For instance, if the SQL is like this:
SELECT name, age*5 as intelligence FROM bla WHERE bla=bla
Then, after parsing the above String, I just want the output to be: name, intelligence.
Firstly, is it possible through Calcite?
Any other option is also welcome.
PS: I want to know this before actually running the query on database.
This is definitely doable with Calcite. You'll want to start by creating an instance of SqlParser and parsing the query:
SqlParser parser = SqlParser.create(query)
SqlNode parsed = parser.parseQuery()
From there, you'll probably have the most success implementing the SqlVisitor interface. You'll want to first find a SqlSelect instance and then visit each expression being selected by calling visit on each element of getSelectList.
From there, how you proceed will depend on the complexity of expressions you want to support. However, it's probably sufficient to recursively visit all SqlCall nodes and their operands and then collect any SqlIdentifier values that you see.
It can be as simple as:
SqlParser parser = SqlParser.create(yourQuery);
SqlSelect selectNode = (SqlSelect) parser.parseQuery();
SqlNodeList list = selectNode.getList();
for (int i = 0; i < list.size(); i++) {
System.out.println("Column " + (i + 1) + ": " + list.get(i).toString());
}

How to pass array of strings dynamically to SQL "IN" clause in Java? [duplicate]

This question already has answers here:
PreparedStatement IN clause alternatives?
(33 answers)
Closed 9 years ago.
I have a array of Strings "String[]" with certain values. I want to pass that array dynamically to SQL "IN" clause something like:
Select * from Employee where emp_name in (?);
Here "?" has to replaced with String Array. I want to do this in Java Class. I tried with
Array array = conn.createArrayOf("VARCHAR", new Object[]{"1", "2","3"});
pstmt.setArray(1, array);
But it is not working and getting exception "SQLFeatureException".
Thanks!!!
Basically the field emp_name is not an array but a VARCHAR so when you set a value for it, it must be a String. So having only 1 ? in the query represents a single possible value for emp_name. You would have to list as many ?'s as the length of the array and substitute these individually with their values.
Assuming that empNames is a String[], you could do this to prepare the query:
StringBuilder query = new StringBuilder("Select * from Employee where emp_name in (");
for (int i = 0; i < empNames.length; i++) {
if (i > 0) {
query.append(",");
}
query.append("?");
}
query.append(")");
and this to set the individual values behind the ?'s:
for (int i = 0; i < empNames.length; i++) {
pstmt.setString(i+1, empNames[i]);
}
We can appy Select batching to resolve your problem. Reference:
link
You can create the query with IN clause by iterating the String array using StringBuilder.
I would recommend that don't get into complexity of using Arrays.toString() unless you really need that. There will not be much difference in the performance since both are needed to iterate the array to create the String literal.
In my approach we can have a good control over iteration of the array adding the single quote and comma etc.

How to generate String "elegantly" in Java?

I want to generate a string such as sql command:
"INSERT INTO xxx VALUES(XXX, XXX, XXX)"
currently I use StringBuilder and some String constant like "INSERT INTO" to concatenate input String parameters for the table name and inserted values.
However, other than performance issue, this plain concatenation looks not elegant.
Is there any other way of doing this?
In my opinion, JDBC's prepared statement is one good example of such a "command template":
PreparedStatement pstmt=connection.createPreparedStatement("INSERT INTO ? VALUES(?,?,?)");
then you can set the table name and inserted value.
pstmt.setString(1,"tableA");
pstmt.setInt(2, 100);
...
However, I can not use prepared statement, since what I want is just String...
And someone give me some hint to use java.util.Regex or JavaCC to produce the String.
But as far as I can see, whatever is chosen for some code elegancy issue, Java String must be generated by something like StringBuilder, right???
You could use String.format():
String.format("insert into %s values('%s', '%s', '%s')", "user", "user123", "pass123", "yellow");
It's worth noting though, that any of these "string building" techniques leave you vulnerable to SQL injection attacks. You should really use JDBC parameterised queries wherever possible.
Edited to add quotes around strings.
Maybe you are looking for java.text.MessageFormat
int planet = 7;
String event = "a disturbance in the Force";
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
planet, new Date(), event);
Have you tried just using '+' ?
String sql = "INSERT INTO " + table
+" VALUES(" + value1 + ", " + value2 + ", " = value3+")";
Given the variety of other answers and none of them met your approval, perhaps you should accept that the actual String generation (sans JPA, PreparedStatement, etc.) is going to be fairly inelegant and create a utility class with static sql generators.
edit Showing an example of how I'd go about this if a pre-existing class such as PreparedStatement weren't an option. It's not the most elegant, but it does what it's supposed to (assuming I typed it all in correctly).
public class SQLUtil {
public static String generateInsertSQL(String tableName, List<CustomParameter> parmList){
StringBuilder sb = new Stringbuilder();
sb.append("insert into ");
sb.append(tableName);
sb.append(" values (");
for (int i = 0; i < parmList.size(); i++){
customParameter parm = parmList.get(i);
switch (parm.getType()) { // enum with your desired sql types
case ParmTypes.String:
sb.append("'");
sb.append(StringEscapeUtils.escapeSql(String.valueOf(parm.getValue())));
sb.append("'");
break;
case ParmTypes.Integer:
sb.append(Integer.valueOf(parm.getValue()));
break;
}
if (i < parmList.size() - 1) sb.append(",");
}
sb.append(")");
return sb.toString();
}
}
This way, your business code will remain relatively elegant and you can play around with the SQL String generation to your heart's content. You can also use this to "guarantee" all your inserts are protected against such attacks as SQL injection.
Use StringTemplate (http://www.stringtemplate.org/) maybe a good choice:
This looks better, right?
StringTemplate insert = new StringTemplate("INSERT $table$ VALUES ($value; separator=\",\"$)");
insert.setAttribute("table", "aTable");
String[] values = {"1", "1", "'aaa'", "'bbb'"};
for(int i = 0;i < values.length;i++){
insert.setAttribute("value", values[i]);
}
System.out.println(insert.toString());

Need help with parsing sql in java

I have the below code that splits the sql statement and give its indices for the columns.
String sql = "INSERT INTO Table1(SSN, EMPID) VALUES (?,?)";
public static List<Object[]> indices(String stmt) {
List<Object[]> list = new ArrayList<Object[]>();
String variables[] = null;
try {
variables = stmt.substring(stmt.indexOf('(')+1,
stmt.indexOf(')', stmt.indexOf('(')+1)).split("\\,");
} catch (Exception e) {}
for (int i=0; i < variables.length; ++i ) {
Object [] str = new Object [2] ;
str[0] = variables[i].trim() ;
str[1] = ((Integer)(i+1)) ;
list.add(str) ;
}
return list;
}
Result -
list[0] >>
array[0] = SSN
array[1] = 1
list [1] >>
array[0] = EMPID
array[1] = 2
Can some one point me with appropriate regular expression to split the following sql instead -
sql = "if not exists (select * from Table1 where SSN = ? and EMPID =?)
INSERT INTO Table1(SSN, EMPID) VALUES (?,?)"
I guess the output would be something like -
list[0] >>
array[0] = SSN
array[1] = 1
list [1] >>
array[0] = EMPID
array[1] = 2
list[2] >>
array[0] = SSN
array[1] = 1
list [3] >>
array[0] = EMPID
array[1] = 2
Thank You
Attempting to parse non-trivial languages like SQL using regexes or other low-level string bashing is a BAD IDEA. You end up with unreadable code and a fragile "parser" that breaks when supplied with input that is invalid or valid-but-different.
You either need to implement a proper SQL parser (or use an existing one), or change your code so that you are not parsing SQL but assembling it from something else.
I have an application depending on a framework and don't want to introduce new libraries!
That is a bad reason for not doing proper parsing. What is wrong with not using another library???
What about this one as an alternative: Zql, a SQL parser. Could make it much easier to access the 'elements' of any SQL statement.
EDIT
Easiest approach for the second SQL:
just do a sql.split("INSERT INTO") and apply your existing code to the second array entry (should be " Table1(SSN, EMPID) VALUES (?,?)"). As far as I understand your code, it should give the correct result.
Yes, I missed your point. Use a parser.
ZQL parser is great.
It can parse almost all queries except CREATE
Features:
list colums,
list tables,
FOR clause,
WHERE clause
etc

Categories