How to do a rtrim() to a Android Cursor query? - android

I have the following query:
Cursor c = sd.query(itemsTable.Table_Name, columns, itemsTable.ItemNumber + "= ?", selectionArgs, null, null, null);
I need to be able to do this:
'SQL Query I am running on the database using for testing
select * from items where rtrim(itemnumber) = '292664'
Where itemnumber is my selectionArgs.
The SQL query returns the correct results but the cursor query returns null.
I would rather not change the way I am running queries and would like to know if there is a way to convert my existing query to work the same as the SQL query.

Try the following:
String selection = "RTRIM(" + itemsTable.ItemNumber + ") = ?";
String[] selectionArgs = new String[] {"292664"}; // or whatever
Cursor c = sd.query(itemsTable.Table_Name, columns, selection, selectionArgs, null, null, null);

Related

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

SimpleAdapter needs an _id field

I got this :
Cursor c = db.query("Org", null, null, null, null, null, null);
which means I choose a table "Org", but together with this I need to make this :
Cursor c = db.rawQuery(" SELECT "+ id + " AS _id")
because SimpleAdapter need to have an _id field necessarily for some reason or it will crash with an error. How do I combine this 2 into one query?
The second parameter of the query function is the list of columns.
If you want to rename a column, you cannot just blindy return all columns but have to list the desired columns:
String[] columns = new String[] { id+" AS _id", "Name", "Color", "whatever..." };
Cursor c = db.query("Org", columns, null, null, null, null, null);
For your statement : Cursor c = db.query("Org", null, null, null, null, null, null); the second parameter is wrong, you shoukd mention the column names in it.
public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
Whereas for,
Cursor c = db.rawQuery(" SELECT "+ id + " AS _id from Org");
means that you Select id and create an alias of it using AS into _id, and you are selecting this id from Org table.
so now you will be able to access the result from this query from the column name _id, and in order to access the result use:
c.moveToFirst();
while (c.moveToNext())
{
System.out.println(c.getString(c.getColumnIndex("_id"));
}

Android SQLite "BETWEEN" not inclusive or returns all records

Very simple task it would seem, trying to get a given range of records/rows in my SQLite db in Android app with the following :
String[] projection = {"_id"};
String selection = "_id between ? and ?";
String[] selectionArgs = {"1", "10"};
queryBuilder.query(db, projection, selection, selectionArgs, null, null, null);
With the above selectionArgs I'm getting just the two rows, row 1 and 10. If I change arg to anything else I'm getting the whole lot (entire set of records/rows) as if there was no condition. Been banging my head for a day why this works the way it does, perhaps there's some special thing to know about the use of "between" in SQLite ? Any comments/help much appreciated.
You can use this code.
private SQLiteDatabase productDatabase;
public Cursor get_result(){
Cursor c;
String sql = "SELECT * FROM " + tableName +"WHERE _id BETWEEN" + value1 +"AND" + value2;
c = productDatabase.rawQuery(sql, null);
}
Cursor cursor=get_result();
if(cursor.moveToNext()){
Log.d("count of product id="+cursor.getString(0));
}
Seems problem from your side I checked and it works fine,
Method
public Cursor GetBetween(String[] projection,String selection, String[] args){
return db.query(TBL_NAME, projection, selection, args, null, null, null);
}
Implementation
String[] projection = new String[]{"_id"};
String[] selectionArgs = new String[]{"1","3"};
String selection = "_id between ? and ?";
Cursor cursorGetBetween = helper.GetBetween(projection,selection, selectionArgs);
startManagingCursor(cursorGetBetween);
cursorGetBetween.moveToFirst();
while(!cursorGetBetween.isAfterLast()){
Log.d("value of cursorGetBetween", cursorGetBetween.getString(0));
cursorGetBetween.moveToNext();
}
Output
01-31 18:42:58.176: D/value of cursorGetBetween(647): 1
01-31 18:42:58.176: D/value of cursorGetBetween(647): 2
01-31 18:42:58.176: D/value of cursorGetBetween(647): 3

Group By in ContentResolver in Ice Cream Sandwich

I am making a query on the Android Contacts ContentProvider. I need a Group By clause. In Gingerbread and Honeycomb, I do something like this to search phone numbers and emails at the same time:
(The actual WHERE clause is much more complicated as it includes types checks. This is a simplification, but it yields the same result)
String request = Phone.NUMBER + " LIKE ? OR " + Email.DATA + " LIKE ?";
String[] params = new String["%test%", "%test%"];
Cursor cursor = getContentResolver().query(
Data.CONTENT_URI,
new String[] { Data._ID, Data.RAW_CONTACT_ID },
request + ") GROUP BY (" + Data.RAW_CONTACT_ID,
params, "lower(" + Data.DISPLAY_NAME + ") ASC");
The injection of the ')' finishes the WHERE clause and allow the insertion of a GROUP BY clause.
However, in Ice Cream Sandwich, it appears that the ContentProvider detects this and adds the correct number of parenthesis to prevent my injection. Any other way of doing this in a single cursor query?
Edit
Currently, I have removed the GROUP BY, and added a MatrixCursor to limit the impact, but I'd rather have a real cursor:
MatrixCursor result = new MatrixCursor(new String[] { Data._ID, Data.RAW_CONTACT_ID });
Set<Long> seen = new HashSet<Long>();
while (cursor.moveToNext()) {
long raw = cursor.getLong(1);
if (!seen.contains(raw)) {
seen.add(raw);
result.addRow(new Object[] {cursor.getLong(0), raw});
}
}
I recently battled this issue querying the CallLog.Calls DB (where we were not able to modify the ContentProvider). What we ended up going with was building a query that looked like this:
SELECT _id, date, duration, type, normalized_number FROM calls WHERE _id IN (
SELECT _id FROM calls WHERE date < ? GROUP BY normalized_number ORDER BY date DESC LIMIT ?
);
The idea here is that we place any valid sqlite in our subquery, return a list of ids and then query again for all calls with those ids.
The final code looked something like this:
String whereClause = "_id IN (SELECT _id FROM calls WHERE data < ? GROUP BY normalized_number ORDER BY date DESC LIMIT ?)";
Cursor cursor = context.getContentResolver().query(
CallLog.Calls.CONTENT_URI,
new String[] { "_id", "date", "duration", "normalized_number" },
whereClause,
new String[]{ String.valueOf(amount), String.valueOf(dateFrom) },
null
);
...
In the case that you're querying for contacts, it would look something like this:
String whereClause = "_id IN (SELECT _id FROM contacts WHERE " + Phone.NUMBER + " LIKE ? OR " + Email.DATA + " LIKE ? GROUP BY " + Data.RAW_CONTACT_ID + " ORDER BY lower(" + Data.DISPLAY_NAME + ") ASC)";
String[] params = new String["%test%", "%test%"];
Cursor cursor = getContentResolver().query(
Data.CONTENT_URI,
new String[] { Data._ID, Data.RAW_CONTACT_ID },
whereClause,
params,
null
);
There will be some decrease in performance (since we're essentially querying twice for the same results), but it will surely be a lot faster than querying for all calls and doing the GROUP BY work in java world and also allows you to build up the query with additional clauses.
Hope this helps. We used this on Oreo and it fulfilled our needs.
You could create a custom Uri such that when your UriMatcher in your ContentProvider gets it, you can insert your group by clause and then execute the raw sql directly on the database.
first off all excuse my POOR English!
I'm new to Java/Android, started with 4.2.1 and fight with that too almost 2 days, then i start reading some more details about SQLiteQueryBuilder the query part is pretty much that what u are looking for ;)
it have:
public Cursor query (SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder)
the query "function" of the Content Provider only gives you:
query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)
here u can trick around, i will post you my code snip:
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
/* a String is a Object, so it can be null!*/
String groupBy = null;
String having = null;
switch (sUriMatcher.match(uri)) {
...
...
...
case EPISODES_NEXT:
groupBy = "ShowID";
queryBuilder.setTables(EpisodenTable.TableName);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
Cursor c = queryBuilder.query(db, projection, selection, selectionArgs,
groupBy, having, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
thats its!
here the code i use to execute:
Cursor showsc = getContext().getContentResolver().query(
WhatsOnTVProvider.CONTENT_EPISODES_NEXT_URI,
EpisodenTable.allColums_inclCount,
String.valueOf(Calendar.getInstance().getTimeInMillis() / 1000)
+ " < date", null, null);

How to perform an SQLite query within an Android application?

I am trying to use this query upon my Android database, but it does not return any data. Am I missing something?
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String select = "Select _id, title, title_raw from search Where(title_raw like " + "'%Smith%'" +
")";
Cursor cursor = db.query(TABLE_NAME, FROM,
select, null, null, null, null);
startManagingCursor(cursor);
return cursor;
This will return you the required cursor
Cursor cursor = db.query(TABLE_NAME, new String[] {"_id", "title", "title_raw"},
"title_raw like " + "'%Smith%'", null, null, null, null);
Alternatively, db.rawQuery(sql, selectionArgs) exists.
Cursor c = db.rawQuery(select, null);
This will also work if the pattern you want to match is a variable.
dbh = new DbHelper(this);
SQLiteDatabase db = dbh.getWritableDatabase();
Cursor c = db.query(
"TableName",
new String[]{"ColumnName"},
"ColumnName LIKE ?",
new String[]{_data+"%"},
null,
null,
null
);
while(c.moveToNext()){
// your calculation goes here
}
I came here for a reminder of how to set up the query but the existing examples were hard to follow. Here is an example with more explanation.
SQLiteDatabase db = helper.getReadableDatabase();
String table = "table2";
String[] columns = {"column1", "column3"};
String selection = "column3 =?";
String[] selectionArgs = {"apple"};
String groupBy = null;
String having = null;
String orderBy = "column3 DESC";
String limit = "10";
Cursor cursor = db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
Parameters
table: the name of the table you want to query
columns: the column names that you want returned. Don't return data that you don't need.
selection: the row data that you want returned from the columns (This is the WHERE clause.)
selectionArgs: This is substituted for the ? in the selection String above.
groupBy and having: This groups duplicate data in a column with data having certain conditions. Any unneeded parameters can be set to null.
orderBy: sort the data
limit: limit the number of results to return
Try this, this works for my code
name is a String:
cursor = rdb.query(true, TABLE_PROFILE, new String[] { ID,
REMOTEID, FIRSTNAME, LASTNAME, EMAIL, GENDER, AGE, DOB,
ROLEID, NATIONALID, URL, IMAGEURL },
LASTNAME + " like ?", new String[]{ name+"%" }, null, null, null, null);

Categories

Resources