Debugging sqlite - iphone

Is there a way to see what the resulting 'showStatement' is after sqlite3_prepare_v2 and sqlite3_bind_xxx ?
Running this query :
SELECT *
FROM shows, locations
WHERE (shows.day_id = 1)
AND (shows.id IN (6,7,15,19,23,66))
AND (shows.location_id = locations.id)
ORDER by locations.sort_order
runs perfectly in SQLite Manager and in code when I enter it EXACTLY like that. If I however do parameter substitution the query returns no results...
if (sqlite3_open([databasePath UTF8String],&showsDatabase) == SQLITE_OK){
const char *sqlStatement = "SELECT * FROM shows, locations WHERE (shows.day_id = ?) AND (shows.id IN (?)) AND (shows.location_id = locations.id) ORDER by locations.sort_order";
sqlite3_stmt *showStatement;
if(sqlite3_prepare_v2(showsDatabase, sqlStatement, -1, &showStatement, NULL) == SQLITE_OK) {
sqlite3_bind_int(showStatement, 1, forDay);
sqlite3_bind_text(showStatement, 2, allFavorites,-1,NULL);
int error = sqlite3_step(showStatement);
while(sqlite3_step(showStatement) == SQLITE_ROW) {
...
The problem must lie in the IN (6,7...) part, without that it works perfect.
My debugger shows me that forDay = 1 and that allFavorites = 6,7,15,19,23,66
but the error = 101 = sqlite3_step() has finished executing = no lines found
Being able to see the 'showStatement' variable in one way or another would solve the problem, however the debugger doesn't give that info

You can't bind IN (?) with an array.
You need to write shows.id IN (?, ?, ?, ?, ?, ?) and bind each parameter separately. The number of question marks also has to match the number of parameters so you might need to construct the query dynamically if the number can vary.

Related

Calling prepare with mysqli - SQL syntax error

$q2 = "UPDATE `tasks` SET `title` = ?, task = ?, rules = ?, media = ?, type = ?, xp = ?, available = ?, timestamp = ? WHERE id = ?";
if ($stmt = $mysqli->prepare($q2)) {
$stmt->bind_param("sssssissi", $_POST["tasktitle"], $_POST["editor"], $_POST["rules"], serialize($_POST["media"]), $_POST["type"], $_POST["xp"], $a = 0, strtotime("now"), $_GET['id']);
$stmt->execute();
$stmt->close();
}
$r = $mysqli->query($q2) or die($mysqli->error);
I got this error msg:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?, task = ?, rules = ?, media = ?, type = ?, xp = ?, available = ?, timestamp = ' at line 1
What is problem, and how can i solve it?
I'm pretty certain it's coming from the call to $mysqli->query() which needs a properly escaped query (ie, none of that nice safe parameter stuff). That explains why it's complaining at the first ?.
Quick way to check is to actually comment out the entire if statement and se if the error still appears. If so, you know it's the query rather than the prepared statement execution.
My question to you is: why are you executing the prepared statement and then trying to run it again as a query?
I think you'll find the execute does your update quite well enough. Get rid of the call to query and you should be fine.

Why we use NULL in sqlite3_prepare_v2( )

Please can anyone tell me why we write NULL in the fifth parameter below?
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
Thanks in advance.
As long as your sql has only one statement, you don't need to use the fifth parameter. When sql has more than one statement, you can receive a pointer to the beginning of the next statement.
For example:
const char* sql =
"DROP TABLE price_list;"
"CREATE TABLE price_list ( item TEXT, price INTEGER)";
while ( *sql ) {
sqlite3_stmt* statement;
sqlite3_prepare_v2(db, sql, -1, &statement, &sql);
sqlite_step(statement);
sqlite_finalize(statement);
}
Because you don't care about the uncompiled part of the SQL statement. From the docs:
If pzTail is not NULL then *pzTail is made to point to the first byte past the end of the first SQL statement in zSql. These routines only compile the first statement in zSql, so *pzTail is left pointing to what remains uncompiled.
It's useful to have this if you have a string with many SQL statements, but if you don't then it's just cruft.

Xcode: How do I wrap a long string around to the next line in the xcode editor

I've got a long string an sql statement, which I want to wrap onto the next line in the xcode editor, how do I wrap it round e.g.
[db executeUpdate:#"insert into test (rid, one, two, amount, startdate, recurrance) values (nil, ?, ?, ?, ?, ?)",
Try:
[db executeUpdate:#"insert into test (rid, one, two, amount, values"
" startdate, recurrance)(nil, ?, ?, ?, ?, ?)",...
I had similar issue... call me paranoid.. but i like my sqlstring to look pretty and easy to trace in case something went wrong i used the stringWithFormat
example:
NSString sqlString = [NSString stringWithFormat: #"%# %# %# %# %#",
#"SELECT name, address, phone",
#"FROM whateverDatabase",
#"LEFT JOIN ...",
#"WHERE ...",
#"AND ...."];
hopefully if this is what you are looking for
(i figured i posted on the wrong page... maybe here is better)

How to bind literal text to an SQLite query?

I'm trying to use the SQLite C API in my iPhone app. I'm trying to query an SQLite database for the number of records that have been completed after a certain date. The database saves the completed date as text in YYYY-MM-dd format. For example the text 2009-04-10 might appear as a completed date.
When I query the database from the commandline my query works, but when run from the app, it doesn't. Here's what I'm doing:
From the commandline, I run this query:
sqlite> SELECT COUNT(*) FROM tasks WHERE completed > '2009-04-09'
...> go
1
As you can see, there is one record found as I expect.
In my app, I execute this code (written in Objective-C, obviously):
static sqlite3_stmt *count_tasks_statement = nil;
if(count_tasks_statement == nil) {
const char *sql = "SELECT COUNT(*) FROM tasks WHERE completed > '?'";
if (sqlite3_prepare_v2(database, sql, -1, &count_tasks_statement, NULL) != SQLITE_OK) {
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
NSString *today = #"2009-04-09";
sqlite3_bind_text(count_tasks_statement, 1, [today UTF8String], -1, SQLITE_TRANSIENT);
// Get the row count from the query
NSInteger taskCount = 0;
if(sqlite3_step(count_tasks_statement) == SQLITE_ROW) {
// The second parameter indicates the column index into the result set.
taskCount = sqlite3_column_int(count_tasks_statement, 0);
}
// Reset the statement for future reuse.
sqlite3_reset(count_tasks_statement);
When I use the debugger on this code, and examine the taskCount variable, it is set to 0, indicating that no records were found. (If I change the code to return primary keys for found rows, it still returns nothing.)
Since it works from the commandline, but doesn't in my code, I assume that I'm doing something wrong with either the quoting of the question mark in my SQL, or with the binding of the literal text date to the query. But, I've tried it lots of different ways with no luck. Help!
Don't put parameter placeholders inside quotes, even if the value is a string or date literal.
const char *sql = "SELECT COUNT(*) FROM tasks WHERE completed > ?";
I think that you do not need the extra quotes around the question mark.
Try
const char *sql = "SELECT COUNT(*) FROM tasks WHERE completed > ?";
and it should work.

How to use LIKE query in sqlite & iPhone

I'm using the following for a LIKE query. Is this technique for LIKE correct?
selectstmtSearch = nil;
if(selectstmtSearch == nil){
const char *sql = "SELECT col1, col2 FROM table1 t1 JOIN table2 t2 ON t1.cityid = t2.cityid where t1.cityname like ?001 order by t1.cityname";
if(sqlite3_prepare_v2(databaseSearch, sql, -1, &selectstmtSearch, NULL) == SQLITE_OK)
{
sqlite3_bind_text(selectstmtSearch, 1, [[NSString stringWithFormat:#"%%%#%%", searchText] UTF8String], -1, SQLITE_TRANSIENT);
}
}
The problem I'm having is after a few uses of this, I get an error 14 on sqlite3_open(), which is unable to open database. If I replace the LIKE with something such as:
SELECT col1, col2
FROM table1 t1
JOIN table2 t2 ON t1.cityid = t2.cityid
where t1.cityname = ?
order by t1.cityname
It works fine. I do open/close the DB before after the above code. Is there a way to troubleshoot exactly why the database can't be opened and what its relationship to my LIKE syntax is?
You must sqlite3_reset or sqlite3_finalize(selectstmtSearch) before you close the database connection.