How to make select query with StringTokenizer? - java

I'm trying to make a query with selected fields for final user from view (JSP) to controller, but I don't know how.
For example, I have this parameters from view (JSP)
IDUSER,>,2,OR,USERNAME,=,'KURT'
So, I'll want to have something like this,
SELECT IDUSER, USERNAME FROM TABLE_NAME WHERE IDUSER > 2 OR USERNAME = 'KURT'
but I have next result
SELECT null FROM TABLE_NAME WHERE IDUSER > 2 OR USERNAME = 'KURT'
I'm parsing string with StringTokenizer class, where query is: String query = request.getParameter("data"); and data is IDUSER,>,2,OR,USERNAME,=,'KURT'.
StringTokenizer field = new StringTokenizer(query, ",");
nFields = field.countTokens();
System.out.println("nFields: " + nFields);
String[] fields = new String[nFields];
for(int i = 0; i < fields.length; i++) {
while(field.hasMoreTokens()) {
fields[i] = field.nextToken();
}
System.out.println("fields[i]: " + fields[i]);
myQuery = "SELECT " + fields[i] + " FROM "+tableName+ " WHERE ";
System.out.println("myQuery 1: " + myQuery);
}
StringTokenizer token= new StringTokenizer(query, "|,");
while(token.hasMoreTokens()) {
myQuery = myQuery + token.nextToken() + " ";
}
System.out.println("QUERY RESOLVED: " + myQuery);
PLEASE HELP ME

Here is the solution after minor tweak in your query (redefined the separators)
public static void main(String[] args) {
// Redefine the separators as single , separators is difficult to process
//You would need to define possible operators like this (#OR# , #AND# ) ,surrounded by special characters to identify.
String query ="IDUSER_>_2#OR#USERNAME_=_'KURT'";
String tableName="TESTTABLE";
String operator=null;
//you can choose operator conditionally
if(query.contains("#OR#")) operator="#OR#";
// if(query.contains("#AND#")) operator="#AND#";
//Used split instead of Tokenizer.
String cols[]= query.split(operator);
String myQuery = "SELECT ";
String select="";
for(String col:cols){
if(!select.isEmpty()){
select+=" , ";
}
// Only the first element is retrieved (for select)
select+=col.split("_")[0];
}
myQuery+=select+" FROM "+tableName+ " WHERE ";
// Removes all special charecters (like, # and _ with white space)
String subQuery = query.replaceAll("#", " ");
subQuery=subQuery.replaceAll("_", "");
myQuery+=subQuery;
System.out.println("QUERY RESOLVED: " + myQuery);
}
Note : ',' is replaced with '_' and operators are surrounded by '#'
Cheers!!

I think the problem is this line in your while loop:
myQuery = "SELECT " + fields[i] + " FROM "+tableName+ " WHERE ";
This will keep changing the value of myQuery as the while loop executes.
Maybe you need to replace this with:
myQuery = "SELECT " + fields[0] + " FROM "+tableName+ " WHERE ";
break;
I am assuming your selection criteria is the first field in the parameter from your view.

Do not see where does IDPERFIL come from. Also, I don't like this:
while(field.hasMoreTokens()) {
fields[i] = field.nextToken();
}
That will iterate tokenizer to the end, and stop at last element. I am sure you don't want this. Fix that, tell where IDPERFIL come from, and then, maybe, you'll understand answer by yourself. Otherwise, I'll try to help further.

Related

How to implement Room database query at runtime or dynamically

I need to create a room database query dynamically because I have lots of fields for UPDATE in the database.
If I used like below method then it works, but I have lots of fields that's why I can't create a separate UPDATE method like this.
#Query("UPDATE PROCEDUREMODEL SET patient_in_time = :val WHERE procedure_sr_number LIKE :sr")
void updateP(String val, String sr);
Now I try below but it does not work.
In DAO class I created this
#RawQuery
ProcedureModel updateProcedure(SupportSQLiteQuery supportSQLiteQuery);
And use like this
public static void updateProcedure(Context context, String colName, String val, String id) {
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = :" + val + " WHERE procedure_sr_number LIKE :" + id;
SupportSQLiteQuery supportSQLiteQuery = new SimpleSQLiteQuery(s);
Thread thread = new Thread(() -> {
DatabaseHelper.getInstance(context).getDao().updateProcedure(supportSQLiteQuery);
});
thread.start();
}
I want to run the UPDATE query at runtime in Room database.
I believe that your issue is with the SQL being passed:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = :" + val + " WHERE procedure_sr_number LIKE :" + id;
As the value val is non-numeric, because of the :'s (which you probably don't want), likewise for the id (if not numeric) the values should be enclosed in single quotes.
So using:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = ':" + val + "' WHERE procedure_sr_number LIKE '" + id + "'";
would work. Although you very likely don't want the : as part of the value so you very likely want:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = '" + val + "' WHERE procedure_sr_number LIKE '" + id + "'";
Saying that it is not recommended to apply literal values via string concatenation but to utilise parameter binding. This protects against SQL injection. As such you may wish to consider the following version:-
public static void updateProcedureBetter(Context context, String colName, String val, String id) {
String s = "UPDATE PROCEDUREMODEL SET " + colName + "=? WHERE procedure_sr_number LIKE ?";
Thread thread = new Thread(() -> {
DatabaseHelper.getInstance(context).getDao().updateProcedure(new SimpleSQLiteQuery(s,new Object[]{val,id}));
});
thread.start();
}
notice the ?'s in the SQL these being replaced by the objects in the Object[], the values being properly enclosed by SQLite parameter binding.
the replacement is on a 1 by/for 1 basis (first ? replace by first object in array, 2nd ? by second object ....)
note also that the intermediate supportSQLiteQuery object has been done away with.
component names (tables, columns etc) typically cannot be bound/changed so the column name has to be concatenated.

