iphone - improve INSERT into sqlite - ios

In my app, I need to INSERT multiple times some entry.
Each time, I am using this function:
- (int) insertFunction:(NSString *)stringa{
NSDate * start = [NSDate date];
sqlite3_stmt *statement;
NSString *file = [self getWritableDBPath];
if (sqlite3_open([file UTF8String] , &_database) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:#"%#",stringa];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_database, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
//NSLog(#"Contact added");
} else {
NSLog(#"Failed to add contact");
}
sqlite3_finalize(statement);
}
sqlite3_close(_database);
int row_id = (int)sqlite3_last_insert_rowid(_database);
NSLog(#"SINGLE INSERT took: %f", -[start timeIntervalSinceNow]);
return row_id;
}
that took about 0.020 second, and make my app frezing about 5 second.
-EDIT- My getWritableDBPath is:
- (NSString *) getWritableDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:DATABASE_NAME];
}
What I can do to improve that time? For example, avoiding to open the data base each time? In this case how?
Thanks in advance

You might want to look at the closeDatabase call, if the version of SQLite you are using is new enough it will probably have placed your writes into the WAL and will be committing them into the main database. Although 5 seconds does seems quite slow.
For your other comment about leaving the database open, simply call the open one time only and hold onto the sqlite3* handle in a class variable, and then close it when the class gets dealloc'ed, you will see much better performance.

Related

does it possible to save Db file with application and not by adding in from itunes

