What exactly is where?whereval in android sqlite? - android

There are two pieces of code,which i thought were similar ,but one gives me an error and one doesn't,so I have a few questions to ask
What exactly is "where","whereval"?
The below code gives me an error
String where = android.provider.MediaStore.Audio.Media.ALBUM
+ "="+img.get(position).Album;//here is the difference
Cursor cursor = managedQuery(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns,
where, null , orderBy);//whereval is null here
The below code doesn't give me any error
String where = android.provider.MediaStore.Audio.Media.ALBUM
+ "=?";here is the difference
String whereVal[] = {img.get(position).Album};here is the difference
Cursor cursor = managedQuery(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns,
where, whereVal , orderBy);//i have included whereVal
Please explain me the difference between the two pieces of code ??
Also how can i use two conditions in sqlite ??

In SQL, string literals are quoted 'like this'. If you insert a string literal in SQL without the quotes, you'll likely get an SQL syntax error. It's the same as in Java where "any string" without the quotes is unlikely to be valid Java code but it's valid as a string literal.
? is a placeholder for a literal. The SQL is compiled with the placeholder in place and the literal value is bound to the compiled statement. Think of it as a variable in programming languages. The value for the variable comes from the bind arguments. In Android Java sqlite wrapper, the bind args are supplied in the string array.
Further reading: http://www.sqlite.org/lang_expr.html#varparam - though the Android wrapper code adds some leaky abstractions on top of sqlite C API.
suppose i have to use the code1 to achieve the result that i am getting from code 2..what should be the syntax ??
Quote the string literal with '...':
String where = android.provider.MediaStore.Audio.Media.ALBUM
+ "='"+img.get(position).Album+"'";
Based on the comments you want a conjuction expression. Just add an AND between subexpressions, like
String where = "foo='bar' AND baz='xyzzy'";

Related

SQLite query in Android Nougat is not backwards compatible

I have an SQLite query that does not return a record by _id on Android Nougat but does return a record on Android pre-Nougat.
When I attach a debugger to the Nougat emulator and start poking around, I observe the following:
Original Code
readableDatabase.query("report_view", null, "_id = ?", new String[]{"2016309001"}, null, null, null).getCount()
Result: 0
Poking around / Evaluate expression
readableDatabase.rawQuery("SELECT * FROM report_view WHERE _id = 2016309001", null).getCount()
Result: 1
Enabling the SQLite log results in (note the single quotes):
V/SQLiteStatements: /data/user/0/xyz/bla.db: "SELECT * FROM report_view WHERE _id = '2016309001'"
For the non-raw query on Nougat. I cannot seem to enable the SQLite log on the pre-Nougat (Marshmallow) device.
So it seems the issue is caused by Android surrounding the parameter with single quotes. The _id column is of type integer. And a value surrounded by quotes is of type string. Why is this suddenly an issue on Nougat?
Unless I am mistaken your original code passes the date parameter explicitly as a string (new String[]), and the Android documentation for the query method, selectioArgs parameter states
selectionArgs String: You may include ?s in selection, which will be
replaced by the values from selectionArgs, in order that they appear
in the selection. The values will be bound as Strings.
So if you want something else than strings, you should probably perform a cast, or better, do not use the query and rawQuery methods, but prepared statements (SQLiteStatement), which will allow you to specify the type of parameters.
Also the '?' being substituted in the log should be a "fake" substitution for logging purposes (at least I hope it is a fake substitution for logging purposes, as Android should be using a bound parameter there, and not replace it in the query).
Finally the field types in Android are used only for type affinity, so it is entirely possible that even if you declared your field as "integer" in the table, if you used the Query method and its String-only parameters, you actually ended up with strings in your records.
In theory, SQLite should not behave differently. It is possible that you are using a different table definition that results in a different affinity.
Anyway, the parameter you give to the query function is a string, so it is not surprising that the database handles it as a string.
If you want to give a number to the database, you have to make the parameter a number.
And the Android framework doesn't allow this for most database functions, so you have to put it directly into the string:
db.query("report_view", null, "_id = " + "2016309001", null, null, null, null).getCount();
Please note that there is a helper function for counting rows:
DatabaseUtils.queryNumEntries(db, "report_view", "_id = " + "2016309001");

SQLite - Queries with non-English characters don't show any results

I'm using a SearchView widget and it works well, except for the fact the if the string I enter contains any non-English character the result is empty, even if it is clear that there ARE results
Example:
In the image shown above there are two results for the string "chu" but if I type "ñ" the ListView won't show any results and it's obvious that there are results.
This is what I've tried so far
public Cursor searchProductByDescription(String description) {
String where = PRODUCT_DESCRIPTION + " LIKE LOWER( ? ) ";
String[] whereArgs = { "%" + description + "%" };
this.openReadableDB();
Cursor cursor = db.query(PRODUCT_TABLE, null, where, whereArgs, null,
null, null);
if (cursor != null) {
cursor.moveToFirst();
}
this.closeDB();
return cursor;
}
I'm not sure if this is an issue related to the searchview widget or to SQLite.
I've seen a couple of question in which they suggest converting the string to LOWER o UPPER case, but this solution didn't work for me.
I'd really appreciate if you could help me here.
Thanks
LOWER() only knows how to lowercase ASCII characters. LIKE is also case insensitive only with ASCII characters. And ñ is not an ASCII character.
For a solution, consider the following:
Add another column to your table that you use for searches and use the original column only for display purposes.
Store data in this column in a normalized form such as NFC and with the case converted consistently to upper/lowercase. For example:
String stringToStore = Normalizer.normalize(originalString.toLowerCase(), Normalizer.Form.NFC);
Normalize your search strings similarly in code.
If you want to ignore accent e.g. have n also match ñ, use a slightly different approach to remove the accents.