Java - Search Oracle DB for a row with spaces (ORA-00920)

I am trying to execute a select query from Java, the tricky part is that both the condition and the column have a String with spaces :
String query = "select rule_name "+
" from rules " +
" where rule_name = " m_rule; //rule_name = str tf //m_rule = str tf
So the query output :
select rule_name
from rules
where rule_name = str tf
The error code - ORA-00920 - I belive it is because of the spaces.
Is there any way to fix this?
The error that you are facing basically means :
ORA-00920: invalid relational operator
This is the blank that is causing the issue. Your Java code should enclose the conditional parameter in quotes:
String query = "select rule_name "+
" from rules " +
" where rule_name = '" + m_rule + "'";
Hope this will help!

How to concatenate a character to a SQL string in a preparedstatemenet

When I concatenate a character namely tid
to this string in Java. I will get
where sc.CategoryCode = C
But I actually need
where sc.CategoryCode = 'C'
when I add a single quote both on the start
and on the end side of tid
like
where sc.CategoryCode = '" + tid + "'";
I'll get
where sc.CategoryCode = 'C"
And it seems very strange.
Thanks
Jack
String str = "select sc.* from SubCategory sc"
+ " where sc.CategoryCode = " + tid;
You shouldn't build up your SQL like this - you should use parameterized SQL instead:
// TODO: Closing the statement etc
String sql = "select sc.* from SubCategory sc where sc.CategoryCode = ?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(tid); // Or statement.setString(String.valueOf(tid))
ResultSet results = statement.executeQuery();
Reasons for using parameterized SQL:
Avoiding SQL injection attacks
Avoiding unnecessary (and potentially problematic) conversions, particularly with dates/times
Keeping your code (the SQL) separate from the data (the parameters), which aids readability
I don't know if you are working with jdbc template... i post you an example.
select :
private static final String SELECT_SANCIONS_GIM = "SELECT * " + "FROM "
+ Constants.T_GPT_V_DETALL_SANCIO_GIM + " WHERE "
+ Constants.EXP_ID_ENS + " =:idEns" + " AND " + Constants.EXP_ANY_EXP
+ " =:anyExp" + " AND " + Constants.EXP_NUM_EXP + " =:numExp" + " AND "
+ Constants.ACRONIM_EXP + " =:acr";
//=:variable
I use Stringbuilder, take a look:
StringBuilder sql = new StringBuilder();
sql.append(SELECT_SANCIONS_GIM);
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("idEns",clauExpedient.getIdEns() );
parameters.addValue("anyExp",clauExpedient.getAnyExp());
parameters.addValue("numExp",clauExpedient.getNumExp() );
parameters.addValue("acr", clauExpedient.getAcrProcediment());
I hope it helps.

fetch value from SQL query list

So i just wrote down this SQL query and i am trying to capture the value of rest_id in query.list(). However, this is giving the value as [1] . I want just 1 without the braces. How do i do it? Please check the code below for reference:
String sql1 = "select rest_id from rest_details where rest_name = '" + nameclicked + "' and rest_location = '" +locclicked + "'" ;
SQLQuery query1 = session.createSQLQuery(sql1);
System.out.println("sql1 " + query1.list());
Use below code to get the element inside list:
System.out.println("sql1 " + query1.list().get(0));
This always returns only the first element from the list.
Replace
System.out.println("sql1 " + query1.list());
By :
for(String id : query1.list() ) System.out.println("sql1 " + id);

How to get words in a file which contains a single dot or period?

