Get boolean from database using Android and SQLite - java

How can I obtain the value of a boolean field in an SQLite database on Android?
I usually use getString(), getInt(), etc. to get the values of my fields, but there does not seem to be a getBoolean() method.

It is:
boolean value = cursor.getInt(boolean_column_index) > 0;

There is no bool data type in SQLite. Use an int that you fix to 0 or 1 to achieve that effect. See the datatypes reference on SQLite 3.0.

boolean value = (cursor.getInt(boolean_column_index) == 1);

Most of the answers here can result in NumberFormatExceptions or "operator is undefined for the types null, int" if the column you stored the int in was allowed to also hold null.
The decent way to do this would be to use
Boolean.parseBoolean(cursor.getString(booleanColumnIndex));`
though you are now limited to storing the strings "true" and "false" rather than 0 or 1.

An implementation found at Ormlite Cursor also checks for Null which none of the other answers do.
public boolean getBoolean(int columnIndex) {
if (cursor.isNull(columnIndex) || cursor.getShort(columnIndex) == 0) {
return false;
} else {
return true;
}
}

You can also use
boolean value =cursor.getString(boolean_column_index).equals("True");

boolean datatype is not available in Cursor.
you will get the result in an int, so you need to convert that int value to a boolean.
You can either use
boolean b = cursor.getInt(boolean_column_index) > 0;
or
boolean b = (cursor.getInt(boolean_column_index) != 0);

Another option
boolean value = (cursor.getString(column_index)).equals("1");

boolean b = (cursor.getInt(cursor.getColumnIndex("item")) != 0);

Well, that's very simple:
public boolean getBooleanState(SQLiteDatabase db){
boolean result = false;
try{
String QUERY = "SELECT " + BOOLEAN_DATA + " FROM " + TABLE_NAME + " WHERE " + ID + " = 1";
Cursor cursor = db.rawQuery(QUERY, null);
if (cursor.moveToFirst()){
if(cursor.getString(0).equalsIgnoreCase("1")){
result = true;
}
}
c.close();
}catch(Exception ee){
Log.e(TAG, "err getBooleanState: " + TABLE_NAME );
}
return result;
}

For an optional (nullable) Boolean stored as INTEGER, you can create a Kotlin extension:
fun Cursor.getBoolean(columnIndex: Int): Boolean? {
return if (isNull(columnIndex))
null
else
getInt(columnIndex) != 0
}
and use it like this:
val value: Boolean? = cursor.getBoolean(boolean_column_index)

thats what I used:
val work = Work()
work.id = cursor.getInt(0)
work.date = cursor.getString(1)
work.work_value = cursor.getFloat(2)
work.place = cursor.getString(3)
work.wind = cursor.getFloat(4)
work.isCompetition = cursor.getInt(5) > 0
return work

I face the same thing in kotlin.
There was the value "true/false" in the database
and I access it with this code:
cursor.getString(4).toBoolean()
//first as a string then converting them to boolean

Related

cursor is crashing with CursorIndexOutOfBoundsException

My cursor is crashing my application with the android database error.
CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
I made another much less optimized slider that scans my database and I find the good value.
public Cursor getAllDataTableStaffDatabase(String table_name){
this.open();
Cursor result =this.mDb.rawQuery("SELECT * FROM " + table_name,null);
return result;// fonctionne très bien
}
public String findNameOfStaffBymail(String mail) {
String sql = " SELECT * FROM " + DatabaseStaffHandler.STAFF_TABLE_NAME + " WHERE " + DatabaseStaffHandler.STAFF_MAIL + " = ? ";
Cursor result = super.mDb.rawQuery(sql, new String[]{mail});
Cursor data = super.getAllDataTableStaffDatabase(DatabaseStaffHandler.STAFF_TABLE_NAME);
String test = result.getString(1); //error
while (data.moveToNext()) {
if (data.getString(3).equals(mail)) {
viewAll();
return data.getString(1);
}
}
}
I would like to retrieve the value name that corresponds to the email address.
This usually happens when you do not have the data in your Cursor and you are still trying to access the data. It is similar to the ArrayIndexOutOfBoundsException. I found nothing wrong with your query so far. However, I think you might consider adding null checking in your code which will prevent your application from crashing. Especially in the while loop, you need to put a null check in the condition.
And you need to use the moveToFirst function wherever necessary.
public Cursor getAllDataTableStaffDatabase(String table_name) {
this.open();
Cursor result = this.mDb.rawQuery("SELECT * FROM " + table_name,null);
return result;
}
public String findNameOfStaffBymail(String mail) {
String sql = " SELECT * FROM " + DatabaseStaffHandler.STAFF_TABLE_NAME + " WHERE " + DatabaseStaffHandler.STAFF_MAIL + " = ? ";
Cursor result = super.mDb.rawQuery(sql, new String[]{mail});
Cursor data = super.getAllDataTableStaffDatabase(DatabaseStaffHandler.STAFF_TABLE_NAME);
// Add a null checking here.
if (result != null) {
result.moveToFirst();
String test = result.getString(1);
}
if(data != null) data.moveToFirst();
while (data != null) {
if (data.getString(3).equals(mail)) {
viewAll();
return data.getString(1);
}
data.moveToNext();
}
}
Hope that solves your problem.
Thank you for your reply. I found my problem thanks to you. I wonder if the cursor does not boot at the end. But it is good practice to check if received is not null. Thank you and have a nice day

Checking to see if an ID exists in resources (R.id.something)

So, I have code that's generating ID's for a number of elements using an AtomicInteger that's set by default at Integer.MAX_VALUE and is decremented from there with each view that gets assigned an ID. So the first view with a generated ID would be Integer.MAX_VALUE - 1, the second would be Integer.MAX_VALUE - 2, etc. The problem I'm afraid of is a collision with IDs generated by Android in R.java.
So my question is how can I detect if an ID is already in use and skip it when I'm generating the IDs. I'm only generating at most 30 IDs so this isn't a huge priority nut I'ld like to make this as bug free as possible.
The following code will tell you if the identifier is an id or not.
static final String PACKAGE_ID = "com.your.package.here:id/"
...
...
int id = <your random id here>
String name = getResources().getResourceName(id);
if (name == null || !name.startsWith(PACKAGE_ID)) {
// id is not an id used by a layout element.
}
I modified Jens answer from above since, as stated in comments, name will never be null and exception is thrown instead.
private boolean isResourceIdInPackage(String packageName, int resId){
if(packageName == null || resId == 0){
return false;
}
Resources res = null;
if(packageName.equals(getPackageName())){
res = getResources();
}else{
try{
res = getPackageManager().getResourcesForApplication(packageName);
}catch(PackageManager.NameNotFoundException e){
Log.w(TAG, packageName + "does not contain " + resId + " ... " + e.getMessage());
}
}
if(res == null){
return false;
}
return isResourceIdInResources(res, resId);
}
private boolean isResourceIdInResources(Resources res, int resId){
try{
getResources().getResourceName(resId);
//Didn't catch so id is in res
return true;
}catch (Resources.NotFoundException e){
return false;
}
}
You can use Java Reflection API to access whatever elements are present in an object of R.id Class.
The code is like this:
Class<R.id> c = R.id.class;
R.id object = new R.id();
Field[] fields = c.getDeclaredFields();
// Iterate through whatever fields R.id has
for (Field field : fields)
{
field.setAccessible(true);
// I am just printing field name and value, you can place your checks here
System.out.println("Value of " + field.getName() + " : " + field.get(object));
}
You can use View.generateViewId() which requires min API 17.
From sdk
Generate a value suitable for use in setId(int). This value will not collide with ID values generated at build time by aapt for R.id.
Just an idea ... you could use the findViewById (int id) to check if the id is already in use.

Finding Difference of 2 sets in Java

I have two hashsets in Java, of which I want to find the difference
I tried the following code as recommended by Oracle's doc
HashSet<RunningTaskInfo> difference = new HashSet<ActivityManager.RunningTaskInfo>(newRunningTasks);
HashSet<RunningTaskInfo> oldRunningTaskInfos = new HashSet<ActivityManager.RunningTaskInfo>(oldRunningTasks);
difference.removeAll(oldRunningTaskInfos);
for(RunningTaskInfo d : difference){
ComponentName cn = d.baseActivity;
Log.d("com.manugupt1.fua","Comparing : " + i + cn.getPackageName() + "****" + cn.getClassName() + "****" + cn.getShortClassName());
}
Only those data values that are not in oldRunningTasks should be shown but I get only the elements from oldRunningTasks. Any suggestions
EDIT: Adding Matt's comments
RemoveAll is comparing objects pointers instead of the content, and that's why it's not able to find any coincidences.
You can check this by watching the return value of
difference.removeAll(oldRunningTaskInfos);
(false means "no coincidences")
Probably the best approach would be encapsulating RunningTask into an object that overrides equals() and hashcode() methods, and then invoke removeAll. Consider the following sample code that do the same but using List's:
// Getting two snapshots
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> oldRunningTasks=am.getRunningTasks (100);
List<ActivityManager.RunningTaskInfo> newRunningTasks=am.getRunningTasks (100);
// We add a new fake task to test that removeAll() is working
ActivityManager.RunningTaskInfo fakeTask=new ActivityManager.RunningTaskInfo ();
fakeTask.baseActivity=new ComponentName("Fake","Fake");
fakeTask.id=1234;
newRunningTasks.add(fakeTask);
// Converting to lists of Comparable objects and get the differences.
List<RunningTaskInfoComparable> list_difference = convertToComparable(newRunningTasks);
List<RunningTaskInfoComparable> list_oldRunningTaskInfos = convertToComparable(oldRunningTasks);
boolean res=list_difference.removeAll(list_oldRunningTaskInfos);
for(RunningTaskInfoComparable d : list_difference){
ComponentName cn = d.getBaseActivity();
Log.d("com.test.tasks","Comparing List: " + cn.getPackageName() + "****" + cn.getClassName() + "****" + cn.getShortClassName());
}
where RunningTaskInfoComparable is implemented like this:
public class RunningTaskInfoComparable {
android.app.ActivityManager.RunningTaskInfo runningTaskObject;
public RunningTaskInfoComparable (android.app.ActivityManager.RunningTaskInfo obj)
{
runningTaskObject=obj;
}
// Observer
public ComponentName getBaseActivity(){
return runningTaskObject.baseActivity;
}
#Override
public int hashcode()
{
int result = HashCodeUtil.SEED;
// More data could be added to the hash...
result = HashCodeUtil.hash( result, runningTaskObject.id);
return result;
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof RunningTaskInfoComparable)) {
return false;
}
// Criteria: Same task id means same entity
return (runningTaskObject.id==((RunningTaskInfoComparable)obj).runningTaskObject.id);
}
}
and convertToComparable looks like:
private List<RunningTaskInfoComparable> convertToComparable (List<ActivityManager.RunningTaskInfo> _original)
{
List<RunningTaskInfoComparable> retList=new ArrayList<RunningTaskInfoComparable>();
for(RunningTaskInfo t : _original){
RunningTaskInfoComparable tc = new RunningTaskInfoComparable(t);
retList.add(tc);
}
return retList;
}

ResultSet convert to int from query

So I am trying to get the result as count from a sql query as follows
ResultSet rs = st.executeQuery("SELECT count(employeeID) FROM employee WHERE " +
"employeeID='"+_empID+"' AND password = '"+_password + "'");
so i am also trying to convert that value to int and I tried the follwing
for (; rs.next();) {
val = (Integer) rs.getObject(1);
}
I have also try
val = Integer.parseInt(rs.getObject(1));
but nothing I get the following errors
java.lang.Long cannot be cast to java.lang.Integer
How can I do this.. so if that returns a 0,3 or 4 that it becomes an integer?
Thank you
EDITED TO: (STILL GETTING ERROR)
long countLong = 0;
for (; rs.next();) {
countLong = rs.getLong(1);
}
if(countLong < 1)
{
isAuthentic = false;
}
else
{
isAuthentic = true;
}
A good trick to use when you are not sure about the exact number type is to cast it to the parent class of all numeric type, Number:
val = ((Number) rs.getObject(1)).intValue();
This will work for all numeric types, eg float, long, int etc.
Use ResultSet.getLong method:
long countLong = resultSet.getLong(1);
//if you really want and you are sure that it fits you can now cast
int count = (int)countLong;
Try a getString() and then Long.parseLong().
Cast it to a string and then to an int or long or whatever you want:
Integer.parseInt(rs.getObject(1).toString());

Hibernate order by with nulls last

Hibernate used with PostgreSQL DB while ordering desc by a column puts null values higher than not null ones.
SQL99 standard offers keyword "NULLS LAST" to declare that null values should be put lower than not nulls.
Can "NULLS LAST" behaviour be achieved using Hibernate's Criteria API?
This feature has been implemented during Hibernate 4.2.x and 4.3.x releases as previously mentioned.
It can be used as for example:
Criteria criteria = ...;
criteria.addOrder( Order.desc( "name" ).nulls(NullPrecedence.FIRST) );
Hibernate v4.3 javadocs are less omissive here.
Given that HHH-465 is not fixed and is not going to get fixed in a near future for the reasons given by Steve Ebersole, your best option would be to use the CustomNullsFirstInterceptor attached to the issue either globally or specifically to alter the SQL statement.
I'm posting it below for the readers (credits to Emilio Dolce):
public class CustomNullsFirstInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = -3156853534261313031L;
private static final String ORDER_BY_TOKEN = "order by";
public String onPrepareStatement(String sql) {
int orderByStart = sql.toLowerCase().indexOf(ORDER_BY_TOKEN);
if (orderByStart == -1) {
return super.onPrepareStatement(sql);
}
orderByStart += ORDER_BY_TOKEN.length() + 1;
int orderByEnd = sql.indexOf(")", orderByStart);
if (orderByEnd == -1) {
orderByEnd = sql.indexOf(" UNION ", orderByStart);
if (orderByEnd == -1) {
orderByEnd = sql.length();
}
}
String orderByContent = sql.substring(orderByStart, orderByEnd);
String[] orderByNames = orderByContent.split("\\,");
for (int i=0; i<orderByNames.length; i++) {
if (orderByNames[i].trim().length() > 0) {
if (orderByNames[i].trim().toLowerCase().endsWith("desc")) {
orderByNames[i] += " NULLS LAST";
} else {
orderByNames[i] += " NULLS FIRST";
}
}
}
orderByContent = StringUtils.join(orderByNames, ",");
sql = sql.substring(0, orderByStart) + orderByContent + sql.substring(orderByEnd);
return super.onPrepareStatement(sql);
}
}
You can configure "nulls first" / "nulls last" in hibernate properties so it will be picked up by any criteria call by default: hibernate.order_by.default_null_ordering=last (or =first).
See this hibernate commit for details.
We can create Pageable object with following Sort parameter:
JpaSort.unsafe(Sort.Direction.ASC, "ISNULL(column_name), (column_name)")
We can prepare HQL as well:
String hql = "FROM EntityName e ORDER BY e.columnName NULLS LAST";
Here's my update to the class by (Pascal Thivent):
for (int i = 0; i < orderByNames.length; i++) {
if (orderByNames[i].trim().length() > 0) {
String orderName = orderByNames[i].trim().toLowerCase();
if (orderName.contains("desc")) {
orderByNames[i] = orderName.replace("desc", "desc NULLS LAST");
} else {
orderByNames[i] = orderName.replace("asc", "asc NULLS FIRST");
}
}
}
This fixes the problem:
This breaks if sql has limit/offset after order by – Sathish Apr 1 '11 at 14:52
Also here's how you can use this within JPA (hibernate):
Session session = entityManager.unwrap(Session.class);
Session nullsSortingProperlySession = null;
try {
// perform a query guaranteeing that nulls will sort last
nullsSortingProperlySession = session.getSessionFactory().withOptions()
.interceptor(new GuaranteeNullsFirstInterceptor())
.openSession();
} finally {
// release the session, or the db connections will spiral
try {
if (nullsSortingProperlySession != null) {
nullsSortingProperlySession.close();
}
} catch (Exception e) {
logger.error("Error closing session", e);
}
}
I've tested this on postgres and it fixes the 'nulls are higher than non-nulls' issue that we were having.
Another variant, if you create SQL on the fly and don't use Criteria API:
ORDER BY COALESCE(,'0') [ASC|DESC]
This works either for varchar or numeric columns.
For future travellers... I solved this by overriding the Hibernate dialect. I needed to add null first for asc and null last for desc by default in CriteriaQuery, which is for some reason not supported. (It's supported in legacy CriteriaAPI)
package io.tolgee.dialects.postgres
import org.hibernate.NullPrecedence
import org.hibernate.dialect.PostgreSQL10Dialect
#Suppress("unused")
class CustomPostgreSQLDialect : PostgreSQL10Dialect() {
override fun renderOrderByElement(expression: String?, collation: String?, order: String?, nulls: NullPrecedence?): String {
if (nulls == NullPrecedence.NONE) {
if (order == "asc") {
return super.renderOrderByElement(expression, collation, order, NullPrecedence.FIRST)
}
if (order == "desc") {
return super.renderOrderByElement(expression, collation, order, NullPrecedence.LAST)
}
}
return super.renderOrderByElement(expression, collation, order, nulls)
}
}
There appears to be a change request/bug ticket open for this

Categories