index out of bound exception with sqlite database - android

I try to implement the following code
In the activity.java file
DatabaseEvent mDbHelper = new DatabaseEvent(getApplicationContext());
mDbHelper.open();
Cursor notesCursor = mDbHelper.fetchEvent();
startManagingCursor(notesCursor);
String[] from = new String[]{DatabaseEvent.KEY_ETITLE, DatabaseEvent.KEY_DISTANCE, DatabaseEvent.KEY_IMGNAME, DatabaseEvent.KEY_DESCRIPTION, DatabaseEvent.KEY_EID};
int[] to = new int[]{R.id.title, R.id.duration, R.id.list_image, R.id.artist, R.id.id};
SimpleCursorAdapter event =
new SimpleCursorAdapter(getApplicationContext(), R.layout.list_row, notesCursor, from, to);
In the DatabaseEvent.java
public long createEvent(String title, String distance, String imgname, String description, String eid) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_ETITLE, title);
initialValues.put(KEY_DISTANCE, distance);
initialValues.put(KEY_IMGNAME, imgname);
initialValues.put(KEY_DESCRIPTION, description);
initialValues.put(KEY_EID, eid);
Log.v("INFO1","inserting db");
return mDb.insert(EVENT_TABLE, null, initialValues);
}
public Cursor fetchEvent() {
Log.v("INFO1","fetching db");
Cursor mCursor = mDb.query(EVENT_TABLE, new String[] {KEY_ROWID, KEY_ETITLE, KEY_DISTANCE,
KEY_IMGNAME, KEY_DESCRIPTION, KEY_EID}, null, null,null,null, KEY_DISTANCE+" ASC");
return mCursor;
}
On the logcat, I can clearly see that the log message "inserting db" is printed three times mean the data date really added to the database, but the log message "fetching db" printed once and give me the flowing error says:
CursorIndexOutOfBoundException index -1, requsted, with a size of 60,
I tried different function like moveToFirst() and moveToNext() but still couldn't solve the problem, any one could give me hand, any help will be greately appreciated!

you forgot to include mCursor.moveToFirst();
Change your code to
public Cursor fetchEvent() {
Log.v("INFO1","fetching db");
Cursor mCursor = mDb.query(EVENT_TABLE, new String[] {KEY_ROWID, KEY_ETITLE, KEY_DISTANCE,
KEY_IMGNAME, KEY_DESCRIPTION, KEY_EID}, null, null,null,null, KEY_DISTANCE+" ASC");
mCursor.moveToFirst();
return mCursor;
}

Related

Getting multiple entries for SELECT DISTINCT sqlite android?

I am trying to get the unique column name and show it as a list adapter.
public String[] getAllUsers() {
String[] contactList = new String[100];
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.query(true,TABLE_TRANS, new String[] { KEY_ID ,KEY_NAME, KEY_CASH,KEY_DESC,KEY_DATE }, null, null, KEY_NAME, null, null, null);
int i=0;
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
contactList[i] = cursor.getString(1);
i++;
} while (cursor.moveToNext());
}
// return contact list
return contactList;
}
The above is method in my database class.
And from mainActivity I call this method
private void updateUserList() {
// TODO Auto-generated method stub
String[] contactList = new String[100];
contactList = db.getAllUsers();
Log.d("User List",contactList[0]);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, contactList);
setListAdapter(adapter);
}
The list is getting updated ,but list is getting repeated as a whole
I don't know if I fully understood your question.
If you want to get columns KEY_ID ,KEY_NAME, KEY_CASH,KEY_DESC,KEY_DATE from all rows in database without KEY_NAME repetitions use this query:
Cursor cursor = db.query(true,TABLE_TRANS,
new String[] { KEY_ID ,KEY_NAME, KEY_CASH,KEY_DESC,KEY_DATE },
null, null, null, null, null, null);
In your methods do not use Array instead use ArrayList<String>
public ArrayList<String> getAllUsers() {
ArrayList<String> contactList = new ArrayList<String>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.query(true,TABLE_TRANS,
new String[] { KEY_ID ,KEY_NAME, KEY_CASH,KEY_DESC,KEY_DATE },
null, null, null, null, null, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
contactList.add(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
} while (cursor.moveToNext());
}
// return contact list
return contactList;
}
And updateUserList():
private void updateUserList() {
// TODO Auto-generated method stub
ArrayList<String> contactList;
contactList = db.getAllUsers();
Log.d("User List", contactList.get(0));
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, contactList);
setListAdapter(adapter);
}
As you only use the column KEY_NAME from cursor the query can be simplified to return only that column.
Cursor cursor = db.query(true,TABLE_TRANS,
new String[] {KEY_NAME}, null, null, null, null, null, null);
The problem was with initializing the String array as 100. I wrote a method to get the total number of counts and it works fine.
public int getUsersCount() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(true,TABLE_TRANS, new String[] { KEY_ID ,KEY_NAME, KEY_CASH,KEY_DESC,KEY_DATE }, null, null, KEY_NAME, null, null, null);
//cursor.close();
// return count
return cursor.getCount();}

