HANA query with dynamic placeholder executed using jdbcTemplate in Spring Boot - spring-boot

I have a few HANA queries that rely on PLACEHOLDER input. The input to this is currently hardcoded which is leading to SQL injection vulnerability being detected by Veracode.
In order to fix that, I am trying to parameterize the value given to PLACEHOLDER using PreparedStatement, but getting the below error :
PreparedStatementCallback; uncategorized SQLException for SQL [SELECT * FROM some_table (PLACEHOLDER.\"$$<IP_SOME_COLUMN>$$\" => ?) WHERE some_flag = ?; ]; SQL state [HY000]; error code [2048]; SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306002: An internal error occurred\n; nested exception is com.sap.db.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306002: An internal error occurred
I have already checked this solution and gone through the documentation for input parameters in SAP HANA. Below is my code :
String sqlQuery = SELECT * FROM some_table ( PLACEHOLDER.\"$$<IP_SOME_COLUMN>$$\" => ? ) WHERE some_flag = ? ;
PreparedStatementSetter preparedStatementSetter = (PreparedStatement ps) -> {
ps.setString(1, firstInput);
ps.setString(2, secondInput);
}
ResultSetExtractor<T> rse = new DataResultSetExtractor();
getJdbcTemplate().query(sqlQuery, preparedStatementSetter, rse);
The same works well with the hardcoded way (prone to SQL injection) :
StringBuffer sql = new StringBuffer();
sql.append("SELECT * FROM some_table ").append("( 'PLACEHOLDER' = ('$$IP_SOME_COLUMN$$',").append(firstColumnValue).append("))");
//Map<String,Object> paramMap = new HashMap<String,Object>();
//getNamedParameterJdbcTemplate().query(sql.toString(), paramMap, rse);
How do I fix this error?

Figured the issue out. It seems, in the new syntax you need to provide the input parameter in single quotes and not in triple single quotes
Works : 'foo'
Doesn't work : '''bar'''

Related

DB2 returning keys in insert not working

I'm having a problem while returning generated keys when insert a row with jdbc in a DB2 database (version 10.1). I tried several ways to do it, but no one works fine.
Method 1:
stmt = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
When executing this line, I get this exception:
com.ibm.db2.jcc.am.SqlSyntaxErrorException: ILLEGAL SYMBOL "". SOME SYMBOLS THAT MIGHT BE LEGAL ARE:. SQLCODE=-104, SQLSTATE=42601, DRIVER=3.61.75
Method 2:
stmt = con.prepareStatement(query, pkMapper.getPkFieldNames());
List<Object> params = getInsertParams(object, pkMapper);
for (int i = 0; i < params.size(); i++) {
Object param = params.get(i);
stmt.setObject(i+1, param);
}
pkMapper.getPkFieldNames() returns an array of string with PK column names. When executing stmt.setObject(i+1, param); I get an exception like this:
com.ibm.db2.jcc.am.SqlSyntaxErrorException: ILLEGAL SYMBOL "". SOME SYMBOLS THAT MIGHT BE LEGAL ARE:. SQLCODE=-104, SQLSTATE=42601, DRIVER=3.61.75
Method 3:
stmt = con.prepareStatement(query);
With this form, insert is executed fine, but no keys are returned with stmt.getGeneratedKeys();
Has anyone any idea of what is happening?

SPRING jdbcTemplate.update java.sql.SQLException: No value specified for parameter

I'have already solved the problem but i just wondered why jdbcTemplate not accept my query with the jdbcTemplate.update but work with jdbcTemplate.execute, here the code for the example with coordinates:
String query = "UPDATE geodomaindocument SET latitude=? , longitude=? WHERE url=?";
Object[] values = new Object[]{0,0,"http://example.com"}
jdbcTemplate.update(query, values);
return this exception:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [UPDATE geodomaindocument SET latitude=? , longitude=? WHERE url=?]; nested exception is java.sql.SQLException: No value specified for parameter 2
but is worked with the same query but with the execute:
query = "UPDATE geodomaindocument SET latitude='"+values[0]+"', longitude='"+values[1]+"' WHERE url='http://example.com'";
jdbcTemplate.execute(query);
Ty in advance for any help.
UPDATE
Ok,I'm just stupid, it's was a simple index error.
Your latitude and longitude are of type string. Try this
Object[] values = new Object[]{"0","0","http://example.com"}

JPA EclipseLink oracle db missing right parenthesis

I have a criteriaQuery:
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.where(criteriaBuilder.equal(root.get("type"), 1));
Then build rowCount query from the existing query:
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
Predicate restriction = criteriaQuery.getRestriction();
if (restriction != null)
countQuery.where(restriction);
countQuery.select(criteriaBuilder.countDistinct(root));
From debugging,
Predicate restriction = criteriaQuery.getRestriction();
criteriaQuery.where is (TYPE = ?), seen from debugger.
the restriction above returned is not (TYPE = ?), but ((TYPE = ?) = ?).
Eclipse generated SQL:
SELECT COUNT(DISTINCT(ID)) FROM EMPLOYEE WHERE ((TYPE = ?) = ?)
that causes error on oracle 11g db.
Error Code: 907
Call: SELECT COUNT(DISTINCT(ID)) FROM EMPLOYEE WHERE ((TYPE = ?) = ?)
bind => [1, true]
Query: ReportQuery(referenceClass=Employee.class sql="SELECT COUNT(DISTINCT(ID)) FROM EMPLOYEE WHERE ((TYPE = ?) = ?)")
00:31:24,718 ERROR [system] ORA-00907: missing right parenthesis
java.sql.SQLSyntaxErrorException: ORA-00907: missing right parenthesis
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:886)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1175)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1296)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3657)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1495)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2675)
at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:848)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:517)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400)
what is the reason for generating ((TYPE = ?) = ?) instead of (TYPE = ?).
Thanks for any help.
Without knowing much about the actual value of "TYPE" being bound, it seems that embedded single quotes within the actual value being bound may be causing this error.
A quote from the following site explains this: ORA-00907: missing right parenthesis tips
If you are using single quotes in phrases that are surrounded by other single quotes, you have to add another single quote by the inner single quotes to avoid ORA-00907. For example, you have to use '''''' instead of '''' in order for ORA-00907 to not be thrown over syntax.
*EDIT 1
Consider also looking at static metamodel representations of your typed parameters. For example:
ParameterExpression<String> typeParam = criteriaBuilder.parameter( Integer.class );
criteriaQuery.where( criteriaBuilder.equal( root.get( Employee_.type ), typeParam ) );
Where Employee_ type is a static metamodel as defined by the JPA spec.
Here is an example of this using an older version of EclipseLink. YMMV:
JPA 2.0 Criteria API with Maven and EclipseLink
You cannot reuse predicates/restrictions between the queries as they are tied to a specific CriteriaBuilder which is tied to a specific query. EclipseLink does allow reusing a built query, but you have to access native API and clone the underlying EclipseLink query before making changes.

org.hibernate.MappingException :No Dialect mapping for JDBC type: -9 [duplicate]

This question already has answers here:
JPA SQL Server No Dialect mapping for JDBC type: -9
(5 answers)
Closed 3 years ago.
When I am trying to fetch the record from a table in SQLServer2008 am getting the exception called: org.hibernate.MappingException :No Dialect mapping for JDBC type: -9 why?
Although the config file is correct.
It's the problem of hibernate mapping types.
you can extends a dialect.
eg:
public class SQLServerDialectOverrider extends SQLServerDialect{
public SQLServerDialectOverrider() {
super();
registerHibernateType(Types.NVARCHAR, Hibernate.STRING.getName());
registerHibernateType(Types.LONGVARCHAR, Hibernate.TEXT.getName());
}
}
Use this class as the dialect class.
I changed the query and explicitly cast it to varchar and it worked.......
String myquery = "select cast(t2.name as varchar) column_name from sys.objects t1 inner join sys.columns t2 on t2.object_id = t1.object_id"+
" left join sys.indexes t3 on t3.object_id = t1.object_id and t3.is_unique = 1 left join sys.index_columns t4 on t4.object_id = t1.object_id and t4.index_id = t3.index_id and t4.column_id = t2.column_id where (upper(t1.type) = 'U' or upper(t1.type) = 'V') and upper(schema_name(t1.schema_id)) = 'dbo' and upper(t1.name) = 'TEST'";
This issue occurs if you are accessing the database table data in the different format on which its store in database
Example:
in data base column type is "nvarchar" and you are accessing data as a string via hibernate.
To avoid this you can add scalar in hibernate which will explicitly cast the column data as per requirement. scalar can be added in java while executing the query also in the hbm.xml file.

calling derby (java db) 'show tables' from jdbc

I need to enumerate the tables in a Derby (aka Java DB) database using JDBC in a Java program. All I am aware of for doing this is the SHOW TABLES command.
I first tried with something similar to this...
String strConnectionURL = "jdbc:derby:/path/to/derby/database;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
Statement statement = connection.createStatement();
boolean boResult = statement.execute("SHOW TABLES");
if (boResult) {
System.out.println("yay!");
}
...but that throws an exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "SHOW" at line 1, column 1.
So next I thought maybe I needed to use a CallableStatement so I tried this...
String strConnectionURL = "jdbc:derby:/path/to/derby/db;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
CallableStatement statement = connection.prepareCall("SHOW TABLES");
boolean boResult = statement.execute();
if (boResult) {
System.out.println("yippee!");
}
...but that throws the same exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "SHOW" at line 1, column 1.
So, can anyone help me enumerate the tables in my Derby (Java DB) database from JDBC?
EDIT: I'm looking around and starting to get a feeling this may be a general JDBC question. In other words, one could/would enumerate all a db's tables with the DatabaseMetaData object that can be retrieved from the Connection object. Looking into that (and looking forward to responses)...
EDIT 2: I found a pure JDBC solution, but am still happy to hear alternatives...
String strConnectionURL = "jdbc:derby:/path/to/db;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
DatabaseMetaData dbmd = connection.getMetaData();
ResultSet resultSet = dbmd.getTables(null, null, null, null);
while (resultSet.next()) {
String strTableName = resultSet.getString("TABLE_NAME");
System.out.println("TABLE_NAME is " + strTableName);
}
Show Tables is an ij command, not a base SQL statement, so you can't directly execute it. As you noted in your "EDIT 2", you can use the DatabaseMetaData to do this. Two other ways to do it are: you can select from the system catalogs (see http://db.apache.org/derby/docs/10.8/ref/rrefsistabs24269.html) , or you can use the "ij.runScript" method to run the ij tool from within your program, and pass it the "show tables" command (see http://db.apache.org/derby/docs/10.8/publishedapi/jdbc3/org/apache/derby/tools/ij.html)
As Bryan suggested ij.runScript - the code would look like this:
public void showTbls() throws Exception{
String sqlIn = "SHOW TABLES;";
InputStream stream = new ByteArrayInputStream(sqlIn.getBytes(StandardCharsets.UTF_8));
ij.runScript(conn,stream,StandardCharsets.UTF_8.name(), System.out,"UTF-8");
stream.close();
}
assumming conn is a opened derby Connection
But the disadvantage is that you are getting only string output. Not an ResultSet as you would get from:
Statement stmt = conn.createStatement();
ResultSet results = stmt.executeQuery("SELECT * FROM sys.systables");
or if you want only user table names you can use following SQL:
ResultSet results = stmt.executeQuery("SELECT TABLENAME FROM SYS.SYSTABLES WHERE TABLETYPE='T'");
A very similar output to
SHOW TABLES;
can be produced by using the following jdbc compliant query:
SELECT TABLENAME, (SELECT SCHEMANAME
FROM SYS.SYSSCHEMAS
WHERE SYS.SYSTABLES.SCHEMAID = SYS.SYSSCHEMAS.SCHEMAID)
AS SCHEMANAME
FROM SYS.SYSTABLES WHERE TABLETYPE='T'
It also shows you the probably useful SCHEMA information for each TABLE entry. Skip
TABLETYPE='T'
if you also want to see the system tables of your database as the user before has mentioned already.

Resources