Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deallocating database, deleting it and rebuilding one. #139

Closed
FredericJacobs opened this issue Feb 6, 2015 · 10 comments
Closed

Deallocating database, deleting it and rebuilding one. #139

FredericJacobs opened this issue Feb 6, 2015 · 10 comments

Comments

@FredericJacobs
Copy link

Hey,

In my app, I want the user to be able to wipe the database when the user deletes his account.

To do so, I wanted to make sure to deallocate the YapDatabase instance that I initiated and then delete the file and recreate the database.

Thing is, every database connection in the respective view controllers that might still be in the hierarchy have database connections to the previous database instance, preventing it to be deallocated.

What's the best way to deal with this situation? NSNotificationCenter notification to set to nil view controller database connections before setting the YapDatabase instance to nil?

@mackross
Copy link
Contributor

mackross commented Feb 6, 2015

Looping through collections and calling delete all keys method has been the simplest way in my experience if you want to keep the same db file.

@FredericJacobs
Copy link
Author

Well, the entire point of my approach is that I want to wipe the database file from the device.

Wondering if @robbiehanson or @calebd had any recommendations about how to approach this problem.

@robbiehanson
Copy link
Contributor

There have been a few questions about this. Essentially, the YapDatabase class is just a retainer for the filepath, blocks, config, etc. (It does some other stuff, but let's simplify for now.) And YapDatabaseConnection(s) open a sqlite connection to the file. Thus I've configured it such that a YDBConnection instance retains the YapDatabase instance. (As you know.)

What I propose is this:

In your code, you'll have to figure out a way to notify interested parties that they must drop their YDBConnection properties. This will allow the YapDatabase instance to eventually be deallocated.

Then we add code that posts a NSNotification from within [YapDatabase dealloc] that broadcasts the filepath of the database that was just released. And you can use this as a hook to delete the file.

PS - there is a related ticket that discusses the lifetime of the internal connections used to register extensions. I may need to address this too.

@FredericJacobs
Copy link
Author

Thanks Robbie for the insight.

I'll give it a try and open a pull request with the suggested enhancement if it works.

@calebd
Copy link
Contributor

calebd commented Feb 9, 2015

When I build things like this, I tend to destroy the entire view / view controller hierarchy by reassigning the window's root view controller to a fresh state. This will cause all connections to be implicitly cleaned.

@robbiehanson
Copy link
Contributor

Related: commit 4ebc53d (in 2.6 branch)

Added extension registration methods that take a YapDatabaseConnection parameter. This allows for more fine grained control of YapDatabase lifetime.

robbiehanson added a commit that referenced this issue May 14, 2015
…nd thus has closed all references to the underlying sqlite files. Fixes issue #139
@robbiehanson
Copy link
Contributor

You can now use the YapDatabaseClosedNotification.

/**
 * This notification is posted when a YapDatabase instance is deallocated,
 * and has thus closed all references to the underlying sqlite files.
 * 
 * If you intend to delete the sqlite file(s) from disk,
 * it's recommended you use this notification as a hook to do so.
 * 
 * More info:
 * The YapDatabase class itself is just a retainer for the filepath, blocks, config, etc.
 * And YapDatabaseConnection(s) open a sqlite connection to the database file,
 * and rely on the blocks & config in the parent YapDatabase class.
 * Thus a YapDatabaseConnection instance purposely retains the YapDatabase instance.
 * This means that in order to fully close all references to the underlying sqlite file(s),
 * you need to deallocate YapDatabase and all associated YapDatabaseConnections.
 * While this may be simple in concept, it's generally difficult to know exactly when all
 * the instances have been deallocated. Especially when there may be a bunch of asynchronous operations going.
 * 
 * Therefore the best approach is to do the following:
 * - destroy your YapDatabase instance (set it to nil)
 * - destroy all YapDatabaseConnection instances
 * - wait for YapDatabaseClosedNotification
 * - use notification as hook to delete all associated sqlite files from disk
 *
 * The userInfo dictionary will look like this:
 * @{
 *     YapDatabasePathKey    : <NSString of full filePath to db.sqlite file>,
 *     YapDatabasePathWalKey : <NSString of full filePath to db.sqlite-wal file>,
 *     YapDatabasePathShmKey : <NSString of full filePath to db.sqlite-shm file>,
 * }
 *
 * This notification is always posted to the main thread.
**/
extern NSString *const YapDatabaseClosedNotification;

extern NSString *const YapDatabasePathKey;
extern NSString *const YapDatabasePathWalKey;
extern NSString *const YapDatabasePathShmKey;

@rgigger
Copy link

rgigger commented Oct 29, 2015

In order to delete the files and start over is it best to just use the file system APIs to delete the files databasePath, databasePath_shm, and databasePath_wal that are returned from the notification? Or is there SQLite api that handles this better?

@calebd
Copy link
Contributor

calebd commented Oct 29, 2015

I always put my database files in a folder so that I can delete the folder and everything it contains at once.

@robbiehanson
Copy link
Contributor

is it best to just use the file system APIs to delete the files

Yes, once you get the YapDatabaseClosedNotification you should use the system APIs to delete the 3 files. You can do this by deleting each of the 3 individually, or as @calebd mentioned, if they're in a folder by themselves, you can choose to delete the folder. Either solution should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants