nano-store 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +3 -0
  2. data/.gitmodules +3 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +193 -0
  7. data/Rakefile +1 -0
  8. data/app/app_delegate.rb +5 -0
  9. data/lib/nano-store.rb +1 -0
  10. data/lib/nano_store/bag.rb +98 -0
  11. data/lib/nano_store/model.rb +142 -0
  12. data/lib/nano_store/nano_store.rb +36 -0
  13. data/lib/nano_store/store_extension.rb +150 -0
  14. data/lib/nano_store/version.rb +3 -0
  15. data/lib/nano_store.rb +14 -0
  16. data/nano-store.gemspec +17 -0
  17. data/resources/.gitignore +0 -0
  18. data/spec/bag_spec.rb +66 -0
  19. data/spec/model_spec.rb +130 -0
  20. data/spec/nano_store_spec.rb +48 -0
  21. data/spec/store_extension_spec.rb +110 -0
  22. data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.h +542 -0
  23. data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.m +1781 -0
  24. data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.h +137 -0
  25. data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.m +265 -0
  26. data/vendor/NanoStore/Classes/Private/NSFNanoBag_Private.h +37 -0
  27. data/vendor/NanoStore/Classes/Private/NSFNanoEngine_Private.h +69 -0
  28. data/vendor/NanoStore/Classes/Private/NSFNanoExpression_Private.h +35 -0
  29. data/vendor/NanoStore/Classes/Private/NSFNanoGlobals_Private.h +99 -0
  30. data/vendor/NanoStore/Classes/Private/NSFNanoObject_Private.h +35 -0
  31. data/vendor/NanoStore/Classes/Private/NSFNanoPredicate_Private.h +35 -0
  32. data/vendor/NanoStore/Classes/Private/NSFNanoResult_Private.h +43 -0
  33. data/vendor/NanoStore/Classes/Private/NSFNanoSearch_Private.h +48 -0
  34. data/vendor/NanoStore/Classes/Private/NSFNanoStore_Private.h +57 -0
  35. data/vendor/NanoStore/Classes/Private/NanoStore_Private.h +37 -0
  36. data/vendor/NanoStore/Classes/Public/NSFNanoBag.h +306 -0
  37. data/vendor/NanoStore/Classes/Public/NSFNanoBag.m +485 -0
  38. data/vendor/NanoStore/Classes/Public/NSFNanoExpression.h +125 -0
  39. data/vendor/NanoStore/Classes/Public/NSFNanoExpression.m +103 -0
  40. data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.h +323 -0
  41. data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.m +145 -0
  42. data/vendor/NanoStore/Classes/Public/NSFNanoObject.h +298 -0
  43. data/vendor/NanoStore/Classes/Public/NSFNanoObject.m +187 -0
  44. data/vendor/NanoStore/Classes/Public/NSFNanoObjectProtocol.h +119 -0
  45. data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.h +123 -0
  46. data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.m +130 -0
  47. data/vendor/NanoStore/Classes/Public/NSFNanoSearch.h +381 -0
  48. data/vendor/NanoStore/Classes/Public/NSFNanoSearch.m +835 -0
  49. data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.h +124 -0
  50. data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.m +79 -0
  51. data/vendor/NanoStore/Classes/Public/NSFNanoStore.h +475 -0
  52. data/vendor/NanoStore/Classes/Public/NSFNanoStore.m +1375 -0
  53. data/vendor/NanoStore/Classes/Public/NanoStore.h +463 -0
  54. data/vendor/NanoStore/LICENSE +25 -0
  55. data/vendor/NanoStore/NanoStore.bridgesupport +1215 -0
  56. data/vendor/NanoStore/README.md +411 -0
  57. metadata +118 -0
