Can I have multiple statements in a native query in JPA 2 - java

I want to execute the following query to conditionally drop a temporary table.
String dropSql = "BEGIN EXECUTE IMMEDIATE 'DROP TABLE " + tmpTblName + "';" +
" EXCEPTION" +
" WHEN OTHERS THEN" +
" IF SQLCODE!=-942 THEN" +
" RAISE;" +
" END IF;" +
" END";
And then execute it as a native query like this:
JPA.em().createNativeQuery(dropSql)
.executeUpdate();
However, JPA will not let me or rather, the oracle db won't. Apparently the ; get escaped or misinterpreted somehow.
Caused by: java.sql.SQLException: ORA-06550: line 1, column 120:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
; <an identifier> <a double-quoted delimited-identifier>
The symbol ";" was substituted for "end-of-file" to continue.
Will I have to live with using separate queries to achieve my goal or is there some trick to this?

You missed a semicolon after the END block finally.
String dropSql = "BEGIN EXECUTE IMMEDIATE 'DROP TABLE " + tmpTblName + "';" +
" EXCEPTION" +
" WHEN OTHERS THEN" +
" IF SQLCODE!=-942 THEN" +
" RAISE;" +
" END IF;" +
" END;";

Related

Spring data jpa failed to pass named parameters in native subquery for db2

