Search SQLite database returns empty cursor - android

I am using a searchView to get a query to search database with a string, the Cursor does not return as null but is empty.
The call to search from my search activity (which is a ListActivity implementing SearchView.OnQueryTextListener):
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
//handleIntent(intent);
Log.d("LIST ACTIVITY SEARCH", "onQueryTextCahanged called: "+ newText);
Cursor c = data.getWordMatches(newText, null);
Log.d("LISTACTIVITY", "CURSOR QUERY ROWS/COLS = "+ c.getCount()+" "+c.getColumnCount());
//now set bind cursor data to list view using custim ItemAdpter class
adapter = new ItemAdapter(ViewListOfTests.this, c);
this.setListAdapter(adapter);
return false;
}
And the search method in SQLite Databasetaking the String query from method above:
/*
* methods to search database with String query form searchable widget intent
* in ViewListOfDives ListActivity search bar. Each search returns a cursor which is set to adpter
* in ViewListOfYesys List Activity
*/
public Cursor getWordMatches(String query, String[] columns){
String selection = database.KEY_TESTNAME + " MATCH ?";
String[] selectionArgs = new String[] {query+"*"}; //wildcard *
return query(selection, selectionArgs, columns);
}//end getWordMatches
private Cursor query(String selection, String[] selectionArgs,
String[] columns) {
// return cursor form params passed getWordMatches(Styring query) from search widget ListActivity
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(DATABASE_TABLE);
dbHelperObject = new DbHelper(ourContext);
Cursor cursor = builder.query(dbHelperObject.getReadableDatabase(), columns, selection, selectionArgs, null, null, null);
if(cursor == null){
return null;
}else if(!cursor.moveToFirst()){
cursor.close();
return null;
}
return cursor;
}//end query
The else if code executes here returning an empty cursor :
else if(!cursor.moveToFirst()){
cursor.close();
return null;
Any input appreciated!
Ciaran

instead of this :
if(cursor == null){
return null;
}else if(!cursor.moveToFirst()){
cursor.close();
return null;
}
return cursor;
use this:
if(cursor == null){
return null;
}else{
cursor.moveToFirst();
}
return cursor;

Got it, seems i was passing the wrong parameter to the curosr.rawQuery().
I was passing a ref to dataBase helper object getReadableDB call:
Cursor cursor = builder.query(mDatabaseOpenHelper.getReadableDatabase(),
columns, selection, selectionArgs, null, null, null);
When I replaced this parameter with the database object it worked fine:
SQLiteDatabase ourDataBase = ourDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
Cursor cursor = builder.query(ourDataBase, columns, selection, selectionArgs, null, null, null);
The training documentation stated pass the former mDatabaseOpenHelper.getReadableDatabase() but this did not seem to work, not why.http://developer.android.com/training/search/search.html

Related

search sqlite with multiple columns

Hi every one I'm trying to search my sqlite data base which has 4 columns but the app crashes and the log error is :-
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
I'm wondering if there is a method to search sqlite data base with multiple columns and with single columns.
The code for the cursor is :-
cursor = mReadableDB.query(WORD_LIST_TABLE, columns, where, whereArgs, null, null, null);
DataBase Code is :
public Cursor search(String searchString) {
String[] columns = new String[]{KEY_WORD};
String where = KEY_WORD + " LIKE ?";
searchString = "%" + searchString + "%";
String[] whereArgs = new String[]{searchString};
Cursor cursor = null;
if (mReadableDB == null) {
mReadableDB = getReadableDatabase();
}
cursor = mReadableDB.query(WORD_LIST_TABLE, columns, where, whereArgs, null, null, null);
return cursor;
}
and the search class is :
public void showResult(View view) {
String word = editText_search.getText().toString();
textView.setText("Result for " + word + ":\n\n");
Cursor cursor = mDataBase.search(word);
cursor.moveToFirst();
if (cursor != null & cursor.getCount() > 0) {
int index;
String result;
do {
index = cursor.getColumnIndex(mDataBase.KEY_WORD);
result = cursor.getString(index);
textView.append(result + "\n");
} while (cursor.moveToNext());
cursor.close();
} else {
textView.append("no result");
}
}
Your cursor does not return anything. this is how I usually use database in android: by using .rawQuery(); and SQLite.
e.g.
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM tasks WHERE id = " + id, null);
And you can also check if the cursor is empty or not by calling cursor.moveToFirst();.
If cursor was empty, the method returns false. else it returns true.
After checking that, you can go to the row that you want by using cursor.move(rowNumber); and get the value of the column you want with get methods e.g. cursor.getString(1);

SQLite selectionArgs not working

I am having some kind of weird problem with my content provider: selectionArgs refused to work for a particular column.
Insertion
void saveFile(File file, Cursor cursor, Context context) {
if (file.isDirectory()) {
throw new IllegalArgumentException(file.getName() + " must be a file");
}
values.put(IS_DIRECTORY, false);
// Some other values.put()
context.getContentResolver().insert(FolderContract.CONTENT_URI, values);
}
And
void saveFolder(File file, String filesNum, Context context, int directTracks) {
if (!file.isDirectory()) {
throw new IllegalArgumentException(file.getName() + " must be a directory");
}
ContentValues values = new ContentValues();
values.put(IS_DIRECTORY, true);
// Some other values.put()
context.getContentResolver().insert(FolderContract.CONTENT_URI, values);
}
My Query
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Timber.w("onCreateLoader: ");
String selection = String.format("%s = ? AND %s = ?", FolderContract.IS_DIRECTORY, FolderContract.PARENT_ID);
String[] selectionArgs = selectionArgs = new String[]{"0", args.getString(FOLDER_PATH)};
return new CursorLoader(getActivity(), FolderContract.CONTENT_URI, null, selection, selectionArgs, null);
}
I want the the query to return the rows with FolderContract.PARENT_ID column = args.getString(FOLDER_PATH) while the FolderContract.IS_DIRECTORY column will be false.
But the above query returns zero results however if I run it without the FolderContract.IS_DIRECTORY in the selection it returns all the matching
results.The weird thing is that if I loop through the cursor, some of the returned rows has its FolderContract.IS_DIRECTORY column as 0 while
others is 1.
ContentProvider
#Override
public Uri insert(#NonNull Uri uri, ContentValues values) {
final SQLiteDatabase database = dbHelper.getWritableDatabase();
long insertedRowId = database.insert(FolderContract.TABLE_NAME, null, values);
if (insertedRowId > -1) {
Uri insertedUri = ContentUris.withAppendedId(CONTENT_URI, insertedRowId);
getContext().getContentResolver().notifyChange(insertedUri, null);
return insertedUri;
}
database.close();
return uri;
}
#Override
public Cursor query(#NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final SQLiteDatabase database = dbHelper.getReadableDatabase();
Cursor cursor = database.query(FolderContract.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
Please any idea what I am doing wrong?

android-how to close cursor in a class like this

I have this function inside my dbhelper class :
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(DATABASE_TABLE, ALL_KEYS, where, null, null, null,null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
when I come to the activity where this class calls, I get this error (Please notice when I enter this activity I get this error not when leaving the activity ):
Finalizing a Cursor that has not been deactivated or closed. database......
Application did not close the cursor or database object that was opened here
it's a very long error .
someone told me to use c.close(); above return c, something like this:
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(DATABASE_TABLE, ALL_KEYS, where, null, null, null,null, null);
if (c != null) {
c.moveToFirst();
}
c.close();
return c;
}
I tried it but now I get this error :
Access closed cursor
What should I do ? How should I close the cursor in this class?
You should close the Cursor in your Activity. like
Cursor c=getRow(rowID_Value);
c.close();
After getting used of your DB you must close this Cursor.
Close the cursor after using getRow function,i.e.
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(DATABASE_TABLE, ALL_KEYS, where, null, null, null,null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
and use it like this
Cursor c1 = getRow(rowId);
//use cursor
//....
if(c1 != null)c1.close();
Note : rowId is the value of row which you want from database in long format.
Edit
Create Cursor c1; in your activity class.
check first if cursor is not null,then close it.
if(c1 != null)c1.close();
then get cursor as
c1 = getRow(rowId);
And onStop/onDestroy close cursor as
if(c1 != null)c1.close();
hello i have face this same problem i have solve this problem like
when i am query and returning ArrayList or JSON object not cursor
may you need to change your query
public JSONObject getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(DATABASE_TABLE, ALL_KEYS, where, null, null, null,null, null);
if (c!= null & c.moveToFirst()) {
JSONObject jsonObj = new JSONObject();
jsonObj.put("key_Name", c.getString(c.getColumnIndex("your_column_name")));
// do for your all column and return this jsonObj and before returning close cursor
}
c.close();
return jsonObj;
}
this is for only returning one record for retuning set of record i am use this lib
https://github.com/commonsguy/cwac-loaderex
it will manage cursor operation itself and return us sqliteCursorLoader

Slow to call onLoadFinished

I'm using Loader and Content Provider to fill a listview with data from my database.
My problem is that, if I use the line below in my Content Provider to get data from database, the query and onLoadFinished is executed very fast (no problem to fill the listview):
Cursor c = this.mDb.rawQuery("SELECT * FROM " + DATABASE_TABLE , null);
However, If I change the line to :
Cursor c = this.mDb.rawQuery("SELECT DISTINCT D._id, D.Name, D.Icon FROM Plain A, Test B, Exercise C, Group D WHERE A.ID=1 AND B.PlainID=A._id AND B.TestID=C._id AND C.ExerciseID=D._id", null);
The query continues to run fast, but the application takes approximately 2s to call onLoadFinished and fill the listview.
why this delay if the cursor already executed query?
My Loader:
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.d(TAG, "onCreateLoader");
Uri uri = ContentProviderGroup.CONTENT_URI;
String[] projection = { Group.KEY_ROW_ID, Group.KEY_NAME, Group.KEY_ICON };
CursorLoader cursorLoader = new CursorLoader(this, // Parent activity context
uri, // Table to query
projection, // Projection to return
null, // No selection clause
null, // No selection arguments
null); // Default sort order
Log.d(TAG, "END onCreateLoader");
return cursorLoader;
}
My Content Provider (query function):
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor cursor;
if(uriMatcher.match(uri) == CODE){
Log.d(TAG, "CALL SELECT");
cursor = mCustomerDB.getGroup(selection, selectionArgs);
Log.d(TAG, "END SELECT");
return cursor;
}else{
return null;
}
}
My DBAdapter (getGroup function):
public Cursor getGroup(String selection, String[] selectionArgs){
Log.d(TAG, "SELECT INIT");
/////// HERE I USE the rawQuery /////////
Log.d(TAG, "SELECT END");
return c;
}
Thank You

