How to use android SQLITE SELECT with two parameters? - android-sqlite

This code return empty cursor.What is wrong here?
Data is already there in sqlitedb.
public static final String COL_2 = "ID";
public static final String COL_3 = "TYPE";
public Cursor checkData(String id, String type){
SQLiteDatabase db = getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM "+ TABLE_NAME + " WHERE " + COL_2 + " = " + id+ " AND " + COL_3 + " = " + type , null);
return res;
}

When you pass strings as parameters you must quote them inside the sql statement.
But by concatenating quoted string values in the sql code your code is unsafe.
The recommended way to do it is with ? placeholders:
public Cursor checkData(String id, String type){
SQLiteDatabase db = getWritableDatabase();
String sql = "SELECT * FROM "+ TABLE_NAME + " WHERE " + COL_2 + " = ? AND " + COL_3 + " = ?";
Cursor res = db.rawQuery(sql , new String[] {id, type});
return res;
}
The parameters id and type are passed as a string array in the 2nd argument of rawQuery().

I finally solved it.
public Cursor checkData(String id, String type){
SQLiteDatabase db = getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM "+ TABLE_NAME + " WHERE " + COL_2 + " = '" + id+ "' AND " + COL_3 + " = '" + type +"'" , null);
return res;
}

if COL_3 type is string try this:
Cursor res = db.rawQuery("SELECT * FROM "+ TABLE_NAME + " WHERE " + COL_2 + " = " + id+ " AND " + COL_3 + " = '" + type + "'" , null);

Related

JpaSystemException: No Dialect mapping for JDBC type: 1111

I have viewed some of the related question but the solutions on them are bit older. Most of them are using EntityManager. I have written the following native query in JpaRepository and when I get geojson as a String I'm getting the error mentioned in the title.
Here is my query
#Query(value = "SELECT\n"
+ " json_build_object(\n"
+ " 'type', 'FeatureCollection',\n"
+ " 'features', json_agg(\n"
+ " json_build_object(\n"
+ " 'type', 'Feature',\n"
+ " 'geometry', ST_AsGeoJSON(a.check_in_geom)\\:\\:json,\n"
+ " 'properties', json_build_object(\n"
+ " 'username', a.username,\n"
+ " 'users', (\n"
+ " -- Generate json array of \"users\"\n"
+ " SELECT array_to_json(array_agg(u.*)) \n"
+ " FROM users u \n"
+ " WHERE u.username = a.username\n"
+ " GROUP BY u.username\n"
+ " )\n"
+ " )\n"
+ " )\n"
+ " )\n"
+ " ) Json\n"
+ "FROM\n"
+ " attendances a, users u\n"
+ " WHERE a.username = u.username AND u.designation = 'Manager' AND date_trunc('day', a.created_at)\\:\\:DATE = '2022-04-04'"
+ " ;", nativeQuery = true)
String getAttendanceGeoJsonByDesignationAndDate(String designation, String dateStr);
For now I'm passing designation and date as static values.
When I run this query on Postgresql it runs successfully and return the expected geojson. But spring boot does not allow the result to be as String or it throws exception while running the query.
Please let me know how can I fix it. Also if I need to provide more detail, do let me know.

PSQLException: The column name clazz_ was not found in this ResultSet