Unable to pass named parameters in #NamedNativeQuery in spring data jpa
my repo:
#Query(value = "select stat.desc as desc," +
" stat.priority as priority," +
" (case when sum(activeUser) is null then 0 else sum(activeUser) end) as activeUser," +
" (case when sum(totalUser) is null then 0 else sum(totalUser) end) as totalUser" +
" from lookup.user stat left outer join" +
" (" +
" select user.role as role, " +
" sum (case when user.STATUS = 'ACTIVE' then 1 else 0 end) as activeUser," +
" count(*) as totalUser," +
" user.group as group" +
" from Ctrl.user user" +
" where user.group =:userGroup " +
" and user.branch_code =:branchCode " +
" group by user.role,user.group" +
" ) as tbl on stat.role = tbl.role and stat.group = tbl.group" +
" where stat.group =:userGroup " +
" group by stat.desc, stat.priority" +
"", nativeQuery = true)
public List<com.cimb.dto.UserStatusSummary> getSummaryReport(#Param(value = "userGroup") String userGroup, #Param(value = "branchCode") String branchCode);
The underlying database is DB2
When I tried to access that method I am hitting following error.
DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.25.13
if I hard code those named parameters with values then it's working.
I can not use jpql as real queries have some subqueries in it, so I cant use JPQL
Edit Update
After some digging, I have found out that, the parameters I am passing are in the subquery, since JPA don't have subquery concept it's not injecting into named parameters which resulting in a syntax error.
Now how to work with Subqueries in JPA
Please help.

Stacktrace with SQL injection?

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.

INSERT INTO with embedded apostrophe

Eclipse neon.1 (4.6.1) java;
SQLite 3.8.7 (sqlite-jdbc-3.8.7.jar)
I am attempting to insert customer's data into a table using the following code snippet:
PreparedStatement ps;
insertSQL = "INSERT INTO tbl_TotalPatent "
+ "(Abstract, `Application/Filing Date`, `Application Number`) "
+ "VALUES ("
+ "'" + _field[0] + "', "
+ "'" + _field[1] + "', "
+ "'" + _field[2] + "');";
ps = con.prepareStatement(insertSQL);
ps.execute();
Unfortunately, the client's data has an embedded apostrophe, which I cannot change. The "INSERT INTO" statement bombs out when finding the apostrophe, assuming it is a single quote:
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (near "s": syntax error)
I've tried various permutations of the INSERT INTO statement to use different characters for the single quote - to no avail.
I presume there is an "easy" work-around, but I can't find it. The solution is probably posted somewhere on stackoverflow, but I can't find it. Can someone point me in the right direction?
you can replace that apostrophe with an double apostrophe, which is the standard SQL escape sequence for '
simply do that whith the following snippet:
+ "'" + _field[x].replaceAll("'", "''") + "', "
You could also use " instead of ' in your sql statement like the following:
+ "\"" + _field[x] + "\", "

Pass email as a parameter for SQL query, PostreSQL, JAVA

I'm trying to pass the email as a parameter for the SELECT SQL query in my JAVA back-end.
As i understood, for some reason it pass only "email_name" from the "email_name#email.com". (Getting this error):
Threw a SQLException creating the list of blogs.
ERROR: column "email_name" does not exist
Position: 174
There is an existed rows, which contains "email_name#email.com".
(Why "ERROR: column"? according to query it should look for a value, no?)
Here is My query:
String active_user = "email_name#email.com"; //email_name#email.com - example, active_user receive some path variable and on this particular moment(before query execution) contains exactly "email_name#email.com".
ResultSet rs = st.executeQuery("SELECT \n" +
" goods.item_title, \n" +
" goods.item_descr, \n" +
" goods.item_email,\n" +
" goods.item_images,\n" +
" goods.item_phone, \n" +
" goods.item_price \n" +
"FROM \n" +
" public.goods\n" +
"WHERE goods.owner = "+active_user+"\n" +
"ORDER BY\n" +
" goods.item_id ASC;");
So the question is - how to pass full email to query?
Try using String active_user = "'email_name#email.com'";. with single quotes. Since postgre recognized as column when you use double quotes.
You should use PreparedStatement. this is a example
Very unsafe approach, you should use PreparedStatement to avoid SQL injection. Here is existing answer

how to pass positional parameters to createnativequery jpa java

I have the following SQL query in my j2ee web app that I am unable to get to work, as-is. The named parameters sourceSystem and sourceClientId do not appear to get passed to the query, and therefore it does not return any records. I added a watch to the Query object querySingleView and it maintained a value of null as the debugger ran through the code. I also inserted a System.out.println statement just under the method declaration and confirmed that the correct values sourceSystem and sourceClientId are being passed to the method signature. I am using NetBeans 8.0, JPA 2.1, running on a JBoss EAP 6.21 server. I have multiple Entities mapped to several tables in an Oracle database.
Here is the query (I should note that the items in the query follow a schema.table.column format - not sure if that is part of the problem, but it does work in one test, see my comment and sample below the main query below):
public List<String> searchSingleView (String sourceSystem, String sourceClientId) {
//Change the underscore character in the source system value to a dash, and make it uppercase. This is what single view accepts
if (!sourceSystem.equals("")) {
sourceSystemSingleView = sourceSystem.replace('_', '-').toUpperCase();
}
String sqlSingleViewQuery = "SELECT DISTINCT " +
"MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM AS POLICY_SYSTEM, " +
"MDMCUST_ORS.C_BO_CONTRACT.SRC_POLICY_ID AS POLICY_ID, " +
"MDMCUST_ORS.C_BO_CONTRACT.ISSUE_DT, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.SRC_CLIENT_ID AS SRC_CLIENT_ID, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.PERS_FULL_NAME_TXT, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.ORG_LEGAL_NAME_TXT, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.ORG_LEGAL_SFX_TXT, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.ORG_NAME_TXT, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.SIN_BIN_TEXT, " +
"MDMCUST_ORS.C_BO_PARTY_XREF.PERS_BIRTH_DT, " +
"MDMCUST_ORS.C_LU_CODES.CODE_DESCR_EN AS ADDRESS_PURPOSE_CD, " +
"MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.COMPLETE_ADDRESS_TXT, " +
"MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.CITY_NAME, " +
"MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.COUNTRY_NAME, " +
"MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.POSTAL_CD, " +
"MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.STATE_PROVINCE_NAME " +
"FROM MDMCUST_ORS.C_BO_PARTY_XREF " +
"LEFT JOIN MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR ON MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.PARTY_ROWID = MDMCUST_ORS.C_BO_PARTY_XREF.ROWID_OBJECT " +
"LEFT JOIN MDMCUST_ORS.C_LU_CODES ON MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.POSTAL_ADDR_PURPOSE_CD = MDMCUST_ORS.C_LU_CODES.CODE " +
"LEFT JOIN MDMCUST_ORS.C_BO_PARTY_REL ON MDMCUST_ORS.C_BO_PARTY_XREF.ROWID_OBJECT = MDMCUST_ORS.C_BO_PARTY_REL.FROM_PARTY_ROWID " +
"LEFT JOIN MDMCUST_ORS.C_BO_CONTRACT ON MDMCUST_ORS.C_BO_PARTY_REL.CONTRACT_ROWID = MDMCUST_ORS.C_BO_CONTRACT.ROWID_OBJECT " +
"WHERE MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM = :sourceSystemSingleView " +
"AND MDMCUST_ORS.C_BO_PARTY_XREF.SRC_CLIENT_ID = :sourceClientId " +
"AND MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.POSTAL_ADDR_PURPOSE_CD = '56|07' " +
"AND MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR.LAST_ROWID_SYSTEM = MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM " +
"ORDER BY MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM";
querySingleView = emSingleView.createQuery(sqlSingleViewQuery);
querySingleView.setParameter("sourceSystemSingleView", sourceSystemSingleView);
querySingleView.setParameter("sourceClientId", sourceClientId);
querySingleViewResult = (List<String>) querySingleView.getResultList();
return querySingleViewResult;
}
}
However, if I put literal values in the SQL query in place of the positional parameters it works fine (without using the setParameter method).
WHERE MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM = 'ADMIN' " +
"AND MDMCUST_ORS.C_BO_PARTY_XREF.SRC_CLIENT_ID = '0000001234' " +
I have looked online but haven't as yet found anything that seems to address this specific question. Any help would be greatly appreciated. Thank you!

Categories