I use errorMsg in my NSAssert, but I only defined it as NULL and never used it to get the actual error message. So, it will always be NULL and there is no point to use it in NSAssert.
<...>
char *errorMsg = NULL;
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, update, -1, &stmt, nil)
== SQLITE_OK) {
sqlite3_bind_int(stmt, 1, i);
sqlite3_bind_text(stmt, 2, [field.text UTF8String], -1, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE)
NSAssert(0, #"Error updating table: %s", errorMsg);
<...>
will anyone give a solution?
when I run the app, there is no harm. but then, when I press the home button, the process paused and shows me this:
2013-05-20 23:57:50.156 SQLite Persistence[5373:c07] * Assertion failure in -[LPEViewController applicationWillResignActive:], /Users/Me/Developer/SQLite Persistence/SQLite Persistence/LPEViewController.m:84 2013-05-20 23:57:50.158 SQLite Persistence[5373:c07] Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error updating table: (null)' ** First throw call stack: (0x2094012 0x11a1e7e 0x2093e78 0xc37665 0x3c09 0xc624f9 0x20ee0c5 0x2048efa 0xb96bb2 0xe2bb1 0xe2c3d 0xece0c 0xf5e74 0xf6beb 0xe8698 0x1fefdf9 0x1fefad0 0x2009bf5 0x2009962 0x203abb6 0x2039f44 0x2039e1b 0x1fee7e3 0x1fee668 0xe5ffc 0x2b4d 0x2a75) libc++abi.dylib: terminate called throwing an exception (lldb)
A couple of issues:
You never set the errorMsg. Make sure to set it to sqlite3_errmsg (or just use that function directly).
Your custom error message ("Error updating table") is a little misleading, too, as it would imply that you're reporting the name of a table, whereas your choice of variable name suggested you really wanted to report the SQLite error message.
If sqlite3_prepare_v2 fails, you don't report any error message. Furthermore, rather than stopping and reporting an error if sqlite3_prepare_v2 failed, you proceed to try to call sqlite3_step, even though there's no valid statement to perform. The problem with that is that it would undoubtedly replace the meaningful error message you would have received after sqlite3_prepare_v2 failed with some useless message about executing statements in the wrong order.
You don't check the success or failure of your sqlite3_bind statements. It would be prudent to do so (though I suspect you're more likely to fail at the sqlite3_prepare_v2 statement).
Anyway, maybe you want something like:
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) != SQLITE_OK)
NSAssert(0, #"prepare failure: %s", sqlite3_errmsg(database));
if (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) {
sqlite3_finalize(stmt);
NSAssert(0, #"bind 1 failure: %s", sqlite3_errmsg(database));
}
if (sqlite3_bind_text(stmt, 2, [field.text UTF8String], -1, NULL) != SQLITE_OK) {
sqlite3_finalize(stmt);
NSAssert(0, #"bind 2 failure: %s", sqlite3_errmsg(database));
if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_finalize(stmt);
NSAssert(#"step error: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(stmt);
Whether you want to use NSAssert or just NSLog and immediately return, I'll defer to you, but this code sample will check more SQLite failure conditions and report meaningful errors.
Related
Im making an application for IOS 9, using swift, and my application will consist of using a database. I searched on the internet and set up a SqLite database and am using the Firefox add on to have a GUI to view it. I make a Xcode project and as many tutorials said to do I went to my Build Phases > Link Binary With Libraries and searched for libsqlite3.0.dylib but I only found libsqlite3.tbd and libsqlite3.0.tbd . I said ok and clicked on libsqlite3.tbd hoping that it wouldnt matter, but I got stuck at the next step of using sqlite in IOS. I had to
#import <sqlite3.h>
but the thing was that i would get an error when ever that happened. I just need some step by step instructions on how to get my SqLite database to start working!!! I can't find anything on the web that isn't using IOS 7 and adding libsqlite3.dylib to their build phase. Please help!!
You may try the following:
When expand Link Binary and hit + , then click 'Add other', when the window pops up hit CTRL+Shift + G. In the Go to folder field put /usr/lib -> Go and you will find 'libsqlite3.dylib'
Why don't you use a Swift SQLite wrapper such as https://github.com/groue/GRDB.swift or https://github.com/stephencelis/SQLite.swift?
If you want to use Swift then Here is an easy solution.
Step 1: Import SQLite
import SQLite3
Step 2: Create and Open a database file
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("YourFileName.sqlite")
if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
print("error opening database")
}
Step 4: Create a Table
if sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS Heroes (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, powerrank INTEGER)", nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}
Step 5: Insert Values
var stmt: OpaquePointer?
let queryString = "INSERT INTO Heroes (name, powerrank) VALUES (?,?)"
if sqlite3_prepare(db, queryString, -1, &stmt, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
return
}
if sqlite3_bind_text(stmt, 1, name, -1, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_bind_int(stmt, 2, (powerRanking! as NSString).intValue) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_step(stmt) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting hero: \(errmsg)")
return
}
By following these steps you can easily insert some rows in your table. For other operations like, reading visit this nice step by step guide - Swift SQLite Tutorial.
I am running code from this tutorial sqlite database iOS app tutorial .The query function is :
- (IBAction)saveInfo:(id)sender
{
// Prepare the query string.
// If the recordIDToEdit property has value other than -1, then create an update query. Otherwise create an insert query.
NSString *query;
if (self.recordIDToEdit == -1)
{
query = [NSString stringWithFormat:#"insert into peopleInfo values(null, '%#', '%#', '%#')", self.txtFirstname.text, self.txtLastname.text, self.txtAge.text ];
}
else
{
query = [NSString stringWithFormat:#"update peopleInfo set firstname='%#', lastname='%#', age='%#' where peopleInfoID=%d", self.txtFirstname.text, self.txtLastname.text, self.txtAge.text, self.recordIDToEdit];
}
NSLog(#"The query is: %#",query);
// Execute the query.
[self.dbManager executeQuery:query];
// If the query was succesfully executed then pop the view controller.
if (self.dbManager.affectedRows != 0) {
NSLog(#"Query was executed successfully. Affacted rows = %d", self.dbManager.affectedRows);
// Inform the delegate that editing was finished.
[self.delegate editingInfoWasFinished];
// Pop the view controller.
[self.navigationController popViewControllerAnimated:YES];
}
else
{
NSLog(#"Could not execute the query");
}
}
Program is giving sql error on inserting record
The query is: insert into peopleInfo values(null, 'Project 1', 'Test 1', '2014-12-15 05:00:20 +0000')
DB Execute Query Error: SQL logic error or missing database
Could not execute the query.
How to get remove this error ?
See the highlighted folder. Copy that into your project. Your code seems to be fine. And make sure db.sql is in there.
Having an sqlite issue. The query runs fine on the firefox addon SQLiteManager. It does not run on iOS however. I get an error code of 1. The database gets connected to fine.
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"featureDB"
ofType:#"sqlite3"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
DLog(#"Failed to open database!");
} else {
DLog(#"Connected to db");
}
NSString *query = [NSString stringWithFormat:#"SELECT * FROM featureTable"];
sqlite3_stmt *statement;
NSLog(#"could not prepare statement: %s\n", sqlite3_errmsg(_database));
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
DLog(#"row");
int uniqueId = sqlite3_column_int(statement, 0);
}
sqlite3_finalize(statement);
DLog(#"sqliteStep");
} else {
DLog(#"statement Error %d", sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil));
}
The log for "row or sqliteStep" never fires.
Your else statement should not call sqlite3_prepare_v2 again, but rather should:
DLog(#"prepare error: %s", sqlite3_errmsg(_database));
What does this error message report?
Note: You already are logging sqlite3_errmsg before you call sqlite3_prepare_v2. Of course that's going to report no error, because no error could have possibly has taken place yet. Do this logging inside the else clause where you know sqlite3_prepare_v2 (a) has been called; but (b) didn't return SQLITE_OK. And don't call any SQLite functions between when sqlite3_prepare_v2 failed and where you log the error message.
The most common problem is that it reports that there is no such table. And if that's what you see, in this case that could be a result of failing to include the database in the app bundle (see the "Copy Bundle Resources" section of the "Build Phases" section of your target settings).
Alternatively, if it says something about the database is busy, that can happen if you have mismatched your database open calls and your database close calls (like you have in this code sample).
please make sure your sqlite db is not opened with any sqlite db browser when you are running app in simulator.
It happened with me, I had my sqlite db opened in sqlite browser to test my query and when I was running app from simulator it was not updating anything in db.
The problem was my file was of sqlite extension, but the code specified an extension of sqlite3. I thought the two were synonymous but they weren't
How can I figure out the error that SQLite3 is giving me when I make an SQL call:
int success = sqlite3_prepare_v2(database, sql, -1, &stmt, NULL);
if(success != SQLITE_OK) {
NSLog(#"create stmt failed %#",stmt);
}
All as I know is if it failed, but is there a way to get the actual error, or reason why it failed?
You can use the sqlite3_errmsg function. You need to pass in the db handle. The following code will log the error
NSLog(#"Error %s while preparing statement", sqlite3_errmsg(_dbHandle));
Sure, if success != SQLITE_OK, then it must be one of these error codes:
http://www.sqlite.org/c3ref/c_abort.html
I always use NSLog to print out contents of objects when I am debugging my iOS applications. But any time I come across a "nil" object, the program crashes. In Java, if an object is null, it will print "null". Is there a way to do this in Objective-C?
Something like:
if (questionableObject == nil) {
NSLog(#"questionableObject is nil.");
} else {
NSLog(#"questionableObject is: %#", questionableObject);
}
I've only really run into this problem when I send a message to an object inside the NSLog parameter list that uses a nil object as a parameter. Something like this:
if (questionableObject == nil) {
NSLog(#"questionableObject is nil.");
} else {
NSLog(#"result is: %#", [something someMessage:questionableObject]);
}
What do you mean by "print out contents of objects"? If you're dereferencing a nil pointer, that'll cause a problem. If you're just printing the pointer, that should be OK. You can also send messages to nil without problem, so you could do this:
NSLog(#"theObject is: %#", [theObject description]);