@@ -0,0 +1,463 @@
1
+ /*
2
+ NanoStore.h
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 "NSFNanoObjectProtocol.h"
28
+ #import "NSFNanoObject.h"
29
+ #import "NSFNanoGlobals.h"
30
+ #import "NSFNanoStore.h"
31
+ #import "NSFNanoPredicate.h"
32
+ #import "NSFNanoExpression.h"
33
+ #import "NSFNanoSearch.h"
34
+ #import "NSFNanoSortDescriptor.h"
35
+ #import "NSFNanoResult.h"
36
+ #import "NSFNanoBag.h"
37
+ #import "NSFNanoEngine.h"
38
+ #import "NSFNanoGlobals.h"
39
+
40
+ /**
41
+ @mainpage Welcome To NanoStore
42
+
43
+ @section whatis_sec What is NanoStore?
44
+
45
+ NanoStore is an open source, lightweight schema-less local key-value document store written in Objective-C for Mac OS X and iOS.
46
+
47
+ Relational databases tend to have a rich understanding of the structure of your data, but requires some planing beforehand and some level of
48
+ maintenance as well. NanoStore provides the flexibility that comes with key-value document stores, but still understands something about your data.
49
+ Because the data is key-value based, it can be accessed quickly and can grow as much as needed... all without ever worrying about the schema.
50
+
51
+ @section mainadv_sec Main advantages
52
+
53
+ - No SQL knowledge required
54
+ - Schema-less
55
+ - Key-value based storage
56
+ - Store your own custom objects
57
+ - Bags, a free-form relational system
58
+ - Fast, direct object manipulation
59
+ - Dynamic queries
60
+ - Full index support, inner-objects, embedded arrays and dictionaries
61
+ - Convenience methods to access, manipulate and maintain SQLite databases
62
+ - Full SQLite access available
63
+ - Mac OS X Lion 10.7 and iOS 5 ready
64
+ - iOS library runs on the device and simulator
65
+ - ARC compliant
66
+
67
+ @section installation_sec Installation
68
+
69
+ Building NanoStore is very easy. Just follow these steps:
70
+
71
+ - 1) Download NanoStore
72
+ - 2) Open the NanoStore.xcodeproj file
73
+ - 3) Select Universal > My Mac 64-bit or 32-bit from the Scheme popup
74
+ - 4) Build (Command-B)
75
+
76
+ Now you should have a new <i>Distribution</i> directory within the NanoStore project directory which contains the Universal static library (armv6/armv7/i386)
77
+ as well as the header files. To add it in your project, do the following:
78
+
79
+ - 1) Drag the Distribution directory to the Project Navigator panel
80
+ - 2) Include #import "NanoStore.h" in your code
81
+
82
+ @details <b>Example:</b>
83
+ @code
84
+ #import "NanoStore.h"
85
+
86
+ @implementation MyDemoAppDelegate
87
+
88
+ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
89
+ {
90
+ // Override point for customization after application launch.
91
+ // Instantiate a NanoStore and open it
92
+
93
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
94
+ ...
95
+ @endcode
96
+
97
+ @note
98
+ If you want to add a dependency between your project and NanoStore so that it gets automatically rebuilt when
99
+ you update NanoStore, do the following (we'll assume your app is called "MyDemoApp"):
100
+
101
+ - 1) Select the MyDemoApp project in the Project Navigator
102
+ - 2) Select the MyDemoApp target
103
+ - 3) Expand the Target Dependencies box
104
+ - 4) Click "+" and add NanoStore
105
+
106
+ @section howitworks_sec How does NanoStore work?
107
+
108
+ The basic unit of data in NanoStore is called NanoObject. A NanoObject is any object which conforms to the NSFNanoObjectProtocol protocol.
109
+
110
+ At its core, a NanoObject is nothing more than a wrapper around two properties:
111
+
112
+ - A dictionary which contains the metadata (provided by the developer)
113
+ - A key (UUID) that identifies the object (provided by NanoStore)
114
+
115
+ The dictionary <i>must</i> be serializable, which means that only the following data types are allowed:
116
+
117
+ - NSArray
118
+ - NSDictionary
119
+ - NSString
120
+ - NSData (*)
121
+ - NSDate
122
+ - NSNumber
123
+
124
+ (*) The data type NSData is allowed, but it will be excluded from the indexing process.
125
+
126
+ To save and retrieve objects from the document store, NanoStore moves the data around by encapsulating it in NanoObjects. In order to store the objects in
127
+ NanoStore the developer has three options:
128
+
129
+ - Use the NSFNanoObject class directly
130
+ - Expand your custom classes by inheriting from NSFNanoObject
131
+ - Expand your custom classes by implementing the NSFNanoObjectProtocol protocol
132
+
133
+ Regardless of the route you decide to take, NanoStore will be able to store and retrieve objects from the document store seamlessly. The beauty of this system is that
134
+ NanoStore returns the object as it was stored, that is, instantiating an object of the class that was originally stored.
135
+
136
+ @note
137
+ If the document store is opened by another application that doesn't implement the object that was stored, NanoStore will instantiate a
138
+ NSFNanoObject instead, thus allowing the app to retrieve the data seamlessly. If the object is then updated by this application, the original
139
+ class name will be honored.
140
+
141
+ <b>Example:</b>
142
+
143
+ - App A stores an object of class <i>Car</i>.
144
+ - App B retrieves the object, but since it doesn't know anything about the class <i>Car</i>, NanoStore returns a NSFNanoObject.
145
+ - App B updates the object, perhaps adding a timestamp or additional information. NanoStore saves it as a <i>Car</i>, not as a NSFNanoObject.
146
+ - App A retrieves the updated object as a <i>Car</i> object, in exactly the same format as it was originally stored.
147
+
148
+ @section typesofdocumentstores Types of Document Stores
149
+
150
+ There are three types of document stores available in NanoStore: in-memory, temporary and file-based. These document stores are defined by the \link NSFGlobals::NSFNanoStoreType NSFNanoStoreType \endlink type:
151
+
152
+ - NSFMemoryStoreType: create the transient backing store in RAM. Its contents are lost when the process exits. Fastest, uses more RAM (*).
153
+ - NSFTemporaryStoreType: create a transient temporary backing store on disk. Its contents are lost when the process exits. Slower, uses less RAM than NSFMemoryStoreType.
154
+ - NSFPersistentStoreType:create a persistant backing store on disk. Slower, uses less RAM than NSFMemoryStoreType (*).
155
+
156
+ @note
157
+ Until the limit set by NSFNanoEngine's \link NSFNanoEngine::cacheSize - (NSUInteger)cacheSize \endlink has been reached, memory usage would be the same for in-memory store and on-disk store. When the size
158
+ of the store grows beyond \link NSFNanoEngine::cacheSize - (NSUInteger)cacheSize \endlink in-memory stores start to consume more memory than on-disk ones, because it has nowhere to push pages out of the cache.
159
+
160
+ Typically, most developers may want to create and open the document store. To do that, use NSFNanoStore's \link createAndOpenStoreWithType:path:error: + (NSFNanoStore *)createAndOpenStoreWithType:(NSFNanoStoreType)theType path:(NSString *)thePath error:(out NSError **)outError \endlink method.
161
+
162
+ @details <b>Example:</b>
163
+ @code
164
+ // Instantiate an in-memory document store and open it. The path parameter is unused.
165
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
166
+
167
+ // Instantiate a temporary document store and open it. The path parameter is unused.
168
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFTemporaryStoreType path:nil error:nil];
169
+
170
+ // Instantiate a file-based document store and open it. The path parameter must be specified.
171
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFPersistentStoreType path:@"~/Desktop/myDatabase.database" error:nil];
172
+ @endcode
173
+
174
+ @note
175
+ In the case of file-based document stores, the file gets created automatically if it doesn't exist and then opened. If it already exists, it gets opened and made available for use right away.
176
+
177
+ There are instances where you may want to fine-tune the engine. Tunning the engine has to be performed before the document store is opened. Another method is available In NSFNanoStore for this
178
+ purpose: \link createStoreWithType:path: + (NSFNanoStore *)createStoreWithType:(NSFNanoStoreType)theType path:(NSString *)thePath \endlink.
179
+
180
+ @details <b>Example:</b>
181
+ @code
182
+ // Instantiate a file-based document store but don't open it right away. The path parameter must be specified.
183
+ NSFNanoStore *nanoStore = [NSFNanoStore createStoreWithType:NSFPersistentStoreType path:@"~/Desktop/myDatabase.database" error:nil];
184
+
185
+ // Obtain the engine
186
+ NSFNanoEngine *nanoStoreEngine = [nanoStore nanoStoreEngine];
187
+
188
+ // Set the synchronous mode setting
189
+ [nanoStoreEngine setSynchronousMode:SynchronousModeOff];
190
+ [nanoStoreEngine setEncodingType:NSFEncodingUTF16];
191
+
192
+ // Open the document store
193
+ [nanoStore openWithError:nil];
194
+ @endcode
195
+
196
+ @note
197
+ Check the section Performance Tips below for important information about how to get the most out of NanoStore.
198
+
199
+ @section workingwithnanoobject_sec Working with a NanoObject
200
+
201
+ There are three basic operations that NanoStore can perform with a NanoObject:
202
+
203
+ - Add it to the document store
204
+ - Update an existing object in the document store
205
+ - Remove it from the document store
206
+
207
+ To add an object, instantiate a \link NSFNanoObject::nanoObject NanoObject, \endlink populate it and add it to the document store.
208
+
209
+ @details <b>Example:</b>
210
+ @code
211
+ // Instantiate a NanoStore and open it
212
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
213
+
214
+ // Generate an empty NanoObject
215
+ NSFNanoObject *object = [NSFNanoObject nanoObject];
216
+
217
+ // Add some data
218
+ [object setObject:@"Doe" forKey:@"kLastName"];
219
+ [object setObject:@"John" forKey:@"kFirstName"];
220
+ [object setObject:[NSArray arrayWithObjects:@"jdoe@foo.com", @"jdoe@bar.com", nil] forKey:@"kEmails"];
221
+
222
+ // Add it to the document store
223
+ [nanoStore addObject:object error:nil];
224
+
225
+ // Close the document store
226
+ [nanoStore closeWithError:nil];
227
+ @endcode
228
+
229
+ Alternatively, you can instantiate a \link NSFNanoObject::nanoObject NanoObject \endlink providing a dictionary via \link NSFNanoObject::nanoObjectWithDictionary: + (NSFNanoObject*)nanoObjectWithDictionary:(NSDictionary *)theDictionary. \endlink
230
+ NanoStore will assign a UUID automatically when the \link NSFNanoObject::nanoObjectWithDictionary: NanoObject \endlink
231
+ is instantiated. This means that requesting the key from the \link NSFNanoObject::nanoObjectWithDictionary: NanoObject \endlink will return a valid UUID.
232
+ The same holds true for objects that inherit from NSFNanoObject. However, classes that implement the NSFNanoObjectProtocol protocol should
233
+ make sure they return a valid key via \link NSFNanoObjectProtocol::nanoObjectKey - (NSString *)nanoObjectKey \endlink
234
+
235
+ @warning
236
+ If an attempt is made to add or remove an object without a valid key, an exception of type \ref NSFGlobals::NSFNanoObjectBehaviorException
237
+ "NSFNanoObjectBehaviorException" will be raised.
238
+
239
+ To update an object, simply modify the object and add it to the document store. NanoStore will replace the existing object with the one being added.
240
+
241
+ @details <b>Example:</b>
242
+ @code
243
+ // Instantiate and open a NanoStore
244
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
245
+
246
+ // Assuming the dictionary exists, instantiate a NanoObject
247
+ NSDictionary *info = ...;
248
+ NSFNanoObject *object = [NSFNanoObject nanoObjectWithDictionary:info];
249
+
250
+ // Add the NanoObject to the document store
251
+ [nanoStore addObject:object error:nil];
252
+
253
+ // Update the NanoObject with new data
254
+ [object setObject:@"foo" forKey:@"SomeKey"];
255
+
256
+ // Update the NanoObject in the document store
257
+ [nanoStore addObject:object error:nil];
258
+ @endcode
259
+
260
+ To remove an object, there are several options available. The most common methods are found in NSFNanoStore:
261
+
262
+ - \link NSFNanoStore::removeObject:error: - (BOOL)removeObject:(id <NSFNanoObjectProtocol>)theObject error:(out NSError **)outError \endlink
263
+ - \link NSFNanoStore::removeObjectsWithKeysInArray:error: - (BOOL)removeObjectsWithKeysInArray:(NSArray *)theKeys error:(out NSError **)outError \endlink
264
+ - \link NSFNanoStore::removeObjectsInArray:error: - (BOOL)removeObjectsInArray:(NSArray *)theObjects error:(out NSError **)outError \endlink
265
+
266
+ @details <b>Example:</b>
267
+ @code
268
+ // Instantiate and open a NanoStore
269
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
270
+
271
+ // Assuming the dictionary exists, instantiate a NanoObject
272
+ NSDictionary *info = ...;
273
+ NSFNanoObject *object = [NSFNanoObject nanoObjectWithDictionary:info];
274
+
275
+ // Add the NanoObject to the document store
276
+ [nanoStore addObject:object error:nil];
277
+
278
+ // Remove the object
279
+ [nanoStore removeObject:object error:nil];
280
+
281
+ // ... or you could pass the key instead
282
+ [nanoStore removeObjectsWithKeysInArray:[NSArray arrayWithObject:[object nanoObjectKey]] error:nil];
283
+ @endcode
284
+
285
+ @section notaflatworld_sec It's not a flat World
286
+
287
+ Most database solutions force the developer to think in a two-dimensional space (rows and columns), forcing the developer to plan the schema ahead of
288
+ time. This situation is not ideal because in most cases schema refinements could be required, oftentimes impacting the code as well.
289
+
290
+ NanoStore goes beyond that allowing the developer to store objects in their natural form. These objects must conform to the NSFNanoObjectProtocol
291
+ protocol, providing NanoStore with the NSDictionary that will be stored. By using a dictionary data can be inspected very quickly, and it also allows the
292
+ structure to be defined in a hierarchical fashion as well, due to the fact that it includes support for nested collections (of type NSDictionary and NSArray.)
293
+ Each inner-object is indexed automatically, thus allowing to quickly find objects which contain a specific key and/or value.
294
+
295
+ By default, NanoStore allows objects to be stored without any sense of relationship to other objects. This simple format, while powerful, is limited because
296
+ the developer has to keep track of the relationships among objects. Some applications may need to relate objects, some of them perhaps of different nature or class
297
+ type. This is exactly what NanoBag (represented by the NSFNanoBag class) does: it allows any object conforming to the NSFNanoObjectProtocol protocol to be
298
+ added to the bag. By saving the bag with one single call, the new and/or modified are taken care of seamlessly.
299
+
300
+ The NSFNanoBag API is rich, allowing the developer to add, remove, reload and undo its changes, deflate it (thus saving memory) and inflate it whenever it's
301
+ required. In addition, it provides methods to obtain all bags, specific bags matching some keys, and bags containing a specific object
302
+ (see NSFNanoStore for more information).
303
+
304
+ @section wherearetheobjects_sec Where are my objects?
305
+
306
+ While NSFNanoStore provides some convenience methods to obtain standard objects such as bags, the bulk of the search mechanism is handled by NSFNanoSearch.
307
+ The steps involved to perform a search are quite simple:
308
+
309
+ - 1) Instantiate a search object
310
+ - 2) Configure the search via its accessors
311
+ - 3) Obtain the results specifying whether objects or keys should be returned (*)
312
+
313
+ (*) If introspecting the data is needed, request objects. You should request keys if you need to feed the result to another method, such as NSFNanoStore
314
+ \link NSFNanoStore::removeObjectsWithKeysInArray:error: -(BOOL)removeObjectsWithKeysInArray:(NSArray *)theKeys error:(out NSError **)outError \endlink method.
315
+
316
+ @details <b>Example: finding all objects with the attribute 'LastName' and value 'Doe'.</b>
317
+ @code
318
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:nanoStore];
319
+
320
+ search.attribute = @"LastName";
321
+ search.match = NSFEqualTo;
322
+ search.value = @"Doe";
323
+
324
+ // Returns a dictionary with the UUID of the object (key) and the NanoObject (value).
325
+ NSDictionary *searchResults = [search searchObjectsWithReturnType:NSFReturnObjects error:nil];
326
+ @endcode
327
+
328
+ @details <b>Example: removing all objects with the attribute 'LastName' and value 'Doe'.</b>
329
+ @code
330
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:nanoStore];
331
+
332
+ search.attribute = @"LastName";
333
+ search.match = NSFEqualTo;
334
+ search.value = @"Doe";
335
+
336
+ // Returns an array of matching UUIDs
337
+ NSArray *matchingKeys = [search searchObjectsWithReturnType:NSFReturnKeys error:nil];
338
+
339
+ // Remove the NanoObjects matching the selected UUIDs
340
+ NSError *outError = nil;
341
+ if (YES == [nanoStore removeObjectsWithKeysInArray:matchingKeys error:&outError]) {
342
+ NSLog(@"The matching objects have been removed.");
343
+ } else {
344
+ NSLog(@"An error has occurred while removing the matching objects. Reason: %@", [outError localizedDescription]);
345
+ }
346
+ @endcode
347
+
348
+ Another cool feature is the possibility to invoke aggregated functions (count, avg, min, max and total) on the search results. Using the search snippet above,
349
+ calculating the average salary of all people with last name equal to 'Doe' is very easy.
350
+
351
+ @details <b>Example: calculating the average salary of all objects with the attribute 'LastName' and value 'Doe'.</b>
352
+ @code
353
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:nanoStore];
354
+
355
+ search.attribute = @"LastName";
356
+ search.match = NSFEqualTo;
357
+ search.value = @"Doe";
358
+
359
+ float averageSalary = [[search aggregateOperation:NSFAverage onAttribute:@"Salary"]floatValue];
360
+ @endcode
361
+
362
+ @section sorting_sec Sorting
363
+
364
+ Combining search and sort is an extremely easy operation. There are two simple parts:
365
+
366
+ - 1) Preparing your classes for sorting
367
+ - 2) Setup a search operation and set its sort descriptors
368
+
369
+ @section preparesorting_sec Preparing your classes for sorting
370
+
371
+ Since NanoStore relies on KVC to perform the sorts, a hint of the location where the data lives within the object is required. Since KVC uses a key path to reach the element being sorted, we need a way to "point" to it. Most custom classes will return <i>self</i>, as is the case for NSFNanoBag:
372
+
373
+ @code
374
+ - (id)rootObject
375
+ {
376
+ return self;
377
+ }
378
+ @endcode
379
+
380
+ <i>Self</i> in this case represents the top level, the location where the variables <i>name</i>, <i>key</i> and <i>hasUnsavedChanges</i> are located:
381
+
382
+ @code
383
+ @interface NSFNanoBag : NSObject <NSFNanoObjectProtocol, NSCopying>
384
+ {
385
+ NSFNanoStore *store;
386
+ NSString *name;
387
+ NSString *key;
388
+ BOOL hasUnsavedChanges;
389
+ }
390
+ @endcode
391
+
392
+ Assume we have an object that represents a person and its root object is set to <i>self</i>, just as demonstrated above:
393
+
394
+ @code
395
+ @interface Person : NSFNanoObject
396
+ {
397
+ NSString *firstName;
398
+ NSString *lastName;
399
+ NSString *email;
400
+ }
401
+ @endcode
402
+
403
+ If we wanted to retrieve all the existing people with <i>firstName</i> equal to <i>John</i> sorted by <i>lastName</i> we would do the following:
404
+
405
+ @code
406
+ // Assume NanoStore has been opened elsewhere
407
+ NSFNanoStore *nanoStore = ...;
408
+
409
+ // Prepare the search
410
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:nanoStore];
411
+ search.attribute = @"firstName";
412
+ search.match = NSFEqualTo;
413
+ search.value = @"John";
414
+
415
+ // Prepare and set the sort descriptor
416
+ NSFNanoSortDescriptor *sortByLastName = [[NSFNanoSortDescriptor alloc]initWithAttribute:@"lastName" ascending:YES];
417
+ search.sort = [NSArray arrayWithObject:sortByLastName];
418
+
419
+ // Perform the search
420
+ NSArray *searchResults = [search searchObjectsWithReturnType:NSFReturnObjects error:nil];
421
+
422
+ // Cleanup
423
+ [sortByLastName release];
424
+ @endcode
425
+
426
+ @section performancetips_sec Performance Tips
427
+
428
+ NanoStore by defaults saves every object to disk one by one. To speed up inserts and edited objects, increase NSFNanoStore's \link NSFNanoStore::saveInterval saveInterval \endlink property.
429
+
430
+ @details <b>Example:</b>
431
+ @code
432
+ // Instantiate and open a NanoStore
433
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
434
+
435
+ // Increase the save interval
436
+ [nanoStore setSaveInterval:1000];
437
+
438
+ // Do a bunch of inserts and/or edits
439
+
440
+ // Don't forget that some objects could be lingering in memory. Force a save.
441
+ [nanoStore saveStoreAndReturnError:nil];
442
+ @endcode
443
+
444
+ @note If you set the saveInterval value to anything other one, keep in mind that some objects may still be left unsaved after being added or modified. To make sure they're saved properly, call \link NSFNanoStore::saveStoreAndReturnError: - (BOOL)saveStoreAndReturnError:(out NSError **)outError \endlink.
445
+
446
+ Choosing a good saveInterval value is more art than science. While testing NanoStore using a medium-sized dictionary (iTunes' MP3 dictionary) setting saveInterval to 1000 resulted in the best performance. You may want to test with different numbers and fine-tune it for your data set.
447
+
448
+ @warning Setting saveInterval to a large number could result in decreased performance because SQLite's would have to spend more time reading the journal file and writing the changes to the database.
449
+
450
+ @section needhelp_sec Need more help?
451
+ There are two quick ways to find answers: reading the documentation and browsing the Unit tests.
452
+
453
+ While several attempts have been made to make the documentation easy to read and understand, it's far from perfect. If you find that the documentation is
454
+ incomplete, incorrect or needs some clarification, please file a bug. I'll appreciate it and correct it as soon as possible:
455
+
456
+ - NanoStore Documentation: http://dl.dropbox.com/u/2601212/NanoStore%202.0/html/index.html
457
+ - NanoStore Bug Tracker: https://github.com/tciuro/NanoStore/issues
458
+ - Twitter: http://twitter.com/nanostoredev
459
+
460
+ @section officialsourcerepo_sec Official Source Repository
461
+ The official repository for NanoStore is hosted on GitHub: https://github.com/tciuro/NanoStore
462
+
463
+ */
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2010, Tito Ciuro, Webbo, L.L.C. All rights reserved.
2
+ Redistribution and use in source and binary forms, with or without
3
+ modification, are permitted provided that the following conditions are met:
4
+
5
+ * Redistributions of source code must retain the above copyright notice, this
6
+ list of conditions and the following disclaimer.
7
+ * Redistributions in binary form must reproduce the above copyright notice,
8
+ this list of conditions and the following disclaimer in the documentation
9
+ and/or other materials provided with the distribution.
10
+ * Neither the name of Tito Ciuro, Webbo, L.L.C. nor the names of its
11
+ contributors may be used to endorse or promote products derived from this
12
+ software without specific prior written permission.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22
+ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
24
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25
+ DAMAGE.