using sqlite (with FTS) on Android - android

I am using sqlite FTS3 database, with my Android application.
public Cursor getWordMatches(String query, String[] columns) {
String selection = KEY_WORD + " MATCH ?";
String[] selectionArgs = new String[] {query+"*"};
return query(selection, selectionArgs, columns);
}
.....
private Cursor query(String selection, String[] selectionArgs, String[] columns) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(FTS_VIRTUAL_TABLE);
builder.setProjectionMap(mColumnMap);
Cursor cursor = builder.query(mDatabaseOpenHelper.getReadableDatabase(),
columns, selection, selectionArgs, null, null, null);
if (cursor == null) {
return null;
} else if (!cursor.moveToFirst()) {
cursor.close();
return null;
}
return cursor;
}
If I make a query and search for 'house' I will get:
household
house
apartment house
big house
(I am getting everything that has house in it, in regex house)
How can I get this kind of result for my query?
household
house
(So i only want results that start with house, in regex house*)
My android application FORCE CLOSES if I use LIKE statement(maybe because db has 200000 rows).
So should I somehow combine MATCH and LIKE statement?
Is it even possible to do this on Android, if it is not maybe I should try to run some regex on cursor after I get it from this query?

Full text search tables should always use MATCH and not LIKE, because a LIKE query performs a full scan of the table which defeats the purpose of creating the FTS table in the first place.
To solve your problem, trying using a tokenizer other than the default when creating your fts table:
-- Create a table using the simple tokenizer.
CREATE VIRTUAL TABLE simple USING fts3(tokenize=porter);
By default, SQLite uses a simple tokenizer which may be generating the matches you don't want. Switch to the porter tokenizer and see what happens. Worst case, you can implement your own custom tokenizer. See the SQLite documentation for further info.

Related

how to fetch data from sqlite by name