Concatenate 2 columns Android SQLite

So far I have this:
Cursor cursor = dbHelper.getAllPatients();
String[] data = new String[]{DBHelper.KEY_LNAME,
DBHelper.KEY_FNAME, DBHelper.KEY_DIAGNOSIS};
int[] to = new int[] {R.id.fullname, R.id.diagnosis};
dataAdapter = new SimpleCursorAdapter(this, R.layout.custom_row, cursor, data, to, 0);
dbHelper.close();
lv.setAdapter(dataAdapter);
lv.setTextFilterEnabled(true);
getAllPatients() method
public Cursor getAllPatients()
{
Cursor localCursor =
this.myDataBase.query(DB_TABLE, new String[] {
KEY_ID, KEY_FNAME, KEY_LNAME, KEY_DIAGNOSIS }, null, null, null, null, null);
if (localCursor != null)
localCursor.moveToFirst();
return localCursor;
}
I want the columns FNAME, and LNAME to be as one but I'm confused how and where to put the concatenate operator + in the String array. Do you have any idea to do this? I would gladly appreciate your help. Thanks.
Do the following when you query
Cursor localCursor =
this.myDataBase.query(DB_TABLE, new String[] {
KEY_ID, KEY_FNAME +"||"+ KEY_LNAME, KEY_DIAGNOSIS }, null, null, null, null, null);
And while assigning values using your adapter do as follows,
String[] data = new String[]{DBHelper.KEY_LNAME +"||"+ DBHelper.KEY_FNAME, DBHelper.KEY_DIAGNOSIS};
int[] to = new int[] {R.id.fullname, R.id.diagnosis};
try this
SELECT CONCAT(ColA, ColB) AS ColC FROM Table
or
String query = "select" +ColA+"+"+ColB +"as CompleteAddress from YourTable";

SQLite, getting last item in table

