SQL query for user t1, t2, . . . , tm terms in where clause - java

User gives String as input of terms they can be t1, ...tm now I have to embed these t1,... tm in sql where clause.
Select * from documents where term = t1 OR term = t2 ...... term=tm
At the moment I am splitting string into string array:
String[] terms = term.split("\\s+");
for (int i =0; i<term.length; i++) {
if (i == term.length -1) {
str += "term = " + term[i];
}
else {
str += "term = " + term[i] + " OR ";
}
Now I am getting
string str= "term = document OR term = word Or term = explanation".
But term is my column name and document value how can I pass this in where clause of SQL?

I assume, since you are splitting by spaces, that the user's input is like this:
document word explanation
First use trim() to remove any leading spaces from term.
Then inside the for loop enclose all the items of the array in single quotes (although this is not the safe way to construct a query, you could use a Prepared Statement and ? placeholders):
String[] terms = term.trim().split("\\s+");
for (int i = 0; i < terms.length; i++) {
str += "term = '" + terms[i] + "'";
if (i < terms.length -1) {
str += " OR ";
}
}
The result will be:
term = 'document' OR term = 'word' OR term = 'explanation'

Related

Is there a way to make consistent result out of split function?(same amounts of words)

I am working on search function and I am splitting search query into separated words. I know that there will be no more than 10 words, but there might be less.
Since I need to make SQL query, with consistent amount of words, let's say 10, I need to add 8 more blank words in case user typed only 2.
Is there any smart way how to do it or should I just make a loop from 1 to 10 and check if that particular position is null, if yes then fill it with blank word?
SQL query would look something like this(but with 9 ANDs):
SELECT * FROM mytable
WHERE column1 LIKE '%word1%'
AND column1 LIKE '%word2%'
AND column1 LIKE '%word3%'
Basically what I want to do is this, but maybe in some smarter way:
String[] finalSearch = new String[10];
String[] search=searchInput.split(" ", -1);
for (int i=0; i<10; i++){
if (search[i]!=null){
finalSearch[i] = search[i];
}else{
finalSearch[i]="";
}
}
You can generate query depends on user input like this:
static String getQuery(String ... userInput){
StringBuilder sb=new StringBuilder("SELECT * FROM mytable");
if (userInput.length>0){
sb.append(" where");
for (int i=0;i<userInput.length;i++){
sb.append(" column1 LIKE '%"+userInput[i]+"%'");
if (i!=userInput.length-1) sb.append(" AND");
}
}
sb.append(";");
return sb.toString();
}
Let's say you have a list with the terms you want to search for:
// List<String> terms
StringBuilder sqlQuery = new StringBuilder("SELECT * FROM mytable ");
if (terms.isEmpty()) { throw new IllegalArgumentException("SOME DESCRIPTION HERE") }
sqlQuery.append("WHERE column1 LIKE ? ");
for (int i = 1; i < terms.length(), i++) {
sqlQuery.append("AND column1 LIKE ? ");
}
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// Get your JDBC connection as usual
// connection = getJdbcConnection();
preparedStatement = connection.prepareStatement(sqlQuery.toString());
for (int i = 0; i < terms.length(), i++) {
preparedStatement.setString(i + 1, "%" + terms[i] + "%");
}
} catch (SQLException e) {
// Do something here with he exception
} finally {
// Make sure you close JDBC resources here
}
Instead of having a fixed number of words (10) could you have it build the query with only the words you need?
Could you do something like this:
String [] words = search.split ();
query = "SELECT * FROM my table WHERE";
for (int i = 0; i < words.length; i++){
query += "columns LIKE " + words[i];
If (i < words.length - 1)
query += "AND";
}

How to remove whitespace in String imported from Excel

