nano-store 0.3.8 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/Gemfile.lock +3 -3
  2. data/Rakefile +1 -1
  3. data/lib/nano_store/finder.rb +12 -6
  4. data/lib/nano_store/version.rb +1 -1
  5. data/vendor/Podfile.lock +2 -2
  6. data/vendor/Pods/Headers/NanoStore/NSFNanoBag.h +8 -2
  7. data/vendor/Pods/Headers/NanoStore/NSFNanoSearch.h +2 -0
  8. data/vendor/Pods/Headers/NanoStore/NSFNanoStore_Private.h +1 -1
  9. data/vendor/Pods/NanoStore/Classes/Private/NSFNanoStore_Private.h +1 -1
  10. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoBag.h +8 -2
  11. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoBag.m +7 -4
  12. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoExpression.m +2 -6
  13. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSearch.h +2 -0
  14. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSearch.m +9 -7
  15. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoStore.m +14 -4
  16. data/vendor/Pods/Pods.bridgesupport +8 -1
  17. metadata +8 -43
  18. data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.h +0 -542
  19. data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.m +0 -1781
  20. data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.h +0 -137
  21. data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.m +0 -265
  22. data/vendor/NanoStore/Classes/Private/NSFNanoBag_Private.h +0 -37
  23. data/vendor/NanoStore/Classes/Private/NSFNanoEngine_Private.h +0 -69
  24. data/vendor/NanoStore/Classes/Private/NSFNanoExpression_Private.h +0 -35
  25. data/vendor/NanoStore/Classes/Private/NSFNanoGlobals_Private.h +0 -99
  26. data/vendor/NanoStore/Classes/Private/NSFNanoObject_Private.h +0 -35
  27. data/vendor/NanoStore/Classes/Private/NSFNanoPredicate_Private.h +0 -35
  28. data/vendor/NanoStore/Classes/Private/NSFNanoResult_Private.h +0 -43
  29. data/vendor/NanoStore/Classes/Private/NSFNanoSearch_Private.h +0 -48
  30. data/vendor/NanoStore/Classes/Private/NSFNanoStore_Private.h +0 -57
  31. data/vendor/NanoStore/Classes/Private/NanoStore_Private.h +0 -37
  32. data/vendor/NanoStore/Classes/Public/NSFNanoBag.h +0 -306
  33. data/vendor/NanoStore/Classes/Public/NSFNanoBag.m +0 -485
  34. data/vendor/NanoStore/Classes/Public/NSFNanoExpression.h +0 -125
  35. data/vendor/NanoStore/Classes/Public/NSFNanoExpression.m +0 -103
  36. data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.h +0 -323
  37. data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.m +0 -145
  38. data/vendor/NanoStore/Classes/Public/NSFNanoObject.h +0 -298
  39. data/vendor/NanoStore/Classes/Public/NSFNanoObject.m +0 -187
  40. data/vendor/NanoStore/Classes/Public/NSFNanoObjectProtocol.h +0 -119
  41. data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.h +0 -123
  42. data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.m +0 -130
  43. data/vendor/NanoStore/Classes/Public/NSFNanoSearch.h +0 -381
  44. data/vendor/NanoStore/Classes/Public/NSFNanoSearch.m +0 -835
  45. data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.h +0 -124
  46. data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.m +0 -79
  47. data/vendor/NanoStore/Classes/Public/NSFNanoStore.h +0 -475
  48. data/vendor/NanoStore/Classes/Public/NSFNanoStore.m +0 -1375
  49. data/vendor/NanoStore/Classes/Public/NanoStore.h +0 -463
  50. data/vendor/NanoStore/LICENSE +0 -25
  51. data/vendor/NanoStore/NanoStore.bridgesupport +0 -1215
  52. data/vendor/NanoStore/README.md +0 -411