I need some help with using the database that I created. I need to access the last item in the database. This is my code that gets a single item. How can I change it to only get the last?
// Getting single user
User getuser(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_USER, new String[] { KEY_ID,
KEY_NAME, KEY_AGE, KEY_WEIGHT, KEY_HEIGHT,
KEY_GOAL, KEY_BMI }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if(cursor!=null && cursor.getCount()!=0){
cursor.moveToFirst();
}
User user = new User(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getInt(2),cursor.getInt(3), cursor.getInt(4),
cursor.getString(5), cursor.getFloat(6));
return user;
}
Cursor cursor = db.query(TABLE_USER, new String[] { KEY_ID,
KEY_NAME, KEY_AGE, KEY_WEIGHT, KEY_HEIGHT,
KEY_GOAL, KEY_BMI }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, KEY_ID + " DESC", "LIMIT 1");
if the id uniquely identifies the user then you will be getting only one row as the result for the id you are passing so you dont have to worry about it is the last or first in the database. if it is just that you want the last row in your database then you dont have to pass an id you can do a select * and after retrieving move the cursor to last ie cursor.moveToLast().
Do this if you just want the last row
User getuser() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_USER, new String[] { KEY_ID,
KEY_NAME, KEY_AGE, KEY_WEIGHT, KEY_HEIGHT,
KEY_GOAL, KEY_BMI }, null,
null, null, null, null, null);
if(cursor!=null && cursor.getCount()!=0){
cursor.moveToLast();
}
User user = new User(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getInt(2),cursor.getInt(3), cursor.getInt(4),
cursor.getString(5), cursor.getFloat(6));
return user;
}
and your call can be like this
User currentUser = db.getUser();
If you are passing an id to get a user details an the id uniquely identifies the user then what you have done will work
Are you perhaps looking for cursor.moveToLast()? This will move the cursor to the last record selected from your query. You can then get the fields values as usual using cursor.getString(n) etc.
You simply need to change a little in your code,
// Getting single user
User getuser(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_USER, new String[] { KEY_ID,
KEY_NAME, KEY_AGE, KEY_WEIGHT, KEY_HEIGHT,
KEY_GOAL, KEY_BMI }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if(cursor!=null && cursor.getCount()!=0){
cursor.moveToLast(); // Change here
}
User user = new User(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getInt(2),cursor.getInt(3), cursor.getInt(4),
cursor.getString(5), cursor.getFloat(6));
return user;
}
Try this one:
Cursor c = db.rawquery("Select *from tablename");
c.movetoLast();
and if you want to get the data from last to first use this codes:
Cursor c = db.rawquery("Select *from tablename");
c.movetoLast();
int count = c.getCount();
for(int i = 0; i < count; i++){
c.movetoPrevious();
}

Android SQLite get data from database to an array

i want to get the value from the cursor without the SimpleCursorAdapter part.here is the code
public Cursor queueAll(){
String[] columns = new String[]{KEY_ID, KEY_CONTENT1, KEY_CONTENT2,KEY_CONTENT3};
Cursor cursor = sqLiteDatabase.query(MYDATABASE_TABLE, columns,
null, null, null, null, null);
return cursor;
}
and the activity side code
cursor = mySQLiteAdapter.queueAll();
from = new String[]{SQLiteAdapter.KEY_ID, SQLiteAdapter.KEY_CONTENT1, SQLiteAdapter.KEY_CONTENT2, SQLiteAdapter.KEY_CONTENT3};
int[] to = new int[]{R.id.id, R.id.text1, R.id.text2,R.id.text3};
cursorAdapter =
new SimpleCursorAdapter(this, R.layout.row, cursor, from, to);
listContent.setAdapter(cursorAdapter);
while(!cursor.isAfterLast())
{
String tilt = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_CONTENT1));
String pkg = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_CONTENT3));
if(tilt.equals("LEFT"))
{
Log.v("LEFT",pkg);
}
else if(tilt.equals("RIGHT"))
{
Log.v("RIGHT",pkg);
}
cursor.moveToNext();
}
i am getting the pkg value correct.but i want to get the values directly from the cursor while removing SimpleCursorAdapter part the code doesn't work.
any help would be appreciated :)
You can get values without declaring adapters. Adapters are need if you want to show the data in the list widgets. So your can be the following:
cursor = mySQLiteAdapter.queueAll();
if (cursor == null) {
//check if there are errors or query just return null
}
if (cursor.moveToFirst()) {
while(!cursor.isAfterLast())
{
String tilt = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_CONTENT1));
String pkg = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_CONTENT3));
if(tilt.equals("LEFT"))
{
Log.v("LEFT",pkg);
}
else if(tilt.equals("RIGHT"))
{
Log.v("RIGHT",pkg);
}
cursor.moveToNext();
}
}
First you must count how many rows are in your table. Then assign that count to variable and it use to create an array. For array size you can use that count variable. Then create a for loop and use that count variable for rounds. After create your query and assign values to your arrays. 100% worked!.
int sqlcount;
Cursor mFetch;
SQLiteDatabase mydb = openOrCreateDatabase("your database name", MODE_PRIVATE, null);
mydb.execSQL("create table if not exists customer(name varchar,email varchar)");
Cursor mCount = mydb.rawQuery("select count(*) from customer", null);
mCount.moveToFirst();
sqlcount = mCount.getInt(0);
mCount.close();
String cname[] = new String[sqlcount];
String cemail[] = new String[sqlcount];
for(int i=0;i<sqlcount;i++) {
mFetch= mydb.rawQuery("select name,email from customer", null);
mFetch.moveToPosition(i);
cname[i] = mFetch.getString(0);
cemail[i] = mFetch.getString(1);
}
mFetch.close();
Toast.makeText(MainActivity.this,String.valueOf(cname[0]),Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this,String.valueOf(cemail[1]),Toast.LENGTH_SHORT).show();

