SQLite get second to last element - java

I have to get two last elements from table (or just id). My element's id is increased but not increment (next value is always larger but it is possible that more than 1 - elements are created by someone else and I am not supposed to modified them).
I know how to id it for last one:
public Long getLastDay(){
Cursor cursor= mDatabase.query(DatabaseHelper.TABLE_DAYS, new String[]{"MAX(" + DatabaseHelper.COLUMN_DAY_ID + ")"}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
return (cursor.getLong(0));
}
return Long.parseLong("0");
}
For example for ids:
1 4 7 11 14 15 19 25 28
I want to get 28 (it works) and 25.
How is it possible to get the second value?
#EDIT:
My code is:
public Long getSecondLastDay(){
Cursor cursor= mDatabase.rawQuery("SELECT "+DatabaseHelper.COLUMN_DAY_ID+" FROM " + DatabaseHelper.TABLE_DAYS+ " LIMIT 2", null);
if (cursor != null) {
cursor.moveToFirst();
return (cursor.getLong(0));
}
return Long.parseLong("0");
}

Sort the days in the reverse direction, and then just take the first two rows:
Cursor cursor = mDatabase.query(DatabaseHelper.TABLE_DAYS,
new String[]{ DatabaseHelper.COLUMN_DAY_ID },
null, null, null, null,
DatabaseHelper.COLUMN_DAY_ID + " DESC",
"2");
long secondToLastDay = 0, lastDay = 0;
if (cursor.moveToFirst()) {
lastDay = cursor.getLong(0);
if (cursor.moveToNext())
secondToLastDay = cursor.getLong(0);
}

use cursor.moveToLast and then cursor.moveToPreviuous

Related

How to get my desired results in Android Sqlite Search LIKE % where search key word in bangla language

cursor = sqLiteDatabase.query(MyTableName, allColumns,
Database.COLUMN_TO + " LIKE ?", new String[]{"%বিবেচন%" }, null, null, null);
myMeaning="বিবেচন";
cursor = sqLiteDatabase.query(MyTableName, allColumns,
Database.COLUMN_TO + " LIKE ?", new String[] {"%"+myMeaning+"%"}, null, null, null);
The first gives my desired result. I want to know why the second one can not give the desired result?
Solved, problem was in myMeaning variable which is myMeangin="বিবচন"; not "বিবেচন"

I'm getting the following error from the CursorAdapter Make sure the Cursor is initialized correctly before accessing data from it

