Sqlite cursor.getCount() crashing app when ran - android

This code seems to crash my app every time it runs but data is stored in the data base and can be extracted anyone know why?
public int getContactsCount() {
String countQuery = "SELECT * FROM " + TABLE_CONTACTS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
cursor.close();
// return count
return cursor.getCount();
}
}

Dude! You closed your cursor!

Once you do cursor.close(), all the resources for cursor are released so you are trying to getCount on something that is not there.

Related

Android Studio SQLite database. unknown error

I am getting an error with the method below.
I would like to do a SELECT WHERE statement.
My goal is to know, if the variable name is already in my database.
The error seems to occur at statement.execute(); It is :-
"Caused By : unknown error (code 0): Queries can be performed using SQLiteDatabase query or rawQuery methods only. "
The program has worked properly many times before but now it does not.
The method is :-
public int count(String name) {
SQLiteDatabase database = getWritableDatabase();
String countQuery = "SELECT * FROM myBD WHERE NAME1 = ?";
SQLiteStatement statement = database.compileStatement(countQuery);
statement.clearBindings();
statement.bindString(1, name);
statement.execute();
//database.close();
SQLiteDatabase db = this.getReadableDatabase();enter code here
Cursor cursor = db.rawQuery(countQuery, null);
int count = cursor.getCount();
cursor.close();
database.close();
return count;
}
You could use the query convenience method e.g. :-
public int count(String name) {
SQLiteDatabase database = getWritableDatabase();
String whereclause = "NAME1=?";
String[] whereargs = new String[]{name};
Cursor cursor = database.query("myBD",null,whereclause,whereargs,null,null,null);
int count = cursor.getCount();
cursor.close();
database.close();
return count;
}
Note the above is in-principle code, it hasn't been checked or run and may therefore contain some errors.
Unknown errors are often related to subsequent lines following a ; the convenience methods enclose arguments and build the SQL on your behalf.
You can also use
database.rawQuery("Your query here");

SQLite db cursor crash

I am using a sqlite DB to store my users location while they are online, but for some reason I am getting this crash report and I don't know what it is or how to fix it.
android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed.
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:138)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
at com.tech.databases.Routes_DB.savedGPSHasEntries(Routes_DB.java:109)
at com.tech.activity.Menu_dashboard.onLocationChanged(Menu_dashboard.java:2602)
at com.google.android.gms.c.b.r.a(Unknown:-1)
at com.google.android.gms.common.api.internal.h.b(Unknown:-1)
at com.google.android.gms.common.api.internal.h$c.handleMessage(Unknown:-1)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6314)
at java.lang.reflect.Method.invoke(Method.java:-2)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)
Every thing I have looked up says that it is caused by not closing my cursor, but on my code I close it every single time:
public boolean savedGPSHasEntries(){
boolean hasEntry = false;
String countQuery = "SELECT * FROM " + TABLE_SAVED_ROUTE;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
int cnt = cursor.getCount();
if (cnt > 0)
hasEntry = true;
// Log.e("Database", "Count: " + cnt);
cursor.close();
return hasEntry;
}
And this is how I query the data:
if (routesDB.savedGPSHasEntries()) {
Log.e(TAG, "DB isn't empty");
}
So I am confused about this error or how to even begin to find out how to fix it.
CursorWindowAllocationException
This exception is thrown when a CursorWindow couldn't be allocated,
most probably due to memory not being available.
You should use
String countQuery = "SELECT count(*) FROM " + TABLE_SAVED_ROUTE;
Make sure, Close your DB also .
DEMO
cursor.close();
db.close();
Try with
String countQuery = "SELECT count(*) FROM " + TABLE_SAVED_ROUTE;
Cursor cursor = db.rawQuery(countQuery, null);
cursor.moveToFirst();
int count = cursor.getInt(0);
if(count>0)
{
}
For more info, See How to get row count in sqlite using Android?

What is the significance of closing the cursor in android sqlite?

