IOS Sqlite3 Passing Opened database to a method - ios

Using php for an example:
$conn = new mysqli('localhost', 'xxx', '123456', 'xxx');
Just define $conn once, I can pass $conn to all other methods, so that i don't need to repeat the connection again when I run another query, and it's a lot faster.
function example($conn) {
// do some db stuff here
}
Can I do the same thing in IOS sqlite3? Many thanks for helping.
- (void) syncScale {
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
databasePath = [[NSString alloc]
initWithString: [docsDir stringByAppendingPathComponent:#"ALDI.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
NSString *postSetting ;
postSetting = [NSString stringWithFormat:#"scaleData={\"scaleDB\":["];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *querySQL = #"SELECT * From Table1";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
// do something here
}
sqlite3_finalize(statement);
} else {
NSLog(#"Steps Data not found");
}
sqlite3_close(contactDB);
}
}

What I usually do, is that keep the opening of database in separate block/function with a boolean return ,rather finalize and rest the sqlite statement; Since the opening of database is made of almost static contents, the function doesn't need any parameters

Related

Unable to delete row data in my table view from sqlite

I am trying to delete the data from my table view.The data is coming from the database.
if (editingStyle == UITableViewCellEditingStyleDelete) {
DetailData *datatoDelete;//=[DetailData new];
datatoDelete= dataArray[indexPath.row];
NSLog(#"ID at selected row is %#",datatoDelete.ID);
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
databasePath = [[NSString alloc]
initWithString: [docsDir stringByAppendingPathComponent:
#"MYDat.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &myDatabase) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM ABC WHERE ID=%#",datatoDelete.ID];
// i tried ID='%#' too
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(myDatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"statement deleted successfully"); // i am seeing this statement when i click delete
}
sqlite3_finalize(statement);
sqlite3_close(myDatabase);
}
// [dataArray removeObjectAtIndex:indexPath.row];
[tableView reloadData];
}
Here when I click on delete, i am getting "the statement data deleted successfully" but,when I check the database file after the delete operation, the data still exists there.Could anyone tell me whats wrong in here?
The sqlite3_prepare_v2 only prepares a statement, you need to use sqlite3_step for executing it.
if (sqlite3_prepare_v2(myDatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"statement deleted successfully");
}
}
For referece:
sqlite_step
Evaluate An SQL Statement

How to retrieve data from sqlite manager [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I created database and also created table in that by using sqlite manager(mozilla).Now i want to retrieve that data into my iOS application.How can i do with programatically. Can you please any one help me how to do that. Thank you.
Use something like this:
import:
#import "sqlite3.h"
CHECK IF DB EXISTS:
NSString *docsDir;
NSArray *dirPaths;
NSString *databasePath;
sqlite3 *DB;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"YourDbName.sqlite"]]; //put your db name here
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &DB) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS YourTable (Value INTEGER PRIMARY KEY, column TEXT)";
if (sqlite3_exec(DB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
}
sqlite3_close(DB);
}
}
Get DB Values:
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &DB) == SQLITE_OK) //News is a sqlite variable initialized like this: sqlite3* News;
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM YourDBName"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(DB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString* example; //example variable to assign data from db
example = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)]; //change the 0 to 1,2,3.... for every column of your db
}
sqlite3_finalize(statement);
}
sqlite3_close(DB);
}
To retrieve that data into your iOS application.follow following steps
lets consider your SQlite DB have name YourDB which have table information and columns Name, Place and City and DatabasePath is your path where you store your SQlite DB
const char *dbpath = [DatabasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &YourDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:
#"SELECT Place, City FROM students WHERE Name=Bob"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(YourDB,query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *Place = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
NSString *City = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 1)];
}
sqlite3_finalize(statement);
}
sqlite3_close(YourDB);
}
Put that "sqlite" file in App's bundle and then you can use that file.

if (sqlite3_step(compiledStatement) == SQLITE_ROW) is fail

