Skip to content

Commit 88ef306

Browse files
committed
The YapDatabaseSanitizer is now split into YapDatabasePreSanitizer & YapDatabasePostSanitizer.
1 parent 447f5a4 commit 88ef306

File tree

5 files changed

+132
-62
lines changed

5 files changed

+132
-62
lines changed

Testing/Benchmarking/BenchmarkYapDatabase.m

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,8 @@ + (void)runTestsWithCompletion:(dispatch_block_t)completionBlock
244244
// options.pragmaSynchronous = YapDatabasePragmaSynchronous_Off; // Use for fastest speed
245245

246246
database = [[YapDatabase alloc] initWithPath:databasePath
247-
objectSerializer:NULL
248-
objectDeserializer:NULL
249-
metadataSerializer:NULL
250-
metadataDeserializer:NULL
251-
objectSanitizer:NULL
252-
metadataSanitizer:NULL
247+
serializer:NULL
248+
deserializer:NULL
253249
options:options];
254250

255251
// Create database connection (can have multiple for concurrency)

YapDatabase/Internal/YapDatabasePrivate.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,17 @@ extern NSString *const YapDatabaseNotificationKey;
7171

7272
NSArray *previouslyRegisteredExtensionNames; // Only to be used by YapDatabaseConnection
7373

74-
YapDatabaseSerializer objectSerializer; // Read-only by transactions
75-
YapDatabaseDeserializer objectDeserializer; // Read-only by transactions
74+
YapDatabaseSerializer objectSerializer; // Read-only by transactions
75+
YapDatabaseDeserializer objectDeserializer; // Read-only by transactions
7676

77-
YapDatabaseSerializer metadataSerializer; // Read-only by transactions
78-
YapDatabaseDeserializer metadataDeserializer; // Read-only by transactions
77+
YapDatabaseSerializer metadataSerializer; // Read-only by transactions
78+
YapDatabaseDeserializer metadataDeserializer; // Read-only by transactions
7979

80-
YapDatabaseSanitizer objectSanitizer; // Read-only by transactions
81-
YapDatabaseSanitizer metadataSanitizer; // Read-only by transactions
80+
YapDatabasePreSanitizer objectPreSanitizer; // Read-only by transactions
81+
YapDatabasePostSanitizer objectPostSanitizer; // Read-only by transactions
82+
83+
YapDatabasePreSanitizer metadataPreSanitizer; // Read-only by transactions
84+
YapDatabasePostSanitizer metadataPostSanitizer; // Read-only by transactions
8285
}
8386

8487
/**

YapDatabase/YapDatabase.h

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,40 @@ typedef NSData* (^YapDatabaseSerializer)(NSString *collection, NSString *key, id
6060
typedef id (^YapDatabaseDeserializer)(NSString *collection, NSString *key, NSData *data);
6161

6262
/**
63-
* Is it safe to store mutable objects in the database?
63+
* The sanitizer block allows you to enforce desired behavior of the objects you put into the database.
6464
*
65-
* That question is answered extensively in the wiki article "Thread Safety":
66-
* https://github.com/yaptv/YapDatabase/wiki/Thread-Safety
65+
* If set, the sanitizer block will be run on all items being input into the database via
66+
* the setObject:forKey:inCollection: (and other setObject:XXX: methods).
67+
*
68+
* You have 2 different hooks for running a sanitizer block:
6769
*
68-
* The sanitizer block can be run on all objects as they are being input into the database.
69-
* That is, it will be run on all objects passed to setObject:forKey:inCollection: before
70-
* being handed to the database internals.
70+
* The PreSanitizer is run:
71+
* - Before the object is serialized
72+
* - Before the object is stored in the cache
73+
* - Before the object is passed to extensions
74+
*
75+
* The PostSanitizer is run:
76+
* - After the object has been serialized
77+
* - After the object has been stored in the cache
78+
* - After the object has been passed to extensions
79+
*
80+
* The PreSanitizer is generally used validate the objects going into the database,
81+
* and/or to enforce immutability of those objects.
82+
*
83+
* Enforcing immutability is a topic covered in the "Object Policy" wiki article:
84+
* https://github.com/yapstudios/YapDatabase/wiki/Object-Policy
85+
*
86+
* The PostSanitizer is generally used to "clear flags" that are used by extensions.
87+
* For example, your objects might have a "changedProperties" property that tells extensions exactly
88+
* what properties where changed on a modified object. And the extension uses that information
89+
* in order to automatically sync the changes to the cloud. Thus the PostSanitizer would be used
90+
* to clear the "changedProperties" after the extension has processed the modified object.
91+
*
92+
* An example of such a use for the PostSanitizer is discussed in the YapDatabaseCloudKit wiki article:
93+
* https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseCloudKit
7194
**/
72-
typedef id (^YapDatabaseSanitizer)(NSString *collection, NSString *key, id object);
73-
95+
typedef id (^YapDatabasePreSanitizer)(NSString *collection, NSString *key, id obj);
96+
typedef void (^YapDatabasePostSanitizer)(NSString *collection, NSString *key, id obj);
7497

