motion-yapper 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.lock +63 -0
  6. data/README.md +16 -0
  7. data/Rakefile +20 -0
  8. data/app/app_delegate.rb +5 -0
  9. data/lib/yapper.rb +30 -0
  10. data/lib/yapper/attachment.rb +48 -0
  11. data/lib/yapper/bson.rb +20 -0
  12. data/lib/yapper/config.rb +18 -0
  13. data/lib/yapper/db.rb +151 -0
  14. data/lib/yapper/document.rb +54 -0
  15. data/lib/yapper/document/attachment.rb +26 -0
  16. data/lib/yapper/document/callbacks.rb +86 -0
  17. data/lib/yapper/document/persistance.rb +171 -0
  18. data/lib/yapper/document/relation.rb +84 -0
  19. data/lib/yapper/document/selection.rb +100 -0
  20. data/lib/yapper/extensions.rb +80 -0
  21. data/lib/yapper/log.rb +5 -0
  22. data/lib/yapper/sync.rb +134 -0
  23. data/lib/yapper/sync/data.rb +12 -0
  24. data/lib/yapper/sync/event.rb +194 -0
  25. data/lib/yapper/sync/queue.rb +164 -0
  26. data/lib/yapper/timestamps.rb +16 -0
  27. data/lib/yapper/version.rb +3 -0
  28. data/lib/yapper/yapper.rb +2 -0
  29. data/spec/helpers/time_helper.rb +3 -0
  30. data/spec/integration/all_spec.rb +40 -0
  31. data/spec/integration/callback_spec.rb +87 -0
  32. data/spec/integration/db_spec.rb +40 -0
  33. data/spec/integration/find_spec.rb +51 -0
  34. data/spec/integration/persistance_spec.rb +118 -0
  35. data/spec/integration/relation_spec.rb +174 -0
  36. data/spec/integration/sync_spec.rb +42 -0
  37. data/spec/integration/timestamps_spec.rb +34 -0
  38. data/spec/integration/types_spec.rb +23 -0
  39. data/spec/integration/when_spec.rb +29 -0
  40. data/spec/integration/where_spec.rb +132 -0
  41. data/vendor/Podfile.lock +24 -0
  42. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.h +641 -0
  43. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.m +1396 -0
  44. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h +133 -0
  45. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m +327 -0
  46. data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.h +113 -0
  47. data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.m +321 -0
  48. data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.h +71 -0
  49. data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.m +150 -0
  50. data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  51. data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.m +157 -0
  52. data/vendor/Pods/AFNetworking/AFNetworking/AFNetworking.h +43 -0
  53. data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  54. data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.m +143 -0
  55. data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h +370 -0
  56. data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m +848 -0
  57. data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.h +89 -0
  58. data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.m +167 -0
  59. data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.h +78 -0
  60. data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.m +191 -0
  61. data/vendor/Pods/AFNetworking/LICENSE +19 -0
  62. data/vendor/Pods/AFNetworking/README.md +208 -0
  63. data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPClient.h +641 -0
  64. data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPRequestOperation.h +133 -0
  65. data/vendor/Pods/BuildHeaders/AFNetworking/AFImageRequestOperation.h +113 -0
  66. data/vendor/Pods/BuildHeaders/AFNetworking/AFJSONRequestOperation.h +71 -0
  67. data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  68. data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworking.h +43 -0
  69. data/vendor/Pods/BuildHeaders/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  70. data/vendor/Pods/BuildHeaders/AFNetworking/AFURLConnectionOperation.h +370 -0
  71. data/vendor/Pods/BuildHeaders/AFNetworking/AFXMLRequestOperation.h +89 -0
  72. data/vendor/Pods/BuildHeaders/AFNetworking/UIImageView+AFNetworking.h +78 -0
  73. data/vendor/Pods/BuildHeaders/CocoaLumberjack/ContextFilterLogFormatter.h +65 -0
  74. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDASLLogger.h +41 -0
  75. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
  76. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDFileLogger.h +334 -0
  77. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog.h +601 -0
  78. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDTTYLogger.h +167 -0
  79. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DispatchQueueLogFormatter.h +116 -0
  80. data/vendor/Pods/BuildHeaders/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
  81. data/vendor/Pods/BuildHeaders/Reachability/Reachability.h +109 -0
  82. data/vendor/Pods/BuildHeaders/YapDatabase/YapCache.h +90 -0
  83. data/vendor/Pods/BuildHeaders/YapDatabase/YapCollectionKey.h +20 -0
  84. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabase.h +547 -0
  85. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnection.h +447 -0
  86. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnectionState.h +29 -0
  87. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseDefaults.h +37 -0
  88. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtension.h +15 -0
  89. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionConnection.h +11 -0
  90. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionPrivate.h +440 -0
  91. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionTransaction.h +11 -0
  92. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredView.h +108 -0
  93. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewConnection.h +12 -0
  94. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewPrivate.h +19 -0
  95. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTransaction.h +39 -0
  96. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearch.h +89 -0
  97. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchConnection.h +32 -0
  98. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchPrivate.h +69 -0
  99. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
  100. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchTransaction.h +68 -0
  101. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseLogging.h +158 -0
  102. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseManager.h +17 -0
  103. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabasePrivate.h +424 -0
  104. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseQuery.h +42 -0
  105. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndex.h +100 -0
  106. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexConnection.h +33 -0
  107. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +73 -0
  108. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetup.h +33 -0
  109. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +58 -0
  110. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseStatement.h +13 -0
  111. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseString.h +121 -0
  112. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseTransaction.h +541 -0
  113. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseView.h +186 -0
  114. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChange.h +272 -0
  115. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChangePrivate.h +94 -0
  116. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewConnection.h +115 -0
  117. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappings.h +825 -0
  118. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappingsPrivate.h +72 -0
  119. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewOptions.h +56 -0
  120. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPage.h +36 -0
  121. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPageMetadata.h +27 -0
  122. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPrivate.h +153 -0
  123. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptions.h +330 -0
  124. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +17 -0
  125. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTransaction.h +447 -0
  126. data/vendor/Pods/BuildHeaders/YapDatabase/YapMemoryTable.h +74 -0
  127. data/vendor/Pods/BuildHeaders/YapDatabase/YapNull.h +17 -0
  128. data/vendor/Pods/BuildHeaders/YapDatabase/YapSet.h +41 -0
  129. data/vendor/Pods/BuildHeaders/YapDatabase/YapTouch.h +15 -0
  130. data/vendor/Pods/CocoaLumberjack/LICENSE.txt +18 -0
  131. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.h +41 -0
  132. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.m +99 -0
  133. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.h +102 -0
  134. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.m +727 -0
  135. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.h +334 -0
  136. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.m +1353 -0
  137. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.h +601 -0
  138. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.m +1083 -0
  139. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.h +167 -0
  140. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.m +1479 -0
  141. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.h +65 -0
  142. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.m +191 -0
  143. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.h +116 -0
  144. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.m +251 -0
  145. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/README.txt +7 -0
  146. data/vendor/Pods/CocoaLumberjack/README.markdown +37 -0
  147. data/vendor/Pods/Headers/AFNetworking/AFHTTPClient.h +641 -0
  148. data/vendor/Pods/Headers/AFNetworking/AFHTTPRequestOperation.h +133 -0
  149. data/vendor/Pods/Headers/AFNetworking/AFImageRequestOperation.h +113 -0
  150. data/vendor/Pods/Headers/AFNetworking/AFJSONRequestOperation.h +71 -0
  151. data/vendor/Pods/Headers/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  152. data/vendor/Pods/Headers/AFNetworking/AFNetworking.h +43 -0
  153. data/vendor/Pods/Headers/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  154. data/vendor/Pods/Headers/AFNetworking/AFURLConnectionOperation.h +370 -0
  155. data/vendor/Pods/Headers/AFNetworking/AFXMLRequestOperation.h +89 -0
  156. data/vendor/Pods/Headers/AFNetworking/UIImageView+AFNetworking.h +78 -0
  157. data/vendor/Pods/Headers/CocoaLumberjack/ContextFilterLogFormatter.h +65 -0
  158. data/vendor/Pods/Headers/CocoaLumberjack/DDASLLogger.h +41 -0
  159. data/vendor/Pods/Headers/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
  160. data/vendor/Pods/Headers/CocoaLumberjack/DDFileLogger.h +334 -0
  161. data/vendor/Pods/Headers/CocoaLumberjack/DDLog.h +601 -0
  162. data/vendor/Pods/Headers/CocoaLumberjack/DDTTYLogger.h +167 -0
  163. data/vendor/Pods/Headers/CocoaLumberjack/DispatchQueueLogFormatter.h +116 -0
  164. data/vendor/Pods/Headers/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
  165. data/vendor/Pods/Headers/Reachability/Reachability.h +109 -0
  166. data/vendor/Pods/Headers/YapDatabase/YapCache.h +90 -0
  167. data/vendor/Pods/Headers/YapDatabase/YapCollectionKey.h +20 -0
  168. data/vendor/Pods/Headers/YapDatabase/YapDatabase.h +547 -0
  169. data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnection.h +447 -0
  170. data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnectionState.h +29 -0
  171. data/vendor/Pods/Headers/YapDatabase/YapDatabaseDefaults.h +37 -0
  172. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtension.h +15 -0
  173. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionConnection.h +11 -0
  174. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionPrivate.h +440 -0
  175. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionTransaction.h +11 -0
  176. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredView.h +108 -0
  177. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewConnection.h +12 -0
  178. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewPrivate.h +19 -0
  179. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTransaction.h +39 -0
  180. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearch.h +89 -0
  181. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchConnection.h +32 -0
  182. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchPrivate.h +69 -0
  183. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
  184. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchTransaction.h +68 -0
  185. data/vendor/Pods/Headers/YapDatabase/YapDatabaseLogging.h +158 -0
  186. data/vendor/Pods/Headers/YapDatabase/YapDatabaseManager.h +17 -0
  187. data/vendor/Pods/Headers/YapDatabase/YapDatabasePrivate.h +424 -0
  188. data/vendor/Pods/Headers/YapDatabase/YapDatabaseQuery.h +42 -0
  189. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndex.h +100 -0
  190. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexConnection.h +33 -0
  191. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +73 -0
  192. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexSetup.h +33 -0
  193. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +58 -0
  194. data/vendor/Pods/Headers/YapDatabase/YapDatabaseStatement.h +13 -0
  195. data/vendor/Pods/Headers/YapDatabase/YapDatabaseString.h +121 -0
  196. data/vendor/Pods/Headers/YapDatabase/YapDatabaseTransaction.h +541 -0
  197. data/vendor/Pods/Headers/YapDatabase/YapDatabaseView.h +186 -0
  198. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChange.h +272 -0
  199. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChangePrivate.h +94 -0
  200. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewConnection.h +115 -0
  201. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappings.h +825 -0
  202. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappingsPrivate.h +72 -0
  203. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewOptions.h +56 -0
  204. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPage.h +36 -0
  205. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPageMetadata.h +27 -0
  206. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPrivate.h +153 -0
  207. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptions.h +330 -0
  208. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +17 -0
  209. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTransaction.h +447 -0
  210. data/vendor/Pods/Headers/YapDatabase/YapMemoryTable.h +74 -0
  211. data/vendor/Pods/Headers/YapDatabase/YapNull.h +17 -0
  212. data/vendor/Pods/Headers/YapDatabase/YapSet.h +41 -0
  213. data/vendor/Pods/Headers/YapDatabase/YapTouch.h +15 -0
  214. data/vendor/Pods/Headers/____Pods-AFNetworking-prefix.h +17 -0
  215. data/vendor/Pods/Headers/____Pods-CocoaLumberjack-prefix.h +5 -0
  216. data/vendor/Pods/Headers/____Pods-NSData+MD5Digest-prefix.h +5 -0
  217. data/vendor/Pods/Headers/____Pods-Reachability-prefix.h +5 -0
  218. data/vendor/Pods/Headers/____Pods-YapDatabase-prefix.h +5 -0
  219. data/vendor/Pods/Headers/____Pods-environment.h +38 -0
  220. data/vendor/Pods/Manifest.lock +24 -0
  221. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
  222. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.m +39 -0
  223. data/vendor/Pods/NSData+MD5Digest/README.md +11 -0
  224. data/vendor/Pods/Pods-AFNetworking-Private.xcconfig +5 -0
  225. data/vendor/Pods/Pods-AFNetworking-dummy.m +5 -0
  226. data/vendor/Pods/Pods-AFNetworking-prefix.pch +17 -0
  227. data/vendor/Pods/Pods-AFNetworking.xcconfig +1 -0
  228. data/vendor/Pods/Pods-Acknowledgements.markdown +96 -0
  229. data/vendor/Pods/Pods-Acknowledgements.plist +142 -0
  230. data/vendor/Pods/Pods-CocoaLumberjack-Private.xcconfig +5 -0
  231. data/vendor/Pods/Pods-CocoaLumberjack-dummy.m +5 -0
  232. data/vendor/Pods/Pods-CocoaLumberjack-prefix.pch +5 -0
  233. data/vendor/Pods/Pods-CocoaLumberjack.xcconfig +0 -0
  234. data/vendor/Pods/Pods-NSData+MD5Digest-Private.xcconfig +5 -0
  235. data/vendor/Pods/Pods-NSData+MD5Digest-dummy.m +5 -0
  236. data/vendor/Pods/Pods-NSData+MD5Digest-prefix.pch +5 -0
  237. data/vendor/Pods/Pods-NSData+MD5Digest.xcconfig +0 -0
  238. data/vendor/Pods/Pods-Reachability-Private.xcconfig +5 -0
  239. data/vendor/Pods/Pods-Reachability-dummy.m +5 -0
  240. data/vendor/Pods/Pods-Reachability-prefix.pch +5 -0
  241. data/vendor/Pods/Pods-Reachability.xcconfig +1 -0
  242. data/vendor/Pods/Pods-YapDatabase-Private.xcconfig +5 -0
  243. data/vendor/Pods/Pods-YapDatabase-dummy.m +5 -0
  244. data/vendor/Pods/Pods-YapDatabase-prefix.pch +5 -0
  245. data/vendor/Pods/Pods-YapDatabase.xcconfig +1 -0
  246. data/vendor/Pods/Pods-dummy.m +5 -0
  247. data/vendor/Pods/Pods-environment.h +38 -0
  248. data/vendor/Pods/Pods-resources.sh +68 -0
  249. data/vendor/Pods/Pods.bridgesupport +5096 -0
  250. data/vendor/Pods/Pods.xcconfig +5 -0
  251. data/vendor/Pods/Pods.xcodeproj/project.pbxproj +5536 -0
  252. data/vendor/Pods/Reachability/LICENCE.txt +24 -0
  253. data/vendor/Pods/Reachability/README.md +65 -0
  254. data/vendor/Pods/Reachability/Reachability.h +109 -0
  255. data/vendor/Pods/Reachability/Reachability.m +527 -0
  256. data/vendor/Pods/YapDatabase/LICENSE.txt +18 -0
  257. data/vendor/Pods/YapDatabase/README.md +30 -0
  258. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +19 -0
  259. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +108 -0
  260. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +175 -0
  261. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h +12 -0
  262. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m +41 -0
  263. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +39 -0
  264. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +966 -0
  265. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +69 -0
  266. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h +89 -0
  267. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m +146 -0
  268. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h +32 -0
  269. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +298 -0
  270. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
  271. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m +95 -0
  272. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h +68 -0
  273. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +1352 -0
  274. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +440 -0
  275. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.h +15 -0
  276. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +58 -0
  277. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h +11 -0
  278. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m +46 -0
  279. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h +11 -0
  280. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +180 -0
  281. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +73 -0
  282. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +100 -0
  283. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +149 -0
  284. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h +33 -0
  285. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +330 -0
  286. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h +33 -0
  287. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m +184 -0
  288. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h +58 -0
  289. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +1166 -0
  290. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h +94 -0
  291. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h +72 -0
  292. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h +36 -0
  293. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm +296 -0
  294. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h +27 -0
  295. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m +28 -0
  296. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +153 -0
  297. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h +17 -0
  298. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +272 -0
  299. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +2494 -0
  300. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +825 -0
  301. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +1567 -0
  302. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h +330 -0
  303. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m +141 -0
  304. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +186 -0
  305. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +191 -0
  306. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +115 -0
  307. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +897 -0
  308. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +56 -0
  309. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m +27 -0
  310. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +447 -0
  311. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +4505 -0
  312. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +90 -0
  313. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +453 -0
  314. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.h +29 -0
  315. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.m +48 -0
  316. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.h +37 -0
  317. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.m +83 -0
  318. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.h +158 -0
  319. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.m +73 -0
  320. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.h +17 -0
  321. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.m +56 -0
  322. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +424 -0
  323. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.h +13 -0
  324. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.m +26 -0
  325. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseString.h +121 -0
  326. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.h +74 -0
  327. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.m +603 -0
  328. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.h +17 -0
  329. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.m +31 -0
  330. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.h +15 -0
  331. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.m +31 -0
  332. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.h +20 -0
  333. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +194 -0
  334. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h +42 -0
  335. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m +96 -0
  336. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h +41 -0
  337. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.m +82 -0
  338. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.h +547 -0
  339. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.m +2022 -0
  340. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +447 -0
  341. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +3874 -0
  342. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +541 -0
  343. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +5282 -0
  344. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.bridgesupport +16 -0
  345. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.h +13 -0
  346. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.m +20 -0
  347. data/yapper.gemspec +24 -0
  348. metadata +458 -0