I am trying to fetch a PlaceEntity. I've previously stored a bunch of GooglePlaceEntity objects where
#Entity
#Table(name = "place")
#Inheritance(
strategy = InheritanceType.JOINED
)
public class PlaceEntity extends AbstractTimestampEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
and
#Entity
#Table(name = "google_place")
public class GooglePlaceEntity extends PlaceEntity {
// Additional fields ..
}
However, neither do I want to send information stored in google_place nor do I want to load it unnecessarily. For this reason I am only fetching
public interface PlaceRepository extends JpaRepository<PlaceEntity, Long> {
#Query(value = "" +
"SELECT * " +
"FROM place " +
"WHERE earth_distance( " +
" ll_to_earth(place.latitude, place.longitude), " +
" ll_to_earth(:latitude, :longitude) " +
") < :radius",
nativeQuery = true)
List<PlaceEntity> findNearby(#Param("latitude") Float latitude,
#Param("longitude") Float longitude,
#Param("radius") Integer radius);
}
and what I get is this:
org.postgresql.util.PSQLException: The column name clazz_ was not found in this ResultSet.
at org.postgresql.jdbc.PgResultSet.findColumn(PgResultSet.java:2588) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
at org.postgresql.jdbc.PgResultSet.getInt(PgResultSet.java:2481) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
at com.zaxxer.hikari.pool.HikariProxyResultSet.getInt(HikariProxyResultSet.java) ~[HikariCP-2.7.8.jar:na]
at org.hibernate.type.descriptor.sql.IntegerTypeDescriptor$2.doExtract(IntegerTypeDescriptor.java:62) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
...
I am able to run this statement in pure PostgreSQL:
SELECT * FROM place WHERE
earth_distance(
ll_to_earth(place.latitude, place.longitude),
ll_to_earth(17.2592522, 25.0632745)
) < 1500;
but not using the JpaRepository.
And by the way, fetching a GooglePlaceEntity is working however:
#Query(value = "" +
"SELECT * " +
"FROM place JOIN google_place ON google_place.id = place.id " +
"WHERE earth_distance( " +
" ll_to_earth(place.latitude, place.longitude), " +
" ll_to_earth(:latitude, :longitude) " +
") < :radius",
nativeQuery = true)
List<GooglePlaceEntity> findNearby(#Param("latitude") Float latitude,
#Param("longitude") Float longitude,
#Param("radius") Integer radius);
In case of #Inheritance(strategy = InheritanceType.JOINED), when you retrieve data without nativeQuery=True in JPA repository, Hibernate will execute SQL like the following:
SELECT
table0_.id as id1_1_,
table0_.column2 as column2_2_1_,
... (main_table cols)
table0_1_.column1 as column1_1_0_,
... (table1 to N-1 cols)
table0_N_.column1 as column1_1_9_,
... (tableN-th cols)
CASE WHEN table0_1_.id is not null then 1
... (table1 to N-1 cols)
WHEN table0_N_.id is not null then N
WHEN table0_.id is not null then 0
END as clazz_
FROM table table0_
left outer join table1 table0_1_ on table0_.id=table0_1_.id
... (other tables join)
left outer join table2 table0_N_ on table0_.id=table0_N_.id
From the above SQL you can see clazz specification. If you want to map ResultSet to your super instance (PlaceEntity), you should specify clazz_ column in SELECT by yourself.
In your case it will be:
#Query(value = "" +
"SELECT *, 0 AS clazz_ " +
"FROM place " +
"WHERE earth_distance( " +
" ll_to_earth(place.latitude, place.longitude), " +
" ll_to_earth(:latitude, :longitude) " +
") < :radius",
nativeQuery = true)
You should use the name of the class instead of the table name on the query. Change place to PlaceEntity.
#Query(value = "" +
"SELECT * " +
"FROM place JOIN google_place ON google_place.id = place.id " +
"WHERE earth_distance( " +
" ll_to_earth(place.latitude, place.longitude), " +
" ll_to_earth(:latitude, :longitude) " +
") < :radius",
nativeQuery = true)
List<GooglePlaceEntity> findNearby(#Param("latitude") Float latitude,
#Param("longitude") Float longitude,
#Param("radius") Integer radius);

Spring Data JPA JSONB Paramaterization

What is the correct syntax (JPA, Spring Data, or SpEL) to convert this query into a Spring Data Repository nativeQuery?
SELECT *
FROM mytable
WHERE f_jsonb_arr_lower(myjsonb -> 'myArray', 'subItem', 'email')
#> '"foo#foo.com"';
I want to use an input parameter instead of hard-coding "foo#foo.com".
My model: Postgres myTable with a JSONB column myJsonb:
{
"myArray": [
{
"subItem": {
"email": "bar#bar.com"
}
},
{
"subItem": {
"email": "foo#foo.com"
}
}
]
}
Index described here.
The hard-coded version works:
#Query(value =
"SELECT m.* " +
" FROM mytable AS m " +
" WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " +
" #> '\"foo#foo.com\"' " +
" ORDER BY ?#{#pageable} ",
// Spring Data nativeQueries with Pageable require a separate countQuery:
countQuery =
"SELECT count(m.id) " +
" FROM mytable AS m " +
" WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " +
" #> '\"foo#foo.com\"' ",
nativeQuery = true)
Page<MyTableEntity> findAllHardcodedPageable(Pageable pageable);
But trying to leverage the lowercaseEmailAddress parameter in a Spring Data repository nativeQuery does not work:
#Query(value =
"SELECT m.* " +
" FROM mytable AS m " +
" WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " +
" #> '\"?{lowercaseEmailAddress}\"' " +
" ORDER BY ?#{#pageable} ",
countQuery =
"SELECT count(m.id) " +
" FROM mytable AS m " +
" WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " +
" #> '\"?{lowercaseEmailAddress}\"' ",
nativeQuery = true)
Page<MyTableEntity> findAllByEmailPageable
(String lowercaseEmailAddress, Pageable pageable);
In my Postgres query logging, I can see that the lowercaseEmailAddress parameter is never set:
LOG: execute S_2: COMMIT
LOG: execute S_3: BEGIN
LOG: execute <unnamed>: SELECT count(m.id) FROM mytable
AS m WHERE f_jsonb_arr_lower(myjsonb -> 'myArray',
'subitem', 'email') #> '"?1"'
LOG: execute S_11: ROLLBACK
Found the answer:
1) Pass only a double-quoted String to the spring data repository method:
String emailAddressWithDoubleQuotes = String.format("\"%s\"",emailAddress);
result = repository.findAllByEmailPageable(emailAddressWithDoubleQuotes, pageRequest).getContent();
2) The Spring Repository #Query needs to have the SpEL expression in parenthesis and be casted to jsonb:
static final String FIND_ALL_BY_EMAIL_QUERY = " FROM mytable AS m " +
" WHERE f_jsonb_arr_lower(metadata -> 'myArray', 'subItem', 'email') " +
" #> ( ?#{#lowercaseEmailAddress} )\\:\\:jsonb";
#Query( // only use 'ORDER BY #pageableWithNativeSort' on 'value' query:
value = "SELECT m.* " + FIND_ALL_BY_EMAIL_QUERY + " ORDER BY ?#{#pageableWithNativeSort} ",
// Spring Data nativeQueries with Pageable require a separate 'countQuery':
countQuery = "SELECT count(m.id) " + FIND_ALL_BY_EMAIL_QUERY,
nativeQuery = true)
Page<OrderEntity> findAllBysubItemEmail(
#Param("lowercaseEmailAddress") String lowercaseEmailAddress,
#Param("pageableWithNativeSort") Pageable pageableWithNativeSort);

Access list of object array with alias in jpa

i have written a native query in jpa which fetch list of object array
list = entityManager.createNativeQuery("select emp.card Card,emp.code Code,emp.emp_name EmpName,ln.BAL Balance, ln.cum_intr CumIntr, ln.install Install,ln.install_no InstallNo, "
+ " led.BAL ledgBAL,led.cum_intr ledgCum,led.install ledgInstall,led.install_no ledgInstallNo "
+ " from LOANS ln "
+ " inner join "
+ " LOAN_LEDGER led "
+ " on (led.EMPLOYEES_ID = ln.EMPLOYEES_ID and ln.LOAN_UID= led.LOAN_UID and (ln.bal!= led.BAL or ln.cum_intr!= led.cum_intr or ln.INSTALL != led.INSTALL )) "
+ " inner join EMPLOYEES emp "
+ " on ln.employees_id = emp.id "
+ " where led.ledger_month in "
+ " ( 201312 )").getResultList();
I assigned alias for each field.this is my code to access this object array.
Iterator it = list.iterator();
while (it.hasNext()) {
Object[] result = (Object[]) it.next();
System.err.println("Result Arrayyyyy "+result[0]);
}
Now i want to access this result array using alias . How can I do it?

Writing query with parameters to avoid SQL Injections

I have done that before, but in this case I have an insert into table query where value of the column of the target table comes as a result from another query. Having that, I'm not sure if my parametarized query is formatted the right way.
Here is an original query without before Sql Injection fix:
cmd.CommandText += "insert into controlnumber (controlnumber, errorid)
values ('" + ControlNumber + "', (select errorid from error where
errordescription = '" + ErrorDescription + "' and errortype = '" +
ErrorType + "' + and applicationid = " + ApplicationID + " and statusid =
" + StatusID + " and userid = " + UserID + " and errortime = '" +
ErrorTime + "');";
This is the query after I tried to fix Sql Injection:
cmd.CommandText = "insert into ControlTable(ControlNumber, ErrorID)
values (#ControlNum, (select errorid from error where errordescription =
#ErrorDescription and errortype = #errorType and applicationid =
#ApplicationID and statusid = #StatusID and userid = #UserID and
errortime = #ErrorTime)"
This is where I add parameters:
.....
command.CommandType = CommandType.Text
command.Parameters.AddWithValue("#ErrorDescription ", ErrorDesc);
command.Parameters.AddWithValue("#ControlNum", cntNumber);
command.Parameters.AddWithValue("#errorType",ErrorType);
command.Parameters.AddWithValue("#ApplicationID",AppID);
command.Parameters.AddWithValue("#StatusID",StatusID);
command.Parameters.AddWithValue("#UserID",UserID);
....
I'm just wondering if my CommandText is formatted the right way.
Thank's
try this:
cmd.CommandText = "insert into ControlTable(ControlNumber, ErrorID)
select #ControlNum, errorid from error where errordescription =
#ErrorDescription and errortype = #errorType and applicationid =
#ApplicationID and statusid = #StatusID and userid = #UserID and
errortime = #ErrorTime)"
When using INSERT INTO SELECT FROM, you do not use keyword VALUES. The syntax is:
INSERT INTO TABLE(columns) SELECT ... FROM TABLE2