I want the application which work online as well as offline example WhatsApp. For that i have to sync data from web service then store it in sqlite db file.
And I want that whoever installs this application would have a slot for automatic saving data in database file. Do I have to add db file from iTunes?
I don't want to use core data concept.
Is it possible it will be there in with application?
Like in Android there is something called cache memory where db file is stored so there is any sort of provision for it in ios?
+(int)insert_In_AdverImage:(NSString *)strid ImageName:(NSString *)strimg Isshow:(NSString *)strshow LastUpdateId:(NSString *)date isdelete:(NSString *)isdelete Sortorder:(int)sortOrder{
sqlite3 *database;
int retValue = 0;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *tempSQL = [[NSString alloc] initWithFormat:#"INSERT INTO ADVERIMAGE(advId ,advimg ,isshow ,LastUpdateId ,IsDelete ,SortorderId ) VALUES ('%#', '%#', '%#', '%#', '%#', '%d')", strid, strimg, strshow, date, isdelete, sortOrder];
const char *sqlStatement = [tempSQL cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *compiledStatement;
sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL);
sqlite3_step(compiledStatement);
retValue = (int)sqlite3_last_insert_rowid(database);
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return retValue;
}
works well. But still the db file in app bundle is empty.i got it that whenever we insert something it will be inserted in document and if we have to see the inserted data we have to get it from document
Thanks in advance
Any Help would be appreciated.
Yes. Possible.
You can store SQlite DB in your applications's Document Directory. You need to write your own Query to Open DB, Insert Data, Retrieve Data from DB.
Check out following tutorial for your requirement : http://www.appcoda.com/sqlite-database-ios-app-tutorial/
Hope it helps.
Following function is used to Insert :
NSArray *docsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [docsDirectory objectAtIndex:0];
NSString *databasePath = [docPath stringByAppendingPathComponent:#"Database.sqlite"];
sqlite3 *dbHandler;
const char *dbPath = [databasePath UTF8String];
sqlite3_stmt *sqlStmt;
if(sqlite3_open(dbPath, &dbHandler) == SQLITE_OK)
{
if (sqlite3_prepare_v2(dbHandler, [queryString UTF8String], -1, &sqlStmt, NULL) == SQLITE_OK)
{
if (sqlite3_step(sqlStmt) == SQLITE_DONE)
{
NSLog(#"Data Inserted");
}
else
{
NSLog(#"Not inserted");
}
}
else
{
NSLog(#"Failed to Insert data -InsertDataFunc");
}
sqlite3_close(dbHandler);
}

Issues when reading from a database in an iPhone app

I am making an iPhone app for a school project that reads and writes to a database. I have managed to get my code to write to it but it won't read. Below is the code I'm using to read:
NSString * paths=[self getWritableDBPath];
const char *dbpath = [paths UTF8String];
sqlite3_stmt *statement;
static sqlite3 *database = nil;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT questionright, totalquestions, FROM results", nil];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
//code...
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
}
Here is getWritableDBPath:
-(NSString *) getWritableDBPath {
NSString *myDB = #"appData.db";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:myDB];
}
The reason it doesn't work is that the sqlite3_prepare_v2 if statement is never satisfied.
When I write to the database I copy it to documents.
I am quite sure the results table exists as I am able to write to it. Here is the original sql statement:
DROP TABLE IF EXISTS "Questions";
CREATE TABLE "Questions" ("QuestionID" INTEGER PRIMARY KEY NOT NULL , "Question" TEXT, "RightAnswer" TEXT, "WrongAnswer1" TEXT, "WrongAnswer2" TEXT, "Done" BOOL, "Catagory" TEXT, "Audio" INTEGER);
DROP TABLE IF EXISTS "Results";
CREATE TABLE "Results" ("ResultID" INTEGER PRIMARY KEY NOT NULL , "QuestionRight" INTEGER, "TotalQuestions" INTEGER, "Catagory" TEXT);
I did find a similar question on here but didn't think the answers were that relevant to me.
Thanks for your help.
If you want my advice, don't use the sqlite c libraries directly if you don't really need that, you can use FMDB library and get rid of all the c headache
https://github.com/ccgus/fmdb
You can simply do it like this
FMDatabase *db = [FMDatabase databaseWithPath:#"your full db path in documents goes here"];
if (![db open]) {
return;
}
FMResultSet *s = [db executeQuery:#"Your query goes here"];
if ([s next]) {
int totalCount = [s intForColumn:#"totalCount"];
}

how to scroll a uiwebview using uiscrollview

i have a UIWebView over a UIScrollView. i use some js files to draw some graph like line that will update when the time value changes.
The Problem
Im not able to scroll when the points goes out of the screen.
I'm new to IOS Development so please help me.
thank in advance
After Completion the QUERY, You need to close transaction.
Here's the sample code for you...
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"YOURDB.db"]];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &DB) == SQLITE_OK)
{
NSString *query=[NSString stringWithFormat:#"insert into studentDetails (NAME,Email,adressL1,adressL2,phone,landline,department,DoB,fatherName) values (\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")",
name.text,
email.text,
addressLine1.text,
addressLine2.text,
phone.text,
Landline.text,
Department.text,
DoB.text,
fname.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(YOURDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#" Successfully added");
} else {
NSLog(#" Failed added");
NSLog(#"Error %s",sqlite3_errmsg(ExplorejaipurDB));
}
}
sqlite3_finalize(statement);
sqlite3_close(YOURDB);
}
The database could be locked because of several reasons:
Multiple queries running
multiple threads running
opened the database multiple times
Check your code and see if you have closed the connections to the database sqlite3_close(). A good idea would also be to use sqlite3_finalize() after each SQL statement when you are done with it.
So try try to match all your sqlite3_open() with sqlite3_close() and sqlite3_prepare() (if you are using it) with sqlite3_finalize()

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

Exporting Sqlite table data to csv file programatically [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Exporting Sqlite table data to csv file programatically - xcode iOS 5 (for an ipad app)
I am developing a simple app. I am using sqlite to save data into a table (locally, in app documents folder). I want to problematically export this table data in a csv file and email it to a person. I mean I want to physically access the csv file after conversion in iPad.... Can anybody give an example application to download? Or the code?
Please help
This should give you a good idea. Assuming a table with 2 rows, this code reads all the values in the table and writes them to and NSString, which is then written to a CSV file in the documents directory. Let me know if you need clarification on how to make this code work with your specific project.
NSString *csv = [[NSString alloc] init];
sqlite3 *database;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *sqLiteDb
= [documentsDirectory stringByAppendingPathComponent:#"INSERT_DATABASE_NAME.sqlite3"];
if(sqlite3_open([sqLiteDb UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = [[NSString stringWithFormat:#"SELECT * FROM myTable"] UTF8String];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
//this assumes that there are two rows in your database you want to get data from
[csv stringByAppendingFormat:#"%#,%#\n", [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)], [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]];
}
sqlite3_finalize(compiledStatement);
sqlite3_close(database);
}else{
NSLog(#"database error");
}
}
NSError *error = nil;
[csv writeToFile:[documentsDirectory stringByAppendingPathComponent:#"myFile.csv"]
atomically:YES encoding:NSUTF8StringEncoding error:&error];
[csv release];

Resources