7598
/**
7699
* This notification is posted following a readwrite transaction where the database was modified.
@@ -187,7 +210,9 @@ extern NSString *const YapDatabaseAllKeysRemovedKey;
187210
- (id)initWithPath:(NSString *)path
188211
serializer:(YapDatabaseSerializer)serializer
189212
deserializer:(YapDatabaseDeserializer)deserializer
190-
sanitizer:(YapDatabaseSanitizer)sanitizer;
213+
preSanitizer:(YapDatabasePreSanitizer)preSanitizer
214+
postSanitizer:(YapDatabasePostSanitizer)postSanitizer
215+
options:(YapDatabaseOptions *)options;
191216

192217
/**
193218
* Opens or creates a sqlite database with the given path.
@@ -208,8 +233,7 @@ extern NSString *const YapDatabaseAllKeysRemovedKey;
208233
objectDeserializer:(YapDatabaseDeserializer)objectDeserializer
209234
metadataSerializer:(YapDatabaseSerializer)metadataSerializer
210235
metadataDeserializer:(YapDatabaseDeserializer)metadataDeserializer
211-
objectSanitizer:(YapDatabaseSanitizer)objectSanitizer
212-
metadataSanitizer:(YapDatabaseSanitizer)metadataSanitizer;
236+
options:(YapDatabaseOptions *)options;
213237

214238
/**
215239
* Opens or creates a sqlite database with the given path.
@@ -220,8 +244,10 @@ extern NSString *const YapDatabaseAllKeysRemovedKey;
220244
objectDeserializer:(YapDatabaseDeserializer)objectDeserializer
221245
metadataSerializer:(YapDatabaseSerializer)metadataSerializer
222246
metadataDeserializer:(YapDatabaseDeserializer)metadataDeserializer
223-
objectSanitizer:(YapDatabaseSanitizer)objectSanitizer
224-
metadataSanitizer:(YapDatabaseSanitizer)metadataSanitizer
247+
objectPreSanitizer:(YapDatabasePreSanitizer)objectPreSanitizer
248+
objectPostSanitizer:(YapDatabasePostSanitizer)objectPostSanitizer
249+
metadataPreSanitizer:(YapDatabasePreSanitizer)metadataPreSanitizer
250+
metadataPostSanitizer:(YapDatabasePostSanitizer)metadataPostSanitizer
225251
options:(YapDatabaseOptions *)options;
226252

227253
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -236,8 +262,11 @@ extern NSString *const YapDatabaseAllKeysRemovedKey;
236262
@property (nonatomic, strong, readonly) YapDatabaseSerializer metadataSerializer;
237263
@property (nonatomic, strong, readonly) YapDatabaseDeserializer metadataDeserializer;
238264

239-
@property (nonatomic, strong, readonly) YapDatabaseSanitizer objectSanitizer;
240-
@property (nonatomic, strong, readonly) YapDatabaseSanitizer metadataSanitizer;
265+
@property (nonatomic, strong, readonly) YapDatabasePreSanitizer objectPreSanitizer;
266+
@property (nonatomic, strong, readonly) YapDatabasePostSanitizer objectPostSanitizer;
267+
268+
@property (nonatomic, strong, readonly) YapDatabasePreSanitizer metadataPreSanitizer;
269+
@property (nonatomic, strong, readonly) YapDatabasePostSanitizer metadataPostSanitizer;
241270

242271
@property (nonatomic, copy, readonly) YapDatabaseOptions *options;
243272

YapDatabase/YapDatabase.m

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,15 @@ + (YapDatabaseDeserializer)timestampDeserializer
166166

167167
@synthesize objectSerializer = objectSerializer;
168168
@synthesize objectDeserializer = objectDeserializer;
169+
169170
@synthesize metadataSerializer = metadataSerializer;
170171
@synthesize metadataDeserializer = metadataDeserializer;
171-
@synthesize objectSanitizer = objectSanitizer;
172-
@synthesize metadataSanitizer = metadataSanitizer;
172+
173+
@synthesize objectPreSanitizer = objectPreSanitizer;
174+
@synthesize objectPostSanitizer = objectPostSanitizer;
175+
176+
@synthesize metadataPreSanitizer = metadataPreSanitizer;
177+
@synthesize metadataPostSanitizer = metadataPostSanitizer;
173178

174179
@dynamic options;
175180

@@ -189,8 +194,10 @@ - (id)initWithPath:(NSString *)inPath
189194
objectDeserializer:NULL
190195
metadataSerializer:NULL
191196
metadataDeserializer:NULL
192-
objectSanitizer:NULL
193-
metadataSanitizer:NULL
197+
objectPreSanitizer:NULL
198+
objectPostSanitizer:NULL
199+
metadataPreSanitizer:NULL
200+
metadataPostSanitizer:NULL
194201
options:nil];
195202
}
196203

@@ -203,9 +210,11 @@ - (id)initWithPath:(NSString *)inPath
203210
objectDeserializer:inDeserializer
204211
metadataSerializer:inSerializer
205212
metadataDeserializer:inDeserializer
206-
objectSanitizer:NULL
207-
metadataSanitizer:NULL
208-
options:nil];
213+
objectPreSanitizer:NULL
214+
objectPostSanitizer:NULL
215+
metadataPreSanitizer:NULL
216+
metadataPostSanitizer:NULL
217+
options:nil];
209218
}
210219

211220
- (id)initWithPath:(NSString *)inPath
@@ -218,24 +227,30 @@ - (id)initWithPath:(NSString *)inPath
218227
objectDeserializer:inDeserializer
219228
metadataSerializer:inSerializer
220229
metadataDeserializer:inDeserializer
221-
objectSanitizer:NULL
222-
metadataSanitizer:NULL
230+
objectPreSanitizer:NULL
231+
objectPostSanitizer:NULL
232+
metadataPreSanitizer:NULL
233+
metadataPostSanitizer:NULL
223234
options:inOptions];
224235
}
225236

226237
- (id)initWithPath:(NSString *)inPath
227238
serializer:(YapDatabaseSerializer)inSerializer
228239
deserializer:(YapDatabaseDeserializer)inDeserializer
229-
sanitizer:(YapDatabaseSanitizer)inSanitizer
240+
preSanitizer:(YapDatabasePreSanitizer)inPreSanitizer
241+
postSanitizer:(YapDatabasePostSanitizer)inPostSanitizer
242+
options:(YapDatabaseOptions *)inOptions
230243
{
231244
return [self initWithPath:inPath
232245
objectSerializer:inSerializer
233246
objectDeserializer:inDeserializer
234247
metadataSerializer:inSerializer
235248
metadataDeserializer:inDeserializer
236-
objectSanitizer:inSanitizer
237-
metadataSanitizer:inSanitizer
238-
options:nil];
249+
objectPreSanitizer:inPreSanitizer
250+
objectPostSanitizer:inPostSanitizer
251+
metadataPreSanitizer:inPreSanitizer
252+
metadataPostSanitizer:inPostSanitizer
253+
options:inOptions];
239254
}
240255

241256
- (id)initWithPath:(NSString *)inPath objectSerializer:(YapDatabaseSerializer)inObjectSerializer
@@ -248,34 +263,39 @@ - (id)initWithPath:(NSString *)inPath objectSerializer:(YapDatabaseSerializer)in
248263
objectDeserializer:inObjectDeserializer
249264
metadataSerializer:inMetadataSerializer
250265
metadataDeserializer:inMetadataDeserializer
251-
objectSanitizer:NULL
252-
metadataSanitizer:NULL
266+
objectPreSanitizer:NULL
267+
objectPostSanitizer:NULL
268+
metadataPreSanitizer:NULL
269+
metadataPostSanitizer:NULL
253270
options:nil];
254271
}
255272

256273
- (id)initWithPath:(NSString *)inPath objectSerializer:(YapDatabaseSerializer)inObjectSerializer
257274
objectDeserializer:(YapDatabaseDeserializer)inObjectDeserializer
258275
metadataSerializer:(YapDatabaseSerializer)inMetadataSerializer
259276
metadataDeserializer:(YapDatabaseDeserializer)inMetadataDeserializer
260-
objectSanitizer:(YapDatabaseSanitizer)inObjectSanitizer
261-
metadataSanitizer:(YapDatabaseSanitizer)inMetadataSanitizer;
277+
options:(YapDatabaseOptions *)inOptions
262278
{
263279
return [self initWithPath:inPath
264280
objectSerializer:inObjectSerializer
265281
objectDeserializer:inObjectDeserializer
266282
metadataSerializer:inMetadataSerializer
267283
metadataDeserializer:inMetadataDeserializer
268-
objectSanitizer:inObjectSanitizer
269-
metadataSanitizer:inMetadataSanitizer
284+
objectPreSanitizer:NULL
285+
objectPostSanitizer:NULL
286+
metadataPreSanitizer:NULL
287+
metadataPostSanitizer:NULL
270288
options:nil];
271289
}
272290

273291
- (id)initWithPath:(NSString *)inPath objectSerializer:(YapDatabaseSerializer)inObjectSerializer
274292
objectDeserializer:(YapDatabaseDeserializer)inObjectDeserializer
275293
metadataSerializer:(YapDatabaseSerializer)inMetadataSerializer
276294
metadataDeserializer:(YapDatabaseDeserializer)inMetadataDeserializer
277-
objectSanitizer:(YapDatabaseSanitizer)inObjectSanitizer
278-
metadataSanitizer:(YapDatabaseSanitizer)inMetadataSanitizer
295+
objectPreSanitizer:(YapDatabasePreSanitizer)inObjectPreSanitizer
296+
objectPostSanitizer:(YapDatabasePostSanitizer)inObjectPostSanitizer
297+
metadataPreSanitizer:(YapDatabasePreSanitizer)inMetadataPreSanitizer
298+
metadataPostSanitizer:(YapDatabasePostSanitizer)inMetadataPostSanitizer
279299
options:(YapDatabaseOptions *)inOptions
280300
{
281301
// First, standardize path.
@@ -441,8 +461,11 @@ - (id)initWithPath:(NSString *)inPath objectSerializer:(YapDatabaseSerializer)in
441461
metadataSerializer = inMetadataSerializer ? inMetadataSerializer : defaultSerializer;
442462
metadataDeserializer = inMetadataDeserializer ? inMetadataDeserializer : defaultDeserializer;
443463

444-
objectSanitizer = inObjectSanitizer;
445-
metadataSanitizer = inMetadataSanitizer;
464+
objectPreSanitizer = inObjectPreSanitizer;
465+
objectPostSanitizer = inObjectPostSanitizer;
466+
467+
metadataPreSanitizer = inMetadataPreSanitizer;
468+
metadataPostSanitizer = inMetadataPostSanitizer;
446469

447470
// Mark the queues so we can identify them.
448471
// There are several methods whose use is restricted to within a certain queue.

YapDatabase/YapDatabaseTransaction.m

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4184,23 +4184,23 @@ - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)col
41844184
if (key == nil) return;
41854185
if (collection == nil) collection = @"";
41864186

4187-
if (connection->database->objectSanitizer)
4187+
if (connection->database->objectPreSanitizer)
41884188
{
4189-
object = connection->database->objectSanitizer(collection, key, object);
4189+
object = connection->database->objectPreSanitizer(collection, key, object);
41904190
if (object == nil)
41914191
{
4192-
YDBLogWarn(@"Object sanitizer returned nil for key(%@) object: %@", key, object);
4192+
YDBLogWarn(@"The objectPreSanitizer returned nil for collection(%@) key(%@)", collection, key);
41934193

41944194
[self removeObjectForKey:key inCollection:collection];
41954195
return;
41964196
}
41974197
}
4198-
if (metadata && connection->database->metadataSanitizer)
4198+
if (metadata && connection->database->metadataPreSanitizer)
41994199
{
4200-
metadata = connection->database->metadataSanitizer(collection, key, metadata);
4200+
metadata = connection->database->metadataPreSanitizer(collection, key, metadata);
42014201
if (metadata == nil)
42024202
{
4203-
YDBLogWarn(@"Metadata sanitizer returned nil for key(%@) metadata: %@", key, metadata);
4203+
YDBLogWarn(@"The metadataPresanitizer returned nil for collection(%@) key(%@)", collection, key);
42044204
}
42054205
}
42064206

@@ -4387,6 +4387,15 @@ - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)col
43874387
withMetadata:metadata
43884388
rowid:rowid];
43894389
}
4390+
4391+
if (connection->database->objectPostSanitizer)
4392+
{
4393+
connection->database->objectPostSanitizer(collection, key, object);
4394+
}
4395+
if (metadata && connection->database->metadataPreSanitizer)
4396+
{
4397+
connection->database->metadataPostSanitizer(collection, key, metadata);
4398+
}
43904399
}
43914400

43924401
/**
@@ -4483,12 +4492,12 @@ - (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *
44834492
NSAssert(key != nil, @"Internal error");
44844493
if (collection == nil) collection = @"";
44854494

4486-
if (connection->database->objectSanitizer)
4495+
if (connection->database->objectPreSanitizer)
44874496
{
4488-
object = connection->database->objectSanitizer(collection, key, object);
4497+
object = connection->database->objectPreSanitizer(collection, key, object);
44894498
if (object == nil)
44904499
{
4491-
YDBLogWarn(@"Object sanitizer returned nil for key(%@) object: %@", key, object);
4500+
YDBLogWarn(@"The objectPreSanitizer returned nil for collection(%@) key(%@)", collection, key);
44924501

44934502
[self removeObjectForKey:key inCollection:collection withRowid:rowid];
44944503
return;
@@ -4553,6 +4562,11 @@ - (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *
45534562
{
45544563
[extTransaction handleReplaceObject:object forCollectionKey:cacheKey withRowid:rowid];
45554564
}
4565+
4566+
if (connection->database->objectPostSanitizer)
4567+
{
4568+
connection->database->objectPostSanitizer(collection, key, object);
4569+
}
45564570
}
45574571

45584572
/**
@@ -4645,12 +4659,12 @@ - (void)replaceMetadata:(id)metadata
46454659
NSAssert(key != nil, @"Internal error");
46464660
if (collection == nil) collection = @"";
46474661

4648-
if (metadata && connection->database->metadataSanitizer)
4662+
if (metadata && connection->database->metadataPreSanitizer)
46494663
{
4650-
metadata = connection->database->metadataSanitizer(collection, key, metadata);
4664+
metadata = connection->database->metadataPreSanitizer(collection, key, metadata);
46514665
if (metadata == nil)
46524666
{
4653-
YDBLogWarn(@"Metadata sanitizer returned nil for key: %@", key);
4667+
YDBLogWarn(@"The metadataPreSanitizer returned nil for collection(%@) key(%@)", collection, key);
46544668
}
46554669
}
46564670

@@ -4723,6 +4737,11 @@ - (void)replaceMetadata:(id)metadata
47234737
{
47244738
[extTransaction handleReplaceMetadata:metadata forCollectionKey:cacheKey withRowid:rowid];
47254739
}
4740+
4741+
if (metadata && connection->database->metadataPostSanitizer)
4742+
{
4743+
connection->database->metadataPostSanitizer(collection, key, metadata);
4744+
}
47264745
}
47274746

47284747
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)