While reading the sqlite methods to read a row using a cursor I get to know about that after retrieving the data form the cursor we should close the cursor to avoid any memory leak, but here I have a doubt that in the code below cursor.getCount() is called after closing the cursor? Isn't it wrong to retrieve the data after closing the cursor?
Could anyone can clear this doubt!
Thanks in advance!!
public int getContactsCount() {
String countQuery = "SELECT * FROM " + TABLE_CONTACTS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
cursor.close();
// return count
return cursor.getCount();
}
Here is the source code for SQLiteCursor#close():
#Override
public void close() {
super.close();
synchronized (this) {
mQuery.close();
mDriver.cursorClosed();
}
}
And here is the source code for SQLiteCursor#getCount():
#Override
public int getCount() {
if (mCount == NO_COUNT) {
fillWindow(0);
}
return mCount;
}
As you can see, the row count appears to be stored in a variable mCount, and this value is not reset when the cursor is closed. This might make sense from an efficiency point of view, since it saves the need to clear out state unnecessarily.
So it appears that getting the count after closing the cursor does work, but you probably should not rely upon it because the Javadoc makes no such guarantees, and this behavior could change later on.
Cursor.getCount()
here in your query i think the code is not wrong because the getcount() method just return the number of rows in the cursor and we are not retrieving any data from the cursor

Single value from cursor to int

I can't seem to figure out how I get the result from my select query (which should be one number) into my int min. Found different solution using Google but none worked.
I need the min value in order to check if the score that the current player has is higher than the lowest score in order to get in the highscores.
public int getMin(){
System.out.println("in getmin");
String selectQuery = "SELECT MIN(score) FROM tblscore;";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
int min = "something here to put the result in the int"
cursor.close();
db.close();
return min;
}
You could read the value through a cursor, but for single-valued queries like this, there is helper function in the DatabaseUtils class which makes things simpler:
public int getMin(){
String selectQuery = "SELECT MIN(score) FROM tblscore";
SQLiteDatabase db = this.getReadableDatabase();
try {
return (int)DatabaseUtils.longForQuery(db, selectQuery, null);
} finally {
db.close();
}
}
First you need to point the cursor to the first line:
cursor.moveToFirst();
Then you can use Cursor.getInt to get the value:
int min = cursor.getInt(0);

Update table using rawQuery() method does not work

I tried the following SQLite query:
int idServizo = 150;
String whereClause = id_servizio+" = '"+idServizio+" ' ";
ContentValues cv = new ContentValues();
cv.put("sync", 1);
int r = dbManager.updateTable("myTable", cv, whereClause);
Where fields sync and id_servizio are both integer.
The method updateTable is:
public int updateTable(String table, ContentValues values, String whereClause){
int r = mDb.update(table, values, whereClause, null);
return r;
}
// mDb is SQLiteDatabase object
All this works good.
But if I try this with the rawQuery() method:
public Cursor RawQuery(String sqlQuery, String[] columns){
return mDb.rawQuery(sqlQuery, columns);
}
The table is not updated! even if no error occurs.
int idServizo = 150;
String updateQuery ="UPDATE myTable SET sync = 1 WHERE id_servizio = "+idServizio;
dbManager.RawQuery(updateQuery, null);
Why does this not work?
This is because when a rawQuery is executed cursor is returned. Without the call to cursor.moveToFirst() and cursor.close() the database won't get updated.
int idServizo = 150;
String updateQuery ="UPDATE myTable SET sync = 1 WHERE id_servizio = "+idServizio;
Cursor c= dbManager.rawQuery(updateQuery, null);
c.moveToFirst();
c.close();
I dont know the need to call moveToFirst() but this works fine and the database gets updated.
Problem solved.
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
Can't works because rawQuery runs the provided SQL and returns a Cursor over the result set.
If I want to return a table I have to use rawQuery, otherwise no!
Increase the value of a record in android/sqlite database
You should use db.execSQL() instead db.rawQuery().
Instead of doing this:
Cursor c= dbManager.RawQuery(updateQuery, null);
c.moveToFirst();
c.close();
You just need this:
dbManager.execSQL(updateQuery, null);
----------------------------------------------------------------------------
Posting answer because sometimes many people (like me) not reading comments.
Most popular answer is not correct but Yaqub Ahmad's comment is correct.
Answer from CommonsWare explained in this answer:
rawQuery() is for SQL statements that return a result set. Use
execSQL() for SQL statements, like INSERT, that do not return a result
set.
----------------------------------------------------------------------------
Documentation for execSQL:
public void execSQL (String sql)
Execute a single SQL statement that is NOT a SELECT or any other SQL statement that returns data.
Documentation for rawQuery:
public Cursor rawQuery (String sql,
String[] selectionArgs)
Runs the provided SQL and returns a Cursor over the result set.
Your update call formats the ID as string, while the rawQuery call formats is as number.
Assuming that the ID in the table indeed is a string, use:
String updateQuery = "UPDATE myTable SET sync = 1 WHERE id_servizio = '" + idServizio + "'";

Categories

Resources