Using the code below i can check if a row contains a single string ( String a) but how would i check if a row equals either string (String a or b)?
public Cursor fetchMyList() {
String[] columns = { KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY,
KEY_DESCRIPTION, KEY_EMAIL };
String selection = "description=?";
String a = "blue";
String b = "red";
String[] selectionArgs = { a };
// String[] selectionArgs = { a , b}; ///tried this dont work!!
Cursor cursor = null;
try {
cursor = database.query(DATABASE_TABLE, columns, selection,
selectionArgs, null, null, null);
} catch (Exception e) {
e.printStackTrace();
}
int numberOfRows = cursor.getCount();
if (numberOfRows <= 0) {
return cursor;
}
return cursor;
}
You can only pass 2 arguments if you declare 2 arguments. This is what you want:
String selection = "description=? OR description=?"; // Select rows with either description
String[] selectionArgs = {a , b};
I strongly suggest you check SQL language.
PS: do not catch Exception. You'll regret it later. Catch specifc Exception children; in your case you want to catch SQLException.
PS2: use Log instead of printStackTrace().
Related
I have an SQL query from string and trying to access ContentProvider. The sql query looks like:
String query = "SELECT * FROM application_settings WHERE _id = ?";
I have to access content provider by gettting ContentResolver like:
context.getContentResolver().query()
but query method accepts:
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
Is there a way I can split the string query into projection, selection, selectionArgs and sortOrder?
I do not wish to execute raw queries so I would prefer to have a solution for this function with bind values.
I have just written a library which provides what you need. You only need to copy and paste it into the project and if you would like to add, expand and customize it depending on your requirements.
SqliteHandler.java
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
class SqliteHandler {
// VERY IMPORTANT MAKE SURE IT'S CORRECT AND REGISTERED IN THE MANIFEST
private String PROVIDER_NAME = "com.example.android.mySqlite";
private String CONTENT_URL = "content://" + PROVIDER_NAME + "/";
private Context context;
SqliteHandler(Context context, String PROVIDER_NAME) {
this.context = context;
this.PROVIDER_NAME = PROVIDER_NAME;
}
Cursor exeQuery(String query) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String selection, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String[] projection, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, projection, obj.selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(queryObject obj) {
try {
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
class queryObject {
Uri uri;
String[] projection;
String selection;
String[] selectionArgs;
String sortOrder;
queryObject(String table_name, String[] projection, String selection, String[]
selectionArgs) {
this.uri = Uri.parse(CONTENT_URL + table_name);
this.projection = projection;
this.selection = selection;
this.selectionArgs = selectionArgs;
}
}
queryObject convertQueryStringToQueryObject(String query) {
try {
String selection = null;
String[] selectionArgs = null;
query = query.toLowerCase();
String[] s = query.split("select")[1].split("from");
String[] projection = s[0].split(",");
String[] s2 = s[1].split("where");
String table_name = s2[0];
String logText = "";
if (s2.length > 1) {
selection = s2[1];
String[] args = s2[1].split("=");
selectionArgs = new String[args.length - 1];// half of the args are values others are keys
int count = 0;
for (int i = 1; i < args.length; i++) {
selectionArgs[count] = args[i]
.split("and")[0]
.split("or")[0]
.replace(" ", "")
.replace("and", "")
.replace("or", "");
count++;
}
for (int i = 0; i < selectionArgs.length; i++) {
logText += selectionArgs[i];
if (i < selectionArgs.length - 1) logText += ",";
selection = selection.replace(selectionArgs[i], "?");
}
}
Log.i("table_name", table_name);
Log.i("selection: ", selection == null ? "null" : selection);
Log.i("selectionArgs", logText.equals("") ? "null" : logText);
logText = "";
for (int i = 0; i < projection.length; i++) {
logText += projection[i];
if (i < projection.length - 1) logText += ",";
}
Log.i("projection", logText);
return new queryObject(table_name, projection, selection, selectionArgs);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}}
How To Use
instantiate SqliteHandler, it's very important to pass valid PROVIDER_NAME and also make sure that your CONTENT_PROVIDER was registered in the AndroidManiFest.xml. For an illustration of how does it work, we pass three different queries and get return values which are objects of type queryObject
SqliteHandler sh = new SqliteHandler(this,"PROVIDER_NAME");
SqliteHandler.queryObject obj1 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name");
SqliteHandler.queryObject obj2 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name WHERE _id = ?");
SqliteHandler.queryObject obj3 = sh.convertQueryStringToQueryObject("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
The method convertQueryStringToQueryObject converts query string into query class then we can use this class for getContentResolver().query().
Important Note: because getContentResolver().query() needs Uri. Therefore, we need to create a Uri from the table_name. As a result, we need to pass valid PROVIDER_NAME to the instance of SqliteHandler.
Output Log
As you can see the three different queries broke apart into parameters which we can use in the getContentResolver().query()
// 1th query
I/table_name: table_name
I/selection:: null
I/selectionArgs: null
I/projection: *
// 2th query
I/table_name: table_name
I/selection:: _id = ?
I/selectionArgs: ?
I/projection: *
// 3th query
I/table_name: table_name
I/selection:: param1 =? and param2=? or param3=?
I/selectionArgs: "a","b","c"
I/projection: param1,param2,param3
Complete Example
in The SqliteHandler.java there is the exeQuery method which has several overloads. Moreover, You can have a Cursor at the Content Provider depending on different input parameters.
SqliteHandler sh = new SqliteHandler(this,"PROVIDER_NAME");
SqliteHandler.queryObject obj1 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name");
SqliteHandler.queryObject obj2 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name WHERE _id = ?");
SqliteHandler.queryObject obj3 = sh.convertQueryStringToQueryObject("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
Cursor c = sh.exeQuery(obj1);
Cursor c = sh.exeQuery(obj2);
Cursor c = sh.exeQuery(obj3);
Cursor c = sh.exeQuery("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
Cursor c = sh.exeQuery("SELECT * FROM table_name WHERE _id = ?",new String[]{"whereArg"});
Cursor c = sh.exeQuery("SELECT * FROM table_name"," _id = ? ",new String[]{"whereArg"});
Cursor c = sh.exeQuery("SELECT ? FROM table_name WHERE _id = ?",new String[]{"Field"},new String[]{"whereArg"});
However, if you don't want to use exeQuery try below walking through:
queryObject obj = convertQueryStringToQueryObject(query);
Cursor c = this.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
from the android document https://developer.android.com/guide/topics/providers/content-provider-basics#ClientProvider
cursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, // The content URI of the words table
projection, // The columns to return for each row
selectionClause, // Selection criteria
selectionArgs, // Selection criteria
sortOrder); // The sort order for the returned rows
you can do this
String[] projection = {"*"};
String[] selectionArgs = {"1", "2"}; //your ids here
Cursor cursor = getContentResolver().query(Uri.parse("content://your_provider/your_table"), projection, "_id", selectionArgs, null);
cursor.close();
to create provider see this https://developer.android.com/guide/topics/providers/content-provider-creating#top_of_page
see this answer also https://stackoverflow.com/a/1031101/10989990
How would i go about this, i have COLUMN_ID, COLUMN_NAME and COLUMN_INTE
COLUMN_INTE holds long integers and I want it to be displayed on a List view, which it currently does just not descending from highest to lowest
You need to write your query against your table with an ORDER BY clause that dictates a descending order with the DESC keyword. Something like this should work:
string query = "SELECT COLUMN_ID, COLUMN_NAME, COLUMN_INTE FROM MY_TABLE ORDER BY COLUMN_INTE DESC";
Cursor c = db.rawQuery(query, null);
String[] columns = new String[] { "COLUMN_ID", "COLUMN_NAME"};
int[] to = new int[] {android.R.id.text1, android.R.id.text2};
try {
dataAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_list_item_2, c, columns, to, 0
);
ListView lv = (ListView) findViewById(R.id.MY_LISTVIEW);
lv.setAdapter(dataAdapter);
} catch (Exception ex) {
ex.printStackTrace();
}
You can also use comparator to do sorting . Like an example -
class MySalaryComp implements Comparator{
#Override
public int compare(Empl e1, Empl e2) {
if(e1.getSalary() < e2.getSalary()){
return 1;
} else {
return -1;
}
}
}
You have two options: Use an SQL command that sorts for you or you can get the entire list and sort it yourself.
SQL command sorting:
// Create an object to store rows from the table
tableRowObject = new tableRowObject();
String query = "select * from STATISTICS order by COLUMN_INTE";
Cursor cursor = db.rawQuery(query, null);
if(cursor.getCount()<1) // COLUMN_INTE Not Found
{
cursor.close();
}
else
{
while(cursor.moveToNext())
{
// Get COLUMN_ID, COLUMN_NAME, COLUMN_INTE
int columnID = cursor.getInt(cursor.getColumnIndex("COLUMN_ID"));
String columnName = cursor.getString(cursor.getColumnIndex("COLUMN_NAME"));
int columnInte = cursor.getInt(cursor.getColumnIndex("COLUMN_INTE"));
// Add the variables to a new object
tableRowObject.add(columnID, columnName, columnInte);
}
cursor.close();
}
Sort yourself:
// Create an object to store rows from the table
tableRowObject = new tableRowObject();
String query = "select * from STATISTICS";
Cursor cursor = db.rawQuery(query, null);
if(cursor.getCount()<1) // COLUMN_INTE Not Found
{
cursor.close();
}
else
{
while(cursor.moveToNext())
{
// Get COLUMN_ID, COLUMN_NAME, COLUMN_INTE
int columnID = cursor.getInt(cursor.getColumnIndex("COLUMN_ID"));
String columnName = cursor.getString(cursor.getColumnIndex("COLUMN_NAME"));
int columnInte = cursor.getInt(cursor.getColumnIndex("COLUMN_INTE"));
// Add the variables to a new object
tableRowObject.add(columnID, columnName, columnInte);
}
cursor.close();
}
// Sort the object
how can I retrieve a single contact and some associated data (e.g. emails, phonenumbers, addresses...) by its id/lookupkey?
This is the code I use to add contacts (actually its from the internet and is working for me).
// Asking the Contact provider to create a new contact
try {
result = this.context.getContentResolver().applyBatch(
ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this.context, "Exception: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
Uri myContactUri = result[0].uri;
int lastSlash = myContactUri.toString().lastIndexOf("/");
int length = myContactUri.toString().length();
int contactID = Integer.parseInt((String) myContactUri.toString()
.subSequence(lastSlash + 1, length));
return contactID;
Now I want to fetch this new contact. How do I do it? All I came up with is this:
ContentResolver content = context.getContentResolver();
String[] projection = { Data.LOOKUP_KEY, Data.MIMETYPE,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Email.ADDRESS };
// Defines the selection clause
String selection = Data.LOOKUP_KEY + " = ?";
// Defines the sort order
String sortOrder = Data.LOOKUP_KEY;
String[] args = {"2400"};
Cursor cursor = content.query(Data.CONTENT_URI, projection, selection,
args, sortOrder);
When I remove the selection I get all contacts+all their data. So I looked up the key 2400 in my case and wanted to fetch this contact by its lookupkey. Well, does not work. cursor.getCount() return 0.
Any ideas?
My solution now is to use to following:
String[] projection = { Data.MIMETYPE,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Email.ADDRESS };
// Defines the selection clause
String selection = ContactsContract.Data.RAW_CONTACT_ID + "=?";
// Defines the sort order
String sortOrder = Data.LOOKUP_KEY;
String[] args = { id+"" };
Cursor cursor = content.query(Data.CONTENT_URI, projection, selection,
args, sortOrder);
Sort order doesnt matter, but I use the RAW_CONTACT_ID, which works well!
I wish to pull out of the second row of the column NAME.
case R.id.buttonTest: {
String[] projection = {DbTest.NAME};
String selection = "_id = ?";
String[] selectionArgs = { String.valueOf(1) };
Cursor c = sqdb.query(DbTest.TABLE_NAME,projection,selection,selectionArgs ,null,null,null);
moveToPosition(2);
String name = c.getString(c.getColumnIndex(DbTest.NAME));
textView1.setText(name);
}
break;
Call moveToPosition on reference to cursor:
c.moveToPosition(int)
If you`ll call
cursor.moveToFirst();
then after
cursor.moveToNext();
, you will move to the second position.
I used this in my code,
while (cursor.moveToNext()){
if(cursor.getPosition() == position){
String sss = cursor.getString(0).toString();
}
}
I am trying to make a query to sqlite android to see for example how many users of a given username exist in a table.
This is my function. I must specify that "getContentResolver() != null" and so is variable name.
private int findSelectedUser(String name) {
int count = 0;
try {
String[] whereArgs = new String[] {name};
String[] PROJECTION = new String[] { MyProvider.SETTINGS_USERNAME };
Cursor c = getContentResolver().query(MyProvider.SETTINGS_URI,
PROJECTION, MyProvider.SETTINGS_USERNAME , whereArgs, null);
if (c != null) {
count = c.getCount();
c.close();
}
} catch (NullPointerException e) {
}
System.out.println("Found something? " + count);
return count;
}
And after running i receive the error from the subject...and don't get it. In my where clause i have one column, in my where arguments one value.
Please help me make some sence of this, Thank you.
I guess that works:
String[] whereArgs = new String[] {name};
String[] PROJECTION = new String[] { MyProvider.SETTINGS_USERNAME };
Cursor c = getContentResolver().query(MyProvider.SETTINGS_URI,
PROJECTION, MyProvider.SETTINGS_USERNAME + "=?" , whereArgs, null);
if (c != null) {
count = c.getCount();
c.close();
}
If you want to use whereArgs you have to have the same amount of ? in the where as you have items whereArgs
whereArgs will replace the ? in the final database query
String where = "name = ? OR name = ?";
String[] whereArgs = new String[] {
"Peter",
"Jim"
};
that results in name = 'Peter' OR name = 'Jim' for the query.
Btw: don't catch(NullPointerException e) - make your code safe so they can't happen