rawQuery() in Android SQLite not compiling parameters - android

While trying to implement SQLite storage ran into strange behavior.
The "?"-symbols are not substituted.
My code:
public class DBHandler extends SQLiteOpenHelper {
public void writeTask(JSONObject object) throws JSONException {
SQLiteDatabase db = this.getWritableDatabase();
String id = object.get(OBJECT_ID).toString();
String content = object.toString();
String md5 = "md5"; //testing
Cursor c = db.rawQuery("INSERT OR REPLACE INTO ? ( ? , ? , ? ) VALUES ( ? , ? , ?);", new String[] {TABLE_OBJECTS, OBJECT_ID, OBJECT_CONTENT, OBJECT_MD5, id, content, md5 });
}
}
Then it throws a strange error:
android.database.sqlite.SQLiteException: near "?": syntax error (code 1): , while compiling: INSERT OR REPLACE INTO ? ( ? , ? , ? ) VALUES ( ? , ? , ?);
First mistake corrected, but still not working:
String selectQuery = "INSERT OR REPLACE INTO " + TABLE_OBJECTS + " ("
+ OBJECT_ID + "," + OBJECT_CONTENT + "," + OBJECT_MD5 + ") "
+ "VALUES ( ? , ? , ?);";
String[] args = { id, content, md5 };
Log.d("FP", selectQuery);
Cursor c = db.rawQuery(selectQuery,args);
Now database is untouched after this query. Logs show my query:
INSERT OR REPLACE INTO objects (id,content,md5) VALUES (?,?,?);
Any suggestions?
so, rawQuery() is just for SELECT.
But i still need to do escaping special characters, because content-variable is a stringified JSON and execSQL does not allow this.

You can use ? only for binding literals such as those in your VALUES(), not for identifiers such as table or column names earlier in your SQL.
If you need to use variables for identifiers, use regular string concatenation in Java.
Also note that rawQuery() alone won't execute your SQL. Consider using execSQL() instead.

Related

SQLite - Match results based on string value issue

I'm currently having an issue with my SQL Lite code with regards to counting matching results. In my application the user will have the ability to add a new folder and give it a name. Before the folder is added to the application my code will check to see if a folder with the same name already exists if so it will prompt the user.
When using my code below I receive an error informing me the column doesn't exist. If I remove everything past WHERE then it works perfectly and counts every record within the table.
I've reinstalled the application and changed the database version so that its completely clean, just to make sure. I'm certain its only something very minor I'm missing.
public int countMatchingFolders (String folderName){
String countQuery = "SELECT * FROM " + Primary_Table + " WHERE " + Col_FolderName + " = " + folderName;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
int cnt = cursor.getCount();
cursor.close();
return cnt;
}
Error message I'm receiving
android.database.sqlite.SQLiteException: no such column: testFolder (code 1): , while compiling: SELECT * FROM Folder_Table WHERE Col_FolderName = testFolder
Any assistance to help with the issue would be greatly appreciated.
The error is because the string value doesn't have quotes around it, so it is treated as a table name instead of a string. You should use a bound query argument to fix this. Bound arguments also prevent SQL injection attacks:
String countQuery = "SELECT * FROM " + Primary_Table + " WHERE " + Col_FolderName + " = ?";
Cursor cursor = db.rawQuery(countQuery, new String[]{folderName});
Note that you can do "SELECT COUNT(*) as row_count" ... to let the database engine count the number of records more efficiently.

Saving webview geturl and getitle in Sqlite database. Problem with syntax error apostrophe '

