SimpleCursorAdapter is being difficult to use - android

I have been stuck at one point from long time, i.e with the use of
SimpleCursorAdapter
as it fails while returning the correct value. I have seen similar many post in SO itself, saying that I should add _id column in the cursor database query, rather I should do
db.rawQuery(String,String)
My code in the onCreate(..) is
HospitalData = new Database(this);
HospitalData.open();
Cursor c = HospitalData.getAllRows_Patient_Db();
startManagingCursor(c);
c.moveToFirst();
//HERE SOME LOOP IS NEEDED FOR TRAVERSING AND PUTTING IN THE LISTVIEW
while(c.isAfterLast() == false)
{
String[] columns = new String[] { c.getString(1), c.getString(2) };
int[] to = new int[] { R.id.room_number_db, R.id.pt_initial_db };
adapter = new SimpleCursorAdapter(this,R.layout.patient_db, c,columns,to);
c.moveToNext();
}
setListAdapter(adapter);
And previously my database accessing code was as follows
public Cursor getAllRows_Patient_Db()
{
return db.query(DATABASE_PATIENT_TABLE, new String[] {KEY_ROWID, KEY_ROOM_NUMBER,
KEY_PATIENT_INITIAL
},
null,
null,
null,
null,
null);
}
where KEY_ROWID is defined as follows
public static final String KEY_ROWID = "_id";
And the error with this is
07-04 22:10:23.301: ERROR/AndroidRuntime(16795): Caused by: java.lang.IllegalArgumentException: column '90' does not exist
07-04 22:10:23.301: ERROR/AndroidRuntime(16795): at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:314)
07-04 22:10:23.301: ERROR/AndroidRuntime(16795): at android.widget.SimpleCursorAdapter.findColumns(SimpleCursorAdapter.java:312)
Here column 90 is not the column id but according to my database is the data stored in cursor.getString(1), but I think here it is trying to search cursor.getString(0) which is the row id.
Later I changed my code as follows
public Cursor getAllRows_Patient_Db()
{
String db_sel = "SELECT id as _id, KEY_ROOM_NUMBER" +
",KEY_PATIENT_INITIAL FROM DATABASE_PATIENT_TABLE";
return db.rawQuery(db_sel,null);
}
But still I am getting error, this time error is different
07-04 21:36:12.510: ERROR/global(9861): Deprecated Thread methods are not supported.
07-04 21:36:12.950: ERROR/AndroidRuntime(9861): FATAL EXCEPTION: main
07-04 21:36:12.950: ERROR/AndroidRuntime(9861): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pro/com.pro.CopyOfFirstScreen}: android.database.sqlite.SQLiteException: no such table: DATABASE_PATIENT_TABLE: , while compiling: SELECT id as _id, KEY_ROOM_NUMBER,KEY_PATIENT_INITIAL FROM DATABASE_PATIENT_TABLE
07-04 21:36:12.950: ERROR/AndroidRuntime(9861): Caused by: android.database.sqlite.SQLiteException: no such table: DATABASE_PATIENT_TABLE: , while compiling: SELECT id as _id, KEY_ROOM_NUMBER,KEY_PATIENT_INITIAL FROM DATABASE_PATIENT_TABLE
I am stuck with it from very long time, please help!!
EDIT : Okay now with you guys help my query statement is correct and thanks for that, I am sorry I am not good in understanding the syntax for database query but I am trying to learn
The working query after changes is
String db_sel = "SELECT _id as _id, room_number" +",patient_initial FROM " + DATABASE_PATIENT_TABLE;
Actually I had to change the declared String with the key values
public static final String KEY_ROWID = "_id";
public static final String KEY_ROOM_NUMBER = "room_number";
public static final String KEY_PATIENT_INITIAL = "patient_initial";
But now I see another problem that is not from the query statement but the way I am accessing or using the simplecursorAdapter
As you can see that my table has 2 rows and 3 columns, Now I want to fetch the data from column 2 and column 3 and put it in my listview.
But after the fix from the query I am getting another error
Originally it was
String[] columns = new String[] {c.getString(1), c.getString(2) };
int[] to = new int[] { R.id.room_number_db, R.id.pt_initial_db };
adapter = new SimpleCursorAdapter(this,R.layout.patient_db, c,columns,to);
c.moveToNext();
setListAdapter(adapter);
And the error was
07-05 21:32:29.228: ERROR/AndroidRuntime(1505): Caused by: java.lang.IllegalArgumentException: column '90' does not exist
07-05 21:32:29.228: ERROR/AndroidRuntime(1505): at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:314)
07-05 21:32:29.228: ERROR/AndroidRuntime(1505): at android.widget.SimpleCursorAdapter.findColumns(SimpleCursorAdapter.java:312)
android.widget.SimpleCursorAdapter.findColumns(SimpleCursorAdapter.java:312)
As you can see it is trying to access the data of first column inspite of accessing the row
After that I made changes in my code
int x = 0;
String[] columns = new String[] { c.getString(0),c.getString(1), c.getString(2) };
int[] to = new int[] { x, R.id.room_number_db, R.id.pt_initial_db };
adapter = new SimpleCursorAdapter(this,R.layout.patient_db, c,columns,to);
c.moveToNext();
setListAdapter(adapter);
This was only a guess in order to find out how differently SimpleCursorAdapter works compared to a normal cursor and the error I get is
07-05 21:34:47.947: ERROR/AndroidRuntime(1966): Caused by: java.lang.IllegalArgumentException: column '1' does not exist
07-05 21:34:47.947: ERROR/AndroidRuntime(1966): at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:314)
I know this question is becoming too long :-( do u suggest me to remove some code from here.

The new error is saying that you don't have the table "DATABASE_PATIENT_TABLE" in your database. From your code that appears to be the Static Field name for the string that contains the name of the table in the database and not the name of the table in the database.
In the code below you need to change "DATABASE_PATIENT_TABLE" to the name of the table in the database.
String db_sel = "SELECT id as _id, KEY_ROOM_NUMBER" +
",KEY_PATIENT_INITIAL FROM DATABASE_PATIENT_TABLE";
Try this and see if it will work:
String db_sel = "SELECT id as _id, KEY_ROOM_NUMBER" +
",KEY_PATIENT_INITIAL FROM" + DATABASE_PATIENT_TABLE;
As for your original error a SimpleCursorAdapter must contain the field of _id. The change you made to the SQL Statment that powers the cursor should fix it but you need to make sure you have the right table name in the SQL statement.
Hope this helps.

Have you read this part of error stack:
android.database.sqlite.SQLiteException: no such table: DATABASE_PATIENT_TABLE:
?
You just have no such table in database. It's not CursorAdapter problem.
Your loop seems completely pointless - just read some java handbook.
Ok, lets start to list some problems in your code:
String[] columns = new String[] { c.getString(1), c.getString(2) };
columns[] should contain columns names not values...
In your while{} loop you are creating dozens(?) of SimpleCursorAdapters while only the last on is passed.
This part of code:
String db_sel = "SELECT id as _id, KEY_ROOM_NUMBER" +
",KEY_PATIENT_INITIAL FROM DATABASE_PATIENT_TABLE";
is obviously wrong. I assume that you have something like
private static String DATABASE_PATIENT_TABLE = "patient";
so just use those constants:
String db_sel = "select id as _id, +"KEY_ROOM_NUMBER+", "+ KEY_PATIENT_INITIAL +" from "+DATABASE_PATIENT_TABLE;
Replace that:
String[] columns = new String[] { c.getString(0),c.getString(1), c.getString(2) };
int[] to = new int[] { x, R.id.room_number_db, R.id.pt_initial_db };
With that:
String[] columns = new String[] { c.getColumnName(1), c.getColumnName(2) };
int[] to = new int[] {R.id.room_number_db, R.id.pt_initial_db };

The problem is fixed, the main thing is that I should make sure I always query for the _id with each query to the database, but if I do it with cursor.getString(someIndex) then this gets misleaded as the adapter in my case is taking the content of first column as the rowid and is trying to search the row.
Nether doing rawQuery(),or using "Select _id as _id" stuffs are mandatory. these things are sometime misleading as I felt.
So keeping things simple below is the code.
Database code
public Cursor getAllRows_Patient_Db()
{
return db.query(DATABASE_PATIENT_TABLE, new String[] {
KEY_ROWID,
KEY_ROOM_NUMBER,
KEY_PATIENT_INITIAL
},
null,
null,
null,
null,
null);
}
Activity Code
HospitalData = new Database(this);
HospitalData.open();
Cursor c = HospitalData.getAllRows_Patient_Db();
startManagingCursor(c);
String[] columns = new String[] {HospitalData.KEY_ROOM_NUMBER,HospitalData.KEY_PATIENT_INITIAL };
int[] to = new int[] { R.id.room_number_db, R.id.pt_initial_db };
adapter = new SimpleCursorAdapter(this,R.layout.patient_db, c,columns,to);
c.moveToNext();
setListAdapter(adapter);

Related

Why Sqlite return only last row not all rows data?

I don't know what's wrong with my code I follow the rule but I get wrong result. I want to search db and find all rows data but I only get last row from sqlite. my code to search database is bellow:
public ArrayList<ArrayList<ContractSaveDataFromDB>> ActiveContractData(String phone, String numberId)
{
ArrayList<ContractSaveDataFromDB> UserData = new ArrayList<ContractSaveDataFromDB>();
ArrayList<ArrayList<ContractSaveDataFromDB>> SendUserData =
new ArrayList<ArrayList<ContractSaveDataFromDB>>();
SQLiteDatabase db = this.getReadableDatabase();
String whereClause = "phone = ? AND numberId = ?";
String[] whereArgs = new String[]{
phone,
numberId
};
String orderBy = "activeContract";
Cursor res2=db.query("usersAccount",null,whereClause,whereArgs,null,null,orderBy);
res2.moveToFirst();
do{
UserData.clear();
int index;
ContractSaveDataFromDB contractSaveDataFromDB=new ContractSaveDataFromDB();
index = res2.getColumnIndex("buyAmount");
String buyAmount = res2.getString(index);
contractSaveDataFromDB.setBuyAmount(buyAmount);
UserData.add(contractSaveDataFromDB);
SendUserData.add(UserData);
} while(res2.moveToNext());
res2.close();
db.close();
return SendUserData;
I don't know what's wrong. I appreciate if you help me to solve my problem.
you already added where clause so maybe it is filtering your results try to remove it by change this
Cursor res2=db.query("usersAccount",null,whereClause,whereArgs,null,null,orderBy);
to this
Cursor res2=db.query("usersAccount",null,null,null,null,null,orderBy);
I believe that your issues is that you are trying to use an ArrayList of ArrayList of ContractSaveDataFromDB objects.
I believe that an ArrayList of ContractSaveDataFromDB objects would suffice.
It would also help you if you learnt to do a bit of basic debugging, as an issue could be that you are not extracting multiple rows.
The following is an alternative method that :-
uses the ArrayList of ContractSaveDataFromDB objects,
introduces some debugging by the way of writing some potentially useful information to the log
and is more sound, as it will not crash if no rows are extracted
i.e. if you use moveToFirst and don't check the result (false means the move could not be accomplished) then you would get an error because you are trying to read row -1 (before the first row) as no rows exists in the cursor.
:-
public ArrayList<ContractSaveDataFromDB> ActiveContractData(String phone, String numberId) {
ArrayList<ContractSaveDataFromDB> SendUserData = new ArrayList<ContractSaveDataFromDB>();
SQLiteDatabase db = this.getReadableDatabase();
String whereClause = "phone = ? AND numberId = ?";
String[] whereArgs = new String[]{
phone,
numberId
};
String orderBy = "activeContract";
Cursor res2 = db.query("usersAccount", null, whereClause, whereArgs, null, null, orderBy);
Log.d("RES2 COUNT", "Number of rows in Res2 Cursor is " + String.valueOf(res2.getCount()));
while (res2.moveToNext()) {
ContractSaveDataFromDB current_user_data = new ContractSaveDataFromDB();
current_user_data.setBuyAmount(res2.getString(res2.getColumnIndex("buyAmount")));
Log.d("NEWROW", "Adding data from row " + String.valueOf(res2.getPosition()));
SendUserData.add(current_user_data);
}
res2.close();
db.close();
Log.d("EXTRACTED", "The number of rows from which data was extracted was " + String.valueOf(SendUserData.size()));
return SendUserData;
}
If after running you check the log you should see :-
A line detailing how many rows were extracted from the table
A line for each row (if any were extracted) saying Adding data from row ? (where ? will be the row 0 being the first)
A line saying The number of rows from which data was extracted was ? (? will be the number of elements in the array to be returned)

Complex queries with SQLite in Android

I have a table with 3 columns "ID", "NAME" & "STATUS". I would like to execute a query on my database where I can get only one entry of "ID" which is located at the top row. I have a working sql query,
"SELECT TOP 1 ID from SAMPLE_TABLE WHERE Status='PENDING' ORDER BY ID ASC;"
This is so far what I implemented in android,
// Getting pending items
public int pendingContact() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor mCount = db.query(
TABLE_CONTACTS ,
new String[] { "id" } ,
"status = ?" ,
new String[] { "PENDING" } ,
null ,
null ,
null
);
mCount.moveToFirst();
int count = mCount.getInt(0);
mCount.close();
return count;
}
Al through it gives the desired output but I would like to know if there is any other way of doing this more efficiently.
You can use Limit
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
limit - Limits the number of rows returned by the query, formatted as LIMIT clause. Passing null denotes no LIMIT clause.
You can do this:
Cursor mCount = db.query(TABLE_CONTACTS, new String[] { "id" }, "status = ?", new String[] { "PENDING" }, null, null, "id ASC", "1");
This will keep you from acquiring more data than you need.
When you use ORDER BY, the database will read and sort all PENDING items before it can return the first one.
When using MIN, nothing but the smallest value must be stored temporarily:
SELECT MIN(id) FROM Contacts WHERE Status = 'PENDING'
In code:
Cursor mCount = db.rawQuery("SELECT MIN(id) FROM Contacts WHERE Status = ?",
new String[] { "PENDING" });

Simple Cursor Adapter Throw Exception illegal Argument exception?

My Cursor
Cursor c= db.query(DBHelper.EXAM_DATA,new String [] {DBHelper.EXAM,DBHelper.FILE}, null,null, null, null, null);
Loop for the Cursor
c.moveToFirst();
do
{
name = c.getString(0);
file = c.getString(1);
Toast.makeText(this, name + " "+file ,Toast.LENGTH_LONG).show();
adapter = new SimpleCursorAdapter(this, R.layout.row_reasoning, c, new String [] {file}, new int [] {R.id.txtList});
LvReasoning.setAdapter(adapter);
}while(c.moveToNext());
Logcat Showing This Error
01-20 16:33:55.154: E/AndroidRuntime(2426): FATAL EXCEPTION: main
01-20 16:33:55.154: E/AndroidRuntime(2426): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.androidhive.xmlparsing/com.androidhive.xmlparsing.ListReasoning}: java.lang.IllegalArgumentException: column '_id' does not exist
My Table have _id Column but I do not know how to solve this error
c.moveToFirst();
do
{
name = c.getString(0);
file = c.getString(1);
Toast.makeText(this, name + " "+file ,Toast.LENGTH_LONG).show();
adapter = new SimpleCursorAdapter(this, R.layout.row_reasoning, c, new String [] {DBHelper.FILE}, new int [] {R.id.txtList});
}while(c.moveToNext());
LvReasoning.setAdapter(adapter);
I used this and This is Working. I have passed DBHelper table field name and its Work Fine.. But I really dont know Why that code not worked...
The cursor given to a SimpleCursorAdapter must contain a column named _id. The fact that it exists in the table is not enough, you have to select it so include it in the list of columns returned:
Cursor c= db.query(DBHelper.EXAM_DATA,new String [] {"_id", DBHelper.EXAM, DBHelper.FILE}, null,null, null, null, null);
You also only need to instantiate and set the adapter once. Move these statements outside of the while loop (you can remove the loop entirely if you don't need to toast the contents of each cursor row):
adapter = new SimpleCursorAdapter(this, R.layout.row_reasoning, c, new String [] {file}, new int [] {R.id.txtList});
LvReasoning.setAdapter(adapter);
For each cursor row, the adapter will then map the value of column 'file' to R.id.txtList within R.layout.row_reasoning.

Android SQLite column _id error ,

I am trying to Query in the database.The database is not created in the app, I have created outside, and I am using as this tutorial explain. But I have an error related with column _id.
In the Class DatabaseHelper, I have the following code:
public Cursor Search(Context context,String search){
SQLiteDatabase db= getReadableDatabase();
String cursorFactory = "SELECT * FROM words WHERE eng || ' ' || rus LIKE ?";
Cursor cursor = db.rawQuery(cursorFactory, new String[]{"%" + search + "%"});
return cursor;
}
In the Activity, the code I wrote is:
public void search(View v){
text2search= searchText.getText().toString();
cursor= myDbHelper.Search(mContext, text2search);
adapter =new SimpleCursorAdapter(getBaseContext(),R.layout.list_item,
cursor,
new String[]{"rusword","engword","kind"},
new int[]{R.id.rusWord,R.id.engWord,R.id.knd});
wordsList.setAdapter(adapter);
}
And I get the error related with the _id:(in the LogCat)
09-03 14:12:38.018: E/AndroidRuntime(16581): Caused by:
java.lang.IllegalArgumentException: column '_id' does not exist
But the data base, that I create, it has the "_id" column:( I cant upload image, so here is the link https://www.dropbox.com/s/9a2ol1acrnxmzob/sql-db-rusWjpg.png )
Thank you!
So problem isn't too tricky. Some adapters, in you case SimpleCursorAdapter this adapter needs when are try to select something you need to select column _id.
So try this:
new String[] {"_id", "rusword", "engword", "kind"}
String cursorFactory = "SELECT _id, [next columns] FROM ...;
now it should works.
Similar question is here:
App Crashes On Startup Due To java.lang.IllegalArgumentException:
column '_id' does not
exist
Note: In the case you don't want to have _id column you can use this simple trick:
SELECT keyID AS _id FROM TableName

Help with SimpleCursorAdapter and Listview

I am stuck with SimpleCursorAdapter, I am calling my local SQLite DB and putting it into a cursor which then is passed to the SimpleCursorAdapter.
For same reason the Log Cat keeps showing this error below. I have no idea what is going on and I have been working on this for 6 hours, I didn't think SimpleCursorAdapter would be so difficult to understand.
05-28 19:47:27.524: ERROR/AndroidRuntime(9353): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nyneaxis.android.mpg/com.nyneaxis.android.mpg.userInfo}: java.lang.IllegalArgumentException: column '_id' does not exist
setArray();
rec.open();
Cursor c = rec.getAllVeh();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.userinfo, c, new String[]{c.getString(1)}, new int[]{R.id.nameTxtL});
this.setListAdapter(adapter);
rec.close();
//data adapter
public Cursor getAllVeh() {
try{
return db.query(database_table, new String[] { key_rowid, vehicle_name,
year, make, model, style, vin, plate, notes }, null, null,
null, null, null);
}finally{
}
}
Okay I have modified my code to a rawQuery and I get this error again:
05-28 22:41:48.876: ERROR/AndroidRuntime(1359): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nyneaxis.android.mpg/com.nyneaxis.android.mpg.userInfo}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
private static final String db_sel = "SELECT id as _id, vehicle_name FROM vehicle";
public Cursor getAllVeh() {
try{
return db.rawQuery(db_sel, null);
/*return db.query(database_table, new String[] { key_rowid, vehicle_name,
year, make, model, style, vin, plate, notes }, null, null,
null, null, null);*/
}finally{
}
}
See my answer to this question Android: column '_id' does not exist problem. It explains about the need for the _id column and how to alias it if your DB tables don't have a column with that name.
****EDIT:**** To alias the column in the DB which contains 'unique identifiers' you need to use db.rawQuery(...) instead of db.query(...). The db.rawQuery(...) method takes a SQL string which will allow you to alias the column name to '_id' which is required by the adapter. Example...
Cursor c = db.rawQuery("SELECT <my_unique_column_name> as _id, vehicle_name, ... FROM vehicles");
In the above, replace <my_unique_column_name> with the actual name of the column in the vehicles table which contains unique identifiers. Also, use the actual column names for any other columns that you're requesting the data for.
Well, as the error says your database table definition is missing the default _id column that SimpleCursorAdapter expects to use as the ID column. What is your database table defined as? Add the CREATE TABLE statement you are using to your question.
SimpleCursorAdapter relies on the presence of an _id column: if you don't have it then you'll get that error.
Thanks guys for all you help. I managed to do it a different way and it seems to work like a charm. If anyone has any question or suggestions let me know.
Cursor c = rec.getAllVeh();
while (c.moveToNext()) {
String vehName = c.getString(1);
vehInfo.add(vehName);
}
//put information into the addapter for listview
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice, vehInfo);
//applies adapter to listview
list.setAdapter(adapter);

Categories

Resources