My Binder Class
public void bindView(View view, Context context, Cursor cursor) {
mTitleText = (TextView) view.findViewById(R.id.recycle_title);
mDateAndTimeText = (TextView) view.findViewById(R.id.recycle_date_time);
mRepeatInfoText = (TextView)view.findViewById(R.id.recycle_repeat_info);
mActiveImage = (ImageView) view.findViewById(R.id.active_image);
mThumbnailImage = (ImageView) view.findViewById(R.id.thumbnail_image);
int titleColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_TITLE);
int dateColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_DATE);
int timeColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_TIME);
int repeatColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT);
int repeatNoColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT_NO);
int repeatTypeColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT_TYPE);
int activeColumnIndex = cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_ACTIVE);
int locationColumnIndex= cursor.getColumnIndex(AlarmReminderContract.AlarmReminderEntry.KEY_LOCATION);
String title = cursor.getString(titleColumnIndex);
String date = cursor.getString(dateColumnIndex);
String time = cursor.getString(timeColumnIndex);
String repeat = cursor.getString(repeatColumnIndex);
String repeatNo = cursor.getString(repeatNoColumnIndex);
String repeatType = cursor.getString(repeatTypeColumnIndex);
String active = cursor.getString(locationColumnIndex);
String loc = cursor.getString(activeLocation);
String dateTime = date + " " + time;
Log.e("msg_fa", loc);
if (loc.equals(false)) {
setReminderTitle(title);
setReminderDateTime(dateTime);
setReminderRepeatInfo(repeat, repeatNo, repeatType);
setActiveImage(active);
} else
{
setReminderTitle(title);
setReminderDateTime("Place");
}
}
My Logcat Error
E/CursorWindow: Failed to read row 0, column 8 from a CursorWindow which has 1 rows, 8 columns.
2018-10-24 19:54:06.958 11109-11109/? E/AndroidRuntime: FATAL EXCEPTION: main
Process:PID: 11109
java.lang.IllegalStateException: Couldn't read row 0, col 8 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
I can access the till data columnIndex 7 but i cant get the index from 8
Code for My DB HELPER
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// Create a String that contains the SQL statement to create the reminder table
String SQL_CREATE_ALARM_TABLE = "CREATE TABLE " + AlarmReminderContract.AlarmReminderEntry.TABLE_NAME + " ("
+ AlarmReminderContract.AlarmReminderEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_TITLE + " TEXT NOT NULL, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_DATE + " TEXT, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_TIME + " TEXT, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT + " TEXT, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT_NO + " TEXT, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT_TYPE + " TEXT, "
+ AlarmReminderContract.AlarmReminderEntry.KEY_ACTIVE + " TEXT,"
+AlarmReminderContract.AlarmReminderEntry.KEY_LOCATION + " TEXT,"
+ AlarmReminderContract.AlarmReminderEntry.latitude+" TEXT ,"
+ AlarmReminderContract.AlarmReminderEntry.longitude+" TEXT" +" );";
// Execute the SQL statement
sqLiteDatabase.execSQL(SQL_CREATE_ALARM_TABLE);
Insertion to the database works perfectly but this issue comes when i ask to fetch the data from the 8th index
The main issue which I'm facing is when I try to get the value from the index of KEY_LOCATION the app crashes and it then gives out the error which is displayed in the logcat I'm getting the value till column 7 I tried updating the database version and changing the table name and database name it didn't work as expected.
Here is my Provider Class
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
SQLiteDatabase database = mDbHelper.getReadableDatabase();
// This cursor will hold the result of the query
Cursor cursor = null;
int match = sUriMatcher.match(uri);
switch (match) {
case REMINDER:
cursor = database.query(AlarmReminderContract.AlarmReminderEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
Log.i("msg","Reminder Invoked");
break;
case REMINDER_ID:
selection = AlarmReminderContract.AlarmReminderEntry._ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
cursor = database.query(AlarmReminderContract.AlarmReminderEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI " + uri);
}
The issue is that the Cursor only has 8 (offsets 0-7) of the 11 (offsets 0-10) columns in the table. Hence the message saying that it has failed to read row 0 (the first row) column 8 (the 9th column (location)).
A Cursor will only contain the columns that you specify implicitly or explicitly (SELECT * implies all columns, null as the 2nd parameter to the SQLIteDatabase query method equates to SELECT * and thus implies all columns). This irrespective of the columns in the underlying table or tables.
You issue would appear to be that the String array passed to the Provider Class's as the 2nd parameter (projection) only explicitly specifies 8 columns.
A quick fix (although the most flexible fix) would be to use null insetad of projection as the 2nd parameter when calling the SQLiteDatabase query method.
So instead of :-
database.query(AlarmReminderContract.AlarmReminderEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
You could use :-
database.query(AlarmReminderContract.AlarmReminderEntry.TABLE_NAME, null, selection, selectionArgs,
null, null, sortOrder);
As such the entire query method could be :-
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
SQLiteDatabase database = mDbHelper.getReadableDatabase();
// This cursor will hold the result of the query
Cursor cursor = null;
int match = sUriMatcher.match(uri);
switch (match) {
case REMINDER:
cursor = database.query(AlarmReminderContract.AlarmReminderEntry.TABLE_NAME,
null, //<<<<<<<<<< CHANGED
selection,
selectionArgs,
null, null, sortOrder);
Log.i("msg","Reminder Invoked");
break;
case REMINDER_ID:
selection = AlarmReminderContract.AlarmReminderEntry._ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
cursor = database.query(AlarmReminderContract.AlarmReminderEntry.TABLE_NAME,
null, //<<<<<<<<<< CHANGED
selection,
selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI " + uri);
}
}
Note the 2nd parameter String[] projection passed to the method would be redundant.
An alternative would be to amend the call to the Provider class's query method (as above) so that the String array passed includes the extra column(s) when invoking the Provider class's query method.
e.g.
String[] projection_columns = new String[]{
AlarmReminderContract.AlarmReminderEntry._ID,
AlarmReminderContract.AlarmReminderEntry.KEY_TITLE,
AlarmReminderContract.AlarmReminderEntry.KEY_DATE,
AlarmReminderContract.AlarmReminderEntry.KEY_TIME,
AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT,
AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT_NO,
AlarmReminderContract.AlarmReminderEntry.KEY_REPEAT_TYPE,
AlarmReminderContract.AlarmReminderEntry.KEY_LOCATION,
AlarmReminderContract.AlarmReminderEntry.KEY_ACTIVE,
AlarmReminderContract.AlarmReminderEntry.latitude,
AlarmReminderContract.AlarmReminderEntry.longitude
}
your_provider.query(your_uri, project_columns,your_selection, your_selectionargs, you_sortorder);

SQLITE update ROW not working

im trying to update specific row but no luck.
Im first time working with sqlite, maybe its true im confused with column/row
In ideal i want update text in field with name MESSAGE_HISTORY(id=5)
Same way and code works for field Item0 (id = 1)
public static void updateHistory(ArrayList<MessageModel> models, String id) {
if (database != null) {
Cursor c = database.query(TDatabaseHelper.DATABASE_TABLE,null,null, null, null, null, null);
if (c.moveToFirst()) {
do {
int index1 = c.getColumnIndex(MESSAGE_HISTORY);//return position 5
ContentValues data = new ContentValues();
data.put(MESSAGE_HISTORY, DatabaseHelper.chatHistoryModelsConvert(models, id).toString());
long k = database.update(TDatabaseHelper.DATABASE_TABLE, data, "id=" + index1, null);
DBLogger.w("DATABASE UPDATE STATUS = "+k);
}while(!c.moveToFirst());
}else {
DBLogger.d("Error");
}
}
}
K always return 0
Any help ?
[UPD]
public static void CreateDB() {
if (database != null) {
Cursor c = database.query(TDatabaseHelper.DATABASE_TABLE, null, null, null, null, null, null);
if (!c.moveToFirst()) {
cv.put(TDatabaseHelper.ITEM0, "Item0"); // <---- this item update very good index = 1
cv.put(TDatabaseHelper.MESSAGE_HISTORY, "history"); <-- cant update, index = 5;
cv.put(TDatabaseHelper.ITEM1, "item1");
cv.put(TDatabaseHelper.ITEM2, "item2");
cv.put(TDatabaseHelper.ITEM3, "item3");
long rowID = database.insert(TDatabaseHelper.DATABASE_TABLE, null, cv);
DBLogger.i("row inserted, ID = " + rowID);
}
}
}
[UPD]
this not help :(
String[] args = new String[]{""+index1}; ??database.update(TDatabaseHelper.DATABASE_TABLE, data, "id=?", args);
The following line gives you the index of the column named MESSAGE_HISTORY but it does not give you the value.
int index1 = c.getColumnIndex(MESSAGE_HISTORY);//return position 5
As a result of this, your line
long k = database.update(TDatabaseHelper.DATABASE_TABLE, data, "id=" + index1, null);
updates a row that has an id of "5" and it seems that it does not exist. You need to get the value in column 5, so do something like the following:
String messageValue = c.getString(index1);
long k = database.update(TDatabaseHelper.DATABASE_TABLE, data,
MESSAGE_HISTORY + " = ?", new String[] {messageValue});
It is better to use the whereArgs here since just appending messageValue may cause problems. See the update documentation regarding the whereClause and whereArgs.
In any case, slap the debugger on that last line to see exactly what you are passing to the update method. You may be surprised.

Cursor Index Out of Bounds exception

I keep getting this error message: "Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0" in my code.
I have already referenced the following links, but none of them have worked:
Android cursor out of bounds exception
Cursor index out of bounds
Cursor Index Out Of Bounds Error Android?
cursor index out of bounds exception
public Product getProduct(int id) {
db = this.getReadableDatabase();
Cursor cursor = db.query(
TABLE_NAME,
null,
COLUMN_ID + " = ?",
new String[] { Integer.toString(id)},
null, null, null, null);
Product product = new Product();
cursor.moveToFirst();
if (cursor != null) {
product.setID(cursor.getInt(0));
product.setName(cursor.getString(1));
product.setSize(cursor.getDouble(2));
product.setHp(cursor.getDouble(3));
product.setCategory(cursor.getString(4));
product.setPowerType(cursor.getString(5));
product.setExplosionProof(cursor.getInt(6));
product.setRPM(cursor.getInt(7));
product.setBypassPSI(cursor.getInt(8));
product.setGPM(cursor.getInt(9));
product.setPrice(cursor.getDouble(10));
cursor.close();
}
db.close();
return product;
}
And here are my constants:
private static final String TABLE_NAME = "Products";
private static final String COLUMN_ID = "'_id'";
I would greatly appreciate any help.
Now, it won't go into the if-loop. I got that query model straight from another stack overflow question.
It is very likely that the cursor is empty, as such you need to ascertain why. It could be that there is no underlying data or it could be that the cursor where clause is excluding all data. From what you have provided it is impossible to determine why.
I would suggest removing the where clause to see if this changes matters.
i.e. instead of
Cursor cursor = db.query(
TABLE_NAME,
null,
COLUMN_ID + " = ?",
new String[] { Integer.toString(id)},
null, null, null, null);
use :-
Cursor cursor = db.query(
TABLE_NAME,
null,
null,
null,
null, null, null, null);
This would return all rows from the cursor, if this works then the issue is with the where clause (3rd and 4th parameters passed to db.query). If it doesn't resolve the issue then it is likely that the table itself has no rows.
You could circumvent the CursorIndexOutOfBoundsException by using :-
if (cursor.getCount() > 0) {
cursor.moveToFirst();
product.setID(cursor.getInt(0));
product.setName(cursor.getString(1));
product.setSize(cursor.getDouble(2));
product.setHp(cursor.getDouble(3));
product.setCategory(cursor.getString(4));
product.setPowerType(cursor.getString(5));
product.setExplosionProof(cursor.getInt(6));
product.setRPM(cursor.getInt(7));
product.setBypassPSI(cursor.getInt(8));
product.setGPM(cursor.getInt(9));
product.setPrice(cursor.getDouble(10));
} else {
// setup to return a product not found
}
cursor.close();
However, this won't fix the underlying issue that the cursor is not returning any rows.
You could use something like the following to get more information regarding the cursor (running with the cursor selecting all rows as per change above). This should work for any cursor :-
int rowcount = cursor.getCount();
String colnames = "";
for (String columns : cursor.getColumnNames()) {
colnames = colnames +
"Column Index=" +
Integer.toString(cursor.getColumnIndex(columns)) +
" Name=>" +
columns +
"< ";
}
Log.d("DBCHK","Table has " + Integer.toString(rowcount) + " rows. With columns:- " + colnames);
String values;
while (cursor.moveToNext()) {
values = "";
for (int i = 0; i < cursor.getColumnCount(); i++) {
values = values +
"Column = " +
cursor.getColumnName(i) +
" Index=" +
Integer.toString(i) +
" Value=" + cursor.getString(i) + ": ";
}
Log.d("DBCHK",values);
}
This would write data to the log along the lines of :-
D/DBCHK: Table has 2 rows. With columns:- Column Index=0 Name=>_id< Column Index=1 Name=>myfloat<
D/DBCHK: Column = _id Index=0 Value=null: Column = myfloat Index=1 Value=56.7897:
D/DBCHK: Column = _id Index=0 Value=null: Column = myfloat Index=1 Value=87.7655:
There will be a line per row, these preceded with a line listing the number of rows and what the columns are.

Android SQLite query rows from bottom to top with timestamp to equal current date

I am using SQLite for my app and I kind of have a large database. The database has 3 columns:
id(int auto incerement)|timestamp(int)|value(string)
I want to have the latest records, which have timestamp (millisec) of the current day.
At the I have a code to query all the records in the table, but it is awfully slow:
public List<PhysicalActivity> getAllPhysicalActivities(){
List<PhysicalActivity> all = new ArrayList<PhysicalActivity>();
Cursor cursor = mDatabase.query(PhysicalActivityDatabaseHelper.TABLE_NAME, mColumns
, null, null, null, null, null);
cursor.moveToFirst();
while(!cursor.isAfterLast()) {
PhysicalActivity pa = cursorToPhysicalActivity(cursor);
all.add(pa);
cursor.moveToNext();
}
cursor.close();
return all;
}
I want to do ORDER BY id DESC as you would do in MySQL...I need to have something like this code:
public List<PhysicalActivity> getPhysicalActivitiesForDate(Date date){
List<PhysicalActivity> activities = new ArrayList<PhysicalActivity>();
Cursor cursor = mDatabase.query(PhysicalActivityDatabaseHelper.TABLE_NAME, mColumns
, null, null, null, null, "ORDERBY " + PhysicalActivityDatabaseHelper.COLUMN_ID +
" DESC");
cursor.moveToFirst();
while(!cursor.isAfterLast()){
PhysicalActivity pa = cursorToPhysicalActivity(cursor);
Date d = new Date(pa.getTimestamp());
if(d.getDay() == date.getDay()){
activities.add(pa);
}
cursor.moveToNext();
}
cursor.close();
return activities;
}
Another problem is that getDay() method is deprecated...what should I replace with that to have the same effect (compare the day the row's timestamp represents to the day in the date that passed as an argument).
This query should solve your problem. I´ll explain it.
long curretTime = System.currentTimeMillis()
Cursor cursor = mDatabase.query(
PhysicalActivityDatabaseHelper.TABLE_NAME, //Table name
mColumns, //Queryed columns
PhysicalActivityDatabaseHelper.TIMESTAMP + " = " currentTime, //Select
null, null, null,
PhysicalActivityDatabaseHelper.TIMESTAMP + " DESC" //Order By
);
First of all you're going to get the current time in milis so you can compare it. Then you'll retrieve all the fields of the table (only if you want), then you will retrieve only the rows matching the Select part and order that resulset in base of the Order By.
Hope it helps!

Categories

Resources