How to write a query with two ? placeholders in sequence? - jdbc

I am using a NamedParameterJdbcTemplate, but found that this problem is in the underlying JdbcTemplate class, so I will show the problem as it occurs with the JdbcTemplate (so let's not worry about the safety of the SQL query here).
Here's what I am trying to achieve:
String sql = "SELECT * FROM clients ORDER BY ? ?";
return jdbcTemplate.query(sql,
new Object[] { "name", "ASC" },
new ClientResultSetExtractor());
I expected the first place-holder to be replaced with "name" and the second with "ASC", which would create the valid SQL query:
SELECT * FROM clients ORDER BY name ASC
But unfortunately, running that jdbc query does not work:
ERROR: syntax error at or near "$2" at character 35
STATEMENT: SELECT * FROM clients ORDER BY $1 $2
What am I doing wrong?
EDIT
I had assumed the problem was the two placeholders in sequence, but even when I remove the first one, it still won't accept just the last one, which should tell the query whether to sort in ASC or DESC order. Is this a bug, and if not, why the heck is this not acceptable????

You're trying to use parameters incorrectly.
Parameters are not column names or SQL statement keywords. They're data content (eg., WHERE LastName = ? is a valid parameterized statement, WHERE ? = 'Smith' is not).

Related

Getting Second Order SQL Injection in Spring Hibernate

I am facing Second Order SQL Injection in the Spring-Hibernate application after scanning through the Checkmarx tool, I have gone through multiple questions in StackOverflow and in other platforms as well but did not get the right finding.
could you please look into the below code snip,
public String getOrderId(order_name){
String returnId= null;
Query query = entityManager.createNativeQuery("select order_id from order where order_name=?");
List<String> dataset = query.setParameter(1,order_name).getResultList();
if(dataset!=null){
returnId = dataset. Get(0);
}
return returnId;
}
In this above method, while calling getResultList(), getting a high vulnerability issue that, this method returns data flows through the code without being properly sanitized or validated, and eventually used in further database query in the method.
Earlier code was like this,
public String getOrderId(order_name){
String returnId= null;
String q = "select order_id from order where order_name="+order_name;
Query query = entityManager.createNativeQuery(q);
and directly it was used as a string append in query, which I have modified with set parameter,
Query query = entityManager.createNativeQuery("select order_id from order where order_name=?");
List<String> dataset = query.setParameter(1,order_name).getResultList();
but still after getting data from query.getResultSet(), it is asking for sanitizing and validating the data before use in further database query method.
and this return data is being used in further query like select * from return_Data where clause. (properly used in where clause to set parameter to avoid SQL injection).
and in the above query is used in another method where we pass return_Data as input to it.
could you please help here to know what checks and validation can be added to overcome this type of issue. Thanks in advance for prompt response.

Null and Empty Check for a IN Clause parameter for Spring data jpa #query?

My Spring data JPA code to get the data from db based on some search criteria is not working. My DB is SQL Server 2012, same query seem to work with MYSQL DB.
Code Example :
#Query(value = "select * from entity e where e.emp_id=:#{#mySearchCriteria.empId} and ((:#{#mySearchCriteria.deptIds} is null or :#{#mySearchCriteria.deptIds} ='') or e.dept_id in (:#{#mySearchCriteria.deptIds})) ", nativeQuery = true)
public List<Entity> search(#Param("mySearchCriteria") MySearchCriteria mySearchCriteria);
if list mySearchCriteria.deptIds has more than one value- it's not working(it's actually translating it to wrong query. Any lead? Thanks in advance.
Note: data type for deptIds is List of Integer
Its complaining because values of {#mySearchCriteria.deptIds} is comma separated list e.g. 'Value1', 'Value2' so the query gets translated as ('Value1', 'Value2' is null) which causes this error.
Need to verify if list is empty or not and then change the query with IN clause and one without IN clause.
Surround the list by parentheses. This works for me.
(:#{#mySearchCriteria.deptIds}) is null

Spring jdbcTemplate executing query

I have a strange problem ,
My Query looks like below.
String tokenQuery = "select id from table
where current_timestamp between
creation_time and (creation_time + interval '10' minute)
and token = '"+Token+"'";
But when I run, jdbcTemplate.queryForLong(tokenQuery) , no matter what , it always throws EmptyDataAccessException.
I am executing this in Oracle
Can we not append dynamic values to string and then pass it as a query and execute ?
What could be the issue ?
I assume that what you get is in fact an EmptyResultDataAccessException. The javadoc of this exception says:
Data access exception thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned.
That simply means that the query is executed fine, and is supposed to return one row, but doesn't return any. So no row satisfies the criteria of your query.
If that is expected, then catch the exception, or use a method that returns a list rather then returning a single value. That way, you can test if the returned list is empty.
That said, you should use a parameterized query instead of concatenating the token like you're doing. This would prevent SQL injection attacks. It would also work even if the token contains a quote, for example.

"SELECT VALUE" - value keyword in LINQ/Entity Framework query

What does the keyword "value" mean in this statement, and where would I go to learn more?
What happens if I leave out the keyword "value"? In the code below, z is an entity framework class.
string queryString = "SELECT VALUE q from x.zs as q where q.a = #parm;"
ObjectQuery<z> query = context.CreateQuery<z>
(queryString, new ObjectParameter("parmname",parmvalue));
return query.First();
(This is a part of a practice question for an exam).
The above code is in a function that returns a variable of type z.
That is Entity SQL syntax. Value keyword allows only one value to be specified, and does not add a row wrapper.
Read article about SELECT statement in ESQL
Entity SQL supports two variants of the SELECT clause. The first
variant, row select, is identified by the SELECT keyword, and can be
used to specify one or more values that should be projected out.
Because a row wrapper is implicitly added around the values returned,
the result of the query expression is always a multiset of rows.
Each query expression in a row select must specify an alias. If no
alias is specified,Entity SQL attempts to generate an alias by using
the alias generation rules.
The other variant of the SELECT clause, value select, is identified by
the SELECT VALUE keyword. It allows only one value to be specified,
and does not add a row wrapper.
So, if you want to materialize z object from your query, you should use SELECT VALUE syntax (otherwise you will get exception: cast from MaterializedDataRecord to z type is not valid).
Without VALUE keyword you will get set of rows:
string esql = "SELECT q from x.zs as q where q.a = #parm;";
ObjectQuery<DbDataRecord> query = context
.CreateQuery<DbDataRecord>(esql, new ObjectParameter("parm",parmvalue));
var result = query.First();

Aggregate query with Castle ActiveRecord

I'm trying to perform a simple aggregate query that returns the aggregate's result plus an extra column. This post -> Custom query with Castle ActiveRecord had a good example about how to achieve this, but I can't seem to get it to work. It seems that ActiveRecordMediator.ExecuteQuery returns an ArrayList of objects (instead of ArrayList of object[] which is what I would expect). Also if I try to cast it to ICollection I get a run-time error complaining of invalid cast. Code below, any help appreciated (don't want to use hand-written sql).
HqlBasedQuery query = new HqlBasedQuery(typeof(Something), #"select count(1),
p.Name from Something p
where p.SomeDate > :date
order by p.Name
group by p.Name");
query.SetParameter("date", new DateTime(2009, 1, 1));
var results = from summary in
(ICollection<object[]>)ActiveRecordMediator.ExecuteQuery(query)
select new {
Count = (int)summary[0], Name= (string)summary[1]
};
The line after "from summary in" is the one that throws the invalid cast exception.
(Forgot to mention: using VS2008, .NET 3.5SP1, ActiveRecord 1.0RC3, NHibernate 1.2)
I think you meant count(*) instead of count(1) (this is why you're getting only 1-col rows)
ActiveRecordMediator.ExecuteQuery (at least in RC3) returns an ArrayList (not a generic ICollection) of object[]
Be careful casting count results as int. Some databases return counts as long (e.g. SQL Server)

Resources