Maxime Antoine
Maxime Antoine

Reputation: 25

sqlite ios : attempt to write a readonly database

I use a sqlite database for a project. I can do queries like SELECT but impossible to do INSERTs! On the simulator the INSERT works properly. As soon as I compile on my iPod this error message appears: "attempt to write a readonly database".

Thinking it is a right of the file I did a: chmod 777 mydatabase.sqlite But that does not change!

I also tried as I have read on other site and copy the file to use his copy to have it all right, but to no avail.

Have you a solution? Cordially.

PS: Here is my code:

for(NSDictionary *q in quotes) {
    sqlite3_stmt    *statement;
    sqlite3 *contactDB;
    const char *dbpath = [dbPath UTF8String];

    if (sqlite3_open_v2(dbpath, &contactDB, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK)
    {
        NSInteger identifiant = [[q objectForKey:@"id"] integerValue];
        NSString *texte = [q objectForKey:@"texte_english"];
        NSString *auteur = [q objectForKey:@"auteur"];
        NSString *date = [q objectForKey:@"date"];
        NSInteger auteurId = [[q objectForKey:@"auteur_id"] integerValue];
        NSInteger nbComments = [[q objectForKey:@"nb_comments"] integerValue];

        NSString *insertSQL = 
                [NSString stringWithFormat:@"INSERT INTO quotes (id, texte_english, auteur, date, auteur_id, nb_comments) VALUES (%d, \"%@\", \"%@\", \"%@\", \"%d\", \"%d\")", 
                                          identifiant, 
                                          texte, 
                                          auteur, 
                                          date, 
                                          auteurId, 
                                          nbComments];

        const char *insert_stmt = [insertSQL UTF8String];
        sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);

        if (sqlite3_step(statement) != SQLITE_DONE)
        {
            NSLog(@"ERREUR1: %s",sqlite3_errmsg(contactDB));
        }
        sqlite3_finalize(statement);
        sqlite3_close(contactDB);
    }
}

Upvotes: 2

Views: 8341

Answers (5)

scarer
scarer

Reputation: 101

Swift 3 using GRDB

var dbQueue: DatabaseQueue!

func setUpDatabasePath()
{
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as NSString
    let databasePath = documentsPath.appendingPathComponent("your_database.sqlite")
    print("DATABASE PATH !!!!")
    print(databasePath)
    let fileManager:FileManager = FileManager.default
    var success = fileManager.fileExists(atPath: databasePath)
    if (success)
    {
        dbQueue = try! DatabaseQueue(path: databasePath)
        print("writing to documents directory")
        print(databasePath)
        //break
        return
    }
    if (!success)
    {
        let bundlePath = Bundle.main.path(forResource: "your_database", ofType: "sqlite")
        success = fileManager.fileExists(atPath: bundlePath!)
        print("writing from app bundle")
        if (success)
        {
            try! fileManager.copyItem(atPath: bundlePath!, toPath: databasePath)
            dbQueue = try! DatabaseQueue(path: databasePath)
        }
        else
        {
            print("Could not find database")
        }
        return
    }
}

Upvotes: 0

Symmetric
Symmetric

Reputation: 4031

In case anyone else sees this...I started getting this error on one of my devices (iPhone 4s/iOS7) after upgrading to Xcode 5.2. It didn't happen on my iPhone 5 (iOS 6). It occurred when getting metadata from the store:

NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeURL error:&error];

Deleting my app and reinstalling it fixed the problem.

Upvotes: 0

GuruMurthy
GuruMurthy

Reputation: 139

-(void)createEditablecopyofDatabaseifneeded
{
    BOOL success;
    NSError *error;
    NSFileManager *filemanagr = [NSFileManager defaultManager];

    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *dbPath = [path objectAtIndex:0];
    NSString *finalDBPath = [dbPath stringByAppendingPathComponent:mDataBaseName];
    self.mDataBasePath=finalDBPath;
    success = [filemanagr fileExistsAtPath:finalDBPath];
    if (success) {

    }
    else
    {
        NSString *writableDBPath = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:mDataBaseName];
        success = [filemanagr copyItemAtPath:writableDBPath toPath:finalDBPath error:&error];
        self.mDataBasePath=writableDBPath;
    }
    if (!success) {

    }
}

Check this before you create the DB in the document directory Hope this will help you

Upvotes: 2

Rudi
Rudi

Reputation: 4314

All you need to do is change the root that you are saving your SQLite file in you phone which is readonly at the moment. make these changes :

Add these codes to your AppDelegate :

.h file:

@property (nonatomic,retain) NSFileManager *fileMgr;
@property (nonatomic,retain) NSString *homeDir;
@property (nonatomic,retain) NSString *title;

.m file:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self checkAndCreateDatabase];
    return YES;
}

-(NSString *)GetDocumentDirectory{
    fileMgr = [NSFileManager defaultManager];
    homeDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    return homeDir;
}

    -(void) checkAndCreateDatabase{
    BOOL success;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *databasePath = [self.GetDocumentDirectory stringByAppendingPathComponent:@"YOUR DATABASE NAME.sqlite"];
    success = [fileManager fileExistsAtPath:databasePath];
    if(success) {
        NSLog(@"working");
        return;}
    else{
        NSLog(@"notworking");
    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"YOUR DATABASE NAME.sqlite"];
    [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
    }
}

Also in your SQLite class add these lines :

.h file:

@property (nonatomic,retain) NSFileManager *fileMgr;
@property (nonatomic,retain) NSString *homeDir;

.m file:

-(NSString *)GetDocumentDirectory{
    fileMgr = [NSFileManager defaultManager];
    homeDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    return homeDir;
}

and also in INSERT and SELECT make these changes :

NSString *dbPath = [self.GetDocumentDirectory stringByAppendingPathComponent:@"YOUR DATABASE NAME.sqlite"];
    const char *dbpath = [dbPath UTF8String];

Hope it helps :)

Upvotes: 7

Maxime Antoine
Maxime Antoine

Reputation: 25

I have found the solution :

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:@"tq.sqlite"];

So, i have this error : "no such table: quotes" Any idea ?

I hope it will be useful !

Upvotes: 0

Related Questions