motion-yapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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