On the first implemetation file, all steps
- (void) readCitiesFromDatabase {
databaseName = #"123.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
// Setup the database object
sqlite3 *database;
// Setup the SQL Statement and compile it for faster access
NSString *querySQL = [NSString stringWithFormat:#"SELECT City_Name, City_Picture, City_Id FROM CITIES, COUNTRIES WHERE CITIES.Country_Id=COUNTRIES.Country_Id AND COUNTRIES.Country_Id = '%#'", self.countryID];
const char *sqlStatement = [querySQL UTF8String];
sqlite3_stmt *compiledStatement;
// Init the countries Array
self.cities = [[NSMutableArray alloc] init];
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSLog(#"success");
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
NSLog(#"success");
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"success");
// Read the data from the result row
char *temp_cName = (char *)sqlite3_column_text(compiledStatement, 0);
NSString *cName = temp_cName == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_cName];
char *temp_cPicture = (char *)sqlite3_column_text(compiledStatement, 1);
NSString *cPicture = temp_cPicture == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_cPicture];
char *temp_cId = (char *)sqlite3_column_text(compiledStatement, 2);
NSString *cId = temp_cId == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_cPicture];
NSMutableDictionary *city = [[NSMutableDictionary alloc] init];
[city setObject:cName forKey:#"City_Name"];
[city setObject:cPicture forKey:#"City_Picture"];
[city setObject:cId forKey:#"City_Id"];
[self.cities addObject:city];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
Now I got cities list. When I select a city, I could not see city info.
This is from second implementation.
- (void) readCityInfoFromDatabase:(NSString *)querySQL
{
databaseName = #"123.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
// Setup the database object
sqlite3 *database;
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = [querySQL UTF8String];
sqlite3_stmt *compiledStatement;
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSLog(#"success");
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
NSLog(#"success");
if (sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"success");
char *temp_content = (char *)sqlite3_column_text(compiledStatement, 0);
[self.cityTextView setText:temp_content == NULL ? nil : [[NSString alloc] initWithUTF8String:temp_content]];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
The first two steps are success but,
if (sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"success");
I couldn't see success on this step.
Please help.
You really should be saving the result of sqlite3_step() and checking to see if it is:
SQLITE_ROW = retrieved row of data
SQLITE_DONE = no (more) data to retrieve
Other = some error occurred
On the basis of what you shared, though, there is a good chance that you simply received SQLITE_DONE because there was nothing found. You could get that if there was a mistake in the SQL (e.g. bad join, incorrect WHERE clause, etc.). It's hard to say without seeing the SQL used by readCityInfoFromDatabase and some representative data from the database.
By the way, not only for sqlite3_step(), but rather for all of your sqlite3_xxx() calls, if you receive an error, you should be logging sqlite3_errmsg(). Right now, if there was an error, you'd have to guess what the source of the problem was.

Objective-c sql error - error with statement look like empty result

hi i'm getting stuck with some code. i have a file catalog.db and a class that let me work with it. When i try to retrieve datas from the db it seems like it's empty. With several nslog i can see that it connect and enter the database, i can see it enter in it but then it won't get any value from it.
i tried to see if the query was wrong with an external DB manager software and the query works fine...
this is my class
#import "DBAccess.h"
sqlite3* database;
#implementation DBAccess
-(id)init{
self = [super init];
if (self){
[self initializeDatabase];
}
return self;
}
-(void)initializeDatabase{
NSString *path = [[NSBundle mainBundle]pathForResource:#"catalog" ofType:#"db"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) { NSLog(#"Opening Database"); }
else {
sqlite3_close(database);
NSAssert1(0, #"FAILED to open database '%s'", sqlite3_errmsg(database));
}
}
-(void)closeDatabase{
if (sqlite3_close(database) != SQLITE_OK){
NSAssert1(0, #"ERROR to close databse: '%s'", sqlite3_errmsg(database));
}
}
-(NSMutableArray *)getAllProduct{
NSMutableArray *products = [[NSMutableArray alloc]init];
const char *sql = "SELECT product.ID,product.Name, Manufacturer.name, product.details,product.price, product.quantityOnHand,country.country,product.image FROM product,manufacturer,country WHERE manufacturer.manufacturerID = product.manufacturerID and product.countryOfOriginID = country.countryID";
sqlite3_stmt *statement;
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
NSLog(#"sqlResult: %d", sqlResult);
if (sqlResult == SQLITE_OK){
NSLog(#"sql step statement: %d",sqlite3_step(statement));
NSLog(#"QUERY DONE");
while (sqlite3_step(statement) == SQLITE_ROW){
NSLog(#"TEST");
Product *product = [[Product alloc]init];
char *name = (char *)sqlite3_column_text(statement, 1);
NSLog(#"n %s",name);
char *manufacturer = (char *)sqlite3_column_text(statement, 2);
NSLog(#"m %s", manufacturer);
char *details = (char *)sqlite3_column_text(statement, 3);
NSLog(#"d %s", details);
char *countryoforigin = (char *)sqlite3_column_text(statement, 6);
NSLog(#"%s", countryoforigin);
char *image = (char *)sqlite3_column_text(statement, 7);
NSLog(#"%s", image);
product.ID = sqlite3_column_text(statement, 0);
product.name = (name)?[NSString stringWithUTF8String:name]:#"";
product.manufacturer = (manufacturer)?[NSString stringWithUTF8String:manufacturer]:#"";
product.details = (details)?[NSString stringWithUTF8String:details]:#"";
product.price = sqlite3_column_double (statement, 4);
product.quantity = sqlite3_column_int(statement, 5);
product.countryOfOrigin = (countryoforigin)?[NSString stringWithUTF8String:countryoforigin]:#"";
product.image = (image)?[NSString stringWithUTF8String:image]:#"";
[products addObject:product];
}
sqlite3_finalize(statement);
}
else {
NSLog(#"Problem with database %d",sqlResult);
}
return products;
}
#end
this is what i get in my console
2013-08-14 12:38:58.505 Catalog[1642:c07] Opening Database
2013-08-14 12:38:58.508 Catalog[1642:c07] sqlResult: 0
2013-08-14 12:38:58.509 Catalog[1642:c07] sql step statement: 101
2013-08-14 12:38:58.509 Catalog[1642:c07] QUERY DONE
2013-08-14 12:38:58.510 Catalog[1642:c07] ()
what can be my problem? thanks
Here
NSLog(#"sql step statement: %d",sqlite3_step(statement));
you fetch already the first row (without using the result).
1)Copy the database to your documents directory...
-(void) checkAndCreateDatabase{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"test.sqlite"];
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"test.sqlite"];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
2)Then talk to database in this way.
-(void)sqliteTransaction
{
sqlite3 *database;
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"test.sqlite"];
// Init the animals Array
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "select * from me";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSLog(#"%#",aName);
// Create a new animal object with the data from the database
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
Try like this, before going to SELECT make sure the table is properly connected for selection with the open query like this
sqlite3_open(dbpath, &ProDB)
After that execute your selection. See this below sample code. Hope it will help
ex:
NSMutableArray *sessionDetails = [NSMutableArray array];
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"cPro.db"]];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &ProDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM USER_SESSION_INFO"];
NSLog(#"query: %#",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(ProDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
// Your functionality.
}
}
}
i tried the method you guys suggested but i still get the same problem.
i think i found out what's causing it.
i changed my query with this:
const char *sql = "SELECT product.ID,product.Name, product.details,product.price, product.quantityOnHand,product.image FROM Product";
and this way it works... so it looks like i have trouble reading other tables...
the moment i add another table it stop working. but that's weird cause with external db manager software the query works just fine

How to iterate through sqlite_step result

Could someone be so kind as to fill in the few missing pieces of code below. I am struggling with executing an sqlite statement using sqlite3_step, iterating through each row of results and putting the data into a useable format.
Here is the code that creates the database (Database is only two colums)
// Check if database is setup, if not create it
NSString *documents_directory;
NSArray *directory_path;
// Get the documents directory
directory_path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documents_directory = [directory_path objectAtIndex:0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString: [documents_directory stringByAppendingPathComponent: #"weights.db"]];
NSFileManager *file_manager = [NSFileManager defaultManager];
// Create database if it doesn't already exist
if([file_manager fileExistsAtPath: databasePath ] == NO){
const char *database_path = [databasePath UTF8String];
if(sqlite3_open(database_path, &contactDB) == SQLITE_OK){
char *error_message;
const char *sql_statement = "CREATE TABLE IF NOT EXISTS RECORDED_WEIGHTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, WEIGHT TEXT, TIME TEXT)";
if(sqlite3_exec(contactDB, sql_statement, NULL, NULL, &error_message) != SQLITE_OK){
status.text = #"Failed to create table";
}
sqlite3_close(contactDB);
}else{
status.text = #"Failed to open/create database";
}
}
And here is the code I am trying to complete;
// Get info from database and load it.
const char *database_path = [databasePath UTF8String];
sqlite3_stmt *statement;
if(sqlite3_open(database_path, &contactDB) == SQLITE_OK){
NSString *SQLquery = [NSString stringWithFormat:#"SELECT * FROM RECORDED_WEIGHTS ORDER BY TIME DESC"];
const char *query_statement = [SQLquery UTF8String];
if(sqlite3_prepare_v2(contactDB, query_statement, -1, &statement, NULL) == SQLITE_OK){
// Please help me execute statement and get results into useable format here.
}
sqlite3_finalize(statement);
}
sqlite3_close(contactDB);
Thanks in advance.
You want to do something like this:
while(sqlite3_step(statement) == SQLITE_ROW)
{
// int value
int intValue = sqlite3_column_int(statement,fieldIndex);
// string value
NSString* stringValue;
if (sqlite3_column_type(dbps, fieldIndex) != SQLITE_NULL)
{
const char *c = (const char *)sqlite3_column_text(dbps, fieldIndex);
if (c)
{
stringValue = #(c);
}
}
... etc...
}
Look at the documents for the different column types. You can also look at different objective-c wrappers out there to get an idea of how to access the database.

Resources