@@ -1,835 +0,0 @@
1
- /*
2
- NSFNanoSearch.m
3
- NanoStore
4
-
5
- Copyright (c) 2010 Webbo, L.L.C. All rights reserved.
6
-
7
- Redistribution and use in source and binary forms, with or without modification, are permitted
8
- provided that the following conditions are met:
9
-
10
- * Redistributions of source code must retain the above copyright notice, this list of conditions
11
- and the following disclaimer.
12
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
13
- and the following disclaimer in the documentation and/or other materials provided with the distribution.
14
- * Neither the name of Webbo nor the names of its contributors may be used to endorse or promote
15
- products derived from this software without specific prior written permission.
16
-
17
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
18
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
20
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23
- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
- SUCH DAMAGE.
25
- */
26
-
27
- #import "NanoStore.h"
28
- #import "NanoStore_Private.h"
29
- #import "NSFNanoSearch_Private.h"
30
-
31
- @implementation NSFNanoSearch
32
- {
33
- /** \cond */
34
- @protected
35
- NSFReturnType returnedObjectType;
36
- /** \endcond */
37
- }
38
-
39
-
40
- @synthesize nanoStore, attributesToBeReturned, key, attribute, value, match, expressions, groupValues, sql, sort;
41
-
42
- // ----------------------------------------------
43
- // Initialization / Cleanup
44
- // ----------------------------------------------
45
-
46
- + (NSFNanoSearch*)searchWithStore:(NSFNanoStore *)store
47
- {
48
- return [[self alloc]initWithStore:store];
49
- }
50
-
51
- - (id)initWithStore:(NSFNanoStore *)store
52
- {
53
- if (nil == store) {
54
- [[NSException exceptionWithName:NSFUnexpectedParameterException
55
- reason:[NSString stringWithFormat:@"*** -[%@ %s]: store is nil.", [self class], _cmd]
56
- userInfo:nil]raise];
57
- }
58
-
59
- if ((self = [self init])) {
60
- nanoStore = store;
61
- [self reset];
62
- }
63
-
64
- return self;
65
- }
66
-
67
- /** \cond */
68
-
69
- - (void)dealloc
70
- {
71
- [self reset];
72
- }
73
-
74
- /** \endcond */
75
-
76
- #pragma mark -
77
-
78
- - (NSString *)sql
79
- {
80
- if (nil == sql)
81
- return [self _preparedSQL];
82
-
83
- return sql;
84
- }
85
-
86
- - (NSString*)description
87
- {
88
- NSMutableString *description = [NSMutableString string];
89
-
90
- [description appendString:@"\n"];
91
- [description appendString:[NSString stringWithFormat:@"NanoSearch address : 0x%x\n", self]];
92
- [description appendString:[NSString stringWithFormat:@"Document store : 0x%x\n", nanoStore]];
93
- [description appendString:[NSString stringWithFormat:@"Attributes to be returned : %@\n", (attributesToBeReturned ? [attributesToBeReturned componentsJoinedByString:@","] : @"All")]];
94
- [description appendString:[NSString stringWithFormat:@"Key : %@\n", key]];
95
- [description appendString:[NSString stringWithFormat:@"Attribute : %@\n", attribute]];
96
- [description appendString:[NSString stringWithFormat:@"Value : %@\n", value]];
97
- [description appendString:[NSString stringWithFormat:@"Match : %@\n", NSFStringFromMatchType(match)]];
98
- [description appendString:[NSString stringWithFormat:@"Expressions : %@\n", expressions]];
99
- [description appendString:[NSString stringWithFormat:@"Group Values? : %@\n", (groupValues ? @"YES" : @"NO")]];
100
- [description appendString:[NSString stringWithFormat:@"Sort : %@\n", sort]];
101
-
102
- return description;
103
- }
104
-
105
- #pragma mark -
106
-
107
- - (id)executeSQL:(NSString *)theSQLStatement returnType:(NSFReturnType)theReturnType error:(out NSError **)outError
108
- {
109
- // Make sure we don't have any lingering parameters that could mess with the results, but keep the sort descriptor(s)
110
- NSArray *savedSort = [self sort];
111
- [self reset];
112
- self.sort = savedSort;
113
-
114
- returnedObjectType = theReturnType;
115
- sql = [theSQLStatement copy];
116
-
117
- NSDictionary *results = [self _retrieveDataWithError:outError];
118
-
119
- return [self _sortResultsIfApplicable:results returnType:theReturnType];
120
- }
121
-
122
- - (NSFNanoResult *)executeSQL:(NSString *)theSQLStatement
123
- {
124
- // Make sure we don't have any lingering parameters that could mess with the results...
125
- [self reset];
126
-
127
- sql = theSQLStatement;
128
-
129
- return [nanoStore _executeSQL:theSQLStatement];
130
- }
131
-
132
- - (NSFNanoResult *)explainSQL:(NSString *)theSQLStatement
133
- {
134
- if (nil == theSQLStatement) {
135
- [[NSException exceptionWithName:NSFUnexpectedParameterException
136
- reason:[NSString stringWithFormat:@"*** -[%@ %s]: the SQL statement is nil.", [self class], _cmd]
137
- userInfo:nil]raise];
138
- }
139
-
140
- if (0 == [theSQLStatement length]) {
141
- [[NSException exceptionWithName:NSFUnexpectedParameterException
142
- reason:[NSString stringWithFormat:@"*** -[%@ %s]: the SQL statement is empty.", [self class], _cmd]
143
- userInfo:nil]raise];
144
- }
145
-
146
- return [nanoStore _executeSQL:[NSString stringWithFormat:@"EXPLAIN %@", theSQLStatement]];
147
- }
148
-
149
- - (void)reset
150
- {
151
- attributesToBeReturned= nil;
152
- key = nil;
153
- attribute = nil;
154
- value = nil;
155
- match = NSFContains;
156
- groupValues = NO;
157
- sql = nil;
158
- sort = nil;
159
-
160
- returnedObjectType = NSFReturnObjects;
161
- }
162
-
163
- #pragma mark -
164
-
165
- - (id)searchObjectsWithReturnType:(NSFReturnType)theReturnType error:(out NSError **)outError
166
- {
167
- returnedObjectType = theReturnType;
168
-
169
- // Make sure we don't have a SQL statement around...
170
- sql = nil;
171
-
172
- id results = [self _retrieveDataWithError:outError];
173
-
174
- return [self _sortResultsIfApplicable:results returnType:theReturnType];
175
- }
176
-
177
- - (id)searchObjectsAdded:(NSFDateMatchType)theDateMatch date:(NSDate *)theDate returnType:(NSFReturnType)theReturnType error:(out NSError **)outError
178
- {
179
- returnedObjectType = theReturnType;
180
-
181
- // Make sure we don't have a SQL statement around...
182
- sql = nil;
183
-
184
- id results = [self _retrieveDataAdded:theDateMatch calendarDate:theDate error:outError];
185
-
186
- if (NSFReturnKeys == theReturnType) {
187
- results = [results allKeys];
188
- }
189
-
190
- return results;
191
- }
192
-
193
- - (NSNumber *)aggregateOperation:(NSFAggregateFunctionType)theFunctionType onAttribute:(NSString *)theAttribute
194
- {
195
- NSFReturnType savedObjectTypeReturned = returnedObjectType;
196
- returnedObjectType = NSFReturnKeys;
197
-
198
- NSString *savedSQL = sql;
199
- sql = nil;
200
-
201
- NSString *theSearchSQLStatement = [self sql];
202
- NSMutableString *theAggregatedSQLStatement = [NSMutableString new];
203
-
204
- switch (theFunctionType) {
205
- case NSFAverage:
206
- [theAggregatedSQLStatement appendString:[NSString stringWithFormat:@"SELECT avg(NSFValue) FROM NSFValues WHERE NSFAttribute = '%@' AND NSFKey IN (%@)", theAttribute, theSearchSQLStatement]];
207
- break;
208
- case NSFCount:
209
- [theAggregatedSQLStatement appendString:[NSString stringWithFormat:@"SELECT count(*) FROM NSFValues WHERE NSFAttribute = '%@' AND NSFKey IN (%@)", theAttribute, theSearchSQLStatement]];
210
- break;
211
- case NSFMax:
212
- [theAggregatedSQLStatement appendString:[NSString stringWithFormat:@"SELECT max(NSFValue) FROM NSFValues WHERE NSFAttribute = '%@' AND NSFKey IN (%@)", theAttribute, theSearchSQLStatement]];
213
- break;
214
- case NSFMin:
215
- [theAggregatedSQLStatement appendString:[NSString stringWithFormat:@"SELECT min(NSFValue) FROM NSFValues WHERE NSFAttribute = '%@' AND NSFKey IN (%@)", theAttribute, theSearchSQLStatement]];
216
- break;
217
- case NSFTotal:
218
- /* Note:
219
- Sum() will throw an "integer overflow" exception if all inputs are integers or NULL and an integer overflow occurs at any point
220
- during the computation. Total() never throws an integer overflow.
221
- */
222
- [theAggregatedSQLStatement appendString:[NSString stringWithFormat:@"SELECT total(NSFValue) FROM NSFValues WHERE NSFAttribute = '%@' AND NSFKey IN (%@)", theAttribute, theSearchSQLStatement]];
223
- break;
224
- default:
225
- break;
226
- }
227
-
228
- NSFNanoResult *result = [nanoStore _executeSQL:theAggregatedSQLStatement];
229
-
230
- returnedObjectType = savedObjectTypeReturned;
231
- sql = savedSQL;
232
-
233
- return [NSNumber numberWithFloat:[[result firstValue]floatValue]];
234
- }
235
-
236
- #pragma mark -
237
- #pragma mark Private Methods
238
- #pragma mark -
239
-
240
- /** \cond */
241
-
242
- - (NSDictionary *)_retrieveDataWithError:(out NSError **)outError
243
- {
244
- if (YES == [nanoStore isClosed]) {
245
- return nil;
246
- }
247
-
248
- NSMutableDictionary *searchResults = [NSMutableDictionary dictionary];
249
-
250
- NSString *aSQLQuery = sql;
251
-
252
- if (nil != aSQLQuery) {
253
- // We are going to check whether the user has specified the proper columns based on the search type selected.
254
- // This is to avoid crashing, since the user shouldn't have to know which columns are involved on each type
255
- // of search.
256
- // We basically honor the specified query but replace the columns with the expected ones per returned type.
257
-
258
- NSString *subStatement = [aSQLQuery substringFromIndex:[aSQLQuery rangeOfString:@"FROM" options:NSCaseInsensitiveSearch].location];
259
- NSFReturnType returnType = returnedObjectType;
260
- switch (returnType) {
261
- case NSFReturnKeys:
262
- aSQLQuery = [NSString stringWithFormat:@"SELECT NSFKey %@", subStatement];
263
- break;
264
- case NSFReturnObjects:
265
- aSQLQuery = [NSString stringWithFormat:@"SELECT NSFKey, NSFPlist, NSFObjectClass %@", subStatement];
266
- break;
267
- }
268
- } else {
269
- aSQLQuery = [self _preparedSQL];
270
- }
271
-
272
- _NSFLog(@"_dataWithKey SQL query: %@", aSQLQuery);
273
-
274
- sqlite3 *sqliteStore = [[nanoStore nanoStoreEngine]sqlite];
275
- sqlite3_stmt *theSQLiteStatement = NULL;
276
-
277
- int status = sqlite3_prepare_v2 (sqliteStore, [aSQLQuery UTF8String], -1, &theSQLiteStatement, NULL );
278
-
279
- status = [NSFNanoEngine NSFP_stripBitsFromExtendedResultCode:status];
280
-
281
- if (SQLITE_OK == status) {
282
- switch (returnedObjectType) {
283
- case NSFReturnKeys:
284
- while (SQLITE_ROW == sqlite3_step (theSQLiteStatement)) {
285
- // Sanity check: some queries return NULL, which would cause a crash below.
286
- char *valueUTF8 = (char *)sqlite3_column_text (theSQLiteStatement, 0);
287
- NSString *theValue = nil;
288
- if (NULL != valueUTF8) {
289
- theValue = [[NSString alloc]initWithUTF8String:valueUTF8];
290
- } else {
291
- theValue = [[NSNull null]description];
292
- }
293
-
294
- [searchResults setObject:[NSNull null] forKey:theValue];
295
- }
296
- break;
297
- default:
298
- while (SQLITE_ROW == sqlite3_step (theSQLiteStatement)) {
299
- char *keyUTF8 = (char *)sqlite3_column_text (theSQLiteStatement, 0);
300
- char *dictXMLUTF8 = (char *)sqlite3_column_text (theSQLiteStatement, 1);
301
- char *objectClassUTF8 = (char *)sqlite3_column_text (theSQLiteStatement, 2);
302
-
303
- // Sanity check: some queries return NULL, which would a crash below.
304
- // Since these are values that are NanoStore's resposibility, they should *never* be NULL. Log it for posterity.
305
- if ((NULL == keyUTF8) || (NULL == dictXMLUTF8) || (NULL == objectClassUTF8)) {
306
- NSLog(@"*** Warning! These values are NanoStore's resposibility and should *never* be NULL: keyUTF8 (%s) - dictXMLUTF8 (%s) - objectClassUTF8 (%s)", keyUTF8, dictXMLUTF8, objectClassUTF8);
307
- continue;
308
- }
309
-
310
- NSString *keyValue = [[NSString alloc]initWithUTF8String:keyUTF8];
311
- NSString *dictXML = [[NSString alloc]initWithUTF8String:dictXMLUTF8];
312
- NSString *objectClass = [[NSString alloc]initWithUTF8String:objectClassUTF8];
313
-
314
- NSDictionary *info = [NSFNanoEngine _plistToDictionary:dictXML];
315
- if (nil == info) {
316
- continue;
317
- }
318
-
319
- if ([attributesToBeReturned count] == 0) {
320
- // Will be released below...
321
- } else {
322
- // Since we want a subset of the attributes, we need to traverse
323
- // the attribute list and find out whether the dictionary contains
324
- // the specified attributes. If so, add them to a subset which will
325
- // be returned as requested.
326
-
327
- NSMutableDictionary *subset = [NSMutableDictionary new];
328
-
329
- for (NSString *attributeValue in attributesToBeReturned) {
330
- id theValue = [info valueForKeyPath:attributeValue];
331
- if (nil != theValue) {
332
- if (NSNotFound == [attributeValue rangeOfString:@"."].location) {
333
- [subset setValue:theValue forKeyPath:attributeValue];
334
- } else {
335
- NSDictionary *subInfo = [self _dictionaryForKeyPath:attributeValue value:theValue];
336
- if ([subInfo count] > 0) {
337
- NSString *subInfoKey = [[subInfo allKeys]objectAtIndex:0];
338
- NSString *subInfoValue = [subInfo objectForKey:subInfoKey];
339
- [subset setValue:subInfoValue forKey:subInfoKey];
340
- }
341
- }
342
- }
343
- }
344
-
345
- // Will be released below...
346
- info = subset;
347
- }
348
-
349
- Class storedObjectClass = NSClassFromString(objectClass);
350
- BOOL saveOriginalClassReference = NO;
351
- if (nil == storedObjectClass) {
352
- storedObjectClass = [NSFNanoObject class];
353
- saveOriginalClassReference = YES;
354
- }
355
-
356
- id nanoObject = [[storedObjectClass alloc]initNanoObjectFromDictionaryRepresentation:info forKey:keyValue store:nanoStore];
357
-
358
- // If this process does not have knowledge of the original class as was saved in the store, keep a reference
359
- // so that we can later on restore the object properly (otherwise it would be stored as a NanoObject.)
360
- if (YES == saveOriginalClassReference) {
361
- [nanoObject _setOriginalClassString:objectClass];
362
- }
363
-
364
- [searchResults setObject:nanoObject forKey:keyValue];
365
-
366
- }
367
- break;
368
- }
369
-
370
- sqlite3_finalize (theSQLiteStatement);
371
-
372
- } else {
373
- if (nil != outError) {
374
- NSString *msg = [NSString stringWithFormat:@"SQLite error ID: %ld", status];
375
- *outError = [NSError errorWithDomain:NSFDomainKey
376
- code:NSFNanoStoreErrorKey
377
- userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %s]: %@", [self class], _cmd, msg]
378
- forKey:NSLocalizedFailureReasonErrorKey]];
379
- }
380
- searchResults = nil;
381
- }
382
-
383
- return searchResults;
384
- }
385
-
386
- - (NSDictionary *)_retrieveDataAdded:(NSFDateMatchType)aDateMatch calendarDate:(NSDate *)aDate error:(out NSError **)outError
387
- {
388
- if ([nanoStore isClosed] == YES) {
389
- return nil;
390
- }
391
-
392
- NSString *theSQLStatement = nil;
393
- NSString *normalizedDateString = [NSFNanoStore _calendarDateToString:aDate];
394
-
395
- switch (aDateMatch) {
396
- case NSFBeforeDate:
397
- theSQLStatement = [[NSString alloc]initWithFormat:@"SELECT %@, %@, %@ FROM %@ WHERE %@ < '%@'", NSFKey, NSFPlist, NSFObjectClass, NSFKeys, NSFCalendarDate, normalizedDateString];
398
- break;
399
- case NSFOnDate:
400
- theSQLStatement = [[NSString alloc]initWithFormat:@"SELECT %@, %@, %@ FROM %@ WHERE %@ = '%@'", NSFKey, NSFPlist, NSFObjectClass, NSFKeys, NSFCalendarDate, normalizedDateString];
401
- break;
402
- case NSFAfterDate:
403
- theSQLStatement = [[NSString alloc]initWithFormat:@"SELECT %@, %@, %@ FROM %@ WHERE %@ > '%@'", NSFKey, NSFPlist, NSFObjectClass, NSFKeys, NSFCalendarDate, normalizedDateString];
404
- break;
405
- }
406
-
407
- NSFNanoResult *result = [nanoStore _executeSQL:theSQLStatement];
408
-
409
- NSMutableDictionary *searchResults = [NSMutableDictionary dictionaryWithCapacity:result.numberOfRows];
410
-
411
- if (result.numberOfRows > 0) {
412
- if (NSFReturnKeys == returnedObjectType) {
413
- NSArray *resultsKeys = [result valuesForColumn:[NSString stringWithFormat:@"%@.%@", NSFKeys, NSFKey]];
414
- for (NSString *resultKey in resultsKeys)
415
- [searchResults setObject:[NSNull null] forKey:resultKey];
416
- return searchResults;
417
- } else {
418
- NSArray *resultsObjectClass = [result valuesForColumn:[NSString stringWithFormat:@"%@.%@", NSFKeys, NSFObjectClass]];
419
- NSArray *resultsObjects = [result valuesForColumn:[NSString stringWithFormat:@"%@.%@", NSFKeys, NSFPlist]];
420
- NSArray *resultsKeys = [result valuesForColumn:[NSString stringWithFormat:@"%@.%@", NSFKeys, NSFKey]];
421
- NSUInteger i, count = [resultsKeys count];
422
-
423
- for (i = 0; i < count; i++) {
424
- @autoreleasepool {
425
- NSDictionary *info = [NSFNanoEngine _plistToDictionary:[resultsObjects objectAtIndex:i]];
426
- if (nil != info) {
427
- NSString *keyValue = [resultsKeys objectAtIndex:i];
428
-
429
- NSString *className = [resultsObjectClass objectAtIndex:i];
430
- Class storedObjectClass = NSClassFromString(className);
431
- BOOL saveOriginalClassReference = NO;
432
- if (nil == storedObjectClass) {
433
- storedObjectClass = [NSFNanoObject class];
434
- saveOriginalClassReference = YES;
435
- }
436
-
437
- id nanoObject = [[storedObjectClass alloc]initNanoObjectFromDictionaryRepresentation:info forKey:keyValue store:nanoStore];
438
-
439
- // If this process does not have knowledge of the original class as was saved in the store, keep a reference
440
- // so that we can later on restore the object properly (otherwise it would be stored as a NanoObject.)
441
- if (YES == saveOriginalClassReference) {
442
- [nanoObject _setOriginalClassString:className];
443
- }
444
-
445
- [searchResults setObject:nanoObject forKey:keyValue];
446
- }
447
- }
448
- }
449
- }
450
- }
451
-
452
- return searchResults;
453
- }
454
-
455
- - (NSString *)_preparedSQL
456
- {
457
- NSString *aSQLQuery = nil;
458
-
459
- if (nil == expressions) {
460
- aSQLQuery = [self _prepareSQLQueryStringWithKey:key attribute:attribute value:value matching:match];
461
- } else {
462
- aSQLQuery = [self _prepareSQLQueryStringWithExpressions:expressions];
463
- }
464
-
465
- return aSQLQuery;
466
- }
467
-
468
- - (NSString *)_prepareSQLQueryStringWithKey:(NSString *)aKey attribute:(NSString *)anAttribute value:(id)aValue matching:(NSFMatchType)aMatch
469
- {
470
- NSMutableString *theSQLStatement = nil;
471
- NSString *attributes = nil;
472
-
473
- if (nil != attributesToBeReturned) {
474
- // Prepare the list of attributes we need to gather. Include NSFKEY as well.
475
- NSMutableSet *set = [[NSMutableSet alloc]initWithArray:attributesToBeReturned];
476
- NSArray *objects = [set allObjects];
477
- NSMutableArray *quotedObjects = [NSMutableArray new];
478
- for (NSString *object in objects) {
479
- NSString *theValue = [[NSString alloc]initWithFormat:@"'%@'", object];
480
- [quotedObjects addObject:theValue];
481
- }
482
- attributes = [quotedObjects componentsJoinedByString:@","];
483
- }
484
-
485
- NSFReturnType returnType = returnedObjectType;
486
-
487
- if ((nil == aKey) && (nil == anAttribute) && (nil == aValue)) {
488
- switch (returnType) {
489
- case NSFReturnKeys:
490
- return @"SELECT NSFKEY FROM NSFKeys";
491
- break;
492
- default:
493
- return @"SELECT NSFKey, NSFPlist, NSFObjectClass FROM NSFKeys";
494
- break;
495
- }
496
- } else {
497
- switch (returnType) {
498
- case NSFReturnKeys:
499
- if (NO == groupValues) {
500
- theSQLStatement = [NSMutableString stringWithString:@"SELECT DISTINCT (NSFKEY) FROM NSFValues WHERE "];
501
- } else {
502
- theSQLStatement = [NSMutableString stringWithString:@"SELECT NSFKEY FROM NSFValues WHERE "];
503
- }
504
- break;
505
- default:
506
- theSQLStatement = [NSMutableString stringWithString:@"SELECT NSFKEY FROM NSFValues WHERE "];
507
- break;
508
- }
509
- }
510
-
511
- NSString *segment = nil;
512
- BOOL querySegmentWasAdded = NO;
513
-
514
- if (nil != aKey) {
515
- if ((nil == anAttribute) && (nil == aValue))
516
- segment = [NSFNanoSearch _querySegmentForColumn:NSFKey value:aKey matching:aMatch];
517
- else
518
- segment = [NSFNanoSearch _querySegmentForColumn:NSFKey value:aKey matching:NSFEqualTo];
519
- [theSQLStatement appendString:segment];
520
- querySegmentWasAdded = YES;
521
- }
522
-
523
- if (nil != anAttribute) {
524
- if (YES == querySegmentWasAdded) {
525
- [theSQLStatement appendString:@" AND "];
526
- }
527
-
528
- // We need to introspect whether the attribute contains a dot "." or not. Based on the case, we'll need to GLOB the attribute
529
- // or leave it as is.
530
-
531
- if (NSNotFound == [anAttribute rangeOfString:@"."].location) {
532
- segment = [NSFNanoSearch _querySegmentForAttributeColumnWithValue:anAttribute matching:aMatch valueColumnWithValue:aValue];
533
- } else {
534
- if (nil == aValue)
535
- segment = [NSFNanoSearch _querySegmentForColumn:NSFAttribute value:anAttribute matching:aMatch];
536
- else
537
- segment = [NSFNanoSearch _querySegmentForColumn:NSFAttribute value:anAttribute matching:NSFEqualTo];
538
- }
539
-
540
- [theSQLStatement appendString:segment];
541
- } else {
542
- if (nil != aValue) {
543
- if (YES == querySegmentWasAdded)
544
- [theSQLStatement appendString:@" AND "];
545
- segment = [NSFNanoSearch _querySegmentForColumn:NSFValue value:aValue matching:aMatch];
546
- [theSQLStatement appendString:segment];
547
- }
548
- }
549
-
550
- if (YES == groupValues) {
551
- [theSQLStatement appendString:@" GROUP BY NSFValue"];
552
- }
553
-
554
- if (NSFReturnObjects == returnType) {
555
- if (nil != attributes)
556
- theSQLStatement = [NSString stringWithFormat:@"SELECT DISTINCT (NSFKey),NSFPlist,NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@)", theSQLStatement];
557
- else
558
- theSQLStatement = [NSString stringWithFormat:@"SELECT DISTINCT (NSFKey),NSFPlist,NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@)", theSQLStatement];
559
- }
560
-
561
- return theSQLStatement;
562
- }
563
-
564
- - (NSString *)_prepareSQLQueryStringWithExpressions:(NSArray *)someExpressions
565
- {
566
- NSUInteger i, count = [someExpressions count];
567
- NSMutableArray *sqlComponents = [NSMutableArray new];
568
- NSMutableString *parentheses = [NSMutableString new];
569
- NSFReturnType returnType = returnedObjectType;
570
-
571
- for (i = 0; i < count; i++) {
572
- NSFNanoExpression *expression = [someExpressions objectAtIndex:i];
573
- NSMutableString *theSQL = nil;;
574
-
575
- if (NSFReturnObjects == returnType)
576
- theSQL = [[NSMutableString alloc]initWithFormat:@"SELECT NSFKEY FROM NSFValues WHERE %@", [expression description]];
577
- else
578
- theSQL = [[NSMutableString alloc]initWithFormat:@"SELECT DISTINCT (NSFKEY) FROM NSFValues WHERE %@", [expression description]];
579
-
580
- if ((count > 1) && (i < count-1)) {
581
- [theSQL appendString:@" AND NSFKEY IN ("];
582
- [parentheses appendString:@")"];
583
- }
584
-
585
- [sqlComponents addObject:theSQL];
586
- }
587
-
588
- if ([parentheses length] > 0)
589
- [sqlComponents addObject:parentheses];
590
-
591
- NSString *theValue = [sqlComponents componentsJoinedByString:@""];
592
-
593
- if (NSFReturnObjects == returnType)
594
- theValue = [NSString stringWithFormat:@"SELECT DISTINCT (NSFKey),NSFPlist,NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@)", theValue];
595
-
596
- return theValue;
597
- }
598
-
599
- + (NSString *)_prepareSQLQueryStringWithKeys:(NSArray *)someKeys
600
- {
601
- //Prepare the keys by single quoting them...
602
- NSMutableArray *preparedKeys = [NSMutableArray new];
603
- for (NSString *theKey in someKeys) {
604
- NSString *quotedKey = [[NSString alloc]initWithFormat:@"'%@'", theKey];
605
- [preparedKeys addObject:quotedKey];
606
- }
607
-
608
- NSMutableString *theSQLStatement = [NSMutableString stringWithString:@"SELECT DISTINCT (NSFKEY) FROM NSFValues WHERE NSFKey IN ("];
609
- [theSQLStatement appendString:[preparedKeys componentsJoinedByString:@","]];
610
- [theSQLStatement appendString:@")"];
611
- theSQLStatement = [NSString stringWithFormat:@"SELECT DISTINCT (NSFKey),NSFPlist,NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@)", theSQLStatement];
612
-
613
- return theSQLStatement;
614
- }
615
-
616
- + (NSString *)_querySegmentForColumn:(NSString *)aColumn value:(id)aValue matching:(NSFMatchType)match
617
- {
618
- NSMutableString *segment = [NSMutableString string];
619
- NSMutableString *value = nil;
620
- NSMutableString *mutatedString = nil;
621
- NSInteger mutatedStringLength = 0;
622
- unichar sentinelChar;
623
-
624
- if (YES == [aValue isKindOfClass:[NSString class]]) {
625
- switch (match) {
626
- case NSFEqualTo:
627
- value = [[NSMutableString alloc]initWithFormat:@"%@ = '%@'", aColumn, aValue];
628
- [segment appendString:value];
629
- break;
630
- case NSFBeginsWith:
631
- sentinelChar = [aValue characterAtIndex:[aValue length] - 1] + 1;
632
- value = [[NSMutableString alloc]initWithFormat:@"(%@ >= '%@' AND %@ < '%@%c')", aColumn, aValue, aColumn, aValue, sentinelChar];
633
- [segment appendString:value];
634
- break;
635
- case NSFContains:
636
- value = [[NSMutableString alloc]initWithFormat:@"%@ GLOB '*%@*'", aColumn, aValue];
637
- [segment appendString:value];
638
- break;
639
- case NSFEndsWith:
640
- value = [[NSMutableString alloc]initWithFormat:@"%@ GLOB '*%@'", aColumn, aValue];
641
- [segment appendString:value];
642
- break;
643
- case NSFInsensitiveEqualTo:
644
- value = [[NSMutableString alloc]initWithFormat:@"upper(%@) = '%@'", aColumn, [aValue uppercaseString]];
645
- [segment appendString:value];
646
- break;
647
- case NSFInsensitiveBeginsWith:
648
- mutatedString = [[NSMutableString alloc]initWithString:aValue];
649
- mutatedStringLength = [aValue length];
650
- value = [[NSMutableString alloc]initWithFormat:@"%c", [mutatedString characterAtIndex:mutatedStringLength - 1]+1];
651
- [mutatedString replaceCharactersInRange:NSMakeRange(mutatedStringLength - 1, 1) withString:value];
652
- value = [[NSMutableString alloc]initWithFormat:@"(upper(%@) >= '%@' AND upper(%@) < '%@')", aColumn, [aValue uppercaseString], aColumn, [mutatedString uppercaseString]];
653
- [segment appendString:value];
654
- break;
655
- case NSFInsensitiveContains:
656
- value = [[NSMutableString alloc]initWithFormat:@"%@ LIKE '%@%@%@'", aColumn, @"%", aValue, @"%"];
657
- [segment appendString:value];
658
- break;
659
- case NSFInsensitiveEndsWith:
660
- value = [[NSMutableString alloc]initWithFormat:@"%@ LIKE '%@%@'", aColumn, @"%", aValue];
661
- [segment appendString:value];
662
- break;
663
- case NSFGreaterThan:
664
- value = [[NSMutableString alloc]initWithFormat:@"%@ > '%@'", aColumn, aValue];
665
- [segment appendString:value];
666
- break;
667
- case NSFLessThan:
668
- value = [[NSMutableString alloc]initWithFormat:@"%@ < '%@'", aColumn, aValue];
669
- [segment appendString:value];
670
- break;
671
- }
672
- } else if (YES == [aValue isKindOfClass:[NSArray class]]) {
673
- // Quote the parameters
674
- NSMutableArray *quotedParameters = [[NSMutableArray alloc]initWithCapacity:[aValue count]];
675
- value = [[NSMutableString alloc]initWithFormat:@"%@ IN (", aColumn];
676
- for (NSString *parameter in aValue) {
677
- NSString *quotedParameter = [[NSString alloc]initWithFormat:@"'%@'", parameter];
678
- [quotedParameters addObject:quotedParameter];
679
- }
680
- //Add them to the string delimited by string
681
- [value appendString:[quotedParameters componentsJoinedByString:@","]];
682
- [value appendString:@")"];
683
-
684
- // Complete the query segment
685
- [segment appendString:value];
686
-
687
- // Free allocated resources
688
- }
689
-
690
- return segment;
691
- }
692
-
693
- + (NSString *)_querySegmentForAttributeColumnWithValue:(id)anAttributeValue matching:(NSFMatchType)match valueColumnWithValue:(id)aValue
694
- {
695
- NSMutableString *segment = [NSMutableString string];
696
- NSMutableString *value = nil;
697
-
698
- if ((YES == [aValue isKindOfClass:[NSString class]]) || (nil == aValue)) {
699
- if (nil == aValue) {
700
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@') OR (%@ GLOB '%@.*') OR (%@ GLOB '*.%@.*') OR (%@ GLOB '*.%@')", NSFAttribute, anAttributeValue, NSFAttribute, anAttributeValue, NSFAttribute, anAttributeValue, NSFAttribute, anAttributeValue];
701
- [segment appendString:value];
702
- } else {
703
- switch (match) {
704
- case NSFEqualTo:
705
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ = '%@') OR (%@ GLOB '%@.*' AND %@ = '%@') OR (%@ GLOB '*.%@.*' AND %@ = '%@') OR (%@ GLOB '*.%@' AND %@ = '%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
706
- [segment appendString:value];
707
- break;
708
- case NSFBeginsWith:
709
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ GLOB '%@*') OR (%@ GLOB '%@.*' AND %@ GLOB '%@*') OR (%@ GLOB '*.%@.*' AND %@ GLOB '%@*') OR (%@ GLOB '*.%@' AND %@ GLOB '%@*')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
710
- [segment appendString:value];
711
- break;
712
- case NSFContains:
713
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ GLOB '%@') OR (%@ GLOB '%@.*' AND %@ GLOB '%@') OR (%@ GLOB '*.%@.*' AND %@ GLOB '%@') OR (%@ GLOB '*.%@' AND %@ GLOB '%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
714
- [segment appendString:value];
715
- break;
716
- case NSFEndsWith:
717
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ GLOB '*%@') OR (%@ GLOB '%@.*' AND %@ GLOB '*%@') OR (%@ GLOB '*.%@.*' AND %@ GLOB '*%@') OR (%@ GLOB '*.%@' AND %@ GLOB '*%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
718
- [segment appendString:value];
719
- break;
720
- case NSFInsensitiveEqualTo:
721
- aValue = [aValue uppercaseString];
722
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND upper(%@) = '%@') OR (%@ GLOB '%@.*' AND upper(%@) = '%@') OR (%@ GLOB '*.%@.*' AND upper(%@) = '%@') OR (%@ GLOB '*.%@' AND upper(%@) = '%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
723
- [segment appendString:value];
724
- break;
725
- case NSFInsensitiveBeginsWith:
726
- aValue = [aValue uppercaseString];
727
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND upper(%@) GLOB '%@*') OR (%@ GLOB '%@.*' AND upper(%@) GLOB '%@*') OR (%@ GLOB '*.%@.*' AND upper(%@) GLOB '%@*') OR (%@ GLOB '*.%@' AND upper(%@) GLOB '%@*')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
728
- [segment appendString:value];
729
- break;
730
- case NSFInsensitiveContains:
731
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ LIKE '%@') OR (%@ GLOB '%@.*' AND %@ LIKE '%@') OR (%@ GLOB '*.%@.*' AND %@ LIKE '%@') OR (%@ GLOB '*.%@' AND %@ LIKE '%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
732
- [segment appendString:value];
733
- break;
734
- case NSFInsensitiveEndsWith:
735
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ LIKE '%%%@') OR (%@ GLOB '%@.*' AND %@ LIKE '%%%@') OR (%@ GLOB '*.%@.*' AND %@ LIKE '%%%@') OR (%@ GLOB '*.%@' AND %@ LIKE '%%%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
736
- [segment appendString:value];
737
- break;
738
- case NSFGreaterThan:
739
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ > '%@') OR (%@ GLOB '%@.*' AND %@ > '%@') OR (%@ GLOB '*.%@.*' AND %@ > '%@') OR (%@ GLOB '*.%@' AND %@ > '%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
740
- [segment appendString:value];
741
- break;
742
- case NSFLessThan:
743
- value = [[NSMutableString alloc]initWithFormat:@"(%@ = '%@' AND %@ < '%@') OR (%@ GLOB '%@.*' AND %@ < '%@') OR (%@ GLOB '*.%@.*' AND %@ < '%@') OR (%@ GLOB '*.%@' AND %@ < '%@')", NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue, NSFAttribute, anAttributeValue, NSFValue, aValue];
744
- [segment appendString:value];
745
- break;
746
- }
747
- }
748
- } else if (YES == [aValue isKindOfClass:[NSArray class]]) {
749
- // Quote the parameters
750
- NSMutableArray *quotedParameters = [[NSMutableArray alloc]initWithCapacity:[aValue count]];
751
- value = [[NSMutableString alloc]initWithFormat:@"%@ IN (", NSFAttribute];
752
- for (NSString *parameter in aValue) {
753
- NSString *quotedParameter = [[NSString alloc]initWithFormat:@"'%@'", parameter];
754
- [quotedParameters addObject:quotedParameter];
755
- }
756
- //Add them to the string delimited by string
757
- [value appendString:[quotedParameters componentsJoinedByString:@","]];
758
- [value appendString:@")"];
759
-
760
- // Complete the query segment
761
- [segment appendString:value];
762
-
763
- // Free allocated resources
764
- }
765
-
766
- return segment;
767
- }
768
-
769
- - (NSDictionary *)_dictionaryForKeyPath:(NSString *)keyPath value:(id)theValue
770
- {
771
- NSMutableDictionary *info = [NSMutableDictionary dictionary];
772
- NSMutableArray *keys = [[keyPath componentsSeparatedByString:@"."]mutableCopy];
773
-
774
- if ([keys count] == 1) {
775
- [info setObject:theValue forKey:keyPath];
776
- return info;
777
- }
778
-
779
- NSInteger i;
780
-
781
- for (i = 0; i < [keys count]; i++) {
782
- NSString *keyValue = [keys objectAtIndex:i];
783
- [keys removeObjectAtIndex:0];
784
- NSDictionary *subInfo = [self _dictionaryForKeyPath:[keys componentsJoinedByString:@"."] value:theValue];
785
- if (nil != subInfo)
786
- [info setObject:subInfo forKey:keyValue];
787
- }
788
-
789
- return info;
790
- }
791
-
792
- + (NSString *)_quoteStrings:(NSArray *)strings joiningWithDelimiter:(NSString *)delimiter
793
- {
794
- NSMutableArray *quotedParameters = [[NSMutableArray alloc]initWithCapacity:[strings count]];
795
- for (NSString *string in strings) {
796
- NSString *quotedParameter = [[NSString alloc]initWithFormat:@"\"%@\"", string];
797
- [quotedParameters addObject:quotedParameter];
798
- }
799
-
800
- NSString *quotedString = [quotedParameters componentsJoinedByString:@","];
801
-
802
-
803
- return quotedString;
804
- }
805
-
806
- - (id)_sortResultsIfApplicable:(NSDictionary *)results returnType:(NSFReturnType)theReturnType
807
- {
808
- id theResults = results;
809
-
810
- if (nil != sort) {
811
- NSMutableArray *cocoaSortDescriptors = [NSMutableArray new];
812
-
813
- for (NSFNanoSortDescriptor *descriptor in sort) {
814
- NSString *targetKeyPath = [[NSString alloc]initWithFormat:@"rootObject.%@", descriptor.attribute];
815
- NSSortDescriptor *cocoaSort = [[NSSortDescriptor alloc]initWithKey:targetKeyPath ascending:descriptor.isAscending];
816
- [cocoaSortDescriptors addObject:cocoaSort];
817
- }
818
-
819
- if (NSFReturnObjects == theReturnType) {
820
- theResults = [[results allValues]sortedArrayUsingDescriptors:cocoaSortDescriptors];
821
- } else {
822
- theResults = [results allKeys];
823
- }
824
- }
825
- else if (NSFReturnKeys == theReturnType)
826
- {
827
- theResults = [results allKeys];
828
- }
829
-
830
- return theResults;
831
- }
832
-
833
- /** \endcond */
834
-
835
- @end