Print / Log the SQLite Statement after the binding - objective-c

I like to log the compiled Statement after this:
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_int( compiledStatement, 1, updateThis.web_id);
[...]
}
NSLog(#"Put out the complete SQLite Statement.");
The direct output failed, and i think this is not the way to do it:
NSLog(#"%#",compiledStatement);

You can't print the compiledStatement. What you can do is implement the sqlite3_trace callback function. This will print every executed sql statement.
To implement the function add this before your #implementation block
void sqliteCallbackFunc(void *foo, const char* statement) {
NSLog(#"=> %s", statement);
}
This is the function you will point to.
To point to this function simple call:
sqlite3_trace(db, sqliteCallbackFunc, NULL);

Related

How to bind a LIKE wildcard in SQLite3

I'd like to run the SQL query: SELECT COUNT(id) AS nbr FROM user WHERE name LIKE '%John%', and get the number of records matched by the keyword John.
So I've written the following code :
unsigned int nbr;
char *sql, *like;
sqlite3 *db;
sqlite3_stmt *stmt;
/* Database connection etc. */
like = _make_string("%%%s%%", keyword); /* keyword: John */
printf("Like clause: %s\n", like);
sql = _make_string("SELECT COUNT(id) AS nbr FROM user WHERE name LIKE ?");
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, like, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_ROW) {
/* error, SQL execution failed */
}
nbr = sqlite3_column_int64(stmt, 1);
printf("Number of record: %u\n", nbr);
/* Free strings, finalize statement, disconnect db etc. */
For reason of simplicity, some return value tests are ignored in the snippet. _make_string(const char *fmt, ...) is a printf-like function which can form strings, and it did return %John% to me.
However, my code always returns 0 record. I have tried the SQL in sqlite3 command line shell, but it has found 2 records.
Any idea please ?
I've hard coded the LIKE clause and removed the sqlite3_bind_text function, and it doesn't change the result.
sql = _make_string("SELECT COUNT(id) AS nbr FROM client WHERE name LIKE '%John%'");
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (sqlite3_step(stmt) != SQLITE_ROW) {
/* error */
}
nbr = sqlite3_column_int64(stmt, 1);
printf("Number of record: %u\n", nbr);
The program always returns 0 records.
Well, I've found the answer in the mailing list archive of SQLite Why bind indexes start from 1 and column indexes start from 0?
In fact, the bind index starts from 1, but the column index starts from 0. So the code should be modified as the following
nbr = sqlite3_column_int64(stmt, 0);
printf("Number of record: %u.\n", nbr);
Now the program returns 2 (records) !

iOS - SQLite not updating but prepare and step are successfully executing

The title is pretty much all the information I have because I cannot find an issue with the code. The same instance of database that is being used in the code below is able to successfully insert, delete and select, but this function does not work. No error code is retured(Always 0), and the program continues to run nominally after executing this function.
Here is the table information:
reminder (uniqueID integer primary key autoincrement, title text not null, details text, time integer)
Code in question:
- (void) updateEntryData:(ReminderData *)data
{
sqlite3_stmt *statement;
char *updateCommand = "UPDATE reminder SET title = '?', details = '?', time = ? WHERE uniqueID = ?";
int e = sqlite3_prepare_v2(database, updateCommand, -1, &statement, nil);
if(e != SQLITE_OK) {
NSLog(#"Problem with updateEntryWithUniqueID");
NSLog(#"Error Code: %d, message '%s'", e, sqlite3_errmsg(database));
return;
}
sqlite3_bind_text(statement, 1, [data.title UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [data.details UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(statement, 3, [data.time timeIntervalSince1970]);
sqlite3_bind_int(statement, 4, data.uniqueID);
NSLog(#"\nID: %d\nTitle: %#\nDetails: %#\nTime: %#", data.uniqueID, data.title, data.details, data.time);
if(sqlite3_step(statement) != SQLITE_DONE) {
NSLog(#"Problems updating entry in reminder");
}
/* Finished */
sqlite3_finalize(statement);
}
Any help would be greatly appreciated; I am stumped.
Edit: Forgot to mention that the sql command used works when entered into the sqlite console.
Just remove the single quotes around the parameters. Wrapping the placeholders will make it a value and not a parameter anymore.
char *updateCommand = "UPDATE reminder SET title = ?, details = ? .....";

SQLite3 - select query fails with Unicode characters?

My sqlite3 SELECT query fails if the query contains any Unicode characters. ie, the below query returns 0 instead of the actual count. I am generating the select query using C++/Visual Studio 2010.
SELECT COUNT() FROM mytable where path = "C:\\sølvgut.txt";
When I execute the above query using SQLite Expert editor it working as expected. But in my code I am using a wrapper class CppSQLite3.cpp to execute the query which is causing the issue. In the below code, it getting inside the code else if (nRet == SQLITE_ROW)
CppSQLite3Query CppSQLite3DB::execQuery(const char* szSQL)
{
checkDB();
sqlite3_stmt* pVM = compile(szSQL);
int nRet = sqlite3_step(pVM);
if (nRet == SQLITE_DONE)
{
// no rows
return CppSQLite3Query(mpDB, pVM, true/*eof*/);
}
else if (nRet == SQLITE_ROW)
{
// at least 1 row
return CppSQLite3Query(mpDB, pVM, false/*eof*/);
}
else
{
nRet = sqlite3_finalize(pVM);
const char* szError= sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
}
}

Delete column from Sqlite database

Basically I have to enter all textfield values in database then have to use for sending to webservice. So when the one column details send to service then have to delete that column.
I have done this:
-(void)deleteTableDataFromSavedDataTable:(NSString *)lastID {
NSString *sql_str=[NSString stringWithFormat:#"DELETE FROM FormInfoValues where Phone = %#",lastID];
const char *sql = [sql_str UTF8String];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSLog(#"sql delete statement is ");
sqlite3_stmt *deleteStmt;
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) == SQLITE_OK)
{
NSLog(#"sql delete statement is %#", deleteStmt);
if(sqlite3_step(deleteStmt) != SQLITE_DONE )
{
NSLog( #"Error: %s", sqlite3_errmsg(database) );
}
else
{
NSLog( #"row id = %lld", (sqlite3_last_insert_rowid(database)+1));
NSLog(#"No Error");
}
}
sqlite3_finalize(deleteStmt);
}
sqlite3_close(database);
}
but its not deleting after sending. Why its not calling?
give me ideas..
It's quite possible I'm not understanding your issue properly -- so I apologize in advance if so.
Regarding: "...then have to delete that column."
-- If you want to clear the data in a column (by setting it to zero, or empty string, or NULL) then you'll want to use the UPDATE command in SQL. The DELETE command always deletes ROWS.
-- If you really must remove a column from a table's schema, you'll have to create a new table in sqlite. (Sqlite allows you to ADD a column via ALTER TABLE command, and some other databases DO allow you to drop a column using ALTER TABLE as well.) You can quickly copy a table (without it's constraints, etc) via e.g.:
CREATE TABLE MyOutput as SELECT a,b,d,f,h,z from MyOriginal;
-- If your output is created by a SELECT statement, just avoid using "*" and specify just the columns you want included.

Unix C code cp in system()

I have a C code..
i which I have following code for UNIX:
l_iRet = system( "/bin/cp -p g_acOutputLogName g_acOutPutFilePath");
when I am running the binary generated..I am getting the following error:
cp: cannot access g_acOutputLogName
Can any one help me out?
You should generally prefer the exec family of functions over the system function. The system function passes the command to the shell which means that you need to worry about command injection and accidental parameter expansion. The way to call a subprocess using exec is as follows:
pid_t child;
child = fork();
if (child == -1) {
perror("Could not fork");
exit(EXIT_FAILURE);
} else if (child == 0) {
execlp("/bin/cp", g_acOutputLogName, g_acOutPutFilePath, NULL);
perror("Could not exec");
exit(EXIT_FAILURE);
} else {
int childstatus;
if (waitpid(child, &childstatus, 0) == -1) {
perror("Wait failed");
}
if (!(WIFEXITED(childstatus) && WEXITSTATUS(childstatus) == EXIT_SUCCESS)) {
printf("Copy failed\n");
}
}
Presumably g_acOutputLogName and g_acOutPutFilePath are char[] (or char*) variables in your program, rather than the actual paths involved.
You need to use the values stored therein, rather than the variable names, for example:
char command[512];
snprintf( command, sizeof command, "/bin/cp -p %s %s",
g_acOutputLogName, g_acOutPutFilePath );
l_iRet = system( command );