Return Count(*) in Android SQLite table - java

Here is my simple function:
public int countCats(String tableName) {
int catCount = 0;
Cursor cursor = database.rawQuery("SELECT COUNT(*) FROM " + MySQLiteHelper.TABLE_CAT, null);
if (cursor != null) {
catCount = cursor.getColumnIndex("COUNT");
}
return catCount;
}
There are 11 rows int this table. But this function returns -1. How is appropriate way to handle this?
EDIT:
I have updated to this:
public int countCats(String tableName) {
int catCount = 0;
Cursor cursor = database.rawQuery("SELECT COUNT("+ MySQLiteHelper.COLUMN_CAT+ ") FROM " + MySQLiteHelper.TABLE_CAT, null);
if (cursor.moveToFirst()) {
catCount = cursor.getInt(0);
}
cursor.close();
return catCount;
}
Now I get 0;

You're only asking for the column index for a column COUNT that does not exist in the cursor. Hence -1 is returned.
To retrieve the count value, move the cursor to the first row and get the first column value:
if (cursor.moveToFirst()) {
catCount = cursor.getInt(0);
}
(A COUNT(*) query will always have a result row but it's a good habit to check the result of moveToFirst() anyway.)

You forget to call
cursor.moveToFirst();

You are just looking for the index of the result and not the value itself.
So now you know that the value you like to know is in the first column. Now you have to go to the first row and take that value.
cursor.moveToFirst();
int count=cursor.getInt(1);

Related

IndexOutOfBoundException when i pass arraylist to DBHelper to update database (Android SQlite)

I am new at android and trying to make managing members app with database. what i want to do here is that when user buys any drink it should change drinks name to "bought" in database, but when i pass Arraylist to db class it shows that my Arraylist is empty.
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at com.shashank.managemembers.DB_Controller.update_available(DB_Controller.java:88)
at com.shashank.managemembers.TempActivity$2.onClick(TempActivity.java:90)
userInputActivity
here user selects drink he/she wants and when he presses done button it should change database with drinks name.
And I'm checking it with Toast message that ArrayList is not empty. Toast message always appears with user's choice but db class throws error.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(TempActivity.this, selectedInListView.get(0), Toast.LENGTH_SHORT).show();
dbController.update_available(code, selectedInListView);
onBackPressed();
}
});
here selectedInListView has many items when i am passing it to dbController.update_available.
dbController.java
here I have 9 columns in db starting from DRINK1 to DRINK9.
public void update_available(String memberCode, ArrayList<String> BoughtDrinks) {
Cursor cursor = this.getReadableDatabase().rawQuery("SELECT * FROM MEMBERS WHERE MEMBERCODE = '" + memberCode + "'", null);
int count = cursor.getColumnCount();
while (cursor.moveToNext()) {
for (int i = 5; i < count; i++) {
if (!cursor.getString(i).contains(BoughtDrinks.get(0))) {
this.getReadableDatabase().execSQL("UPDATE MEMBERS SET DRINK"+ i +"='Bought' WHERE DRINK" + i +"='" + BoughtDrinks.get(0) + "'" + "AND MEMBERCODE='" + memberCode + "'");
if(BoughtDrinks.size() > 0 ){
BoughtDrinks.remove(0);
}
}
}
}
cursor.close();
}
I am not understanding why it is throwing an error when I'm passing ArrayList with elements.
You got this error because ,if BoughtDrinks.size()>0 ,your code remove item at 0 then for loop get item at 0.So when you try to get item at 0 after you removed all the item ,you will get index IndexOutOfBoundsException.to avoid that just add if() condition.
public void update_available(String memberCode, ArrayList<String> BoughtDrinks) {
Cursor cursor = this.getReadableDatabase().rawQuery("SELECT * FROM MEMBERS WHERE MEMBERCODE = '" + memberCode + "'", null);
int count = cursor.getColumnCount();
while (cursor.moveToNext()) {
for (int i = 5; i < count; i++) {
if ( BoughtDrinks.size()>0 && !cursor.getString(i).contains(BoughtDrinks.get(0))) {
this.getReadableDatabase().execSQL("UPDATE MEMBERS SET DRINK"+ i +"='Bought' WHERE DRINK" + i +"='" + BoughtDrinks.get(0) + "'" + "AND MEMBERCODE='" + memberCode + "'");
if(BoughtDrinks.size() > 0 ){
BoughtDrinks.remove(0);
}
}
}
}
cursor.close();
}

