nano-store 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGELOG → CHANGELOG.md} +7 -0
- data/README.md +5 -1
- data/Rakefile +1 -1
- data/lib/nano_store.rb +1 -1
- data/lib/nano_store/finder.rb +10 -2
- data/lib/nano_store/model.rb +7 -7
- data/lib/nano_store/version.rb +1 -1
- data/spec/association_spec.rb +6 -6
- data/spec/finder_spec.rb +2 -0
- data/spec/model_spec.rb +33 -3
- data/spec/nano_store_spec.rb +5 -0
- data/spec/spec_helper.rb +14 -0
- data/vendor/Podfile.lock +3 -3
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoBag.h +6 -1
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoEngine.h +5 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoEngine_Private.h +2 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoExpression.h +6 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoExpression_Private.h +1 -1
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoGlobals.h +5 -1
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoGlobals_Private.h +6 -2
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoObject.h +15 -3
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoObject_Private.h +4 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoPredicate.h +6 -1
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoResult.h +5 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoSearch.h +16 -2
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoSortDescriptor.h +7 -1
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoStore.h +12 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoStore_Private.h +3 -1
- data/vendor/Pods/BuildHeaders/NanoStore/NSFOrderedDictionary.h +33 -0
- data/vendor/Pods/BuildHeaders/NanoStore/NanoStore.h +36 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoBag.h +6 -1
- data/vendor/Pods/Headers/NanoStore/NSFNanoEngine.h +5 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoEngine_Private.h +2 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoExpression.h +6 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoExpression_Private.h +1 -1
- data/vendor/Pods/Headers/NanoStore/NSFNanoGlobals.h +5 -1
- data/vendor/Pods/Headers/NanoStore/NSFNanoGlobals_Private.h +6 -2
- data/vendor/Pods/Headers/NanoStore/NSFNanoObject.h +15 -3
- data/vendor/Pods/Headers/NanoStore/NSFNanoObject_Private.h +4 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoPredicate.h +6 -1
- data/vendor/Pods/Headers/NanoStore/NSFNanoResult.h +5 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoSearch.h +16 -2
- data/vendor/Pods/Headers/NanoStore/NSFNanoSortDescriptor.h +7 -1
- data/vendor/Pods/Headers/NanoStore/NSFNanoStore.h +12 -0
- data/vendor/Pods/Headers/NanoStore/NSFNanoStore_Private.h +3 -1
- data/vendor/Pods/Headers/NanoStore/NSFOrderedDictionary.h +33 -0
- data/vendor/Pods/Headers/NanoStore/NanoStore.h +36 -0
- data/vendor/Pods/NanoStore/Classes/Advanced/NSFNanoEngine.h +5 -0
- data/vendor/Pods/NanoStore/Classes/Advanced/NSFNanoEngine.m +142 -131
- data/vendor/Pods/NanoStore/Classes/Advanced/NSFNanoResult.h +5 -0
- data/vendor/Pods/NanoStore/Classes/Advanced/NSFNanoResult.m +148 -51
- data/vendor/Pods/NanoStore/Classes/Advanced/NSFOrderedDictionary.h +33 -0
- data/vendor/Pods/NanoStore/Classes/Advanced/NSFOrderedDictionary.m +148 -0
- data/vendor/Pods/NanoStore/Classes/Private/NSFNanoEngine_Private.h +2 -0
- data/vendor/Pods/NanoStore/Classes/Private/NSFNanoExpression_Private.h +1 -1
- data/vendor/Pods/NanoStore/Classes/Private/NSFNanoGlobals_Private.h +6 -2
- data/vendor/Pods/NanoStore/Classes/Private/NSFNanoObject_Private.h +4 -0
- data/vendor/Pods/NanoStore/Classes/Private/NSFNanoStore_Private.h +3 -1
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoBag.h +6 -1
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoBag.m +126 -117
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoExpression.h +6 -0
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoExpression.m +32 -18
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoGlobals.h +5 -1
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoGlobals.m +6 -3
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoObject.h +15 -3
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoObject.m +152 -31
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoPredicate.h +6 -1
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoPredicate.m +51 -26
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSearch.h +16 -2
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSearch.m +156 -115
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSortDescriptor.h +7 -1
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSortDescriptor.m +34 -17
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoStore.h +12 -0
- data/vendor/Pods/NanoStore/Classes/Public/NSFNanoStore.m +210 -196
- data/vendor/Pods/NanoStore/Classes/Public/NanoStore.h +36 -0
- data/vendor/Pods/NanoStore/README.md +49 -0
- data/vendor/Pods/Pods.bridgesupport +798 -685
- metadata +30 -8
@@ -75,7 +75,7 @@
|
|
75
75
|
@interface NSFNanoSortDescriptor : NSObject
|
76
76
|
|
77
77
|
/** * The property key to use when performing a comparison */
|
78
|
-
@property (nonatomic, readonly) NSString *attribute;
|
78
|
+
@property (nonatomic, copy, readonly) NSString *attribute;
|
79
79
|
/** * The property to indicate whether the comparison should be performed in ascending mode */
|
80
80
|
@property (nonatomic, readonly) BOOL isAscending;
|
81
81
|
|
@@ -119,6 +119,12 @@
|
|
119
119
|
|
120
120
|
- (NSString *)description;
|
121
121
|
|
122
|
+
/** Returns a JSON representation of the sort.
|
123
|
+
* @note Check properties attribute and isAscending to find out the current state of the sort.
|
124
|
+
*/
|
125
|
+
|
126
|
+
- (NSString *)JSONDescription;
|
127
|
+
|
122
128
|
//@}
|
123
129
|
|
124
130
|
@end
|
@@ -26,16 +26,19 @@
|
|
26
26
|
|
27
27
|
#import "NSFNanoSortDescriptor.h"
|
28
28
|
#import "NSFNanoGlobals.h"
|
29
|
+
#import "NSFOrderedDictionary.h"
|
30
|
+
#import "NSFNanoObject_Private.h"
|
29
31
|
|
30
|
-
@
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
32
|
+
@interface NSFNanoSortDescriptor ()
|
33
|
+
|
34
|
+
/** \cond */
|
35
|
+
@property (nonatomic, copy, readwrite) NSString *attribute;
|
36
|
+
@property (nonatomic, readwrite) BOOL isAscending;
|
37
|
+
/** \endcond */
|
37
38
|
|
38
|
-
@
|
39
|
+
@end
|
40
|
+
|
41
|
+
@implementation NSFNanoSortDescriptor
|
39
42
|
|
40
43
|
+ (NSFNanoSortDescriptor *)sortDescriptorWithAttribute:(NSString *)theAttribute ascending:(BOOL)ascending
|
41
44
|
{
|
@@ -46,12 +49,12 @@
|
|
46
49
|
{
|
47
50
|
if (theAttribute.length == 0)
|
48
51
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
49
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
52
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: theAttribute is invalid.", [self class], NSStringFromSelector(_cmd)]
|
50
53
|
userInfo:nil]raise];
|
51
54
|
|
52
55
|
if ((self = [super init])) {
|
53
|
-
|
54
|
-
|
56
|
+
_attribute = theAttribute;
|
57
|
+
_isAscending = ascending;
|
55
58
|
}
|
56
59
|
|
57
60
|
return self;
|
@@ -64,14 +67,28 @@
|
|
64
67
|
|
65
68
|
#pragma mark -
|
66
69
|
|
67
|
-
- (NSString*)description
|
70
|
+
- (NSString *)description
|
71
|
+
{
|
72
|
+
return [self JSONDescription];
|
73
|
+
}
|
74
|
+
|
75
|
+
- (NSFOrderedDictionary *)dictionaryDescription
|
76
|
+
{
|
77
|
+
NSFOrderedDictionary *values = [NSFOrderedDictionary new];
|
78
|
+
|
79
|
+
values[@"Sort descriptor address"] = [NSString stringWithFormat:@"%p", self];
|
80
|
+
values[@"Attribute"] = _attribute;
|
81
|
+
values[@"Is ascending?"] = (_isAscending ? @"YES" : @"NO");
|
82
|
+
|
83
|
+
return values;
|
84
|
+
}
|
85
|
+
|
86
|
+
- (NSString *)JSONDescription
|
68
87
|
{
|
69
|
-
|
88
|
+
NSFOrderedDictionary *values = [self dictionaryDescription];
|
70
89
|
|
71
|
-
|
72
|
-
|
73
|
-
[description appendString:[NSString stringWithFormat:@"Attribute : %@\n", attribute]];
|
74
|
-
[description appendString:[NSString stringWithFormat:@"Is ascending? : %@\n", (isAscending ? @"YES" : @"NO")]];
|
90
|
+
NSError *outError = nil;
|
91
|
+
NSString *description = [NSFNanoObject _NSObjectToJSONString:values error:&outError];
|
75
92
|
|
76
93
|
return description;
|
77
94
|
}
|
@@ -297,6 +297,13 @@
|
|
297
297
|
|
298
298
|
- (NSFNanoBag *)bagWithName:(NSString *)theName;
|
299
299
|
|
300
|
+
/** * Retrieves all bags associated with the specified name.
|
301
|
+
* @param theName the name of the bag.
|
302
|
+
* @returns The bags that match the specified name, an empty array otherwise.
|
303
|
+
*/
|
304
|
+
|
305
|
+
- (NSArray *)bagsWithName:(NSString *)theName;
|
306
|
+
|
300
307
|
/** * Returns a new array containing the bags found in the document store matching the specified list of keys.
|
301
308
|
* @param theKeys the list of bag keys.
|
302
309
|
* @returns An array with the bags that match the specified list of keys.
|
@@ -470,6 +477,11 @@
|
|
470
477
|
|
471
478
|
- (NSString *)description;
|
472
479
|
|
480
|
+
/** Returns a JSON representation of the store.
|
481
|
+
*/
|
482
|
+
|
483
|
+
- (NSString *)JSONDescription;
|
484
|
+
|
473
485
|
//@}
|
474
486
|
|
475
487
|
@end
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
8
8
|
provided that the following conditions are met:
|
9
|
-
|
9
|
+
|
10
10
|
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
11
11
|
and the following disclaimer.
|
12
12
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
@@ -28,23 +28,26 @@
|
|
28
28
|
#import "NSFNanoObjectProtocol.h"
|
29
29
|
#import "NanoStore_Private.h"
|
30
30
|
#import "NSFNanoStore_Private.h"
|
31
|
+
#import "NSFNanoEngine_Private.h"
|
32
|
+
#import "NSFOrderedDictionary.h"
|
31
33
|
|
32
34
|
#include <stdlib.h>
|
33
35
|
|
36
|
+
@interface NSFNanoStore ()
|
37
|
+
|
38
|
+
/** \cond */
|
39
|
+
@property (nonatomic, strong, readwrite) NSFNanoEngine *nanoStoreEngine;
|
40
|
+
@property (nonatomic, readwrite) BOOL hasUnsavedChanges;
|
41
|
+
@property (nonatomic) NSMutableArray *addedObjects;
|
42
|
+
@property (nonatomic) BOOL isOurTransaction;
|
43
|
+
@property (nonatomic, assign) sqlite3_stmt *insertDeleteKeysStatement;
|
44
|
+
@property (nonatomic, assign) sqlite3_stmt *storeValuesStatement;
|
45
|
+
@property (nonatomic, assign) sqlite3_stmt *storeKeysStatement;
|
46
|
+
/** \endcond */
|
47
|
+
|
48
|
+
@end
|
49
|
+
|
34
50
|
@implementation NSFNanoStore
|
35
|
-
{
|
36
|
-
@protected
|
37
|
-
NSFNanoEngine *nanoStoreEngine;
|
38
|
-
NSFEngineProcessingMode nanoEngineProcessingMode;
|
39
|
-
NSUInteger saveInterval;
|
40
|
-
|
41
|
-
/** \cond */
|
42
|
-
NSMutableArray *addedObjects;
|
43
|
-
BOOL _isOurTransaction;
|
44
|
-
sqlite3_stmt *_storeValuesStatement;
|
45
|
-
sqlite3_stmt *_storeKeysStatement;
|
46
|
-
/** \endcond */
|
47
|
-
}
|
48
51
|
|
49
52
|
@synthesize nanoStoreEngine;
|
50
53
|
@synthesize nanoEngineProcessingMode;
|
@@ -82,14 +85,14 @@
|
|
82
85
|
|
83
86
|
if (nil == thePath) {
|
84
87
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
85
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
88
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: the path cannot be nil.", [self class], NSStringFromSelector(_cmd)]
|
86
89
|
userInfo:nil]raise];
|
87
90
|
}
|
88
91
|
|
89
92
|
if ((self = [super init])) {
|
90
93
|
nanoStoreEngine = [[NSFNanoEngine alloc]initWithPath:[thePath stringByExpandingTildeInPath]];
|
91
94
|
if (nil == nanoStoreEngine) {
|
92
|
-
_NSFLog([NSString stringWithFormat:@"*** -[%@
|
95
|
+
_NSFLog([NSString stringWithFormat:@"*** -[%@ %@]: [NSFNanoEngine initWithPath:] failed: %@", [self class], NSStringFromSelector(_cmd), thePath]);
|
93
96
|
[self closeWithError:nil];
|
94
97
|
return nil;
|
95
98
|
}
|
@@ -99,10 +102,11 @@
|
|
99
102
|
_isOurTransaction = NO;
|
100
103
|
saveInterval = 1;
|
101
104
|
|
105
|
+
_insertDeleteKeysStatement = NULL;
|
102
106
|
_storeValuesStatement = NULL;
|
103
107
|
_storeKeysStatement = NULL;
|
104
108
|
|
105
|
-
|
109
|
+
_addedObjects = [[NSMutableArray alloc]initWithCapacity:saveInterval];
|
106
110
|
}
|
107
111
|
|
108
112
|
return self;
|
@@ -111,8 +115,6 @@
|
|
111
115
|
- (void)dealloc
|
112
116
|
{
|
113
117
|
[self closeWithError:nil];
|
114
|
-
|
115
|
-
|
116
118
|
}
|
117
119
|
|
118
120
|
- (NSString *)filePath
|
@@ -126,7 +128,7 @@
|
|
126
128
|
return YES;
|
127
129
|
|
128
130
|
if ([nanoStoreEngine openWithCacheMethod:CacheAllData useFastMode:(NSFEngineProcessingFastMode == nanoEngineProcessingMode)] == NO) {
|
129
|
-
NSString *message = [NSString stringWithFormat:@"*** -[%@
|
131
|
+
NSString *message = [NSString stringWithFormat:@"*** -[%@ %@]: open database failed: %@", [self class], NSStringFromSelector(_cmd), [self filePath]];
|
130
132
|
_NSFLog(message);
|
131
133
|
if (nil != outError)
|
132
134
|
*outError = [NSError errorWithDomain:NSFDomainKey
|
@@ -138,7 +140,7 @@
|
|
138
140
|
}
|
139
141
|
|
140
142
|
if ([self _setupCachingSchema] == NO) {
|
141
|
-
NSString *message = [NSString stringWithFormat:@"*** -[%@
|
143
|
+
NSString *message = [NSString stringWithFormat:@"*** -[%@ %@]: the schema could not be created when opening database: %@", [self class], NSStringFromSelector(_cmd), [self filePath]];
|
142
144
|
_NSFLog(message);
|
143
145
|
if (nil != outError)
|
144
146
|
*outError = [NSError errorWithDomain:NSFDomainKey
|
@@ -150,7 +152,7 @@
|
|
150
152
|
}
|
151
153
|
|
152
154
|
if ([self _initializePreparedStatementsWithError:outError] == NO) {
|
153
|
-
NSString *message = [NSString stringWithFormat:@"*** -[%@
|
155
|
+
NSString *message = [NSString stringWithFormat:@"*** -[%@ %@]: the SQL statements could not be prepared when opening database: %@", [self class], NSStringFromSelector(_cmd), [self filePath]];
|
154
156
|
_NSFLog(message);
|
155
157
|
[self closeWithError:nil];
|
156
158
|
return NO;
|
@@ -173,14 +175,36 @@
|
|
173
175
|
return ([nanoStoreEngine isDatabaseOpen] == NO);
|
174
176
|
}
|
175
177
|
|
176
|
-
- (NSString*)description
|
178
|
+
- (NSString *)description
|
177
179
|
{
|
178
|
-
return [self
|
180
|
+
return [self JSONDescription];
|
181
|
+
}
|
182
|
+
|
183
|
+
- (NSFOrderedDictionary *)dictionaryDescription
|
184
|
+
{
|
185
|
+
NSFOrderedDictionary *values = [NSFOrderedDictionary new];
|
186
|
+
|
187
|
+
values[@"NanoStore address"] = [NSString stringWithFormat:@"%p", self];
|
188
|
+
values[@"Is our transaction?"] = (_isOurTransaction ? @"YES" : @"NO");
|
189
|
+
values[@"Save interval"] = (saveInterval ? @(saveInterval) : @(1));
|
190
|
+
values[@"Engine"] = [nanoStoreEngine dictionaryDescription];
|
191
|
+
|
192
|
+
return values;
|
193
|
+
}
|
194
|
+
|
195
|
+
- (NSString *)JSONDescription
|
196
|
+
{
|
197
|
+
NSFOrderedDictionary *values = [self dictionaryDescription];
|
198
|
+
|
199
|
+
NSError *outError = nil;
|
200
|
+
NSString *description = [NSFNanoObject _NSObjectToJSONString:values error:&outError];
|
201
|
+
|
202
|
+
return description;
|
179
203
|
}
|
180
204
|
|
181
205
|
- (BOOL)hasUnsavedChanges
|
182
206
|
{
|
183
|
-
return ([
|
207
|
+
return ([_addedObjects count] > 0);
|
184
208
|
}
|
185
209
|
|
186
210
|
#pragma mark -
|
@@ -196,16 +220,17 @@
|
|
196
220
|
{
|
197
221
|
if (nil == someObjects) {
|
198
222
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
199
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
223
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: someObjects is nil.", [self class], NSStringFromSelector(_cmd)]
|
200
224
|
userInfo:nil]raise];
|
201
225
|
}
|
202
226
|
|
203
227
|
if ([someObjects count] == 0) {
|
204
|
-
if (nil != outError)
|
228
|
+
if (nil != outError) {
|
205
229
|
*outError = [NSError errorWithDomain:NSFDomainKey
|
206
230
|
code:NSFNanoStoreErrorKey
|
207
|
-
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@
|
231
|
+
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: ([someObjects count] == 0)", [self class], NSStringFromSelector(_cmd)]
|
208
232
|
forKey:NSLocalizedFailureReasonErrorKey]];
|
233
|
+
}
|
209
234
|
return NO;
|
210
235
|
}
|
211
236
|
|
@@ -216,47 +241,32 @@
|
|
216
241
|
// If it's a bag, make sure the name is unique
|
217
242
|
if (YES == [object isKindOfClass:[NSFNanoBag class]]) {
|
218
243
|
NSFNanoBag *bag = (NSFNanoBag *)object;
|
219
|
-
NSString *bagName = bag.name;
|
220
|
-
if (bagName.length > 0) {
|
221
|
-
NSFNanoBag *bagWithSameName = [self bagWithName:bagName];
|
222
|
-
if (nil != bagWithSameName) {
|
223
|
-
if (nil != outError) {
|
224
|
-
*outError = [NSError errorWithDomain:NSFDomainKey
|
225
|
-
code:NSFNanoStoreErrorKey
|
226
|
-
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %s]: a bag named '%@' already exists.", [self class], _cmd, bagName]
|
227
|
-
forKey:NSLocalizedFailureReasonErrorKey]];
|
228
|
-
|
229
|
-
return NO;
|
230
|
-
}
|
231
|
-
}
|
232
|
-
}
|
233
|
-
|
234
244
|
|
235
245
|
// If it's a bag, process it first by gathering. If it's not dirty, there's no need to save...
|
236
|
-
if (YES == [
|
246
|
+
if (YES == [bag hasUnsavedChanges]) {
|
237
247
|
NSError *error = nil;
|
238
248
|
|
239
249
|
// Associate the bag to this store
|
240
|
-
if (nil == [
|
250
|
+
if (nil == [bag store]) {
|
241
251
|
[object _setStore:self];
|
242
252
|
}
|
243
253
|
|
244
|
-
if (NO == [
|
254
|
+
if (NO == [bag _saveInStore:self error:&error]) {
|
245
255
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
246
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
256
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [error localizedDescription]]
|
247
257
|
userInfo:nil]raise];
|
248
258
|
}
|
249
259
|
}
|
250
260
|
} else {
|
251
261
|
if (NO == [(id)object conformsToProtocol:@protocol(NSFNanoObjectProtocol)]) {
|
252
262
|
[[NSException exceptionWithName:NSFNonConformingNanoObjectProtocolException
|
253
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
263
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: the object does not conform to NSFNanoObjectProtocol.", [self class], NSStringFromSelector(_cmd)]
|
254
264
|
userInfo:nil]raise];
|
255
265
|
}
|
256
266
|
|
257
267
|
if (nil == [object nanoObjectKey]) {
|
258
268
|
[[NSException exceptionWithName:NSFNanoObjectBehaviorException
|
259
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
269
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: unexpected NSFNanoObject behavior. Reason: the object's key is nil.", [self class], NSStringFromSelector(_cmd)]
|
260
270
|
userInfo:nil]raise];
|
261
271
|
}
|
262
272
|
|
@@ -284,7 +294,7 @@
|
|
284
294
|
|
285
295
|
if (nil == someKeys)
|
286
296
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
287
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
297
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: someKeys is nil.", [self class], NSStringFromSelector(_cmd)]
|
288
298
|
userInfo:nil]raise];
|
289
299
|
|
290
300
|
NSUInteger count = [someKeys count];
|
@@ -297,31 +307,38 @@
|
|
297
307
|
NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"CREATE TEMP TABLE %@(x);", NSF_Private_ToDeleteTableKey];
|
298
308
|
[nanoStoreEngine executeSQL:theSQLStatement];
|
299
309
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
}
|
310
|
-
|
311
|
-
// Bind and execute the statement...
|
312
|
-
status = sqlite3_bind_text ( statement, 1, [key UTF8String], -1, SQLITE_STATIC);
|
313
|
-
|
314
|
-
// Since we're operating with extended result code support, extract the bits
|
315
|
-
// and obtain the regular result code
|
316
|
-
// For more info check: http://www.sqlite.org/c3ref/c_ioerr_access.html
|
317
|
-
|
318
|
-
status = [NSFNanoEngine NSFP_stripBitsFromExtendedResultCode:status];
|
319
|
-
|
320
|
-
if (SQLITE_OK == status) {
|
321
|
-
[self _executeSQLite3StepUsingSQLite3Statement:statement];
|
310
|
+
if (NULL == _insertDeleteKeysStatement) {
|
311
|
+
theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@ VALUES (?);", NSF_Private_ToDeleteTableKey];
|
312
|
+
BOOL success = [self _prepareSQLite3Statement:&_insertDeleteKeysStatement theSQLStatement:theSQLStatement];
|
313
|
+
if (NO == success) {
|
314
|
+
if (nil != outError) {
|
315
|
+
*outError = [NSError errorWithDomain:NSFDomainKey
|
316
|
+
code:NSFNanoStoreErrorKey
|
317
|
+
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _insertDeleteKeysStatement.", [self class], NSStringFromSelector(_cmd)]
|
318
|
+
forKey:NSLocalizedFailureReasonErrorKey]];
|
322
319
|
}
|
320
|
+
return NO;
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
for (NSString *key in someKeys) {
|
325
|
+
int status = sqlite3_reset (_insertDeleteKeysStatement);
|
326
|
+
if (SQLITE_OK != status) {
|
327
|
+
break;
|
328
|
+
}
|
329
|
+
|
330
|
+
// Bind and execute the statement...
|
331
|
+
status = sqlite3_bind_text ( _insertDeleteKeysStatement, 1, [key UTF8String], -1, SQLITE_STATIC);
|
332
|
+
|
333
|
+
// Since we're operating with extended result code support, extract the bits
|
334
|
+
// and obtain the regular result code
|
335
|
+
// For more info check: http://www.sqlite.org/c3ref/c_ioerr_access.html
|
336
|
+
|
337
|
+
status = [NSFNanoEngine NSFP_stripBitsFromExtendedResultCode:status];
|
338
|
+
|
339
|
+
if (SQLITE_OK == status) {
|
340
|
+
[self _executeSQLite3StepUsingSQLite3Statement:_insertDeleteKeysStatement];
|
323
341
|
}
|
324
|
-
sqlite3_finalize(statement);
|
325
342
|
}
|
326
343
|
|
327
344
|
_NSFLog(@" Before removing the keys to be stored from NSFKeys...");
|
@@ -351,13 +368,13 @@
|
|
351
368
|
for (id object in someObjects) {
|
352
369
|
if (NO == [(id)object conformsToProtocol:@protocol(NSFNanoObjectProtocol)]) {
|
353
370
|
[[NSException exceptionWithName:NSFNonConformingNanoObjectProtocolException
|
354
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
371
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: the object does not conform to NSFNanoObjectProtocol.", [self class], NSStringFromSelector(_cmd)]
|
355
372
|
userInfo:nil]raise];
|
356
373
|
} else {
|
357
374
|
NSString *objectKey = [(id)object nanoObjectKey];
|
358
375
|
if (nil == objectKey) {
|
359
376
|
[[NSException exceptionWithName:NSFNanoObjectBehaviorException
|
360
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
377
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: unexpected NSFNanoObject behavior. Reason: the object's key is nil.", [self class], NSStringFromSelector(_cmd)]
|
361
378
|
userInfo:nil]raise];
|
362
379
|
}
|
363
380
|
[someKeys addObject:objectKey];
|
@@ -374,7 +391,7 @@
|
|
374
391
|
- (NSArray *)bags
|
375
392
|
{
|
376
393
|
NSFNanoSearch *search = [NSFNanoSearch searchWithStore:self];
|
377
|
-
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey,
|
394
|
+
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey, NSFKeyedArchive, NSFObjectClass FROM NSFKeys WHERE NSFObjectClass = \"%@\"", NSStringFromClass([NSFNanoBag class])];
|
378
395
|
|
379
396
|
return [[search executeSQL:theSQLStatement returnType:NSFReturnObjects error:nil]allValues];
|
380
397
|
|
@@ -388,10 +405,20 @@
|
|
388
405
|
search.match = NSFEqualTo;
|
389
406
|
search.value = theName;
|
390
407
|
|
391
|
-
// Returns a dictionary with the UUID of the object (key) and the NanoObject (value).
|
392
408
|
return [[[search searchObjectsWithReturnType:NSFReturnObjects error:nil]allObjects]lastObject];
|
393
409
|
}
|
394
410
|
|
411
|
+
- (NSArray *)bagsWithName:(NSString *)theName
|
412
|
+
{
|
413
|
+
NSFNanoSearch *search = [NSFNanoSearch searchWithStore:self];
|
414
|
+
|
415
|
+
search.attribute = NSF_Private_NSFNanoBag_Name;
|
416
|
+
search.match = NSFEqualTo;
|
417
|
+
search.value = theName;
|
418
|
+
|
419
|
+
return [[search searchObjectsWithReturnType:NSFReturnObjects error:nil]allObjects];
|
420
|
+
}
|
421
|
+
|
395
422
|
- (NSArray *)bagsWithKeysInArray:(NSArray *)someKeys
|
396
423
|
{
|
397
424
|
if ([someKeys count] == 0) {
|
@@ -400,7 +427,7 @@
|
|
400
427
|
|
401
428
|
NSFNanoSearch *search = [NSFNanoSearch searchWithStore:self];
|
402
429
|
NSString *quotedString = [NSFNanoSearch _quoteStrings:someKeys joiningWithDelimiter:@","];
|
403
|
-
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey,
|
430
|
+
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey, NSFKeyedArchive, NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@) AND NSFObjectClass = \"%@\"", quotedString, NSStringFromClass([NSFNanoBag class])];
|
404
431
|
|
405
432
|
return [[search executeSQL:theSQLStatement returnType:NSFReturnObjects error:nil]allValues];
|
406
433
|
}
|
@@ -412,7 +439,7 @@
|
|
412
439
|
}
|
413
440
|
|
414
441
|
NSFNanoSearch *search = [NSFNanoSearch searchWithStore:self];
|
415
|
-
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey,
|
442
|
+
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey, NSFKeyedArchive, NSFObjectClass FROM NSFKeys WHERE NSFKey IN (SELECT DISTINCT (NSFKEY) FROM NSFValues WHERE NSFValue = \"%@\") AND NSFObjectClass = \"%@\"", aKey, NSStringFromClass([NSFNanoBag class])];
|
416
443
|
|
417
444
|
return [[search executeSQL:theSQLStatement returnType:NSFReturnObjects error:nil]allValues];
|
418
445
|
}
|
@@ -425,7 +452,7 @@
|
|
425
452
|
|
426
453
|
NSFNanoSearch *search = [NSFNanoSearch searchWithStore:self];
|
427
454
|
NSString *quotedString = [NSFNanoSearch _quoteStrings:someKeys joiningWithDelimiter:@","];
|
428
|
-
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey,
|
455
|
+
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey, NSFKeyedArchive, NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@)", quotedString];
|
429
456
|
|
430
457
|
return [[search executeSQL:theSQLStatement returnType:NSFReturnObjects error:nil]allValues];
|
431
458
|
}
|
@@ -446,14 +473,14 @@
|
|
446
473
|
{
|
447
474
|
if (nil == theClassName) {
|
448
475
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
449
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
476
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: the class name cannot be nil.", [self class], NSStringFromSelector(_cmd)]
|
450
477
|
userInfo:nil]raise];
|
451
478
|
}
|
452
479
|
|
453
480
|
NSFNanoSearch *search = [NSFNanoSearch searchWithStore:self];
|
454
481
|
search.sort = theSortDescriptors;
|
455
482
|
|
456
|
-
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey,
|
483
|
+
NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey, NSFKeyedArchive, NSFObjectClass FROM NSFKeys WHERE NSFObjectClass = \"%@\"", theClassName];
|
457
484
|
|
458
485
|
if (nil == theSortDescriptors)
|
459
486
|
return [[search executeSQL:theSQLStatement returnType:NSFReturnObjects error:nil] allValues];
|
@@ -465,7 +492,7 @@
|
|
465
492
|
{
|
466
493
|
if (nil == theClassName) {
|
467
494
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
468
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
495
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: the class name cannot be nil.", [self class], NSStringFromSelector(_cmd)]
|
469
496
|
userInfo:nil]raise];
|
470
497
|
}
|
471
498
|
|
@@ -532,7 +559,7 @@
|
|
532
559
|
- (BOOL)saveStoreAndReturnError:(out NSError **)outError
|
533
560
|
{
|
534
561
|
// We are really not saving anything new, just indicating that we should commit the unsaved changes.
|
535
|
-
if (NO ==
|
562
|
+
if (NO == _hasUnsavedChanges) {
|
536
563
|
return YES;
|
537
564
|
}
|
538
565
|
|
@@ -541,7 +568,7 @@
|
|
541
568
|
|
542
569
|
- (void)discardUnsavedChanges
|
543
570
|
{
|
544
|
-
[
|
571
|
+
[_addedObjects removeAllObjects];
|
545
572
|
}
|
546
573
|
|
547
574
|
// ----------------------------------------------
|
@@ -633,7 +660,7 @@
|
|
633
660
|
{
|
634
661
|
if (nil == path)
|
635
662
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
636
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
663
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: path is nil.", [self class], NSStringFromSelector(_cmd)]
|
637
664
|
userInfo:nil]raise];
|
638
665
|
|
639
666
|
// Make sure we've expanded the tilde
|
@@ -643,11 +670,12 @@
|
|
643
670
|
return NO;
|
644
671
|
|
645
672
|
if ([[self nanoStoreEngine]isTransactionActive]) {
|
646
|
-
if (nil != outError)
|
673
|
+
if (nil != outError) {
|
647
674
|
*outError = [NSError errorWithDomain:NSFDomainKey
|
648
675
|
code:NSFNanoStoreErrorKey
|
649
676
|
userInfo:[NSDictionary dictionaryWithObject:@"Cannot backup store. A transaction is still open."
|
650
677
|
forKey:NSLocalizedDescriptionKey]];
|
678
|
+
}
|
651
679
|
return NO;
|
652
680
|
}
|
653
681
|
|
@@ -667,12 +695,12 @@
|
|
667
695
|
|
668
696
|
+ (NSFNanoStore *)_createAndOpenDebugDatabase
|
669
697
|
{
|
670
|
-
NSFNanoStore *db = [NSFNanoStore createStoreWithType:NSFPersistentStoreType path:[@"~/Desktop/NanoStoreDebug.
|
698
|
+
NSFNanoStore *db = [NSFNanoStore createStoreWithType:NSFPersistentStoreType path:[@"~/Desktop/NanoStoreDebug.sqlite" stringByExpandingTildeInPath]];
|
671
699
|
NSError *outError = nil;
|
672
700
|
|
673
701
|
if (NO == [db openWithError:&outError]) {
|
674
702
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
675
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
703
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: could not open the database. Reason: %@", [self class], NSStringFromSelector(_cmd), [outError localizedDescription]]
|
676
704
|
userInfo:nil]raise];
|
677
705
|
}
|
678
706
|
|
@@ -695,31 +723,38 @@
|
|
695
723
|
NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@(%@, %@, %@, %@) VALUES (?,?,?,?);", NSFValues, NSFKey, NSFAttribute, NSFValue, NSFDatatype];
|
696
724
|
hasInitializationSucceeded = [self _prepareSQLite3Statement:&_storeValuesStatement theSQLStatement:theSQLStatement];
|
697
725
|
|
698
|
-
if (
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
726
|
+
if (NO == hasInitializationSucceeded) {
|
727
|
+
if (nil != outError) {
|
728
|
+
*outError = [NSError errorWithDomain:NSFDomainKey
|
729
|
+
code:NSFNanoStoreErrorKey
|
730
|
+
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _storeValuesStatement.", [self class], NSStringFromSelector(_cmd)]
|
731
|
+
forKey:NSLocalizedFailureReasonErrorKey]];
|
732
|
+
}
|
733
|
+
return NO;
|
703
734
|
}
|
704
735
|
}
|
705
736
|
|
706
|
-
if (
|
707
|
-
NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@(%@, %@, %@, %@) VALUES (?,?,?,?);", NSFKeys, NSFKey,
|
737
|
+
if (NULL == _storeKeysStatement) {
|
738
|
+
NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@(%@, %@, %@, %@) VALUES (?,?,?,?);", NSFKeys, NSFKey, NSFKeyedArchive, NSFCalendarDate, NSFObjectClass];
|
708
739
|
hasInitializationSucceeded = [self _prepareSQLite3Statement:&_storeKeysStatement theSQLStatement:theSQLStatement];
|
709
740
|
|
710
|
-
if (
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
741
|
+
if (NO == hasInitializationSucceeded) {
|
742
|
+
if (nil != outError) {
|
743
|
+
*outError = [NSError errorWithDomain:NSFDomainKey
|
744
|
+
code:NSFNanoStoreErrorKey
|
745
|
+
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _storeKeysStatement.", [self class], NSStringFromSelector(_cmd)]
|
746
|
+
forKey:NSLocalizedFailureReasonErrorKey]];
|
747
|
+
}
|
748
|
+
return NO;
|
715
749
|
}
|
716
750
|
}
|
717
751
|
|
718
|
-
return
|
752
|
+
return YES;
|
719
753
|
}
|
720
754
|
|
721
755
|
- (void)_releasePreparedStatements
|
722
756
|
{
|
757
|
+
if (_insertDeleteKeysStatement != NULL) { sqlite3_finalize(_insertDeleteKeysStatement);_insertDeleteKeysStatement = NULL; }
|
723
758
|
if (_storeValuesStatement != NULL) { sqlite3_finalize(_storeValuesStatement);_storeValuesStatement = NULL; }
|
724
759
|
if (_storeKeysStatement != NULL) { sqlite3_finalize(_storeKeysStatement);_storeKeysStatement = NULL; }
|
725
760
|
}
|
@@ -736,29 +771,13 @@
|
|
736
771
|
return _isOurTransaction;
|
737
772
|
}
|
738
773
|
|
739
|
-
- (NSString*)_nestedDescriptionWithPrefixedSpace:(NSString *)prefixedSpace
|
740
|
-
{
|
741
|
-
if (nil == prefixedSpace) {
|
742
|
-
prefixedSpace = @"";
|
743
|
-
}
|
744
|
-
|
745
|
-
NSMutableString *description = [NSMutableString string];
|
746
|
-
[description appendString:@"\n"];
|
747
|
-
[description appendString:[NSString stringWithFormat:@"%@NanoStore address : 0x%x\n", prefixedSpace, self]];
|
748
|
-
[description appendString:[NSString stringWithFormat:@"%@Is our transaction? : %@\n", prefixedSpace, (_isOurTransaction ? @"Yes" : @"No")]];
|
749
|
-
[description appendString:[NSString stringWithFormat:@"%@Save interval : %ld\n", prefixedSpace, (saveInterval == 0 ? 1 : saveInterval)]];
|
750
|
-
[description appendString:[NSString stringWithFormat:@"%@Engine : %@\n", prefixedSpace, [nanoStoreEngine NSFP_nestedDescriptionWithPrefixedSpace:@" "]]];
|
751
|
-
|
752
|
-
return description;
|
753
|
-
}
|
754
|
-
|
755
774
|
- (BOOL)_checkNanoStoreIsReadyAndReturnError:(out NSError **)outError
|
756
775
|
{
|
757
776
|
if (nil == [self nanoStoreEngine]) {
|
758
777
|
if (nil != outError)
|
759
778
|
*outError = [NSError errorWithDomain:NSFDomainKey
|
760
779
|
code:NSFNanoStoreErrorKey
|
761
|
-
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@
|
780
|
+
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: the NSF store has not been set.", [self class], NSStringFromSelector(_cmd)]
|
762
781
|
forKey:NSLocalizedFailureReasonErrorKey]];
|
763
782
|
return NO;
|
764
783
|
}
|
@@ -767,7 +786,7 @@
|
|
767
786
|
if (nil != outError)
|
768
787
|
*outError = [NSError errorWithDomain:NSFDomainKey
|
769
788
|
code:NSFNanoStoreErrorKey
|
770
|
-
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@
|
789
|
+
userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: the store is not open.", [self class], NSStringFromSelector(_cmd)]
|
771
790
|
forKey:NSLocalizedFailureReasonErrorKey]];
|
772
791
|
return NO;
|
773
792
|
}
|
@@ -800,14 +819,15 @@
|
|
800
819
|
|
801
820
|
// Setup the Plist table
|
802
821
|
if ([tables containsObject:NSFKeys] == NO) {
|
803
|
-
theSQLStatement = [NSString stringWithFormat:@"CREATE TABLE %@(ROWID INTEGER PRIMARY KEY, %@ TEXT, %@
|
822
|
+
theSQLStatement = [NSString stringWithFormat:@"CREATE TABLE %@(ROWID INTEGER PRIMARY KEY, %@ TEXT, %@ BLOB, %@ TEXT, %@ TEXT);", NSFKeys, NSFKey, NSFKeyedArchive, NSFCalendarDate, NSFObjectClass];
|
823
|
+
|
804
824
|
success = (nil == [[[self nanoStoreEngine]executeSQL:theSQLStatement]error]);
|
805
825
|
if (NO == success)
|
806
826
|
return NO;
|
807
827
|
|
808
828
|
[[self nanoStoreEngine]NSFP_insertStringValues:[NSArray arrayWithObjects:NSFKeys, NSFRowIDColumnName, rowUIDDatatype, nil] forColumns:[NSArray arrayWithObjects:NSFP_TableIdentifier, NSFP_ColumnIdentifier, NSFP_DatatypeIdentifier, nil]table:NSFP_SchemaTable];
|
809
829
|
[[self nanoStoreEngine]NSFP_insertStringValues:[NSArray arrayWithObjects:NSFKeys, NSFKey, stringDatatype, nil] forColumns:[NSArray arrayWithObjects:NSFP_TableIdentifier, NSFP_ColumnIdentifier, NSFP_DatatypeIdentifier, nil]table:NSFP_SchemaTable];
|
810
|
-
[[self nanoStoreEngine]NSFP_insertStringValues:[NSArray arrayWithObjects:NSFKeys,
|
830
|
+
[[self nanoStoreEngine]NSFP_insertStringValues:[NSArray arrayWithObjects:NSFKeys, NSFKeyedArchive, stringDatatype, nil] forColumns:[NSArray arrayWithObjects:NSFP_TableIdentifier, NSFP_ColumnIdentifier, NSFP_DatatypeIdentifier, nil]table:NSFP_SchemaTable];
|
811
831
|
[[self nanoStoreEngine]NSFP_insertStringValues:[NSArray arrayWithObjects:NSFKeys, dateDatatype, dateDatatype, nil] forColumns:[NSArray arrayWithObjects:NSFP_TableIdentifier, NSFP_ColumnIdentifier, NSFP_DatatypeIdentifier, nil]table:NSFP_SchemaTable];
|
812
832
|
[[self nanoStoreEngine]NSFP_insertStringValues:[NSArray arrayWithObjects:NSFKeys, NSFObjectClass, stringDatatype, nil] forColumns:[NSArray arrayWithObjects:NSFP_TableIdentifier, NSFP_ColumnIdentifier, NSFP_DatatypeIdentifier, nil]table:NSFP_SchemaTable];
|
813
833
|
}
|
@@ -815,27 +835,27 @@
|
|
815
835
|
return YES;
|
816
836
|
}
|
817
837
|
|
818
|
-
- (BOOL)_storeDictionary:(NSDictionary *)someInfo forKey:(NSString *)aKey forClassNamed:(NSString *)
|
838
|
+
- (BOOL)_storeDictionary:(NSDictionary *)someInfo forKey:(NSString *)aKey forClassNamed:(NSString *)classType error:(out NSError **)outError
|
819
839
|
{
|
820
840
|
if (nil == someInfo)
|
821
841
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
822
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
842
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: someInfo is nil.", [self class], NSStringFromSelector(_cmd)]
|
823
843
|
userInfo:nil]raise];
|
824
844
|
|
825
845
|
if (nil == aKey)
|
826
846
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
827
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
847
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: aKey is nil.", [self class], NSStringFromSelector(_cmd)]
|
828
848
|
userInfo:nil]raise];
|
829
849
|
|
830
|
-
if (
|
850
|
+
if (NULL == _storeValuesStatement)
|
831
851
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
832
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
852
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: aStatement is NULL.", [self class], NSStringFromSelector(_cmd)]
|
833
853
|
userInfo:nil]raise];
|
834
854
|
|
835
855
|
NSRange range = [aKey rangeOfString:@"."];
|
836
856
|
if (NSNotFound != range.location)
|
837
857
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
838
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
858
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: aKey cannot contain a period ('.')", [self class], NSStringFromSelector(_cmd)]
|
839
859
|
userInfo:nil]raise];
|
840
860
|
|
841
861
|
NSArray *keys = [someInfo allKeys];
|
@@ -843,7 +863,7 @@
|
|
843
863
|
range = [key rangeOfString:@"."];
|
844
864
|
if (NSNotFound != range.location)
|
845
865
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
846
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
866
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: the keys of the dictionary cannot contain a period ('.')", [self class], NSStringFromSelector(_cmd)]
|
847
867
|
userInfo:nil]raise];
|
848
868
|
}
|
849
869
|
|
@@ -867,7 +887,7 @@
|
|
867
887
|
id value = [flattenedValues objectAtIndex:i];
|
868
888
|
|
869
889
|
// Reset, as required by SQLite...
|
870
|
-
int status = sqlite3_reset (
|
890
|
+
int status = sqlite3_reset (_storeValuesStatement);
|
871
891
|
|
872
892
|
// Since we're operating with extended result code support, extract the bits
|
873
893
|
// and obtain the regular result code
|
@@ -878,8 +898,8 @@
|
|
878
898
|
if (SQLITE_OK == status) {
|
879
899
|
|
880
900
|
// Bind and execute the statement...
|
881
|
-
BOOL resultBindKey = (sqlite3_bind_text (
|
882
|
-
BOOL resultBindAttribute = (sqlite3_bind_text (
|
901
|
+
BOOL resultBindKey = (sqlite3_bind_text (_storeValuesStatement, 1, aKeyUTF8, -1, SQLITE_STATIC) == SQLITE_OK);
|
902
|
+
BOOL resultBindAttribute = (sqlite3_bind_text (_storeValuesStatement, 2, [attribute UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
883
903
|
|
884
904
|
// Take advantage of manifest typing
|
885
905
|
// Branch the type of bind based on the type to be stored: NSString, NSData, NSDate or NSNumber
|
@@ -888,30 +908,36 @@
|
|
888
908
|
|
889
909
|
switch (valueDataType) {
|
890
910
|
case NSFNanoTypeData:
|
891
|
-
resultBindValue = (sqlite3_bind_blob(
|
911
|
+
resultBindValue = (sqlite3_bind_blob(_storeValuesStatement, 3, [value bytes], (int)[value length], NULL) == SQLITE_OK);
|
892
912
|
break;
|
893
913
|
case NSFNanoTypeString:
|
894
914
|
case NSFNanoTypeDate:
|
895
|
-
resultBindValue = (sqlite3_bind_text (
|
915
|
+
resultBindValue = (sqlite3_bind_text (_storeValuesStatement, 3, [[self _stringFromValue:value]UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
896
916
|
break;
|
897
917
|
break;
|
898
918
|
case NSFNanoTypeNumber:
|
899
|
-
resultBindValue = (sqlite3_bind_double (
|
919
|
+
resultBindValue = (sqlite3_bind_double (_storeValuesStatement, 3, [value doubleValue]) == SQLITE_OK);
|
920
|
+
break;
|
921
|
+
case NSFNanoTypeNULL:
|
922
|
+
resultBindValue = (sqlite3_bind_null(_storeValuesStatement, 3) == SQLITE_OK);
|
923
|
+
break;
|
924
|
+
case NSFNanoTypeURL:
|
925
|
+
resultBindValue = (sqlite3_bind_text (_storeValuesStatement, 3, [[self _stringFromValue:value]UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
900
926
|
break;
|
901
927
|
default:
|
902
928
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
903
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
929
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: datatype %@ cannot be stored because its class type is unknown.", [self class], NSStringFromSelector(_cmd), [value class]]
|
904
930
|
userInfo:nil]raise];
|
905
931
|
break;
|
906
932
|
}
|
907
933
|
|
908
934
|
// Store the element's datatype so we can recreate it later on when we read it back from the store...
|
909
935
|
NSString *valueDatatypeString = NSFStringFromNanoDataType(valueDataType);
|
910
|
-
BOOL resultBindDatatype = (sqlite3_bind_text (
|
936
|
+
BOOL resultBindDatatype = (sqlite3_bind_text (_storeValuesStatement, 4, [valueDatatypeString UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
911
937
|
|
912
938
|
success = (resultBindKey && resultBindAttribute && resultBindValue && resultBindDatatype);
|
913
939
|
if (success) {
|
914
|
-
[self _executeSQLite3StepUsingSQLite3Statement:
|
940
|
+
[self _executeSQLite3StepUsingSQLite3Statement:_storeValuesStatement];
|
915
941
|
}
|
916
942
|
}
|
917
943
|
}
|
@@ -920,51 +946,27 @@
|
|
920
946
|
}
|
921
947
|
|
922
948
|
if (YES == success) {
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
NSData *dictData = [NSPropertyListSerialization dataFromPropertyList:someInfo format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorString];
|
928
|
-
if (nil != errorString) {
|
929
|
-
NSLog(@" Dictionary: %@", someInfo);
|
930
|
-
NSLog(@"*** -[%@ %@]: [NSPropertyListSerialization dataFromPropertyList] failure. %@", [self class], NSStringFromSelector(_cmd), errorString);
|
931
|
-
NSLog(@" Dictionary info: %@", someInfo);
|
932
|
-
success = NO;
|
933
|
-
} else {
|
934
|
-
if ([dictData length] > 0)
|
935
|
-
dictXML = [[NSString alloc]initWithBytes:[dictData bytes]length:[dictData length]encoding:NSUTF8StringEncoding];
|
936
|
-
else
|
937
|
-
dictXML = @"";
|
949
|
+
NSData *dictBinData = [NSKeyedArchiver archivedDataWithRootObject:someInfo];
|
950
|
+
{
|
951
|
+
int status = sqlite3_reset (_storeKeysStatement);
|
938
952
|
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
// Reset, as required by SQLite...
|
948
|
-
int status = sqlite3_reset (_storeKeysStatement);
|
949
|
-
|
950
|
-
// Since we're operating with extended result code support, extract the bits
|
951
|
-
// and obtain the regular result code
|
952
|
-
// For more info check: http://www.sqlite.org/c3ref/c_ioerr_access.html
|
953
|
+
// Since we're operating with extended result code support, extract the bits
|
954
|
+
// and obtain the regular result code
|
955
|
+
// For more info check: http://www.sqlite.org/c3ref/c_ioerr_access.html
|
956
|
+
|
957
|
+
status = [NSFNanoEngine NSFP_stripBitsFromExtendedResultCode:status];
|
958
|
+
|
959
|
+
// Bind and execute the statement...
|
960
|
+
if (SQLITE_OK == status) {
|
953
961
|
|
954
|
-
|
962
|
+
BOOL resultBindKey = (sqlite3_bind_text (_storeKeysStatement, 1, aKeyUTF8, -1, SQLITE_STATIC) == SQLITE_OK);
|
963
|
+
BOOL resultBindData = (sqlite3_bind_blob(_storeKeysStatement, 2, [dictBinData bytes], (int)[dictBinData length], SQLITE_STATIC) == SQLITE_OK);
|
964
|
+
BOOL resultBindCalendarDate = (sqlite3_bind_text (_storeKeysStatement, 3, [[NSFNanoStore _calendarDateToString:[NSDate date]]UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
965
|
+
BOOL resultBindClass = (sqlite3_bind_text (_storeKeysStatement, 4, [classType UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
955
966
|
|
956
|
-
|
957
|
-
if (
|
958
|
-
|
959
|
-
BOOL resultBindKey = (sqlite3_bind_text (_storeKeysStatement, 1, aKeyUTF8, -1, SQLITE_STATIC) == SQLITE_OK);
|
960
|
-
BOOL resultBindPlist = (sqlite3_bind_text (_storeKeysStatement, 2, [dictXML UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
961
|
-
BOOL resultBindCalendarDate = (sqlite3_bind_text (_storeKeysStatement, 3, [[NSFNanoStore _calendarDateToString:[NSDate date]]UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
962
|
-
BOOL resultBindClass = (sqlite3_bind_text (_storeKeysStatement, 4, [className UTF8String], -1, SQLITE_STATIC) == SQLITE_OK);
|
963
|
-
|
964
|
-
success = (resultBindKey && resultBindPlist && resultBindCalendarDate && resultBindClass);
|
965
|
-
if (success) {
|
966
|
-
[self _executeSQLite3StepUsingSQLite3Statement:_storeKeysStatement];
|
967
|
-
}
|
967
|
+
success = (resultBindKey && resultBindData && resultBindCalendarDate && resultBindClass);
|
968
|
+
if (success) {
|
969
|
+
[self _executeSQLite3StepUsingSQLite3Statement:_storeKeysStatement];
|
968
970
|
}
|
969
971
|
}
|
970
972
|
}
|
@@ -985,6 +987,10 @@
|
|
985
987
|
return NSFNanoTypeDate;
|
986
988
|
else if ([value isKindOfClass:[NSData class]])
|
987
989
|
return NSFNanoTypeData;
|
990
|
+
else if ([value isKindOfClass:[NSNull class]])
|
991
|
+
return NSFNanoTypeNULL;
|
992
|
+
else if ([value isKindOfClass:[NSURL class]])
|
993
|
+
return NSFNanoTypeURL;
|
988
994
|
|
989
995
|
return type;
|
990
996
|
}
|
@@ -1002,7 +1008,7 @@
|
|
1002
1008
|
return [aValue description];
|
1003
1009
|
} else {
|
1004
1010
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
1005
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1011
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: datatype %@ doesn't respond to selector 'stringValue' or 'description'.", [self class], NSStringFromSelector(_cmd), [aValue class]]
|
1006
1012
|
userInfo:nil]raise];
|
1007
1013
|
}
|
1008
1014
|
}
|
@@ -1022,7 +1028,7 @@
|
|
1022
1028
|
|
1023
1029
|
if (nil == aDate)
|
1024
1030
|
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
1025
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1031
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: aDate is nil.", [self class], NSStringFromSelector(_cmd)]
|
1026
1032
|
userInfo:nil]raise];
|
1027
1033
|
|
1028
1034
|
return [__sNSFNanoStoreDateFormatter stringFromDate:aDate];
|
@@ -1115,10 +1121,10 @@
|
|
1115
1121
|
- (BOOL)_addObjectsFromArray:(NSArray *)someObjects forceSave:(BOOL)forceSave error:(out NSError **)outError
|
1116
1122
|
{
|
1117
1123
|
// Collect the objects
|
1118
|
-
[
|
1124
|
+
[_addedObjects addObjectsFromArray:someObjects];
|
1119
1125
|
|
1120
1126
|
// No need to continue if there's nothing to be saved
|
1121
|
-
NSUInteger unsavedObjectsCount = [
|
1127
|
+
NSUInteger unsavedObjectsCount = [_addedObjects count];
|
1122
1128
|
if (0 == unsavedObjectsCount) {
|
1123
1129
|
return YES;
|
1124
1130
|
}
|
@@ -1133,9 +1139,9 @@
|
|
1133
1139
|
|
1134
1140
|
// Remove all objects non conforming with the NSFNanoObjectProtocol
|
1135
1141
|
while ( i-- ) {
|
1136
|
-
id object = [
|
1142
|
+
id object = [_addedObjects objectAtIndex:i];
|
1137
1143
|
if (NO == [object conformsToProtocol:@protocol(NSFNanoObjectProtocol)]) {
|
1138
|
-
[
|
1144
|
+
[_addedObjects removeObjectAtIndex:i];
|
1139
1145
|
i--;
|
1140
1146
|
continue;
|
1141
1147
|
}
|
@@ -1143,20 +1149,20 @@
|
|
1143
1149
|
NSString *objectKey = [(id)object nanoObjectKey];
|
1144
1150
|
if (nil == objectKey) {
|
1145
1151
|
[[NSException exceptionWithName:NSFNanoObjectBehaviorException
|
1146
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1152
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: unexpected NSFNanoObject behavior. Reason: the object's key is nil.", [self class], NSStringFromSelector(_cmd)]
|
1147
1153
|
userInfo:nil]raise];
|
1148
1154
|
}
|
1149
1155
|
[keys addObject:objectKey];
|
1150
1156
|
}
|
1151
1157
|
|
1152
1158
|
// Recalculate how many elements we have left
|
1153
|
-
unsavedObjectsCount = [
|
1159
|
+
unsavedObjectsCount = [_addedObjects count];
|
1154
1160
|
|
1155
1161
|
if (unsavedObjectsCount > 0) {
|
1156
1162
|
NSError *localOutError = nil;
|
1157
1163
|
if (NO == [self removeObjectsWithKeysInArray:[keys allObjects] error:&localOutError]) {
|
1158
1164
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
1159
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1165
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [localOutError localizedDescription]]
|
1160
1166
|
userInfo:nil]raise];
|
1161
1167
|
}
|
1162
1168
|
}
|
@@ -1174,7 +1180,7 @@
|
|
1174
1180
|
self.saveInterval = 1;
|
1175
1181
|
}
|
1176
1182
|
|
1177
|
-
for (id object in
|
1183
|
+
for (id object in _addedObjects) {
|
1178
1184
|
@autoreleasepool {
|
1179
1185
|
// If the object was originally created by storing a class not recognized by this process, honor it and store it with the right class string.
|
1180
1186
|
NSString *className = nil;
|
@@ -1187,10 +1193,18 @@
|
|
1187
1193
|
className = NSStringFromClass([object class]);
|
1188
1194
|
}
|
1189
1195
|
|
1190
|
-
if (NO == [self _storeDictionary:[object nanoObjectDictionaryRepresentation] forKey:[(id)object nanoObjectKey] forClassNamed:className
|
1196
|
+
if (NO == [self _storeDictionary:[object nanoObjectDictionaryRepresentation] forKey:[(id)object nanoObjectKey] forClassNamed:className error:outError]) {
|
1191
1197
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
1192
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1198
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
|
1193
1199
|
userInfo:nil]raise];
|
1200
|
+
} else {
|
1201
|
+
SEL setStoreSelector = @selector(setStore:);
|
1202
|
+
if (YES == [object respondsToSelector:setStoreSelector]) {
|
1203
|
+
#pragma clang diagnostic push
|
1204
|
+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
1205
|
+
[object performSelector:setStoreSelector withObject:self];
|
1206
|
+
#pragma clang diagnostic pop
|
1207
|
+
}
|
1194
1208
|
}
|
1195
1209
|
|
1196
1210
|
i++;
|
@@ -1199,7 +1213,7 @@
|
|
1199
1213
|
if ((0 == i % self.saveInterval) && transactionStartedHere) {
|
1200
1214
|
if (NO == [self commitTransactionAndReturnError:outError]) {
|
1201
1215
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
1202
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1216
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
|
1203
1217
|
userInfo:nil]raise];
|
1204
1218
|
}
|
1205
1219
|
|
@@ -1207,7 +1221,7 @@
|
|
1207
1221
|
transactionStartedHere = [self beginTransactionAndReturnError:outError];
|
1208
1222
|
if (NO == transactionStartedHere) {
|
1209
1223
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
1210
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1224
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
|
1211
1225
|
userInfo:nil]raise];
|
1212
1226
|
}
|
1213
1227
|
}
|
@@ -1219,7 +1233,7 @@
|
|
1219
1233
|
if (transactionStartedHere) {
|
1220
1234
|
if (NO == [self commitTransactionAndReturnError:outError]) {
|
1221
1235
|
[[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
|
1222
|
-
reason:[NSString stringWithFormat:@"*** -[%@
|
1236
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
|
1223
1237
|
userInfo:nil]raise];
|
1224
1238
|
}
|
1225
1239
|
}
|
@@ -1228,7 +1242,7 @@
|
|
1228
1242
|
double ratio = unsavedObjectsCount/secondsStoring;
|
1229
1243
|
_NSFLog(@" Done. Storing the objects took %.3f seconds (%.0f keys/sec.)", secondsStoring, ratio);
|
1230
1244
|
|
1231
|
-
[
|
1245
|
+
[_addedObjects removeAllObjects];
|
1232
1246
|
}
|
1233
1247
|
|
1234
1248
|
return YES;
|