Selecting Distinct in sqlite Android not working - java

I have the following query in my dbhelper class.
public Cursor search(String searchString,String limit){
searchString=searchString.replaceAll("'", "");
String[] cols = new String[]{CSV_WORD_ID, CATEGORY_ID, MAIN_TEXT, TRANSLATION_TEXT, PRONUNCIATION_IN_ENGLISH, IMAGE_1,IMAGE_2,IMAGE_3,AUDIO,STATUS};
Cursor mCursor = database.query(true, WORD_TABLE, cols, CATEGORY_ID + " NOT IN(0,1) AND "+ MAIN_TEXT + " LIKE '%"+searchString+"%' ", null, MAIN_TEXT, null, null, limit);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
In the above function I want to fetch distinct MAIN_TEXT. But in log I can see it is:-
SELECT DISTINCT csv_word_id, category_id, main_text, translation_text, pronunciation_in_english, image_1, image_2, image_3, audio, status FROM words WHERE category_id NOT IN(0,1) AND main_text LIKE '%m%' GROUP BY main_text LIMIT 10
I want DISTINCT main_text not csv_word_id. How can I do this.

Related

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 delete where clause arguments

I am new to Sqlite. Prior I tried deleting a row in my table using trick_id
public void deleteTrick (int trick_id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(Constants.TRICKS_TABLE, Constants.TRICK_ID + " ?= ", new String[]{ String.valueOf(trick_id)});
db.close();
}
but now I need to delete row based on two constraints trick_id and opn_id.
How to use 'where clause' to delete the row that matches with same opn_id & trick_id that are passed in as parameters to delete method?
public void deleteTrick (int trick_id,int opn_id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(Constants.TRICKS_TABLE, Constants.TRICK_ID + " ?= " WHERE Constants.OPN_ID + " ?= ", new String[]{ String.valueOf(trick_id), String.valueOf(opn_id)};
db.close();
}
to delete :
db.delete(TableName,ID_that_you_want_to_delete + " =?" , new String[]{your id that given for delete }) ;
db.delete(Constants.TRICKS_TABLE, Constants.TRICK_ID + " =? ",new String[]{String.valueOf(opn_id)})
You can use delete method like this
public void deleteTrick() {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(Constants.TRICKS_TABLE, null, null);
db.close();
}
In this codes first null is your WHERE clause,and second null is your Whereargs.If my answer is correct you can accept.Happy coding:)

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.

how to query the contacts content provider given a number

I want to query the contacts provider in android with a given number.
I have something like this
String queryString= "NUMBER='" + msgs[i].getOriginatingAddress() + "'";
Uri contacts = ContactsContract.CommonDataKinds.Phone.CONTENT_URI ;
Cursor cursor = context.getContentResolver().query(
contacts,
null, queryString, null,
null
);
then how do I go upon going to the first row? Like this?
cursor.getString(<how do i reference to the first row?>);
right?
Try this :
String strNumber= "7777777777";
String queryString= "NUMBER='" + strNumber + "'";
Uri contacts = ContactsContract.CommonDataKinds.Phone.CONTENT_URI ;
Cursor cursor = context.getContentResolver().query(
contacts,
null, queryString, null,
null
);
Hope this help!

Android SQLite SELECT Query

I have taken String value from a EditText and set it inside SELECT QUERY after WHERE condition
As
TextView tv = (TextView) findViewById(R.id.textView3);
EditTextet2 et = (EditText) findViewById(R.id.editText1);
String name = et.getText().toString();
Cursor c = db.rawQuery("SELECT * FROM tbl1 WHERE name = '"+name+"'", null);
c.moveToNext();
tv.setText(c.getString(c.getColumnIndex("email")));
But it doesn't work. Any suggestions?
Try trimming the string to make sure there is no extra white space:
Cursor c = db.rawQuery("SELECT * FROM tbl1 WHERE TRIM(name) = '"+name.trim()+"'", null);
Also use c.moveToFirst() like #thinksteep mentioned.
This is a complete code for select statements.
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("SELECT column1,column2,column3 FROM table ", null);
if (c.moveToFirst()){
do {
// Passing values
String column1 = c.getString(0);
String column2 = c.getString(1);
String column3 = c.getString(2);
// Do something Here with values
} while(c.moveToNext());
}
c.close();
db.close();
Try using the following statement:
Cursor c = db.rawQuery("SELECT * FROM tbl1 WHERE name = ?", new String[] {name});
Android requires that WHERE clauses compare to a ?, and you then specify an equal number of ? in the second parameter of the query (where you currently have null).
And as Nambari mentioned, you should use c.moveToFirst() rather than c.moveToNext()
Also, could there be quotations in name? That could screw things up as well.
Here is the below code.
String areaTyp = "SELECT " +AREA_TYPE + " FROM "
+ AREA_TYPE_TABLE + " where `" + TYPE + "`="
+ id;
where id is the condition on which result will be displayed.
public User searchUser(String name) {
User u = new User();
SQLiteDatabase db = this.getWritableDatabase(); //get the database that was created in this instance
Cursor c = db.rawQuery("select * from " + TABLE_NAME_User+" where username =?", new String[]{name});
if (c.moveToLast()) {
u.setUsername(c.getString(1));
u.setEmail(c.getString(1));
u.setImgUrl(c.getString(2));
u.setScoreEng(c.getString(3));
u.setScoreFr(c.getString(4));
u.setScoreSpan(c.getString(5));
u.setScoreGer(c.getString(6));
u.setLevelFr(c.getString(7));
u.setLevelEng(c.getString(8));
u.setLevelSpan(c.getString(9));
u.setLevelGer(c.getString(10));
return u;
}else {
Log.e("error not found", "user can't be found or database empty");
return u;
}
}
this is my code to select one user and one only
so you initiate an empty object of your class then
you call your writable Database
use a cursor in case there many and you need one
here you have a choice Use : 1-
if (c.moveToLast()) { } //it return the last element in that cursor
or Use : 2-
if(c.moveToFirst()) { } //return the first object in the cursor
and don't forget in case the database is empty you'll have to deal with that in my case i just return an empty object
Good Luck
Detailed answer:
String[] selectionArgs = new String[]{name};
Cursor c = db.rawQuery(
"SELECT * FROM " + tabl1 +
" WHERE " + name + " = ? ", selectionArgs
);
selectionArgs : this takes the 'name' you desire to compare with, as argrument.
Here note "A Cursor object, which is positioned before the first entry of the table you refer to".
So,to move to first entry :
c.moveToFirst();
getColumnIndex(String ColumnName) : this returns the zero-based column index for the given column name.
tv.setText(c.getString(c.getColumnIndex("email")));
In case, you want to go searching through multiple rows for a given name under 'name' column then use loop as below:
if (cursor.moveToFirst()){
do{
////go traversing through loops
}while(cursor.moveToNext());
}
This should solve the problem.

Categories

Resources