When im saving webview.getTitle (); in Sqlite database, if in title has apostrophe ('), then i got error -
android.database.sqlite.SQLiteException: near "at": syntax error (code 1): , while compiling: INSERT INTO Favorite VALUES('4 madhab bid'at tavassul', 'file:///android_asset/web/akaid/4maddhab/4.htm' );
My code like this
mysql objcon = new mysql(this, null, null, 1);
SQLiteDatabase db = objcon.getReadableDatabase();
db.execSQL(
"INSERT INTO Favorite VALUES('"
+ txtnombre.getText()
+ "', '"
+ txtlink2.getText()
+"' );"
);
How to solve this problem?
There is a single quote embedded within txtnombre.getText() : '4 madhab bid'at tavassul'. This causes SQLite to wrongly consider that this quote marks the end of the first value to insert.
To avoid that, you could consider manually doubling the single quotes :
db.execSQL(
"INSERT INTO Favorite VALUES('"
+ txtnombre.getText().replaceAll("'","\''")
+ "', '"
+ txtlink2.getText().replaceAll("'","\''")
+"' );"
);
I would recommend using bind parameters. With this option, your database driver handles escaping behind the hood :
q = "INSERT INTO Favorite VALUES(?, ?)";
t1 = txtnombre.getText();
t2 = txtlink2.getText();
db.rawQuery(q, new String[] { t1, t2 });
Finally, another approach in Android would be to use native method sqlEscapeString(), which is primarily built for this purpose.
Also, as commented by pskink, using insert() would better fit your use case than raw SQL.

error occurs when updating a table in sqlite

String updateQuery = "UPDATE Bookdetails SET lastchapter = " + test + " WHERE bookpath=" +sentFilename;
db.execSQL(updateQuery);
Error:
03-04 13:36:23.997: I/System.out(9722): android.database.sqlite.SQLiteException:
near "/": syntax error: , while compiling: UPDATE Bookdetails SET lastchapter =
mukund WHERE bookpath=/mnt/sdcard/Download/What's so great about the doctrine of
grace.epub errors happens
the error is posted above
My table contains the field id, bookpath and lastchapter, book path contains the values
/mnt/sdcard/Download/What's so great about the doctrine of grace.epub
/mnt/sdcard/Download/1b4fdaac-f31d-41e8-9d15-26c9078d891f.epub
/mnt/sdcard/Download/Commentary on Romans.epub
and lastchapter contains the values nothing nothing nothing
id contains 1 2 3
why is the error occurring at "/" there is no hash in my update query it is only there at string which stores bookpath? Is this an error?
String literals in SQL need to be in '' quotes.
However, it's better to use ? placeholders for literals like this:
String updateQuery = "UPDATE Bookdetails SET lastchapter=? WHERE bookpath=?";
db.execSQL(updateQuery, new String[] { test, sentFilename });
I believe your lastchapter & bookpath is of type String (TEXT). Hence when you are adding or updating it's value you should always use ' ( Single cot ) around it. Change your query to this,
String updateQuery = "UPDATE Bookdetails SET lastchapter ='" + test + "' WHERE bookpath='" +sentFilename + "'";
db.execSQL(updateQuery);
However, Direct Execution of SQL query is not advisable at developer.android.com hence you can use alternative way like below code,
String updateQuery = "UPDATE Bookdetails SET lastchapter=? WHERE bookpath=?";
db.execSQL(updateQuery, new String[] { test, sentFilename });

insert string using sqlite in android containing single and double quotes in it

I am having trouble with inserting a string using sqlite in an android app,
I tried,
query = "INSERT OR REPLACE into table(_id, text) VALUES ("+data.get(i).id+", '"+data.get(i).text+"')";
MyClass.db.execSQL(query);
If my string looks like,
'I'm an android developer'
App crashes here, here is logcat result,
Caused by: android.database.sqlite.SQLiteException: near "m": syntax error: , while compiling: INSERT OR REPLACE into table (_id, text) VALUES (4, '"I'm an android developer"' )
I think it assumes that, my query ends here
'"I'
please help me to insert any case of string, either it contains single or double quotes like,
"I'm an "android" developer"
Without any hardcoding or anything you can directly insert with using ContentValues like below..
ContentValues values = new ContentValues();
long retvalue = 0;
values.put("_id", id_here);
values.put("text", your_text_here);
retvalue = MyClass.db.insertWithOnConflict(table, null, values, CONFLICT_REPLACE);
If you are using normal insert statement and if you have any value which contains single quote in it, then you might face a weird issue like this. So,try this..
String insert_info = "INSERT OR REPLACE INTO table(_id,text) VALUES (?,?)";
SQLiteStatement stmt = db.compileStatement(insert_info);
stmt.bindString(1, ""+data.get(i).id);
stmt.bindString(2, ""+data.get(i).text);
stmt.execute();
Multiple options:
Use ContentValues with SQLiteDatabase.insert()
Use variable binding, e.g.
db.execSQL("INSERT INTO table(_id, text) VALUES(?,?)", new String[] { idValue, textValue });
Escape the ' in strings. The SQL way to escape it is '' and you can use DatabaseUtils helpers to do the escaping.
To escape the " in Java strings, use \".
you must replace \' with \'\' in query string:
String getQuery(){
query = "INSERT OR REPLACE into table(_id, text) VALUES ("+data.get(i).id+", '"+getSqlValue(data.get(i).text)+"')";
MyClass.db.execSQL(query);
return query;
}
String getSqlValue(String input){
return input.replace("\'","\'\'");
}
You can use " for skipping " in a string

how to modify an item's value in a SQLite?

Supposing I have this sqlite database structure:
ID PRODUCT_NAME AVAILABILITY
1 foo 0
2 bar 1
3 baz 0
4 faz 1
How cand I modify the value of the AVAILABILITY fom 1 -> 0 where PRODUCT_NAME = 'bar' ?
Something like this,
Pseudocod:
db.execSQL( "UPDATE TABLE" + Table_name + "MODIFY" + availability + "=" + 0 + "WHERE" + product_name + "like ? " + 'bar');
I assume that I also have to drop and recreate table using onCreate() and onUpgrade() methods, right?
Some code will be highly appreciated.
Use this:
SQLiteDatabase db=dbHelper.getWritableDatabase();
String sql="update "+Table_name+" set availability='0' where product_name like 'bar'";
Object[] bindArgs={"bar"};
try{
db.execSQL(sql, bindArgs);
return true;
}catch(SQLException ex){
Log.d(tag,"update data failure");
return false;
}
You want update not alter. alter is for the database schema, update is for the data stored in it.
For example:
update TABLE_NAME set AVAILABILITY = 0 where PRODUCT_NAME like 'bar';
Also, do not just stick strings together to build an sql query. Use a prepared statement or other statement building library to avoid SQL injection attacks and errors.
You could also use the update(), insert(), query(), delete() methods that Android gives you
// define the new value you want
ContentValues newValues = new ContentValues();
newValues.put("AVAILABILITY", 0);
// you can .put() even more here if you want to update more than 1 row
// define the WHERE clause w/o the WHERE and replace variables by ?
// Note: there are no ' ' around ? - they are added automatically
String whereClause = "PRODUCT_NAME == ?";
// now define what those ? should be
String[] whereArgs = new String[] {
// in order the ? appear
"bar"
};
int amountOfUpdatedColumns = db.update("YourTableName", newValues, whereClause, whereArgs);
The advantage here is that you get correct SQL syntax for free. It also escapes your variables which prevents bad things to happen when you use "hax ' DROP TABLE '" as argument for ?.
The only thing that is still not safe is using column LIKE ? with arguments like "hello%world_" because % (match anything of several chars) and _ (match any 1 char) are not escaped.
You would need to escape those manually (e.g. place a ! before each _ or %) and use
String whereClause = "LIKE ? ESCAPE '!'"
String[] whereArgs = new String[] {
likeEscape("bar")
// likeEscape could be replaceAll("!", "!!").replaceAll("%", "!%").replaceAll("_", "!_") maybe
}
Btw: your single code line should work if you use
db.execSQL( "UPDATE " + Table_name + " SET " + availability + "=0 WHERE " + product_name + " like 'bar'");
SqlLite uses "SQL". You need a SQL "update"
db.execSQL( "update mytable set availability=0 where product_name like '%" + bar + "%'");
Here's a good link for SQL "select", "update", "insert" and "delete" ("CRUD") commands:
http://www.w3schools.com/sql/default.asp

Categories

Resources