I need to remove all white character from a string and I am not able to do so.
Anyone has an idea on how to do it?
Here is my string retrieved from an excel file via jxl API :
"Destination à gauche"
And here are its bytes :
6810111511610511097116105111110-96-32321039711799104101
There is the code I use to remove whitespaces :
public static void checkEntetes(Workbook book) {
String sheetName = "mysheet";
System.out.print(sheetName + " : ");
for(int i = 0; i < getColumnMax(book.getSheet(sheetName)); i++) {
String elementTrouve = book.getSheet(sheetName).getCell(i, 0).getContents();
String fileEntete = new String(elementTrouve.getBytes()).replaceAll("\\s+","");
System.out.println("\t" + elementTrouve + ", " + bytesArrayToString(elementTrouve.getBytes()));
System.out.println("\t" + fileEntete + ", " + bytesArrayToString(fileEntete.getBytes()));
}
System.out.println();
}
And this outputs :
"Destination à gauche", 6810111511610511097116105111110-96-32321039711799104101
"Destination àgauche", 6810111511610511097116105111110-96-321039711799104101
I even tried to make it myself and it still leaves a space before the 'à' char.
public static String removeWhiteChars(String s) {
String retour = "";
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(c != (char) ' ') {
retour += c;
}
}
return retour;
}
regular expressions to the rescue:
str = str.replaceAll("\\s+", "")
will remove any sequence of whitespace characters. for example:
String input = "Destination à gauche";
String output = input.replaceAll("\\s+","");
System.out.println("output is \""+output+"\"");
outputs Destinationàgauche
if youre starting point is indeed the raw bytes (byte[]) you will first need to make them into a String:
byte[] inputData = //get from somewhere
String stringBefore = new String(inputData, Charset.forName("UTF-8")); //you need to know the encoding
String withoutSpaces = stringBefore.replaceAll("\\s+","");
byte[] outputData = withoutSpaces.getBytes(Charset.forName("UTF-8"));
If you would like to use a formula, the TRIM function will do exactly what you're looking for:
+----+------------+---------------------+
| | A | B |
+----+------------+---------------------+
| 1 | =TRIM(B1) | value to trim here |
+----+------------+---------------------+
So to do the whole column.
1) Insert a column
2) Insert TRIM function pointed at cell you are trying to correct.
3) Copy formula down the page
4) Copy inserted column
5) Paste as "Values"
Reference: Question number 9578397 on stackoverflow.com

Memory management in java when running sql in a loop

