why Table is not created in sqlite in ios - ios

Here is my code to add a table in my existing database. My code reaches to success callback of sqlite3_prepare_v2 and gives the log table created, but when I open my sqlite database using terminal, I see that there were no tables created. My database table name is fz1.sqlite declared by pragma by this: #define kDBName #"fz1.sqlite"
-(sqlite3 *)mydb:(NSString *)query{
static sqlite3 *database;
static sqlite3_stmt *enableForeignKey;
if (database == NULL) {
sqlite3 *newDBconnection;
// first get the path for the document directory of the application
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dbpath = [paths objectAtIndex:0];
NSString *path = [dbpath stringByAppendingPathComponent:kDBName];
if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK) {
NSLog(#"Database Successfully Opened :)");
database = newDBconnection;
if (sqlite3_prepare_v2(database,[query UTF8String], -1, &enableForeignKey, NULL) != SQLITE_OK) {
NSLog(#"ERROR IN PRAGMA!");
}
else{
sqlite3_exec(database, [query UTF8String], NULL, NULL, NULL);
NSLog(#"faiz's table created");
}
sqlite3_finalize(enableForeignKey);
} else {
NSLog(#"Error in opening database :(");
database = NULL;
}
}
return database;
}

It seems no error with your implementation. I think you are opening the db file placed in the Application bundle and it will bot be updated with the queries you performing.
Once you launch your application the database file will be copied to the device/simulator 's document directory. So if you are running your application in iOS Simulator check the db in the document directory folder.
Open it and check whether updated or not.
Example of the folder structure for Document Dir with db file iOS Simulator
/Users/XYZ/Library/Application Support/iPhone
Simulator/7.1/Applications/B5EC1893-B38F-4AB4-AE7C-48EF685EE35F/Documents/db.sqlite

If you're putting parameters into your query using [NSString stringWithFormat:#"YourSqlStatement %# %#",parameter1,parameter2]; or something similar before calling -(sqlite3 *)mydb:(NSString *)query you might be SQL injecting yourself. If you are doing this then try using sqlite_bind_text to load your parameters and then sqlite_step to execute.
If this isn't relevant to your implementation try logging the output of sqlite_exec and have a look at your error message.

Related

sqlite database file doesn't update in iOS

I have an iOS app that uses sqlite, the sqlite database file is preconfigured and added in xcode. Everything works great until I need to add a new table named "activities" in this sqlite file, so I added the table for the database file, replaced the database file in xcode, and now while running on either simulator or real iOS device, it keeps complaing "no such table: activities". Even if I delete the previously installed app on my device or simulator doesn't work. What is happening there? By the way, below is the code I deal with the database file everytime I instantiate my DatabaseManager:
- (instancetype)initWithDatabaseFilename:(NSString *)dbFilename {
self = [super init];
if (self) {
// Set the documents directory path to the documentsDirectory property.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
self.documentsDirectory = [paths objectAtIndex:0];
// Keep the database filename.
self.databaseFilename = dbFilename;
// Copy the database file into the documents directory if necessary.
[self copyDatabaseIntoDocumentsDirectory];
}
return self;
}
- (void)copyDatabaseIntoDocumentsDirectory {
// Check if the database file exists in the documents directory.
NSString *destinationPath = [self.documentsDirectory stringByAppendingPathComponent:self.databaseFilename];
if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) {
NSLog(#"file not exists");
// The database file does not exist in the documents directory, so copy it from the main bundle now.
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseFilename];
NSError *error;
[[NSFileManager defaultManager] copyItemAtPath:sourcePath toPath:destinationPath error:&error];
// Check if any error occurred during copying and display it.
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
} else {
NSLog(#"file is already there");
}
}
Delete database file from document directory through terminal path generated in copyDatabaseIntoDocumentsDirectory method drag and drop database file in project.make sure tables are created through terminal.

Creating, reading to and writing from a plain text file in ios app

What I want to do is write a method that when called will create a plain text file with a pre-written header (always the same) and then periodically updates the text file with more data until the user requests it to stop. A new text file would be needed for each different time the user uses the app.
I'm having difficulty even getting the app to create the text file in the first place. Any suggestions what I may need to do to accomplish this?
Thanks.
Have a look on following code, it creates a CSV file. Which is exactly what you require. If file doesn't exist it creates a new one and write headers first, otherwise just write the log text.
- (void)log:(NSString *)msg {
NSString *fileName = [self logFilePath];
// if new file the add headers
FILE *file = fopen([fileName UTF8String], "r");
if (file == NULL) {
file = fopen([fileName UTF8String], "at");
fprintf(file, "%s\n", "Date, Time, Latitude, Longitude, Speed, info");
} else {
fclose(file);
file = fopen([fileName UTF8String], "at");
}
fprintf(file, "%s\n", [msg UTF8String]);
fclose(file);
}
You should create your files in document directory, following code shows how to get path to the document directory
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

How to acess one appliction sqlite database in another application

I have one application in that i created the sqlite database and store in the document directory. Now i open other application from existing application and in that i want to access the existing database path. how can i do this can any one help me. I write the code below for open another application and calling the document directory. But it gets the the wrong document directory path.
==============
UIApplication *ourApplication = [UIApplication sharedApplication];
NSString *ourPath = #"POSRetail://";
NSURL *ourURL = [NSURL URLWithString:ourPath];
if ([ourApplication canOpenURL:ourURL])
{
databasePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSLog(#"databasePath : %#",databasePath);
NSString *filePath = [databasePath stringByAppendingPathComponent:#"testapp.sqlite"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if(fileExists)
{
NSMutableString *strRecord =[[NSMutableString alloc]init];
//Retrieve the values of database
const char *dbpath = [filePath UTF8String];
if (sqlite3_open(dbpath, &sdatabase) == SQLITE_OK)
{
// NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM employee"];
// const char *query_stmt = [querySQL UTF8String];
const char *query_stmt = "Select * from info";
sqlite3_stmt *statement;
//const char *query_stmt = "Select * from sqlite_master where type='table'";
NSMutableArray *arrTemp = [[NSMutableArray alloc] init];
if(sqlite3_prepare_v2(sdatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW) {
[arrTemp addObject:[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 0)]];
[strRecord appendFormat:#"%#,",[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 0)]];
[arrTemp addObject:[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 1)]];
[strRecord appendFormat:#" %#,",[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 1)]];
[arrTemp addObject:[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 2)]];
[strRecord appendFormat:#" %#,",[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 2)]];
[arrTemp addObject:[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 3)]];
[strRecord appendFormat:#" %#\n",[NSString stringWithFormat:#"%s",sqlite3_column_text(statement, 3)]];
}
NSLog(#"arrTemp : %#",arrTemp);
sqlite3_finalize(statement);
}
else
{
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(sdatabase));
}
sqlite3_close(sdatabase);
}
else
{
sqlite3_close(sdatabase);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(sdatabase));
}
}
else
{
NSLog(#"SQLITE DATABASE NOT AVAILABLE");
}
}
else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Receiver Not Found" message:#"The Receiver App is not installed. It must be installed." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
As if you want to access other iOS App data then Two Words From Apple
Not Possible
As iOS App is work in SandBox Environment sharing data between applications so sharing data directly through the file system is not possible, But there is also certain ways provided for sharing data review this like
Custom URL Scheme:
the iOS programming guide now has a section on passing data between
apps by having one app claim a certain URL prefix and then having
other apps reference that URL. For this point of your you can look
this Apple Documentation. And Good Thread on SO related
this Question.
UIDocumentInteractionController
A document interaction controller, along with a delegate object,
provides in-app support for managing user interactions with files in
the local system. For example, an email program might use this class
to allow the user to preview attachments and open them in other
apps. Use this class to present an appropriate user interface for
previewing, opening, copying, or printing a specified file.
iCloud API:
iCloud is a free service that lets users access their personal
content on all
their devices—wirelessly and automatically via Apple ID. iCloud does this by
combining network-based storage with dedicated APIs, supported by full
integration with the operating system. Apple provides server infrastructure,
backup, and user accounts, so you can focus on building great iCloud-enabled
apps.
NOTE : No Idea With Jail Break iOS Device I Got the Reference This Great Document.
Currently there is no way to access the data of another application directly.
Because each application is running on a sandbox environment.
But you can do it, how ?
You need to use iCloud. You can share the data stored the iCloud between apps, so store your database file in iCloud.
References:
You can find a tutorial on iCloud here : iCloud Programming
I cloud Data sharing is described here : iCloud Data Sharing
I don't think that's possible at all, each app runs in its own VM, its impossible for other apps to access data of each other, unless the data is written on a shared space like SD card itself.
You can jailbreak your devices, then use some jailbreak development library that can give you each application's sandbox folder, or you can iterate the Application folder yourself.

SQL Error: Not an Error

More SQLite issues. So my interface is as follows (this is all in .m):
#interface Search()
#property (strong, nonatomic) NSString *databasePath; //path to sqlite database file
#property (strong, nonatomic) NSString *databaseName;
#property (nonatomic) sqlite3 *database;
#end
and the init follows:
- (id)init
{
if ((self = [super init]))
{
self.databaseName = DB_NAME;
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
_databasePath = [documentsDir stringByAppendingPathComponent:self.databaseName];
[self checkAndCreateDatabase];
if (sqlite3_open_v2([self.databasePath UTF8String], &_database, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
{
[[[UIAlertView alloc]initWithTitle:#"Missing"
message:#"Database file not found"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil]show];
}
else
{
NSLog(#"%s: sqlite3_open_v2 error: %s", __FUNCTION__, sqlite3_errmsg(self.database));
}
}
The error that the Log in the init returns is: sqlite3_open_v2 error: not an error. In my searches, I've heard that SQLite doesn't return an error when it points to a non-existent database. But I'm not sure why the database wouldn't exist. The copy function I'm using (which I was given and had seemed to work before) is as follows:
-(void) checkAndCreateDatabase
{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
BOOL dbExists;
// 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
dbExists = [fileManager fileExistsAtPath:_databasePath];
// If the database already exists then return without doing anything
if(dbExists)
{
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:_databaseName];
// Copy the database from the package to the users filesystem
//[fileManager copyItemAtPath:databasePathFromApp toPath:_databasePath error:nil];
NSError *error = nil;
if (![fileManager copyItemAtPath:databasePathFromApp toPath:_databasePath error:&error])
{
NSLog(#"%s: copyItemAtPathError: %#", __FUNCTION__, error);
}
}
Finally, I have verified in the iOS Simulator Documents directory that the database exists, and the query I'm trying to execute on it works. Why might I be getting this error?
Having never worked with SQLLite like this, I only want to mention, that in the code above, your else statement gets called, when sqlite_open_v2 == SQL_OK. So maybe in that case, there is just no error to return and everything is fine?!
It turns out the problem was a very simple one. The object I was trying to assign the values to (and then pull them from) was not initialized. It was a very silly oversight on my part, but I'm still new to Objective C.
Additionally, I do recommend icodebuster's suggestions to use FMDB for SQLite in iOS. It cleaned up some of my SQLite mess and made it a lot nicer to use.

FMDB ios no such table

I have a problem with a sqlite project that i'm doing, I'm using FMDB, I follow a simple example, but doesn´t work. And I can't find the error. I did my database schema from the terminal, I put some data on it. I'm very new to ios dev, so I don't know exactly if I did the steps ok.
This is what I did:
1 - I made my Database schema and add some fields. 2 - I copied the database.db into my project folder in xcode. 3 - I add the FMDB files. 4 - I add the sqlite3.dylib 5 - I put this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.dbname = #"database.db";
NSArray * docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * docDIr = [docPath objectAtIndex:0];
self.dbpath = [docDIr stringByAppendingPathComponent:dbname];
[self checkDB];
[self getQ];
return YES;
}
-(void) getQ
{
FMDatabase * db = [FMDatabase databaseWithPath:dbpath];
[db open];
FMResultSet * result = [db executeQuery:#"SELECT * FROM table1"];
NSLog(#"last Error: %#",[db lastErrorMessage]);
NSLog(#"result: %#", result);
}
-(void) checkDB
{
BOOL success;
NSFileManager * fm = [NSFileManager defaultManager];
success = [fm fileExistsAtPath:dbpath];
NSError * error = [[NSError alloc] init];
if (success) return;
NSLog(#"result:");
NSString * dbPathFromApp = [[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:self.dbname];
[fm copyItemAtPath:dbPathFromApp toPath:dbpath error:&error];
}
Apparently the database it's empty, so what happened? why I can't find table1 ? If I open the file with any sqlite gui, the table appears just fine. Thank's for any help
The console show me the next lines:
2013-03-02 14:03:31.839 myApp[21433:c07] last Error: no such table: table1
2013-03-02 14:03:31.841 myApp[21433:c07] result: (null)
A couple of thoughts:
I'd confirm the database has been added to your bundle. Go to your target settings, select "Build Phases", expand "Copy Bundle Resources", and make sure your database is listed there. If not, click on the "+" button and add it.
I'd reset your simulator. If you ever ran the app and didn't copy the database properly, it would have created a blank database for you in your documents folder. By resetting your simulator, you can get rid of any blank databases that might be there.
If it's still not working, I'd check the bundle database in your simulator. Navigate to the simulator folder (~/Library/Application Support/iPhone Simulator), find the app, open up the bundle (by control clicking on the app itself and say "show package contents"), and check the database in there and make sure it has your table1.
After adding the Database file please select that and Tick Mark Target Membership.

Resources