How can I check that a SQL query has no result?

As written in the title, I check my SQL database with following method:
public String[] getRecord(String category){
String[] record = new String[3];
Cursor crsRecord = sqliteDatabase.rawQuery(QUERY_GET_RECORD + category, null);
int i=0;
while(crsRecord.moveToNext()){
record[i] = crsRecord.getString(0);
i++;
}
return record;
}
Now it could be that the line:
Cursor crsRecord = sqliteDatabase.rawQuery(QUERY_GET_RECORD + category, null);
has no result, because I have no appropriate data in my database. How can I check that I have no result?
cursor.moveToFirst();
if (cursor.isAfterLast()){
// You have no results
}
Or, you could just change your code to this:
while(!crsRecord.isAfterLast()){
// Instead of using an int literal to get the colum index,
// use the getColumnIndex method
int index = crsRecord.getColumnIndex(COLUMN_NAME);
if (index == -1) {
// You don't have the column-- do whatever you need to do.
}
else {
record[i] = crsRecord.getString(index);
i++;
}
crsRecord.moveToNext();
}
If there are no records, the while loop never starts.

NullPointerException while counting the number of rows using COUNT() in SQLite helper

I am getting NullPointerException whle performing COUNT() in SQLite. please see the following code -
public int getrcofpersons() {
// TODO Auto-generated method stub
SQLiteDatabase myDB;
int values = 0;
int count = 0;
try {
myDB=this.openDataBase();
Cursor c=myDB.rawQuery("select count(PersonID) from Persons;",null);
if (c != null ) {
String h = "";
c.moveToFirst();
count = c.getInt(c.getColumnIndex("PersonID"));
// put your code to get data from cursor
}
if(c != null) {
c.close();
myDB.close();
}
} catch(SQLException sqle) {
throw sqle;
}
System.out.println(count + " is the rowcount of persons.");
return count;
}
This function is returning Null value. Even System.out.println(count + " is the rowcount of persons."); also showing the count value as 0, which is the initialized value. Now I cannot post the logcat, because this code snippet is associated with many other functionalities, that you might not understand. So, please, tell me if I did any mistake in this code.
Please see the following code. This code is calling the above method(which is in the helper.java).
adapter.java :
public int getrowcountofpersons() {
// TODO Auto-generated method stub
int rc = 0;
try {
//open();
rc = mDbHelper.getrcofpersons(); //Here the nullPointerException is raised.
// close();
}
catch (Exception e)
{Log.v("getrowcountofpersons()","5");
Log.v("Error in getrowcountofpersons() of adapter : ",e.toString());
}
Log.v("getrowcountofpersons()","6");
System.out.println(rc + " is the rowcount of persons in adapter.");
return rc;
}
Thanks in advance.
Change
count = c.getInt(c.getColumnIndex("PersonID"));
to
count = c.getInt(0);
There is no column name PersonID into your Cursor object c. And this will have only one column so you can retrieve that column using 0 (ZERO) index.
After code update :-
Check if mDbHelper is null or not. This might be null. So check if you are initiating the mDbHelper object.

Sorting SQLite table with "ORDER BY" - Android