I have been facing some trouble with memory management. I have some code here that runs an sql query in a loop, puts the data into Array Lists and then does some computations. I have run many similar programs before without this problem. The reason I put the query in a loop was so that too much memory wouldn't be stored in java objects at once. However, now when I run the program, I get a memory error at the exact same place every time (when it is at the 29th iteration of the loop).
Here is the error -
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.grow(Unknown Source)
at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at transnMat.bootTrnsn.main(bootTrnsn.java:82)
I have pasted the code below, I'd really appreciate any tips on what I might change to get rid of this -
Connection conn = null;Statement st = null;ResultSet rstru = null;
for(int i=start;i<stop;i++) {
double[][] forvariance = new double[(demos.length-1)][numsims];
ArrayList<Long> hhids1 = new ArrayList<>();
ArrayList<Double> outlierwt = new ArrayList<>();
ArrayList<String> fbdemos = new ArrayList<>();
ArrayList<String> trudemos = new ArrayList<>();
rstru = st.executeQuery(
"select TRUTH_DEMO_ID, FB_DEMO_ID, RN_ID, OUTLIER_WEIGHT from SCRATCH.." +
months + "monthtable where BRAND_ID = " + brands[i] +
" order by RN_ID");
while (rstru.next()) { //Get query results and put them into a hash map.
String temp0 = rstru.getString(1);
String temp1 = rstru.getString(2);
String temp2 = rstru.getString(3);
String temp3 = rstru.getString(4);
//String temp5 = rstru.getString(6);
hhids1.add(Long.parseLong(temp2.substring(0,11)));
fbdemos.add(temp1);
trudemos.add(temp0);
outlierwt.add(Double.parseDouble(temp3));
}
for(int sim=0;sim<numsims;sim++) {
trnsnpv = new double[demos.length][demos.length-1];
HashMap<Long,Integer> thissampl = bootsampl2.get(sim);
for(int i1=0;i1<fbdemos.size();i1++) {
if(thissampl.containsKey(hhids1.get(i1)))
trnsnpv[dems.get(fbdemos.get(i1))][dems.get(trudemos.get(i1))-1] +=
outlierwt.get(i1)*(double)thissampl.get(hhids1.get(i1));
}
for(int j=0;j<trnsnpv.length;j++) { //27 rows
trnsnpv[j] = normalize(trnsnpv[j]);
for(int k=0;k<trnsnpv[j].length;k++) { //26 columns
forvariance[k][sim] += trnsnpv[j][k];
}
}
}
for(int k = 0; k < (demos.length - 1); k++) {
double d = StdStats.var11(forvariance[k]);
fileIO.fileIO.write2file(brands[i] + "," + demos[k+1] +
"," + String.valueOf(d) + "\n", "vars.csv");
}
System.out.println("Brands processed: " + String.valueOf(i-start) +
" out of: " + (stop-start));
hhids1.clear();
outlierwt.clear();
fbdemos.clear();
trudemos.clear();
}
Several performance problems here:
The database has to recompile the query each time because the SQL is not parameterized. Consider the use of a prepared statement.
Nested loops. I see one point where you have 4 nested loops.
There is no way I can figure out what your logic is doing due to the variable names and excessive looping. If it's possible, and not sure if it is with your logic (depends on what aggregation you are doing), can you do everything one object at a time in your while (rs.next()) loop?
Ex:
while (rs.next()) {
String temp0 = rstru.getString(1);
String temp1 = rstru.getString(2);
String temp2 = rstru.getString(3);
String temp3 = rstru.getString(4);
//String temp5 = rstru.getString(6);
// do all of your work in here, so that your objects
// can be garbage collected before the next iteration
}
Here is the version of the code that did work (for my own reference)..
for(int i=start;i<stop;i++){
double[][] forvariance = new double[(demos.length-1)][numsims];
trnsnpv = new double[numsims][demos.length][demos.length-1];
int size = 0;
Long hhids1;
Double outlierwt;
String fbdemos;
String trudemos;
rstru = st.executeQuery("select TRUTH_DEMO_ID, FB_DEMO_ID, RN_ID, OUTLIER_WEIGHT from SCRATCH.."+months+"monthtable where BRAND_ID = " + brands[i]+" order by RN_ID");
while (rstru.next()) {//Get query results and put them into a hash map.
String temp0 = rstru.getString(1);String temp1 = rstru.getString(2);String temp2 = rstru.getString(3);String temp3 = rstru.getString(4);
hhids1 = (Long.parseLong(temp2.substring(0,11)));
fbdemos = (temp1);
trudemos = (temp0);
outlierwt = (Double.parseDouble(temp3));
for(int sim=0;sim<numsims;sim++){
HashMap<Long,Integer> thissampl = bootsampl2.get(sim);
if(thissampl.containsKey(hhids1))
trnsnpv[sim][dems.get(fbdemos)][dems.get(trudemos)-1] += outlierwt*(double)thissampl.get(hhids1);
}
size++;
}
System.out.print("Processing: " + size + " rows");
for(int sim=0;sim<numsims;sim++){
for(int j=0;j<trnsnpv[sim].length;j++){//27 rows
trnsnpv[sim][j] = normalize(trnsnpv[sim][j]);
for(int k=0;k<trnsnpv[sim][j].length;k++){//26 columns
forvariance[k][sim] += trnsnpv[sim][j][k];
}
}
}
for(int k = 0; k < (demos.length - 1); k++){
double d = StdStats.var11(forvariance[k]);
fileIO.fileIO.write2file(brands[i] + "," + demos[k+1] + "," + String.valueOf(d) + "\n", "vars.csv");
}
System.out.print("Brands processed: " + String.valueOf(i-start + 1 ) + " out of: " + (stop-start) + "\n");
//hhids1.clear();outlierwt.clear();fbdemos.clear();trudemos.clear();
}

Regular Expression to detect query in java