I want to find table names & column names from a file named 'query' below.
var query = " SELECT accounts.name, SUM((COALESCE((jan_val_c),0)+ ";
query += " COALESCE((feb_val_c),0)+ COALESCE((march_val_c),0)+ COALESCE((apr_val_c),0)+ ";
query += " COALESCE((may_val_c),0)+ COALESCE((june_val_c),0)+ COALESCE((july_val_c),0)+ ";
query += " COALESCE((aug_val_c),0)+ COALESCE((sept_val_c),0)+ COALESCE((oct_val_c),0)+ ";
query += " COALESCE((nov_val_c),0)+ COALESCE((dec_val_c),0))) AS sales_plan,SUM((COALESCE((jan_actual_val_c),0)+ ";
query += " COALESCE( (feb_actual_val_c),0)+ COALESCE( (march_actual_val_c),0)+ COALESCE( (apr_actual_val_c),0)+ ";
query += " COALESCE( (may_actual_val_c),0)+ COALESCE( (june_actual_val_c),0)+ COALESCE( (july_actual_val_c),0)+ ";
query += " COALESCE( (aug_actual_val_c),0)+ COALESCE( (sept_actual_val_c),0)+ COALESCE( (oct_actual_val_c),0)+ ";
query += " COALESCE( (nov_actual_val_c),0)+ COALESCE( (dec_actual_val_c),0))) AS Actual_plan ,month_name_c, ";
query += " cl_sales_planning_month.year_c, cl_products.volume,cl_brands.name AS brand ,cl_therapies.name ";
query += " AS therapy,cl_products.name AS product, accounts.created_by,accounts.assigned_user_id , ";
query += " DATE_FORMAT(STR_TO_DATE(CONCAT_WS('-',cl_sales_planning_month.month_name_c, ";
query += " cl_sales_planning_month.year_c),'%M-%Y'),'%b-%y' ) AS monthyear FROM cl_sales_planning_month ";
query += " LEFT JOIN accounts ON cl_sales_planning_month.account_id_c =accounts.id LEFT JOIN cl_products ";
query += " ON cl_sales_planning_month.cl_products_id_c = cl_products.id LEFT JOIN cl_brands ON ";
query += " cl_products.cl_brands_id_c=cl_brands.id LEFT JOIN cl_therapies ON ";
query += " cl_products.cl_therapies_id_c=cl_therapies.id WHERE ";
query += " cl_sales_planning_month.month_name_c = MONTHNAME(CURRENT_DATE - INTERVAL 2 MONTH) AND ";
query += " cl_sales_planning_month.year_c = YEAR(CURRENT_DATE - INTERVAL 2 MONTH) AND";
query += " cl_sales_planning_month.user_id_c IN ("+ params["childs"].value +") ";
query += " GROUP BY therapy,monthyear ";
query += " ORDER BY STR_TO_DATE(cl_sales_planning_month.year_c,'%Y') ASC, ";
query += " STR_TO_DATE(cl_sales_planning_month.month_name_c,'%M') ASC, Actual_plan DESC ";
For this I have written a Java program:
package com.waprau;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.regex.Pattern;
public class SeparateTableNamesColumnNames {
public static void main(String[] args) {
File file = new File("/home/waprau/Desktop/query");
//Pattern = new Pattern("([^\\s]+(\\.(?i))$)");
try {
Scanner scanner = new Scanner(file);
scanner.useDelimiter("\\s|=|,|\\)|\\(|this.|\\].");
while(scanner.hasNext()){
if(scanner.next().matches("(?<!\\.)\\b[a-zA-Z]\\w*\\.[a-zA-Z]\\w*\\b(?!\\.)"))
System.out.println(scanner.next());;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
With above program I am able to separate all words. But I want to get only those words which contains a single dot or period e.g. accounts.name, cl_sales_planning_month.year_c, cl_products.volume, cl_brands.name, cl_therapies.name etc. However I am not able to find a pattern or whatever which can separate these words from file.
But it is not working.
This is the result I am getting:
And this is what I want:
Any help is appreciated.
To match words containing a dot, you can use: "\\w+\\.\\w+"?
\w matches letters, numbers, and underscores.
However, that would also match something which had more than one period. You could improve it by using look-arounds to make sure there is not another period before or after the word you are matching:
"(?<!\\.)\\b\\w+\\.\\w+\\b(?!\\.)"
This matches a word containing a dot, and cannot contain a dot immediately before or after. \b is a word boundary.
However, that would match decimal numbers like 123.45. Tables can contain numbers, but cannot start with one. So we could also ensure that each word starts with a letter:
"(?<!\\.)\\b[a-zA-Z]\\w*\\.[a-zA-Z]\\w*\\b(?!\\.)"
The period . has to be escaped as it means "any character". As this is not normal String escaping (like \n) it uses two backslashes: \\.
Also \\s.
Regardless of the regex (dan1111's answer appears to cover that). You have a flaw in your Java code, scanner.next() gets the next string, and since you call it twice so you won't print what you matched. Instead you will print the item following every match.
If you change your loop as follows it seems to print what you want:
String tmp;
while (scanner.hasNext()) {
// Store next item so we can match AND print it.
tmp = scanner.next();
if (tmp.matches("(?<!\\.)\\b[a-zA-Z]\\w*\\.[a-zA-Z]\\w*\\b(?!\\.)"))
System.out.println(tmp);
}

Categories

Resources