I have a SQLite db for my highscores table. Currently I am having trouble checking if the new score makes the highscores and also sorting the highscores table.
When the game is over, Results.java is called.
Results.java
total_score = dh.calculateTotalScore(score, percentage);
low_score = dh.check(score, percentage, total_score);
if(total_score > low_score) {
dh.delete(10);
dh.insert(score, percentage, total_score);
} else {
dh.insert(score, percentage, 9999999);
}
dh.sort();
All the methods being called in Results.java are coming from DatabaseHelper.java.
DatabaseHelper.java
public void sort() {
db.rawQuery("SELECT * FROM " + DB_TABLE + " ORDER BY " + TOTAL_SCORE, null);
}
public long calculateTotalScore(long score, int percentage) {
long i;
return i = (percentage * 1000) + score;
}
public long check(long score, int percentage, long sum) {
Cursor c = db.rawQuery("SELECT " + TOTAL_SCORE + " FROM " + DB_TABLE, null);
long count = c.getCount();
long low_score;
if(count == 10) {
c.moveToLast();
low_score = c.getInt(c.getColumnIndex(TOTAL_SCORE));
return low_score;
} else {
return count;
}
}
public long insert(long score, int percentage, long total_score) {
ContentValues values = new ContentValues();
values.put(SCORE, score);
values.put(PERCENTAGE, percentage);
values.put(TOTAL_SCORE, total_score);
return db.insert(DB_TABLE, null, values);
}
public void delete(int row) {
db.delete(DB_TABLE, RANK + "=" + row, null);
}
The output for TOTAL_SCORE is being displayed as follows:
1
2
40851
1
2
40804
60811
60811
50816
What I desire is for the output to be in numerical order. Like this:
1
1
2
2
40804
40851
50816
60811
60811
The order they are in above is (I think) just the order they were inserted into the db. No errors happen when the program runs and the program does not crash. More code can be provided if needed.
SELECT does not modify anything; your sort function has no effect.
(The rawQuery function returns the sorted list of records, but you ignore it.)
You have to put the ORDER BY clause into the query that is used to display the scores.

Can I make SQLiteDatabase complain about missing parameters?

Recently, I've had a few bugs because of code like this:
Cursor myCursor = myDb.rawQuery(
"SELECT ... " +
" FROM ...complicated join... " +
" WHERE field1 = ? AND (field2 = ? OR field3 = ?) ",
new String[] {myField1, myField2}); // Oops, forgot about field3
When this happens, the query just silently ignores the missing parameter, causing bugs to go unnoticed. Is there some pedantic setting or anything else that I can use to make SQLite scream (at run-time) when the number of placeholders and the number of fields do not match?
I know that I could build my own wrapper, but I'm wondering if there's something built-in...
Android is basically just passing the args unchecked to native sqlite, see http://www.sqlite.org/c3ref/bind_blob.html
If something is not bound it is simply considered to be bound to NULL. Binding too much should result in an error though
I don't know of / have not seen any debug option in Android's source for that kind of checks but you could probably write some code that checks your sql syntax:
SQLiteChecker mDbChecked = new SQLiteChecker(mDb);
Cursor c = mDbChecked.rawQuery("select complicated from table where stuff=?",
new String[] {"one", "two"});
where SQLiteChecker would be something along the lines of
/**
* Simple Delegate for SQLiteDatabase
*/
public class SQLiteChecker {
private final SQLiteDatabase mDbDelegate;
public SQLiteChecker(SQLiteDatabase db) {
mDbDelegate = db;
}
// ------------ Delegate methods --------------------//
public int delete(String table, String whereClause, String[] whereArgs) {
checkSQL(whereClause, whereArgs);
return mDbDelegate.delete(table, whereClause, whereArgs);
}
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
checkSQL(whereClause, whereArgs);
return mDbDelegate.update(table, values, whereClause, whereArgs);
}
public void execSQL(String sql, Object[] bindArgs) throws SQLException {
checkSQL(sql, bindArgs);
mDbDelegate.execSQL(sql, bindArgs);
}
public Cursor rawQuery(String sql, String[] selectionArgs) {
checkSQL(sql, selectionArgs);
return mDbDelegate.rawQuery(sql, selectionArgs);
}
// add more if you need
// -------------- checking logic -------------------//
private static void checkSQL(String query, Object[] args) {
// bit unreliable but simple:
// just check if amount of ? matches args.length
int expected = countChar(query, '?');
int actual = args != null ? args.length : 0;
if (expected != actual) {
Log.e("CHECK", "You seem to have messed up [" + query + "]");
Log.e("CHECK", "expected:" + expected + " actual:" + actual);
}
}
private static int countChar(String string, char ch) {
if (string == null) return 0;
int count = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == ch)
count++;
}
return count;
}
}

Categories

Resources