I am trying to search a String using Regular Expression.
For example: this is my sample String
**if (c == 0) {
count = 0;
du.insert(ipAddress, c);
} else {
count = c;
}
getDate();
String query1 = "select * from loginmaster where username = '" + username + "' and password = '" + password + "' ;";
//out.println(query1);
//out.println(request.getParameter("Group1"));
session.setAttribute("group", request.getParameter("Group1"));
if (count < 3) {
if (request.getParameter("Group1").equals("With")) {
LoginQuery q = new LoginQuery();
checked = q.Checker(query1);
if (checked == false) {
connection.getConnection();
connection.getDML("insert into attack values('"+ipAddress+"','"+date+"','Attack Detected')");
}
}**
and i am trying to find querys in this String using Regular Expression
String regExp = "\b(ALTER|CREATE|DELETE|DROP|EXEC(UTE){0,1}|INSERT( +INTO){0,1}|MERGE|SELECT|UPDATE|UNION( +ALL){0,1})\b";
and
String regExp = "(;|\\s)(exec|execute|select|insert|update|delete|create|alter|drop|rename|truncate|backup|restore)\\s";
But i am not getting any Output nor Error.
Remaining Code is:
Pattern p = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
while ((line = reader.readLine()) != null) {
Matcher m = p.matcher(line);
if (m.matches()) {
JOptionPane.showMessageDialog(this, "innnnnnnnnnn");
System.err.println(m.group(1));
}
}
Pls help
Your regexes will not match with the input string, because of case mismatch.
Your regular expressions written in upper-case but your input string contains lower-case matches. So, either make the regexes case-insensitive or convert it to lower-case.
By the way, your regexes couldn't separate query insert into attack ... and method: du.insert(ipAddress, c);

Get the Beginning Position Of a field

Hi Guys I am writing a code that reads a text file in this format:
City |First Name| Second Name|Last Name|
The output I currently have is :
Column 1 is 17--------City
Column 2 is 10--------First Name
Column 3 is 12--------Second Name
Column 4 is 9---------Last Name
I need the Begin Position Also Of each Field in the Text File for example:
Column 1 is 17--------City : Position 1
Column 2 is 10--------First Name: Position 18
Column 3 is 12--------Second Name: Position 31
Column 4 is 9---------Last Name: Position 44
Here Is the Code I currently Have. Is there a way to achieve This?
package stanley.column.reader;
import java.io.*;
public class StanleyColumnReader {
public static void main(String[] args) throws IOException {
System.out.println("Developed By Stanley Mungai");
File f = new File("C:/File/");
if (!f.exists()) {
f.createNewFile();
} else {
f.delete();
}
String [] files = f.list();
for (int j = 0; j < files.length; j++){
FileInputStream fs = new FileInputStream("C:/File/" + files[j]);
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String result = "_result";
BufferedWriter is = new BufferedWriter(new FileWriter("C:/File/" + files[j] + result + ".txt"));
for (int i = 0; i < 0; i++) {
br.readLine();
}
String line = br.readLine();
String[] split = line.split("|");
for (int i = 0; i < split.length; i++) {
int k = i + 1;
System.out.println("Calculating the size of field " + k );
is.write("Column " + k + " is " + split[i].length());
is.flush();
is.newLine();
}
}
System.out.println("Success");
System.out.println("Output Saved to C:/File");
}
}
You could do that with a bit more advanced regexp group matching and get the group start index. But might be overkill and too advanced considering the question.
But a quick simple way in your case that might work is to just use indexOf on the line.
That is change your output to include:
" Position "+(line.indexOf(split[i])+1)
As long as a last name, first name and city aren't repeated on the same line...
You hardly need to flush on each line by the way, I suggest to move it outside the loop.
The regexp solution:
//first declare the pattern once in the class
static final Pattern pattern = Pattern.compile("\\s*(.*?)\\s*\\|");
...
//instead of the split loop:
String line = "City |First Name| Second Name|Last Name| Foo |Bar |"; //br.readLine();
Matcher matcher = pattern.matcher(line);
int column = 1;
while (matcher.find(column == 1 ? 0 : matcher.end())) {
String match = matcher.group(1);
System.out.println("Column " + column + " is " + match.length() + "---" + match + ": Position " + (matcher.start() + 1));
column++;
}
Possibly, depending on the exact position you want, you might want to change (matcher.start()+1) to (matcher.start(1)+1)
IS this an assignment? Please tag it properly.
You haven't said whether the delimiters are "|" in the data too but seeing your code, I am assuming it is.
What I don't understand is how the position you mentioned for Column 3 is 31 and column 4 is 44? Column 3 should be 10+17+1 =28 and column 4 should be 10+17+12+1=40. If I am getting it wrong, you need to post your original data too.
String[] split = line.split("|");
int pos=1; //initial position
for (int i = 0; i < split.length; i++) {
System.out.println("Calculating the size of field " + (i+1));
is.write("Column " + (i+1) + " is " + pos+" : Position "+pos);
pos=pos+split[i].length+1; //starting position for next column data
is.flush();
is.newLine();
}
Or you could find position by using indexOf method : line.indexOf(split[i])+1
If I understand what you need. Maybe you can use the indexOf method. This brings you the first coincidence. After finding this, change the pipe for something different and call indexOf pipe in the next iteration again.
String line = br.readLine();
for (int i = 0; i < split.length; i++) {
System.out.println("Calculating the position " + line.indexOf("|") );
line[line.indexOf("|")] = ",";
}

Categories

Resources