Get all rows from SQLite

I have been trying to get all rows from the SQLite database. But I got only last row from the following codes.
FileChooser class:
public ArrayList<String> readFileFromSQLite() {
fileName = new ArrayList<String>();
fileSQLiteAdapter = new FileSQLiteAdapter(FileChooser.this);
fileSQLiteAdapter.openToRead();
cursor = fileSQLiteAdapter.queueAll();
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
fileName.add(cursor.getString(cursor.getColumnIndex(FileSQLiteAdapter.KEY_CONTENT1)));
} while (cursor.moveToNext());
}
cursor.close();
}
fileSQLiteAdapter.close();
return fileName;
}
FileSQLiteAdapter class:
public Cursor queueAll() {
String[] columns = new String[] { KEY_ID, KEY_CONTENT1 };
Cursor cursor = sqLiteDatabase.query(MYDATABASE_TABLE, columns, null,
null, null, null, null);
return cursor;
}
Please tell me where is my incorrect. Appreciate.
try:
Cursor cursor = db.rawQuery("select * from table",null);
AND for List<String>:
if (cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
String name = cursor.getString(cursor.getColumnIndex(countyname));
list.add(name);
cursor.moveToNext();
}
}
Using Android's built in method
If you want every column and every row, then just pass in null for the SQLiteDatabase column and selection parameters.
Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null, null);
More details
The other answers use rawQuery, but you can use Android's built in SQLiteDatabase. The documentation for query says that you can just pass in null to the selection parameter to get all the rows.
selection Passing null will return all rows for the given table.
And while you can also pass in null for the column parameter to get all of the columns (as in the one-liner above), it is better to only return the columns that you need. The documentation says
columns Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
Example
SQLiteDatabase db = mHelper.getReadableDatabase();
String[] columns = {
MyDatabaseHelper.COLUMN_1,
MyDatabaseHelper.COLUMN_2,
MyDatabaseHelper.COLUMN_3};
String selection = null; // this will select all rows
Cursor cursor = db.query(MyDatabaseHelper.MY_TABLE, columns, selection,
null, null, null, null, null);
This is almost the same solution as the others, but I thought it might be good to look at different ways of achieving the same result and explain a little bit:
Probably you have the table name String variable initialized at the time you called the DBHandler so it would be something like;
private static final String MYDATABASE_TABLE = "anyTableName";
Then, wherever you are trying to retrieve all table rows;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from " + MYDATABASE_TABLE, null);
List<String> fileName = new ArrayList<>();
if (cursor.moveToFirst()){
fileName.add(cursor.getString(cursor.getColumnIndex(COLUMN_NAME)));
while(cursor.moveToNext()){
fileName.add(cursor.getString(cursor.getColumnIndex(COLUMN_NAME)));
}
}
cursor.close();
db.close();
Honestly, there are many ways about doing this,
I have been looking into the same problem! I think your problem is related to where you identify the variable that you use to populate the ArrayList that you return. If you define it inside the loop, then it will always reference the last row in the table in the database. In order to avoid this, you have to identify it outside the loop:
String name;
if (cursor.moveToFirst()) {
while (cursor.isAfterLast() == false) {
name = cursor.getString(cursor
.getColumnIndex(countyname));
list.add(name);
cursor.moveToNext();
}
}
Update queueAll() method as below:
public Cursor queueAll() {
String selectQuery = "SELECT * FROM " + MYDATABASE_TABLE;
Cursor cursor = sqLiteDatabase.rawQuery(selectQuery, null);
return cursor;
}
Update readFileFromSQLite() method as below:
public ArrayList<String> readFileFromSQLite() {
fileName = new ArrayList<String>();
fileSQLiteAdapter = new FileSQLiteAdapter(FileChooser.this);
fileSQLiteAdapter.openToRead();
cursor = fileSQLiteAdapter.queueAll();
if (cursor != null) {
if (cursor.moveToFirst()) {
do
{
String name = cursor.getString(cursor.getColumnIndex(FileSQLiteAdapter.KEY_CONTENT1));
fileName.add(name);
} while (cursor.moveToNext());
}
cursor.close();
}
fileSQLiteAdapter.close();
return fileName;
}
Cursor cursor = myDb.viewData();
if (cursor.moveToFirst()){
do {
String itemname=cursor.getString(cursor.getColumnIndex(myDb.col_2));
String price=cursor.getString(cursor.getColumnIndex(myDb.col_3));
String quantity=cursor.getString(cursor.getColumnIndex(myDb.col_4));
String table_no=cursor.getString(cursor.getColumnIndex(myDb.col_5));
}while (cursor.moveToNext());
}
cursor.requery();
public List<String> getAllData(String email)
{
db = this.getReadableDatabase();
String[] projection={email};
List<String> list=new ArrayList<>();
Cursor cursor = db.query(TABLE_USER, //Table to query
null, //columns to return
"user_email=?", //columns for the WHERE clause
projection, //The values for the WHERE clause
null, //group the rows
null, //filter by row groups
null);
// cursor.moveToFirst();
if (cursor.moveToFirst()) {
do {
list.add(cursor.getString(cursor.getColumnIndex("user_id")));
list.add(cursor.getString(cursor.getColumnIndex("user_name")));
list.add(cursor.getString(cursor.getColumnIndex("user_email")));
list.add(cursor.getString(cursor.getColumnIndex("user_password")));
// cursor.moveToNext();
} while (cursor.moveToNext());
}
return list;
}
a concise solution can be used for accessing the cursor rows.
while(cursor.isAfterLast)
{
cursor.getString(0)
cursor.getString(1)
}
These records can be manipulated with a loop

Categories

Resources