I just started learning of android and come to section of Database and I inserted same record in it but now I want to fetch data from database only by name and display it in textview.
Help me
Thank You in advance
Please follow developer document.
https://developer.android.com/training/basics/data-storage/databases.html
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
FeedEntry._ID,
FeedEntry.COLUMN_NAME_TITLE,
FeedEntry.COLUMN_NAME_SUBTITLE
};
// Filter results WHERE "title" = 'My Title'
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };
// How you want the results sorted in the resulting Cursor
String sortOrder =
FeedEntry.COLUMN_NAME_SUBTITLE + " DESC";
Cursor cursor = db.query(
FeedEntry.TABLE_NAME, // The table to query
projection, // The columns to return
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
You access data by using a query which returns a Cursor.
A Cursor is like a spreadsheet table that contains columns and rows.
You tell the query what columns you want and imply the rows that will be returned via an optional WHERE statement.
The simplest of queries is base upon the SQL SELECT * FROM <table>;. This will select all columns (i.e. * means all columns) from the table as specified by <table> ( where would be replaced by a valid table name).
If you want specific columns then ***`` should be replaced with a comma delimited list e.g.SELECT name, address FROM would return a **Cursor** containing all the rows from the table with only the **name** and **address** columns from the table specified by`.
If you want to filter the rows returned then you can add a WHERE clause. e.g. SELECT name,address FROM <table> WHERE name = 'Fred', would return a Cursor containing only the rows that have Fred as the name column with only the name and address columns.
You cannot just type the SQL statments you need to either use the SQLiteDatabase rawQuery or query methods if you need to return a cursor.
Using rawQuery
rawQuery takes two parameters, the first being the SQL as a string, the second optional arguments (not covered here, so null will be used).
To obtain a Cursor with columns name and address and with only rows that have Fred you could use, assuming the table is called mytable :-
`Cursor mycursor = db.rawQuery("SELECT name,address FROM mytable WHERE name = 'Fred'";);`
where db is an instance of an SQLiteDatabase object.
However, rawQuery is not recommended as it is open SQL injection. rather it is recommended only for situations where it has to be used.
Using query
query has a number of overload variations as can be found here SQLiteDatabase.
For this example query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) will be used.
String table, is the name of the table to be queried.
String[] columns, is an array of column names.
String selection is the where clause (null for no where clause).
String[] selectionArgs is an array of arguments that replace the ? placeholder.
The rest of the parameters will be null as these are features that are not being utilised.
As such the code could be :-
String tablename = "mytable";
String[] columns = {"name", "address"};
String whereclause = "name=?"; //note use of placeholder ?
String[] whereargs = {"Fred"};
Cursor mycursor = db.query(tablename,
columns,
whereclause,
whereargs,
null,null,null
);
where db is an instance of an SQLiteDatabase object.
Accessing the Cursor
mycursor contains the data or perhaps not if there isn't a column with the name Fred.
The number of rows in the cursor can be obtained by using:-
int rowsincursor = mycursor.getCount();
Note! A returned Cursor will not be null. (a very common mistake)
To access the data you have to move through the Cursor. Initially the Cursor is before the first row. If you only expect or want the only/first row then you can use the Cursor moveToFirst method.
See Cursor for more move... methods etc
Once the Cursor is appropriately positioned you can use Cursor get methods to get the data. e.g. getString(int columnindex) will return the data as a String. columnindex is a 0 based offset of the column to be accessed. Using the Cursor's getColumnIndex(String columnname) can be used to eliminate errors made by miscalculating offsets.
As such the following could be used to set a TextView (note intentionally over cautious)
if (mycursor.getCCount() > 0) {
if (mycursor.moveToFirst()) {
mytextview.setText(mycursor.getString(mycursor.getColumnIndex("name")));
}
}
mycursor.close() // You should always close a cursor when done with it.

Android SQLite query cursor moveToFirst

I'm making an Android App with a sqlite db, which has a query method like this:
String[] projection = {COLUMN_NAME_ID};
String selection = COLUMN_NAME_TEAM + " = ?";
String[] selectionArgs = {teamId.toString()};
String sortOrder = COLUMN_NAME_NAME + " ASC";
Cursor c = db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
if (c.moveToFirst()){
//...
}
as suggested here. The point is to implement this query:
SELECT PLAYER_ID FROM PLAYERS WHERE TEAM_ID = ? ORDER BY NAME ASC;
According to the SQLiteDatabase.query documentation, this is a valid call to query(), and so far I've been doing it successfully with all my other queries in this App.
For some reason, in this query (and only in this) the App freezes in c.moveToFirst().
Some answers to similar questions suggest that it might be a performance issue. I don't think this is the case, as my table has only 6 rows and the query is quite simple.
Any ideas?
Thanks

SQLiteDatabase Cursor empty only on Android 5.0+ devices

The application has a SearchView which fetches suggestions from a specific database table. Everything worked without any errors until Android 5.0 appeared.
As of then, when the SQLiteQueryBuilder queries the database to fill the Cursor object, the return is empty cursor. Not NULL, but empty.
On other platforms, I can output the Cursor's content via DatabaseUtils.dumpCursorToString(cursorObject), but on Android 5.0+ the method reports output on null objects
Dumping cursor null
<<<<<
Even more: when I extract database file from 5.0+ devices and run the local SQL query, I can fetch all data. So the database is valid indeed. And the query is the simplest one
SELECT rowid AS _id, suggest_text_1, suggest_text_2, rowid AS suggest_intent_data_id
FROM fts
WHERE (fts MATCH '*e*') //<-- I pressed "e" on the keyboard
The logic for selecting data from the database and filling the Cursor object is really simple
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(FTS3_TABLE);
builder.setProjectionMap(mColumnMap);
Cursor cursor = builder.query(db,columns, selection, selectionArgs,
null, null, null);
I tried looking for some deprecated methods, but was without any luck.
I have already spent 3 days debugging each step in the process and I am out of any ideas what could be causing such behaviour.
Anyone has any ideas?
EDIT
The output of the method buildQuery()
String query = builder.buildQuery(columns, selection, null, null, null, null);
RESULT:
SELECT rowid AS _id, suggest_text_1, suggest_text_2, rowid AS suggest_intent_data_id
FROM fts
WHERE (fts MATCH ?)
selection and selectionArgs parameters are created like this
String selection = FTS3_TABLE + " MATCH ?";
String[] selectionArgs = new String[]{"*" + query + "*"};
The RAW query resulted the same thing as query via builder.query()
String query = builder.buildQuery(columns, selection, null, null, null, null);
Cursor temp = db.rawQuery(query, selectionArgs);
String output = DatabaseUtils.dumpCursorToString(temp);
Output: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#295023a7
<<<<<
Answered https://stackoverflow.com/a/30710226/437039 by laalto
MATCH '*foo*' queries never worked correctly in any version of sqlite. The fact that you got some results earlier was just a coincidence. Just the prefix form MATCH 'foo*' (and MATCH 'foo') are supported.
Lollipop ships with a newer version of sqlite. For detailed list of changes between sqlite versions, see the changelog.
Have you tried to query using the SQLiteDatabase query method like the following?
String selection = "fts" + " =? AND " +
String[] selectionArgs = new String [] {
"*e*"
};
String[] projection = new String [] { "rowId", "suggested_text"};
SQLiteDatabase db = mDbHelper.getReadableDatabase();
Cursor cursor = db.query("tableName",
projection,selection, selectionArgs, null, null, null);

How to return all data from one column Android SQL

I have an SQLite Database in my application. It has three columns. being _id, TEXT, and Location. If I want to return all the data from, say, the TEXT column should I use cursor.getColumnIndex(2)? I am obviously new to SQLite. And and all help is appreciated. Thanks everyone!
Yes, friend, you are new.
First off, your database doesn't have three columns, but rather, your table does. Databases have tables, tables of columns (fields) and rows (records).
Secondly, TEXT is not a valid name for a column, as it's a datatype. Let's say you called the three columns id, theText, and location -- then if you selected all three columns to be returned, the second one would be accessible through:
cursor.getString(1); // that's the second column returned
or
cursor.getString(cursor.getColumnIndex( "theText" ) );
However, you can have sqlite do most of the work for you by selecting only the column you're interested in, so then you'd cursor.getString(0) as it's the only column returned.
For more pertinent explanations, please post your code in the question.
simply apply the query of getting all contacts and take an array of string type and then add the required record in that array as shown below
I hope this code help u
in DBHelper getting record of particular column :
public ArrayList<String> getAllCotactsEmail() {
ArrayList<String> arrayList=new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from contacts", null );
res.moveToFirst();
if (res != null)
{
while(res.isAfterLast() == false){
arrayList.add(res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL)));
Log.d("emailssinlisttt",arrayList.toString());
res.moveToNext();
}}
return arrayList;
}
retrieve :
email=mydb.getAllCotactsEmail();
Log.d("emaillllll",email.toString());
You need to query your Database to get your data. This query will return a Cursor with the column you specified in the query.
To make query, you need to call query() method from ContentResolver. To get your ContentResolver, you can use getContentResolver() from a Context like Activity :
getContentResolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
To understand all parameters, see : ContentResolver
In your case, you want only TEXT column so pass a String array with your TEXT column name for projection parameters.
You want all rows so your selection and selectionArgs parameters must be null.
If you don't care about order, pass null for sortOrder (rows will be sort by ID) :
Cursor c = getContentResolver.query(yourUri, new String[]{"TEXT"}, null, null, null)
This query will return a cursor, to extract your values from the cursor, make a loop like :
if(c.moveToFirst()) {
do {
final String text = c.getString(c.getColumnIndex("TEXT"));
} while (c.moveToNext());
}
Hope this will help you :)

Android sql query using WHERE clause

Dear Stack Overflow Community,
I have a question regarding how to incorporate a WHERE clause when querying a sql database in Android. My goal is to return specific records from my database where the date picked by a datepicker matches the date stored.
Here is my code:
private static String datePickerDate = "3/29/2011";
private static String[] FROM = { _ID, NAME, PRICE, DATE, TIME };
private static String ORDER_BY = TIME + " DESC ";
private static String WHERE = DATE + "is like " + datePickerDate;
private Cursor getEvents(){
// Perform a managed Query. The Activity will handle closing
// and re-querying the cursor when needed
SQLiteDatabase db = events.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, ORDER_BY);
startManagingCursor(cursor);
return cursor;
}
My questions are thus:
Where does my "WHERE" statement go?
And is my "WHERE" statement correct?
The documentation I found for db.query doesn't specify if a "WHERE" clause can be used, it just specifies that a "HAVING" clause is possible, but I don't quite think that's what I'm wanting.
db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy)
The selection represents your WHERE clause.
From the doc
selection A filter declaring which
rows to return, formatted as an SQL
WHERE clause (excluding the WHERE
itself). Passing null will return all
rows for the given table.
So you can try this (untested):
private static String WHERE = "DATE like ?";
db.query(table, columns, WHERE , new String[] { datePickerDate }, groupBy, having, orderBy)
If you want to use the WHERE clause, I would suggest using the raw query function in the SQLiteDatabase class, shown here.
This way, you can have the raw query typed out (or in segments) as if you were doing it naturally with SQL.
EDIT: On a side note, the "selection" parameter of the query() function corresponds to the WHERE clause, as noted here
About where you're "WHERE" goes - look here
And regarding the second part, I think you miss the qouts before and after the value, it should be .. like '3/29/2011' and not .. is like 3/29/2011

Categories

Resources