SQL cursor error

I have been using the notepad SQLhelper (notesDBadapter) as a model, some of it works, some doesn't. I can get a cursor for 'fetchallrecords() but it crashes if I try a call passing an argument and using the 'WHERE'. The argument is passed but the cursor fails. My code in activity;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listselectedfile);
//Button ID clicked in previous activity
Bundle bundle = getIntent().getExtras();
int BtnId = bundle.getInt("ButtonID");
Toast.makeText(this, "ButtonID selected in Main:= " + BtnId, Toast.LENGTH_LONG) .show();
mDbHelper = new SectionsDbAdapter(this);
mDbHelper.open();
fillData();
}
private void fillData() {
// Get all of the notes from the database and create the item list
//Cursor c = mDbHelper.fetchAllRecords(); <=== works fine
Cursor c = mDbHelper.fetchRecordsbySource("UK"); <=== fails in DBhelper
startManagingCursor(c);
String[] from = new String[] { SectionsDbAdapter.KEY_DESC };
//String[] from = new String[] { SectionsDbAdapter.KEY_SOURCE }; <=== can fetch this column from table
int[] to = new int[] { R.id.tv_full_width }; //the R.id.xxx= view in the .xml file
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter records =
new SimpleCursorAdapter(this, R.layout.section_row_full_width, c, from, to); //the .xml file containing the R.id.xxxx
setListAdapter(records);
}
In the DBhelper;
This call works and returns the full table;
public Cursor fetchAllRecords() {
return mDb.query(DATABASE_TABLE, new String[] {
KEY_ROWID, KEY_DESC, KEY_DEPTH, KEY_TWEB,
KEY_BF1, KEY_TF1, KEY_BF2, KEY_TF2,
KEY_IMAJOR, KEY_IMINOR,
KEY_PLMAJOR, KEY_PLMINOR,
KEY_JTORSION, KEY_AREA,
KEY_WARPING, KEY_CYCHANNEL,
KEY_SHAPE, KEY_SOURCE,
KEY_UNITS},null, null, null, null, null);
}
This call fails on the cursor (the argument is passed successfully);
public Cursor fetchRecordsbySource(String source) throws SQLException {
Log.v("In fetchRecordsbySource", "source = " +source);
Cursor mCursor = mDb.query(true, DATABASE_TABLE, new String[] {
KEY_ROWID, KEY_DESC}, KEY_SOURCE + " = " + source, null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
There is nothing obvious to me in the Eclipse debug, but, as a newby, I probably have not got the necessary perspective.
Can anyone spot the error?
In the code you have, if source is a non-numeric value, it needs to surrounded by single quotes, like this:
KEY_ROWID, KEY_DESC}, KEY_SOURCE + " = '" + source + "'", null, null, null, null, null)
But you will be better off if you pass your filter arguments as ?; this avoids (among other things) SQL injection attacks
KEY_ROWID, KEY_DESC}, KEY_SOURCE + " = ?", new String[] { source }, null, null, null, null)

Categories

Resources