@@ -0,0 +1,79 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ /**
4
+ * This class represents options that may be passed to the FTS snippet function.
5
+ *
6
+ * It correlates with the snippet funtion arguments as defined in sqlite's FTS module:
7
+ * http://www.sqlite.org/fts3.html#section_4_2
8
+ *
9
+ * For example, if you were searching for the word "favorite",
10
+ * then a returned snippet may look something like this:
11
+ *
12
+ * <b>...</b>one of my <b>favorite</b> cheese pairings is<b>...</b>
13
+ **/
14
+ @interface YapDatabaseFullTextSearchSnippetOptions : NSObject <NSCopying>
15
+
16
+
17
+ + (NSString *)defaultStartMatchText; // @"<b>"
18
+ + (NSString *)defaultEndMatchText; // @"</b>"
19
+ + (NSString *)defaultEllipsesText; // @"..."
20
+
21
+ + (int)defaultNumberOfTokens; // 15
22
+
23
+ - (id)init;
24
+
25
+ /**
26
+ * The startMatchText is inserted before matched terms/phrases, and also before injected ellipses text.
27
+ * It is used to mark the beginning of special text within the snippet.
28
+ *
29
+ * If not set, it will be the defaultStartMatchText: @"<b>"
30
+ *
31
+ * @see defaultStartMatchText
32
+ **/
33
+ @property (nonatomic, copy) NSString *startMatchText;
34
+
35
+ /**
36
+ * The endMatchText is inserted after matched terms/phrases, and also after injected ellipses text.
37
+ * It is used to mark the end of special text within the snippet.
38
+ *
39
+ * If not set, it will be the defaultEndMatchText: @"</b>"
40
+ *
41
+ * @see defaultEndMatchText
42
+ **/
43
+ @property (nonatomic, copy) NSString *endMatchText;
44
+
45
+ /**
46
+ * If the full text from the column is too big, the snippets will be a small subsection of the snippet,
47
+ * centered on matching terms/phrases. When this occurs, and the snippet is truncated on the left and/or right,
48
+ * then the ellipsesText will be inserted on the left and/or right.
49
+ *
50
+ * If not set, it will be the defaultEllipsesText: @"…"
51
+ *
52
+ * @see defaultEllipsesText
53
+ * @see numberOfTokens
54
+ **/
55
+ @property (nonatomic, copy) NSString *ellipsesText;
56
+
57
+ /**
58
+ * The column name from which to extract the returned fragments of text from.
59
+ * If nil, then the text may be extracted from any column.
60
+ *
61
+ * If not set, the default value is nil.
62
+ **/
63
+ @property (nonatomic, copy) NSString *columnName;
64
+
65
+ /**
66
+ * The numberOfTokens is used as the (approximate) number of tokens to include in the returned snippet text value.
67
+ *
68
+ * If not set, it will be defaultNumberOfTokens: 15
69
+ *
70
+ * Setting this to a value of zero resets the value to the default.
71
+ * Negative values are allowed, as the snippet function automatically uses the absolute value.
72
+ *
73
+ * The maximum allowable absolute value is 64.
74
+ *
75
+ * @see defaultNumberOfTokens
76
+ **/
77
+ @property (nonatomic, assign) int numberOfTokens;
78
+
79
+ @end
@@ -0,0 +1,95 @@
1
+ #import "YapDatabaseFullTextSearchSnippetOptions.h"
2
+
3
+
4
+ @implementation YapDatabaseFullTextSearchSnippetOptions
5
+
6
+ + (NSString *)defaultStartMatchText {
7
+ return @"<b>";
8
+ }
9
+
10
+ + (NSString *)defaultEndMatchText {
11
+ return @"</b>";
12
+ }
13
+
14
+ + (NSString *)defaultEllipsesText {
15
+ return @"...";
16
+ }
17
+
18
+ + (int)defaultNumberOfTokens {
19
+ return 15;
20
+ }
21
+
22
+ @synthesize startMatchText = startMatchText;
23
+ @synthesize endMatchText = endMatchText;
24
+ @synthesize ellipsesText = ellipsesText;
25
+ @synthesize columnName = columnName;
26
+ @synthesize numberOfTokens = numberOfTokens;
27
+
28
+ - (id)init
29
+ {
30
+ if ((self = [super init]))
31
+ {
32
+ startMatchText = [[self class] defaultStartMatchText];
33
+ endMatchText = [[self class] defaultEndMatchText];
34
+ ellipsesText = [[self class] defaultEllipsesText];
35
+
36
+ numberOfTokens = [[self class] defaultNumberOfTokens];
37
+ }
38
+ return self;
39
+ }
40
+
41
+ - (id)initForCopy
42
+ {
43
+ if ((self = [super init]))
44
+ {
45
+ // copyWithZone will fill out values for us
46
+ }
47
+ return self;
48
+ }
49
+
50
+ - (id)copyWithZone:(NSZone *)zone
51
+ {
52
+ YapDatabaseFullTextSearchSnippetOptions *copy = [[YapDatabaseFullTextSearchSnippetOptions alloc] initForCopy];
53
+
54
+ copy->startMatchText = startMatchText;
55
+ copy->endMatchText = endMatchText;
56
+ copy->ellipsesText = ellipsesText;
57
+ copy->columnName = columnName;
58
+ copy->numberOfTokens = numberOfTokens;
59
+
60
+ return copy;
61
+ }
62
+
63
+ - (void)setStartMatchText:(NSString *)text
64
+ {
65
+ if (text)
66
+ startMatchText = [text copy];
67
+ else
68
+ startMatchText = [[self class] defaultStartMatchText];
69
+ }
70
+
71
+ - (void)setEndMatchText:(NSString *)text
72
+ {
73
+ if (text)
74
+ endMatchText = [text copy];
75
+ else
76
+ endMatchText = [[self class] defaultEndMatchText];
77
+ }
78
+
79
+ - (void)setEllipsesText:(NSString *)text
80
+ {
81
+ if (text)
82
+ ellipsesText = [text copy];
83
+ else
84
+ ellipsesText = [[self class] defaultEllipsesText];
85
+ }
86
+
87
+ - (void)setNumberOfTokens:(int)count
88
+ {
89
+ if (count != 0)
90
+ numberOfTokens = count;
91
+ else
92
+ numberOfTokens = [[self class] defaultNumberOfTokens];
93
+ }
94
+
95
+ @end
@@ -0,0 +1,68 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ #import "YapDatabaseExtensionTransaction.h"
4
+ #import "YapDatabaseFullTextSearchSnippetOptions.h"
5
+
6
+
7
+ /**
8
+ * Welcome to YapDatabase!
9
+ *
10
+ * The project page has a wealth of documentation if you have any questions.
11
+ * https://github.com/yaptv/YapDatabase
12
+ *
13
+ * If you're new to the project you may want to check out the wiki
14
+ * https://github.com/yaptv/YapDatabase/wiki
15
+ *
16
+ * YapDatabaseFullTextSearch is an extension for performing text based search.
17
+ * Internally it uses sqlite's FTS module which was contributed by Google.
18
+ *
19
+ * After registering the extension, you can access this class within a regular transaction.
20
+ * For example:
21
+ *
22
+ * [databaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){
23
+ *
24
+ * [[transaction ext:@"mySearch"] enumerateKeysMatching:@"birthday party"
25
+ * usingBlock:^(NSString *collection, NSString *key, BOOL *stop){
26
+ * // matching row...
27
+ * }]
28
+ * }];
29
+ **/
30
+ @interface YapDatabaseFullTextSearchTransaction : YapDatabaseExtensionTransaction
31
+
32
+ // Regular query matching
33
+
34
+ - (void)enumerateKeysMatching:(NSString *)query
35
+ usingBlock:(void (^)(NSString *collection, NSString *key, BOOL *stop))block;
36
+
37
+ - (void)enumerateKeysAndMetadataMatching:(NSString *)query
38
+ usingBlock:(void (^)(NSString *collection, NSString *key, id metadata, BOOL *stop))block;
39
+
40
+ - (void)enumerateKeysAndObjectsMatching:(NSString *)query
41
+ usingBlock:(void (^)(NSString *collection, NSString *key, id object, BOOL *stop))block;
42
+
43
+ - (void)enumerateRowsMatching:(NSString *)query
44
+ usingBlock:(void (^)(NSString *collection, NSString *key, id object, id metadata, BOOL *stop))block;
45
+
46
+ // Query matching + Snippets
47
+
48
+ - (void)enumerateKeysMatching:(NSString *)query
49
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)options
50
+ usingBlock:
51
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, BOOL *stop))block;
52
+
53
+ - (void)enumerateKeysAndMetadataMatching:(NSString *)query
54
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)options
55
+ usingBlock:
56
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, id metadata, BOOL *stop))block;
57
+
58
+ - (void)enumerateKeysAndObjectsMatching:(NSString *)query
59
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)options
60
+ usingBlock:
61
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, id object, BOOL *stop))block;
62
+
63
+ - (void)enumerateRowsMatching:(NSString *)query
64
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)options
65
+ usingBlock:
66
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, id object, id metadata, BOOL *stop))block;
67
+
68
+ @end
@@ -0,0 +1,1352 @@
1
+ #import "YapDatabaseFullTextSearchTransaction.h"
2
+ #import "YapDatabaseFullTextSearchPrivate.h"
3
+ #import "YapDatabaseExtensionPrivate.h"
4
+ #import "YapDatabasePrivate.h"
5
+ #import "YapDatabaseString.h"
6
+ #import "YapDatabaseLogging.h"
7
+
8
+ #if ! __has_feature(objc_arc)
9
+ #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
10
+ #endif
11
+
12
+ /**
13
+ * Define log level for this file: OFF, ERROR, WARN, INFO, VERBOSE
14
+ * See YapDatabaseLogging.h for more information.
15
+ **/
16
+ #if DEBUG
17
+ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN;
18
+ #else
19
+ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN;
20
+ #endif
21
+
22
+ /**
23
+ * This version number is stored in the yap2 table.
24
+ * If there is a major re-write to this class, then the version number will be incremented,
25
+ * and the class can automatically rebuild the tables as needed.
26
+ **/
27
+ #define YAP_DATABASE_FTS_CLASS_VERSION 1
28
+
29
+
30
+ @implementation YapDatabaseFullTextSearchTransaction
31
+
32
+ - (id)initWithFTSConnection:(YapDatabaseFullTextSearchConnection *)inFTSConnection
33
+ databaseTransaction:(YapDatabaseReadTransaction *)inDatabaseTransaction
34
+ {
35
+ if ((self = [super init]))
36
+ {
37
+ ftsConnection = inFTSConnection;
38
+ databaseTransaction = inDatabaseTransaction;
39
+ }
40
+ return self;
41
+ }
42
+
43
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44
+ #pragma mark Extension Lifecycle
45
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46
+
47
+ /**
48
+ * Required override method from YapDatabaseExtensionTransaction.
49
+ *
50
+ * This method is called to create any necessary tables (if needed),
51
+ * as well as populate the view (if needed) by enumerating over the existing rows in the database.
52
+ **/
53
+ - (BOOL)createIfNeeded
54
+ {
55
+ int oldClassVersion = [self intValueForExtensionKey:@"classVersion"];
56
+ int classVersion = YAP_DATABASE_FTS_CLASS_VERSION;
57
+
58
+ if (oldClassVersion != classVersion)
59
+ {
60
+ // First time registration
61
+
62
+ [self upgradeFromForOldClassVersion:oldClassVersion];
63
+
64
+ if (![self createTable]) return NO;
65
+ if (![self populate]) return NO;
66
+
67
+ [self setIntValue:classVersion forExtensionKey:@"classVersion"];
68
+
69
+ int userSuppliedConfigVersion = ftsConnection->fts->version;
70
+ [self setIntValue:userSuppliedConfigVersion forExtensionKey:@"version"];
71
+ }
72
+ else
73
+ {
74
+ // Check user-supplied config version.
75
+ // We may need to re-populate the database if the groupingBlock or sortingBlock changed.
76
+
77
+ int oldVersion = [self intValueForExtensionKey:@"version"];
78
+ int newVersion = ftsConnection->fts->version;
79
+
80
+ if (oldVersion != newVersion)
81
+ {
82
+ if (![self dropTable]) return NO;
83
+ if (![self createTable]) return NO;
84
+ if (![self populate]) return NO;
85
+
86
+ [self setIntValue:newVersion forExtensionKey:@"version"];
87
+ }
88
+ }
89
+
90
+ return YES;
91
+ }
92
+
93
+ /**
94
+ * Required override method from YapDatabaseExtensionTransaction.
95
+ *
96
+ * This method is called to prepare the transaction for use.
97
+ *
98
+ * Remember, an extension transaction is a very short lived object.
99
+ * Thus it stores the majority of its state within the extension connection (the parent).
100
+ *
101
+ * Return YES if completed successfully, or if already prepared.
102
+ * Return NO if some kind of error occured.
103
+ **/
104
+ - (BOOL)prepareIfNeeded
105
+ {
106
+ return YES;
107
+ }
108
+
109
+ /**
110
+ * Internal method.
111
+ *
112
+ * This method is used to handle the upgrade process from earlier architectures of this class.
113
+ **/
114
+ - (void)upgradeFromForOldClassVersion:(int)oldClassVersion
115
+ {
116
+ // Reserved for future use...
117
+ }
118
+
119
+ /**
120
+ * Internal method.
121
+ *
122
+ * This method is called, if needed, to drop the old table.
123
+ **/
124
+ - (BOOL)dropTable
125
+ {
126
+ sqlite3 *db = databaseTransaction->connection->db;
127
+
128
+ NSString *tableName = [self tableName];
129
+ NSString *dropTable = [NSString stringWithFormat:@"DROP TABLE IF EXISTS \"%@\";", tableName];
130
+
131
+ int status = sqlite3_exec(db, [dropTable UTF8String], NULL, NULL, NULL);
132
+ if (status != SQLITE_OK)
133
+ {
134
+ YDBLogError(@"%@ - Failed dropping FTS table (%@): %d %s",
135
+ THIS_METHOD, dropTable, status, sqlite3_errmsg(db));
136
+ return NO;
137
+ }
138
+
139
+ return YES;
140
+ }
141
+
142
+ /**
143
+ * Internal method.
144
+ *
145
+ * This method is called, if needed, to create the tables for the view.
146
+ **/
147
+ - (BOOL)createTable
148
+ {
149
+ sqlite3 *db = databaseTransaction->connection->db;
150
+
151
+ NSString *tableName = [self tableName];
152
+
153
+ YDBLogVerbose(@"Creating FTS table for registeredName(%@): %@", [self registeredName], tableName);
154
+
155
+ // CREATE VIRTUAL TABLE pages USING fts4(column1, column2, column3);
156
+
157
+ NSMutableString *createTable = [NSMutableString stringWithCapacity:100];
158
+ [createTable appendFormat:@"CREATE VIRTUAL TABLE IF NOT EXISTS \"%@\" USING fts4(", tableName];
159
+
160
+ __block NSUInteger i = 0;
161
+
162
+ NSOrderedSet *columnNames = ftsConnection->fts->columnNames;
163
+ for (NSString *columnName in columnNames)
164
+ {
165
+ if (i == 0)
166
+ [createTable appendFormat:@"\"%@\"", columnName];
167
+ else
168
+ [createTable appendFormat:@", \"%@\"", columnName];
169
+
170
+ i++;
171
+ }
172
+
173
+ NSDictionary *options = ftsConnection->fts->options;
174
+ [options enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
175
+
176
+ NSString *option = (NSString *)key;
177
+ NSString *value = (NSString *)obj;
178
+
179
+ if (i == 0)
180
+ [createTable appendFormat:@"%@=%@", option, value];
181
+ else
182
+ [createTable appendFormat:@", %@=%@", option, value];
183
+
184
+ i++;
185
+ }];
186
+
187
+ [createTable appendString:@");"];
188
+
189
+ int status = sqlite3_exec(db, [createTable UTF8String], NULL, NULL, NULL);
190
+ if (status != SQLITE_OK)
191
+ {
192
+ YDBLogError(@"%@ - Failed creating FTS table (%@): %d %s",
193
+ THIS_METHOD, tableName, status, sqlite3_errmsg(db));
194
+ return NO;
195
+ }
196
+
197
+ return YES;
198
+ }
199
+
200
+ /**
201
+ * Internal method.
202
+ *
203
+ * This method is called, if needed, to populate the FTS indexes.
204
+ * It does so by enumerating the rows in the database, and invoking the usual blocks and insertion methods.
205
+ **/
206
+ - (BOOL)populate
207
+ {
208
+ // Remove everything from the database
209
+
210
+ [self removeAllRowids];
211
+
212
+ // Enumerate the existing rows in the database and populate the indexes
213
+
214
+ __unsafe_unretained YapDatabaseFullTextSearch *fts = ftsConnection->fts;
215
+
216
+ BOOL needsObject = fts->blockType == YapDatabaseFullTextSearchBlockTypeWithObject ||
217
+ fts->blockType == YapDatabaseFullTextSearchBlockTypeWithRow;
218
+
219
+ BOOL needsMetadata = fts->blockType == YapDatabaseFullTextSearchBlockTypeWithMetadata ||
220
+ fts->blockType == YapDatabaseFullTextSearchBlockTypeWithRow;
221
+
222
+ if (needsObject && needsMetadata)
223
+ {
224
+ __unsafe_unretained YapDatabaseFullTextSearchWithRowBlock block =
225
+ (YapDatabaseFullTextSearchWithRowBlock)fts->block;
226
+
227
+ [databaseTransaction _enumerateRowsInAllCollectionsUsingBlock:
228
+ ^(int64_t rowid, NSString *collection, NSString *key, id object, id metadata, BOOL *stop) {
229
+
230
+ block(ftsConnection->blockDict, collection, key, object, metadata);
231
+
232
+ if ([ftsConnection->blockDict count] > 0)
233
+ {
234
+ [self addRowid:rowid isNew:YES];
235
+ [ftsConnection->blockDict removeAllObjects];
236
+ }
237
+ }];
238
+ }
239
+ else if (needsObject && !needsMetadata)
240
+ {
241
+ __unsafe_unretained YapDatabaseFullTextSearchWithObjectBlock block =
242
+ (YapDatabaseFullTextSearchWithObjectBlock)fts->block;
243
+
244
+ [databaseTransaction _enumerateKeysAndObjectsInAllCollectionsUsingBlock:
245
+ ^(int64_t rowid, NSString *collection, NSString *key, id object, BOOL *stop) {
246
+
247
+ block(ftsConnection->blockDict, collection, key, object);
248
+
249
+ if ([ftsConnection->blockDict count] > 0)
250
+ {
251
+ [self addRowid:rowid isNew:YES];
252
+ [ftsConnection->blockDict removeAllObjects];
253
+ }
254
+ }];
255
+ }
256
+ else if (!needsObject && needsMetadata)
257
+ {
258
+ __unsafe_unretained YapDatabaseFullTextSearchWithMetadataBlock block =
259
+ (YapDatabaseFullTextSearchWithMetadataBlock)fts->block;
260
+
261
+ [databaseTransaction _enumerateKeysAndMetadataInAllCollectionsUsingBlock:
262
+ ^(int64_t rowid, NSString *collection, NSString *key, id metadata, BOOL *stop) {
263
+
264
+ block(ftsConnection->blockDict, collection, key, metadata);
265
+
266
+ if ([ftsConnection->blockDict count] > 0)
267
+ {
268
+ [self addRowid:rowid isNew:YES];
269
+ [ftsConnection->blockDict removeAllObjects];
270
+ }
271
+ }];
272
+ }
273
+ else // if (!needsObject && !needsMetadata)
274
+ {
275
+ __unsafe_unretained YapDatabaseFullTextSearchWithKeyBlock block =
276
+ (YapDatabaseFullTextSearchWithKeyBlock)fts->block;
277
+
278
+ [databaseTransaction _enumerateKeysInAllCollectionsUsingBlock:
279
+ ^(int64_t rowid, NSString *collection, NSString *key, BOOL *stop) {
280
+
281
+ block(ftsConnection->blockDict, collection, key);
282
+
283
+ if ([ftsConnection->blockDict count] > 0)
284
+ {
285
+ [self addRowid:rowid isNew:YES];
286
+ [ftsConnection->blockDict removeAllObjects];
287
+ }
288
+ }];
289
+ }
290
+
291
+ return YES;
292
+ }
293
+
294
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
295
+ #pragma mark Accessors
296
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297
+
298
+ /**
299
+ * Required override method from YapDatabaseExtensionTransaction.
300
+ **/
301
+ - (YapDatabaseReadTransaction *)databaseTransaction
302
+ {
303
+ return databaseTransaction;
304
+ }
305
+
306
+ /**
307
+ * Required override method from YapDatabaseExtensionTransaction.
308
+ **/
309
+ - (YapDatabaseExtensionConnection *)extensionConnection
310
+ {
311
+ return ftsConnection;
312
+ }
313
+
314
+ - (NSString *)registeredName
315
+ {
316
+ return [ftsConnection->fts registeredName];
317
+ }
318
+
319
+ - (NSString *)tableName
320
+ {
321
+ return [ftsConnection->fts tableName];
322
+ }
323
+
324
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
325
+ #pragma mark Logic
326
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
327
+
328
+ - (void)addRowid:(int64_t)rowid isNew:(BOOL)isNew
329
+ {
330
+ YDBLogAutoTrace();
331
+
332
+ sqlite3_stmt *statement = NULL;
333
+ if (isNew)
334
+ statement = [ftsConnection insertRowidStatement];
335
+ else
336
+ statement = [ftsConnection setRowidStatement];
337
+
338
+ if (statement == NULL)
339
+ return;
340
+
341
+ // isNew : INSERT INTO "tableName" ("rowid", "column1", "column2", ...) VALUES (?, ?, ? ...)
342
+ // !isNew : INSERT OR REPLACE INTO "tableName" ("rowid", "column1", "column2", ...) VALUES (?, ?, ? ...)
343
+
344
+ sqlite3_bind_int64(statement, 1, rowid);
345
+
346
+ int i = 2;
347
+ for (NSString *columnName in ftsConnection->fts->columnNames)
348
+ {
349
+ NSString *columnValue = [ftsConnection->blockDict objectForKey:columnName];
350
+ if (columnValue)
351
+ {
352
+ sqlite3_bind_text(statement, i, [columnValue UTF8String], -1, SQLITE_TRANSIENT);
353
+ }
354
+
355
+ i++;
356
+ }
357
+
358
+ int status = sqlite3_step(statement);
359
+ if (status != SQLITE_DONE)
360
+ {
361
+ YDBLogError(@"Error executing '%s': %d %s",
362
+ isNew ? "insertRowidStatement" : "setRowidStatement",
363
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
364
+ }
365
+
366
+ sqlite3_clear_bindings(statement);
367
+ sqlite3_reset(statement);
368
+
369
+ isMutated = YES;
370
+ }
371
+
372
+ - (void)removeRowid:(int64_t)rowid
373
+ {
374
+ YDBLogAutoTrace();
375
+
376
+ sqlite3_stmt *statement = [ftsConnection removeRowidStatement];
377
+ if (statement == NULL) return;
378
+
379
+ // DELETE FROM "tableName" WHERE "rowid" = ?;
380
+
381
+ sqlite3_bind_int64(statement, 1, rowid);
382
+
383
+ int status = sqlite3_step(statement);
384
+ if (status != SQLITE_DONE)
385
+ {
386
+ YDBLogError(@"Error executing 'removeRowidStatement': %d %s",
387
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
388
+ }
389
+
390
+ sqlite3_clear_bindings(statement);
391
+ sqlite3_reset(statement);
392
+
393
+ isMutated = YES;
394
+ }
395
+
396
+ - (void)removeRowids:(NSArray *)rowids
397
+ {
398
+ YDBLogAutoTrace();
399
+
400
+ NSUInteger count = [rowids count];
401
+
402
+ if (count == 0) return;
403
+ if (count == 1)
404
+ {
405
+ int64_t rowid = [[rowids objectAtIndex:0] longLongValue];
406
+
407
+ [self removeRowid:rowid];
408
+ return;
409
+ }
410
+
411
+ // DELETE FROM "tableName" WHERE "rowid" in (?, ?, ...);
412
+ //
413
+ // Note: We don't have to worry sqlite's max number of host parameters.
414
+ // YapDatabase gives us the rowids in batches where each batch is already capped at this number.
415
+
416
+ NSUInteger capacity = 50 + (count * 3);
417
+ NSMutableString *query = [NSMutableString stringWithCapacity:capacity];
418
+
419
+ [query appendFormat:@"DELETE FROM \"%@\" WHERE \"rowid\" IN (", [self tableName]];
420
+
421
+ NSUInteger i;
422
+ for (i = 0; i < count; i++)
423
+ {
424
+ if (i == 0)
425
+ [query appendFormat:@"?"];
426
+ else
427
+ [query appendFormat:@", ?"];
428
+ }
429
+
430
+ [query appendString:@");"];
431
+
432
+ sqlite3_stmt *statement;
433
+
434
+ int status = sqlite3_prepare_v2(databaseTransaction->connection->db, [query UTF8String], -1, &statement, NULL);
435
+ if (status != SQLITE_OK)
436
+ {
437
+ YDBLogError(@"Error creating 'removeRowids' statement: %d %s",
438
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
439
+ return;
440
+ }
441
+
442
+ for (i = 0; i < count; i++)
443
+ {
444
+ int64_t rowid = [[rowids objectAtIndex:i] longLongValue];
445
+
446
+ sqlite3_bind_int64(statement, (int)(i + 1), rowid);
447
+ }
448
+
449
+ status = sqlite3_step(statement);
450
+ if (status != SQLITE_DONE)
451
+ {
452
+ YDBLogError(@"Error executing 'removeRowids' statement: %d %s",
453
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
454
+ }
455
+
456
+ sqlite3_finalize(statement);
457
+
458
+ isMutated = YES;
459
+ }
460
+
461
+ - (void)removeAllRowids
462
+ {
463
+ YDBLogAutoTrace();
464
+
465
+ sqlite3_stmt *statement = [ftsConnection removeAllStatement];
466
+ if (statement == NULL)
467
+ return;
468
+
469
+ int status;
470
+
471
+ // DELETE FROM "tableName";
472
+
473
+ YDBLogVerbose(@"DELETE FROM '%@';", [self tableName]);
474
+
475
+ status = sqlite3_step(statement);
476
+ if (status != SQLITE_DONE)
477
+ {
478
+ YDBLogError(@"%@ (%@): Error in removeAllStatement: %d %s",
479
+ THIS_METHOD, [self registeredName],
480
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
481
+ }
482
+
483
+ sqlite3_reset(statement);
484
+
485
+ isMutated = YES;
486
+ }
487
+
488
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
489
+ #pragma mark Cleanup & Commit
490
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
491
+
492
+ /**
493
+ * Required override method from YapDatabaseExtension
494
+ **/
495
+ - (void)commitTransaction
496
+ {
497
+ // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction.
498
+ // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar,
499
+ // and then use it outside the context of the database transaction block.
500
+ // Thus, this code is here as a safety net to ensure that such accidental misuse doesn't do any damage.
501
+
502
+ ftsConnection = nil; // Do not remove !
503
+ databaseTransaction = nil; // Do not remove !
504
+ }
505
+
506
+ /**
507
+ * Required override method from YapDatabaseExtension
508
+ **/
509
+ - (void)rollbackTransaction
510
+ {
511
+ // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction.
512
+ // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar,
513
+ // and then use it outside the context of the database transaction block.
514
+ // Thus, this code is here as a safety net to ensure that such accidental misuse doesn't do any damage.
515
+
516
+ ftsConnection = nil; // Do not remove !
517
+ databaseTransaction = nil; // Do not remove !
518
+ }
519
+
520
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
521
+ #pragma mark YapDatabaseExtensionTransaction_Hooks
522
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
523
+
524
+ /**
525
+ * YapDatabase extension hook.
526
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
527
+ **/
528
+ - (void)handleInsertObject:(id)object
529
+ forKey:(NSString *)key
530
+ inCollection:(NSString *)collection
531
+ withMetadata:(id)metadata
532
+ rowid:(int64_t)rowid
533
+ {
534
+ YDBLogAutoTrace();
535
+
536
+ __unsafe_unretained YapDatabaseFullTextSearch *fts = ftsConnection->fts;
537
+
538
+ // Invoke the block to find out if the object should be included in the index.
539
+
540
+ if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithKey)
541
+ {
542
+ __unsafe_unretained YapDatabaseFullTextSearchWithKeyBlock block =
543
+ (YapDatabaseFullTextSearchWithKeyBlock)fts->block;
544
+
545
+ block(ftsConnection->blockDict, collection, key);
546
+ }
547
+ else if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithObject)
548
+ {
549
+ __unsafe_unretained YapDatabaseFullTextSearchWithObjectBlock block =
550
+ (YapDatabaseFullTextSearchWithObjectBlock)fts->block;
551
+
552
+ block(ftsConnection->blockDict, collection, key, object);
553
+ }
554
+ else if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithMetadata)
555
+ {
556
+ __unsafe_unretained YapDatabaseFullTextSearchWithMetadataBlock block =
557
+ (YapDatabaseFullTextSearchWithMetadataBlock)fts->block;
558
+
559
+ block(ftsConnection->blockDict, collection, key, metadata);
560
+ }
561
+ else
562
+ {
563
+ __unsafe_unretained YapDatabaseFullTextSearchWithRowBlock block =
564
+ (YapDatabaseFullTextSearchWithRowBlock)fts->block;
565
+
566
+ block(ftsConnection->blockDict, collection, key, object, metadata);
567
+ }
568
+
569
+ if ([ftsConnection->blockDict count] == 0)
570
+ {
571
+ // This was an insert operation, so we don't have to worry about removing anything.
572
+ }
573
+ else
574
+ {
575
+ // Add values to index.
576
+ // This was an insert operation, so we know we can insert rather than update.
577
+
578
+ [self addRowid:rowid isNew:YES];
579
+ [ftsConnection->blockDict removeAllObjects];
580
+ }
581
+ }
582
+
583
+ /**
584
+ * YapDatabase extension hook.
585
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
586
+ **/
587
+ - (void)handleUpdateObject:(id)object
588
+ forKey:(NSString *)key
589
+ inCollection:(NSString *)collection
590
+ withMetadata:(id)metadata
591
+ rowid:(int64_t)rowid
592
+ {
593
+ YDBLogAutoTrace();
594
+
595
+ __unsafe_unretained YapDatabaseFullTextSearch *fts = ftsConnection->fts;
596
+
597
+ // Invoke the block to find out if the object should be included in the index.
598
+
599
+ if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithKey)
600
+ {
601
+ __unsafe_unretained YapDatabaseFullTextSearchWithKeyBlock block =
602
+ (YapDatabaseFullTextSearchWithKeyBlock)fts->block;
603
+
604
+ block(ftsConnection->blockDict, collection, key);
605
+ }
606
+ else if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithObject)
607
+ {
608
+ __unsafe_unretained YapDatabaseFullTextSearchWithObjectBlock block =
609
+ (YapDatabaseFullTextSearchWithObjectBlock)fts->block;
610
+
611
+ block(ftsConnection->blockDict, collection, key, object);
612
+ }
613
+ else if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithMetadata)
614
+ {
615
+ __unsafe_unretained YapDatabaseFullTextSearchWithMetadataBlock block =
616
+ (YapDatabaseFullTextSearchWithMetadataBlock)fts->block;
617
+
618
+ block(ftsConnection->blockDict, collection, key, metadata);
619
+ }
620
+ else
621
+ {
622
+ __unsafe_unretained YapDatabaseFullTextSearchWithRowBlock block =
623
+ (YapDatabaseFullTextSearchWithRowBlock)fts->block;
624
+
625
+ block(ftsConnection->blockDict, collection, key, object, metadata);
626
+ }
627
+
628
+ if ([ftsConnection->blockDict count] == 0)
629
+ {
630
+ // Remove associated values from index (if needed).
631
+ // This was an update operation, so the rowid may have previously had values in the index.
632
+
633
+ [self removeRowid:rowid];
634
+ }
635
+ else
636
+ {
637
+ // Add values to index (or update them).
638
+ // This was an update operation, so we need to insert or update.
639
+
640
+ [self addRowid:rowid isNew:NO];
641
+ [ftsConnection->blockDict removeAllObjects];
642
+ }
643
+ }
644
+
645
+ /**
646
+ * YapDatabase extension hook.
647
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
648
+ **/
649
+ - (void)handleUpdateMetadata:(id)metadata
650
+ forKey:(NSString *)key
651
+ inCollection:(NSString *)collection
652
+ withRowid:(int64_t)rowid
653
+ {
654
+ YDBLogAutoTrace();
655
+
656
+ __unsafe_unretained YapDatabaseFullTextSearch *fts = ftsConnection->fts;
657
+
658
+ // Invoke the block to find out if the object should be included in the index.
659
+
660
+ id object = nil;
661
+
662
+ if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithKey ||
663
+ fts->blockType == YapDatabaseFullTextSearchBlockTypeWithObject)
664
+ {
665
+ // Index values are based on the key or object.
666
+ // Neither have changed, and thus the values haven't changed.
667
+
668
+ return;
669
+ }
670
+ else
671
+ {
672
+ // Index values are based on metadata or objectAndMetadata.
673
+ // Invoke block to see what the new values are.
674
+
675
+ if (fts->blockType == YapDatabaseFullTextSearchBlockTypeWithMetadata)
676
+ {
677
+ __unsafe_unretained YapDatabaseFullTextSearchWithMetadataBlock block =
678
+ (YapDatabaseFullTextSearchWithMetadataBlock)fts->block;
679
+
680
+ block(ftsConnection->blockDict, collection, key, metadata);
681
+ }
682
+ else
683
+ {
684
+ __unsafe_unretained YapDatabaseFullTextSearchWithRowBlock block =
685
+ (YapDatabaseFullTextSearchWithRowBlock)fts->block;
686
+
687
+ object = [databaseTransaction objectForKey:key inCollection:collection];
688
+ block(ftsConnection->blockDict, collection, key, object, metadata);
689
+ }
690
+
691
+ if ([ftsConnection->blockDict count] == 0)
692
+ {
693
+ // Remove associated values from index (if needed).
694
+ // This was an update operation, so the rowid may have previously had values in the index.
695
+
696
+ [self removeRowid:rowid];
697
+ }
698
+ else
699
+ {
700
+ // Add values to index (or update them).
701
+ // This was an update operation, so we need to insert or update.
702
+
703
+ [self addRowid:rowid isNew:NO];
704
+ [ftsConnection->blockDict removeAllObjects];
705
+ }
706
+ }
707
+ }
708
+
709
+ /**
710
+ * YapDatabase extension hook.
711
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
712
+ **/
713
+ - (void)handleTouchObjectForKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid
714
+ {
715
+ // Nothing to do for this extension
716
+ }
717
+
718
+ /**
719
+ * YapDatabase extension hook.
720
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
721
+ **/
722
+ - (void)handleTouchMetadataForKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid
723
+ {
724
+ // Nothing to do for this extension
725
+ }
726
+
727
+ /**
728
+ * YapDatabase extension hook.
729
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
730
+ **/
731
+ - (void)handleRemoveObjectForKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid
732
+ {
733
+ YDBLogAutoTrace();
734
+
735
+ [self removeRowid:rowid];
736
+ }
737
+
738
+ /**
739
+ * YapDatabase extension hook.
740
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
741
+ **/
742
+ - (void)handleRemoveObjectsForKeys:(NSArray *)keys inCollection:(NSString *)collection withRowids:(NSArray *)rowids
743
+ {
744
+ YDBLogAutoTrace();
745
+
746
+ [self removeRowids:rowids];
747
+ }
748
+
749
+ /**
750
+ * YapDatabase extension hook.
751
+ * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook.
752
+ **/
753
+ - (void)handleRemoveAllObjectsInAllCollections
754
+ {
755
+ YDBLogAutoTrace();
756
+
757
+ [self removeAllRowids];
758
+ }
759
+
760
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
761
+ #pragma mark Queries
762
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
763
+
764
+ - (void)enumerateKeysMatching:(NSString *)query
765
+ usingBlock:(void (^)(NSString *collection, NSString *key, BOOL *stop))block
766
+ {
767
+ if (block == nil) return;
768
+ if ([query length] == 0) return;
769
+
770
+ sqlite3_stmt *statement = [ftsConnection queryStatement];
771
+ if (statement == NULL) return;
772
+
773
+ BOOL stop = NO;
774
+ isMutated = NO; // mutation during enumeration protection
775
+
776
+ // SELECT "rowid" FROM "tableName" WHERE "tableName" MATCH ?;
777
+
778
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
779
+ sqlite3_bind_text(statement, 1, _query.str, _query.length, SQLITE_STATIC);
780
+
781
+ int status = sqlite3_step(statement);
782
+ if (status == SQLITE_ROW)
783
+ {
784
+ do
785
+ {
786
+ int64_t rowid = sqlite3_column_int64(statement, 0);
787
+
788
+ NSString *key = nil;
789
+ NSString *collection = nil;
790
+ [databaseTransaction getKey:&key collection:&collection forRowid:rowid];
791
+
792
+ block(collection, key, &stop);
793
+
794
+ if (stop || isMutated) break;
795
+
796
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
797
+ }
798
+
799
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
800
+ {
801
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
802
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
803
+ }
804
+
805
+ sqlite3_clear_bindings(statement);
806
+ sqlite3_reset(statement);
807
+ FreeYapDatabaseString(&_query);
808
+
809
+ if (isMutated && !stop)
810
+ {
811
+ @throw [databaseTransaction mutationDuringEnumerationException];
812
+ }
813
+ }
814
+
815
+ - (void)enumerateKeysAndMetadataMatching:(NSString *)query
816
+ usingBlock:(void (^)(NSString *collection, NSString *key, id metadata, BOOL *stop))block
817
+ {
818
+ if (block == nil) return;
819
+ if ([query length] == 0) return;
820
+
821
+ sqlite3_stmt *statement = [ftsConnection queryStatement];
822
+ if (statement == NULL) return;
823
+
824
+ BOOL stop = NO;
825
+ isMutated = NO; // mutation during enumeration protection
826
+
827
+ // SELECT "rowid" FROM "tableName" WHERE "tableName" MATCH ?;
828
+
829
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
830
+ sqlite3_bind_text(statement, 1, _query.str, _query.length, SQLITE_STATIC);
831
+
832
+ int status = sqlite3_step(statement);
833
+ if (status == SQLITE_ROW)
834
+ {
835
+ do
836
+ {
837
+ int64_t rowid = sqlite3_column_int64(statement, 0);
838
+
839
+ NSString *key = nil;
840
+ NSString *collection = nil;
841
+ id metadata = nil;
842
+ [databaseTransaction getKey:&key collection:&collection metadata:&metadata forRowid:rowid];
843
+
844
+ block(collection, key, metadata, &stop);
845
+
846
+ if (stop || isMutated) break;
847
+
848
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
849
+ }
850
+
851
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
852
+ {
853
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
854
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
855
+ }
856
+
857
+ sqlite3_clear_bindings(statement);
858
+ sqlite3_reset(statement);
859
+ FreeYapDatabaseString(&_query);
860
+
861
+ if (isMutated && !stop)
862
+ {
863
+ @throw [databaseTransaction mutationDuringEnumerationException];
864
+ }
865
+ }
866
+
867
+ - (void)enumerateKeysAndObjectsMatching:(NSString *)query
868
+ usingBlock:(void (^)(NSString *collection, NSString *key, id object, BOOL *stop))block
869
+ {
870
+ if (block == nil) return;
871
+ if ([query length] == 0) return;
872
+
873
+ sqlite3_stmt *statement = [ftsConnection queryStatement];
874
+ if (statement == NULL) return;
875
+
876
+ BOOL stop = NO;
877
+ isMutated = NO; // mutation during enumeration protection
878
+
879
+ // SELECT "rowid" FROM "tableName" WHERE "tableName" MATCH ?;
880
+
881
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
882
+ sqlite3_bind_text(statement, 1, _query.str, _query.length, SQLITE_STATIC);
883
+
884
+ int status = sqlite3_step(statement);
885
+ if (status == SQLITE_ROW)
886
+ {
887
+ do
888
+ {
889
+ int64_t rowid = sqlite3_column_int64(statement, 0);
890
+
891
+ NSString *key = nil;
892
+ NSString *collection = nil;
893
+ id object = nil;
894
+ [databaseTransaction getKey:&key collection:&collection object:&object forRowid:rowid];
895
+
896
+ block(collection, key, object, &stop);
897
+
898
+ if (stop || isMutated) break;
899
+
900
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
901
+ }
902
+
903
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
904
+ {
905
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
906
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
907
+ }
908
+
909
+ sqlite3_clear_bindings(statement);
910
+ sqlite3_reset(statement);
911
+ FreeYapDatabaseString(&_query);
912
+
913
+ if (isMutated && !stop)
914
+ {
915
+ @throw [databaseTransaction mutationDuringEnumerationException];
916
+ }
917
+ }
918
+
919
+ - (void)enumerateRowsMatching:(NSString *)query
920
+ usingBlock:(void (^)(NSString *collection, NSString *key, id object, id metadata, BOOL *stop))block
921
+ {
922
+ if (block == nil) return;
923
+ if ([query length] == 0) return;
924
+
925
+ sqlite3_stmt *statement = [ftsConnection queryStatement];
926
+ if (statement == NULL) return;
927
+
928
+ BOOL stop = NO;
929
+ isMutated = NO; // mutation during enumeration protection
930
+
931
+ // SELECT "rowid" FROM "tableName" WHERE "tableName" MATCH ?;
932
+
933
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
934
+ sqlite3_bind_text(statement, 1, _query.str, _query.length, SQLITE_STATIC);
935
+
936
+ int status = sqlite3_step(statement);
937
+ if (status == SQLITE_ROW)
938
+ {
939
+ do
940
+ {
941
+ int64_t rowid = sqlite3_column_int64(statement, 0);
942
+
943
+ NSString *key = nil;
944
+ NSString *collection = nil;
945
+ id object = nil;
946
+ id metadata = nil;
947
+ [databaseTransaction getKey:&key collection:&collection object:&object metadata:&metadata forRowid:rowid];
948
+
949
+ block(collection, key, object, metadata, &stop);
950
+
951
+ if (stop || isMutated) break;
952
+
953
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
954
+ }
955
+
956
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
957
+ {
958
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
959
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
960
+ }
961
+
962
+ sqlite3_clear_bindings(statement);
963
+ sqlite3_reset(statement);
964
+ FreeYapDatabaseString(&_query);
965
+
966
+ if (isMutated && !stop)
967
+ {
968
+ @throw [databaseTransaction mutationDuringEnumerationException];
969
+ }
970
+ }
971
+
972
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
973
+ #pragma mark Queries with Snippets
974
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
975
+
976
+ - (void)enumerateKeysMatching:(NSString *)query
977
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)inOptions
978
+ usingBlock:
979
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, BOOL *stop))block
980
+ {
981
+ if (block == nil) return;
982
+ if ([query length] == 0) return;
983
+
984
+ sqlite3_stmt *statement = [ftsConnection querySnippetStatement];
985
+ if (statement == NULL) return;
986
+
987
+ YapDatabaseFullTextSearchSnippetOptions *options;
988
+ if (inOptions)
989
+ options = [inOptions copy];
990
+ else
991
+ options = [[YapDatabaseFullTextSearchSnippetOptions alloc] init]; // default snippet options
992
+
993
+ BOOL stop = NO;
994
+ isMutated = NO; // mutation during enumeration protection
995
+
996
+ // SELECT "rowid", snippet("tableName", ?, ?, ?, ?, ?) FROM "tableName" WHERE "tableName" MATCH ?;
997
+
998
+ YapDatabaseString _startMatchText; MakeYapDatabaseString(&_startMatchText, options.startMatchText);
999
+ sqlite3_bind_text(statement, 1, _startMatchText.str, _startMatchText.length, SQLITE_STATIC);
1000
+
1001
+ YapDatabaseString _endMatchText; MakeYapDatabaseString(&_endMatchText, options.endMatchText);
1002
+ sqlite3_bind_text(statement, 2, _endMatchText.str, _endMatchText.length, SQLITE_STATIC);
1003
+
1004
+ YapDatabaseString _ellipsesText; MakeYapDatabaseString(&_ellipsesText, options.ellipsesText);
1005
+ sqlite3_bind_text(statement, 3, _ellipsesText.str, _ellipsesText.length, SQLITE_STATIC);
1006
+
1007
+ int columnIndex = -1;
1008
+ if (options.columnName)
1009
+ {
1010
+ NSUInteger index = [ftsConnection->fts->columnNames indexOfObject:options.columnName];
1011
+ if (index == NSNotFound)
1012
+ {
1013
+ YDBLogWarn(@"Invalid snippet option: columnName(%@) not found", options.columnName);
1014
+ }
1015
+ else
1016
+ {
1017
+ columnIndex = (int)index;
1018
+ }
1019
+ }
1020
+ sqlite3_bind_int(statement, 4, columnIndex);
1021
+ sqlite3_bind_int(statement, 5, options.numberOfTokens);
1022
+
1023
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
1024
+ sqlite3_bind_text(statement, 6, _query.str, _query.length, SQLITE_STATIC);
1025
+
1026
+ int status = sqlite3_step(statement);
1027
+ if (status == SQLITE_ROW)
1028
+ {
1029
+ do
1030
+ {
1031
+ int64_t rowid = sqlite3_column_int64(statement, 0);
1032
+
1033
+ const unsigned char *text = sqlite3_column_text(statement, 1);
1034
+ int textSize = sqlite3_column_bytes(statement, 1);
1035
+
1036
+ NSString *snippet = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding];
1037
+
1038
+ NSString *key = nil;
1039
+ NSString *collection = nil;
1040
+ [databaseTransaction getKey:&key collection:&collection forRowid:rowid];
1041
+
1042
+ block(snippet, collection, key, &stop);
1043
+
1044
+ if (stop || isMutated) break;
1045
+
1046
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
1047
+ }
1048
+
1049
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
1050
+ {
1051
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
1052
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
1053
+ }
1054
+
1055
+ sqlite3_clear_bindings(statement);
1056
+ sqlite3_reset(statement);
1057
+
1058
+ FreeYapDatabaseString(&_startMatchText);
1059
+ FreeYapDatabaseString(&_endMatchText);
1060
+ FreeYapDatabaseString(&_ellipsesText);
1061
+ FreeYapDatabaseString(&_query);
1062
+
1063
+ if (isMutated && !stop)
1064
+ {
1065
+ @throw [databaseTransaction mutationDuringEnumerationException];
1066
+ }
1067
+ }
1068
+
1069
+ - (void)enumerateKeysAndMetadataMatching:(NSString *)query
1070
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)inOptions
1071
+ usingBlock:
1072
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, id metadata, BOOL *stop))block
1073
+ {
1074
+ if (block == nil) return;
1075
+ if ([query length] == 0) return;
1076
+
1077
+ sqlite3_stmt *statement = [ftsConnection querySnippetStatement];
1078
+ if (statement == NULL) return;
1079
+
1080
+ YapDatabaseFullTextSearchSnippetOptions *options;
1081
+ if (inOptions)
1082
+ options = [inOptions copy];
1083
+ else
1084
+ options = [[YapDatabaseFullTextSearchSnippetOptions alloc] init]; // default snippet options
1085
+
1086
+ BOOL stop = NO;
1087
+ isMutated = NO; // mutation during enumeration protection
1088
+
1089
+ // SELECT "rowid", snippet("tableName", ?, ?, ?, ?, ?) FROM "tableName" WHERE "tableName" MATCH ?;
1090
+
1091
+ YapDatabaseString _startMatchText; MakeYapDatabaseString(&_startMatchText, options.startMatchText);
1092
+ sqlite3_bind_text(statement, 1, _startMatchText.str, _startMatchText.length, SQLITE_STATIC);
1093
+
1094
+ YapDatabaseString _endMatchText; MakeYapDatabaseString(&_endMatchText, options.endMatchText);
1095
+ sqlite3_bind_text(statement, 2, _endMatchText.str, _endMatchText.length, SQLITE_STATIC);
1096
+
1097
+ YapDatabaseString _ellipsesText; MakeYapDatabaseString(&_ellipsesText, options.ellipsesText);
1098
+ sqlite3_bind_text(statement, 3, _ellipsesText.str, _ellipsesText.length, SQLITE_STATIC);
1099
+
1100
+ int columnIndex = -1;
1101
+ if (options.columnName)
1102
+ {
1103
+ NSUInteger index = [ftsConnection->fts->columnNames indexOfObject:options.columnName];
1104
+ if (index == NSNotFound)
1105
+ {
1106
+ YDBLogWarn(@"Invalid snippet option: columnName(%@) not found", options.columnName);
1107
+ }
1108
+ else
1109
+ {
1110
+ columnIndex = (int)index;
1111
+ }
1112
+ }
1113
+ sqlite3_bind_int(statement, 4, columnIndex);
1114
+ sqlite3_bind_int(statement, 5, options.numberOfTokens);
1115
+
1116
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
1117
+ sqlite3_bind_text(statement, 6, _query.str, _query.length, SQLITE_STATIC);
1118
+
1119
+ int status = sqlite3_step(statement);
1120
+ if (status == SQLITE_ROW)
1121
+ {
1122
+ do
1123
+ {
1124
+ int64_t rowid = sqlite3_column_int64(statement, 0);
1125
+
1126
+ const unsigned char *text = sqlite3_column_text(statement, 1);
1127
+ int textSize = sqlite3_column_bytes(statement, 1);
1128
+
1129
+ NSString *snippet = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding];
1130
+
1131
+ NSString *key = nil;
1132
+ NSString *collection = nil;
1133
+ id metadata = nil;
1134
+ [databaseTransaction getKey:&key collection:&collection metadata:&metadata forRowid:rowid];
1135
+
1136
+ block(snippet, collection, key, metadata, &stop);
1137
+
1138
+ if (stop || isMutated) break;
1139
+
1140
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
1141
+ }
1142
+
1143
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
1144
+ {
1145
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
1146
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
1147
+ }
1148
+
1149
+ sqlite3_clear_bindings(statement);
1150
+ sqlite3_reset(statement);
1151
+
1152
+ FreeYapDatabaseString(&_startMatchText);
1153
+ FreeYapDatabaseString(&_endMatchText);
1154
+ FreeYapDatabaseString(&_ellipsesText);
1155
+ FreeYapDatabaseString(&_query);
1156
+
1157
+ if (isMutated && !stop)
1158
+ {
1159
+ @throw [databaseTransaction mutationDuringEnumerationException];
1160
+ }
1161
+ }
1162
+
1163
+ - (void)enumerateKeysAndObjectsMatching:(NSString *)query
1164
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)inOptions
1165
+ usingBlock:
1166
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, id object, BOOL *stop))block
1167
+ {
1168
+ if (block == nil) return;
1169
+ if ([query length] == 0) return;
1170
+
1171
+ sqlite3_stmt *statement = [ftsConnection querySnippetStatement];
1172
+ if (statement == NULL) return;
1173
+
1174
+ YapDatabaseFullTextSearchSnippetOptions *options;
1175
+ if (inOptions)
1176
+ options = [inOptions copy];
1177
+ else
1178
+ options = [[YapDatabaseFullTextSearchSnippetOptions alloc] init]; // default snippet options
1179
+
1180
+ BOOL stop = NO;
1181
+ isMutated = NO; // mutation during enumeration protection
1182
+
1183
+ // SELECT "rowid", snippet("tableName", ?, ?, ?, ?, ?) FROM "tableName" WHERE "tableName" MATCH ?;
1184
+
1185
+ YapDatabaseString _startMatchText; MakeYapDatabaseString(&_startMatchText, options.startMatchText);
1186
+ sqlite3_bind_text(statement, 1, _startMatchText.str, _startMatchText.length, SQLITE_STATIC);
1187
+
1188
+ YapDatabaseString _endMatchText; MakeYapDatabaseString(&_endMatchText, options.endMatchText);
1189
+ sqlite3_bind_text(statement, 2, _endMatchText.str, _endMatchText.length, SQLITE_STATIC);
1190
+
1191
+ YapDatabaseString _ellipsesText; MakeYapDatabaseString(&_ellipsesText, options.ellipsesText);
1192
+ sqlite3_bind_text(statement, 3, _ellipsesText.str, _ellipsesText.length, SQLITE_STATIC);
1193
+
1194
+ int columnIndex = -1;
1195
+ if (options.columnName)
1196
+ {
1197
+ NSUInteger index = [ftsConnection->fts->columnNames indexOfObject:options.columnName];
1198
+ if (index == NSNotFound)
1199
+ {
1200
+ YDBLogWarn(@"Invalid snippet option: columnName(%@) not found", options.columnName);
1201
+ }
1202
+ else
1203
+ {
1204
+ columnIndex = (int)index;
1205
+ }
1206
+ }
1207
+ sqlite3_bind_int(statement, 4, columnIndex);
1208
+ sqlite3_bind_int(statement, 5, options.numberOfTokens);
1209
+
1210
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
1211
+ sqlite3_bind_text(statement, 6, _query.str, _query.length, SQLITE_STATIC);
1212
+
1213
+ int status = sqlite3_step(statement);
1214
+ if (status == SQLITE_ROW)
1215
+ {
1216
+ do
1217
+ {
1218
+ int64_t rowid = sqlite3_column_int64(statement, 0);
1219
+
1220
+ const unsigned char *text = sqlite3_column_text(statement, 1);
1221
+ int textSize = sqlite3_column_bytes(statement, 1);
1222
+
1223
+ NSString *snippet = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding];
1224
+
1225
+ NSString *key = nil;
1226
+ NSString *collection = nil;
1227
+ id object = nil;
1228
+ [databaseTransaction getKey:&key collection:&collection object:&object forRowid:rowid];
1229
+
1230
+ block(snippet, collection, key, object, &stop);
1231
+
1232
+ if (stop || isMutated) break;
1233
+
1234
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
1235
+ }
1236
+
1237
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
1238
+ {
1239
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
1240
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
1241
+ }
1242
+
1243
+ sqlite3_clear_bindings(statement);
1244
+ sqlite3_reset(statement);
1245
+
1246
+ FreeYapDatabaseString(&_startMatchText);
1247
+ FreeYapDatabaseString(&_endMatchText);
1248
+ FreeYapDatabaseString(&_ellipsesText);
1249
+ FreeYapDatabaseString(&_query);
1250
+
1251
+ if (isMutated && !stop)
1252
+ {
1253
+ @throw [databaseTransaction mutationDuringEnumerationException];
1254
+ }
1255
+ }
1256
+
1257
+ - (void)enumerateRowsMatching:(NSString *)query
1258
+ withSnippetOptions:(YapDatabaseFullTextSearchSnippetOptions *)inOptions
1259
+ usingBlock:
1260
+ (void (^)(NSString *snippet, NSString *collection, NSString *key, id object, id metadata, BOOL *stop))block
1261
+ {
1262
+ if (block == nil) return;
1263
+ if ([query length] == 0) return;
1264
+
1265
+ sqlite3_stmt *statement = [ftsConnection querySnippetStatement];
1266
+ if (statement == NULL) return;
1267
+
1268
+ YapDatabaseFullTextSearchSnippetOptions *options;
1269
+ if (inOptions)
1270
+ options = [inOptions copy];
1271
+ else
1272
+ options = [[YapDatabaseFullTextSearchSnippetOptions alloc] init]; // default snippet options
1273
+
1274
+ BOOL stop = NO;
1275
+ isMutated = NO; // mutation during enumeration protection
1276
+
1277
+ // SELECT "rowid", snippet("tableName", ?, ?, ?, ?, ?) FROM "tableName" WHERE "tableName" MATCH ?;
1278
+
1279
+ YapDatabaseString _startMatchText; MakeYapDatabaseString(&_startMatchText, options.startMatchText);
1280
+ sqlite3_bind_text(statement, 1, _startMatchText.str, _startMatchText.length, SQLITE_STATIC);
1281
+
1282
+ YapDatabaseString _endMatchText; MakeYapDatabaseString(&_endMatchText, options.endMatchText);
1283
+ sqlite3_bind_text(statement, 2, _endMatchText.str, _endMatchText.length, SQLITE_STATIC);
1284
+
1285
+ YapDatabaseString _ellipsesText; MakeYapDatabaseString(&_ellipsesText, options.ellipsesText);
1286
+ sqlite3_bind_text(statement, 3, _ellipsesText.str, _ellipsesText.length, SQLITE_STATIC);
1287
+
1288
+ int columnIndex = -1;
1289
+ if (options.columnName)
1290
+ {
1291
+ NSUInteger index = [ftsConnection->fts->columnNames indexOfObject:options.columnName];
1292
+ if (index == NSNotFound)
1293
+ {
1294
+ YDBLogWarn(@"Invalid snippet option: columnName(%@) not found", options.columnName);
1295
+ }
1296
+ else
1297
+ {
1298
+ columnIndex = (int)index;
1299
+ }
1300
+ }
1301
+ sqlite3_bind_int(statement, 4, columnIndex);
1302
+ sqlite3_bind_int(statement, 5, options.numberOfTokens);
1303
+
1304
+ YapDatabaseString _query; MakeYapDatabaseString(&_query, query);
1305
+ sqlite3_bind_text(statement, 6, _query.str, _query.length, SQLITE_STATIC);
1306
+
1307
+ int status = sqlite3_step(statement);
1308
+ if (status == SQLITE_ROW)
1309
+ {
1310
+ do
1311
+ {
1312
+ int64_t rowid = sqlite3_column_int64(statement, 0);
1313
+
1314
+ const unsigned char *text = sqlite3_column_text(statement, 1);
1315
+ int textSize = sqlite3_column_bytes(statement, 1);
1316
+
1317
+ NSString *snippet = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding];
1318
+
1319
+ NSString *key = nil;
1320
+ NSString *collection = nil;
1321
+ id object = nil;
1322
+ id metadata = nil;
1323
+ [databaseTransaction getKey:&key collection:&collection object:&object metadata:&metadata forRowid:rowid];
1324
+
1325
+ block(snippet, collection, key, object, metadata, &stop);
1326
+
1327
+ if (stop || isMutated) break;
1328
+
1329
+ } while ((status = sqlite3_step(statement)) == SQLITE_ROW);
1330
+ }
1331
+
1332
+ if ((status != SQLITE_DONE) && !stop && !isMutated)
1333
+ {
1334
+ YDBLogError(@"%@ - sqlite_step error: %d %s", THIS_METHOD,
1335
+ status, sqlite3_errmsg(databaseTransaction->connection->db));
1336
+ }
1337
+
1338
+ sqlite3_clear_bindings(statement);
1339
+ sqlite3_reset(statement);
1340
+
1341
+ FreeYapDatabaseString(&_startMatchText);
1342
+ FreeYapDatabaseString(&_endMatchText);
1343
+ FreeYapDatabaseString(&_ellipsesText);
1344
+ FreeYapDatabaseString(&_query);
1345
+
1346
+ if (isMutated && !stop)
1347
+ {
1348
+ @throw [databaseTransaction mutationDuringEnumerationException];
1349
+ }
1350
+ }
1351
+
1352
+ @end