Binding NULL arguments with queryWithFactory

I'm writing an Android app that needs to write to the SQLite database. Currently it's using rawQueryWithString to build the update query, and I'm using ? placeholders in my query combined with the selectionArgs argument to pass in the actual values.
However, sometimes I actually want to update my column (of type Date) to NULL, but if I pass in null in my selectionArgs then I get this error:
IllegalArgumentException: the bind value at index 1 is null
I can't really see how I'm supposed to make it work when the value is actually null. I guess I could pass in an empty string, which in the case of a Date column like this might just work, but suppose it was a string column and I actually did want to mean NULL in contrast to the empty string (or are they considered equivalent in SQLite?)
Here's the code:
String timestampStr = null; // Obviously not really set like this
SQLiteDatabase d = getWritableDatabase();
DBCursor c = (DBCursor) d.rawQueryWithFactory(
new DBCursor.Factory(),
"Update subject set schedulingTimestamp = ? where identifier = ?",
new String[] { timestampStr, subjId.toString() },
null);
d.close();
The column was added with the following query, so I presume it's a nullable column since I didn't specify otherwise:
ALTER TABLE subject ADD schedulingTimestamp DATE;
Wildcards are not meant to be used for inserting/updating values in SQL, AFAIK. In Android, you can use ContentValues instead in conjunction with the update() method, instead of trying to shoehorn it in the raw query method.

Android - passing field name as selectionArgs to rawQuery

I'm passing the below statement as a rawQuery in Android:
SELECT DISTINCT ltUsers._id,ltUsers.NAME,ltUsers.GLOBAL_ID, ltGroups.GROUP_NAME
FROM ltUsers
JOIN ltGroups ON (ltUsers.GROUP_ID = ltGroups.GLOBAL_ID)
WHERE ltgroups.GLOBAL_ID = ? " +
ORDER BY ltUsers.NAME ASC,ltgroups.GLOBAL_ID ASC;
With the rawQuery as follows:
Cursor c = db.rawQuery(sql,args)
It works just fine if I pass a value to the parameter, e.g.
String[] args = new String[]{"2"}
However, I also want to be able to show all rows, unlimited by the GLOBAL_ID in the WHERE clause. Testing on a dump of my SQLite database outside of Android - as well as in Android by just writing the parameter directly into the statement - shows the following clause to be a valid way to do this:
WHERE ltGroups.GLOBAL_ID = ltGroups.GLOBAL_ID
Yet when I pass the field reference ltGroups.GLOBAL_ID or [ltGroups].[GLOBAL_ID] as a parameter it fails to return any rows in the rawQuery. Any ideas on why this might be happening? Happy to produce any extra information.
Parameters always replace specific values, not anything else.
When you put the string "ltGroups.GLOBAL_ID" into the parameters array, it is interpreted as exactly that, a string.
(To show all records, just omit the WHERE clause.)

Single quote (') in edittext makes my program crash

If I write something into an edittext that contains single quote (') my program crashes. With this edittext I can search for things in my database and some of them contain this single qoute (or apostrophe whatever name it has but the point is that it's about the single qoute). I assume it has some special functions and this is why it crashes. Is there any option to ignore its function or solve this problem somehow?
for example, an item in my database:
cv.put(KEY_NAME, "Jonh's idea");
cv.put(KEY_HOTNESS, "amazing");
cv.put(KEY_MONEY, "500");
ourDatabase.insert(DATABASE_TABLE, null, cv);
Then when I search for it with this method:
return ourDatabase.query(DATABASE_TABLE, new String[] {"_id", "idea_name",},
"idea_name like " + "'%" + qq + "%'", null, null, null, null);
where qq is given by the user (for example Jonh's idea), it crahses. And yes, I get syntax error.
Sounds like the ' is causing an SQL injection of some sort... the ' is causing a syntax error in your SQL statement. There are several things you might consider double checking:
rawQuery() will not protect you from SQL injections, so avoid using it (rather, use the query, insert, update, and delete methods instead).
Prefer formatting your selection and selectionArgs as follows (as it will protect you from SQL injections):
selection = "col_1 = ?";
selectionArgs = new String[] { "value_1" };
(note that the values in the String[] replace the ?s in the selection string).
Set an inputType on your EditText to prevent users from entering these characters in the first place (i.e. if you only want users to enter numbers, then set android:inputType="number").
Overall, as long as you correctly make use of the Android methods in the SQLiteDatabase class, you shouldn't run into any problems with SQL injections (Android does a good job at cleaning this up for you). That said, if you don't choose to make use of these special-purpose methods, then you should check the content of the String at runtime and protect against characters such as ', ;, ", etc. by escaping them.
You can refer to this post for more information:
Android Single Quote In SQL With a LIKE StateMent
You need to use the selectionArgs argument to escape the string (so that the single quote in it doesn't break the SQL). Try something like this:
return ourDatabase.query(DATABASE_TABLE, new String[] {"_id", "idea_name",}, "idea_name like ?", new String[] { "%" + qq + "%" }, null, null, null);
It seems like SQL-injection. U have to escape your input.
One more jugaad. You can replace ' with `. You won't have to recheck your code. Just modify the following:
String input = edittext.getText().toString();
if(input.contains("'"))
{
input = input.replace("'", "`");
}
//now proceed with the database operation ...
This will enable the user to input text like RD's jugaad to RD`s jugaad

Categories

Resources