datahike-browser-tests 1.0.0

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 (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
@@ -0,0 +1,128 @@
1
+ (ns ^:no-doc datahike.index.hitchhiker-tree.upsert
2
+ (:require [datahike.index.utils :as diu]
3
+ [hitchhiker.tree :as tree]
4
+ [hitchhiker.tree.op :as op]))
5
+
6
+ (defn- increase-by-one?
7
+ "Returns true if elements in vector 'indices' form a prefix of the vector indices.
8
+ This is equivalent to check whether the elements increase by one and contains 0.
9
+ E.g., [0 1 2] => true, [0 2 3] => false, [1 2] => false."
10
+ [indices]
11
+ (if (.contains ^clojure.lang.PersistentVector indices 0)
12
+ (let [m (apply max indices)
13
+ s (apply + indices)]
14
+ (= s (/ (* m (+ 1 m)) 2)))
15
+ false))
16
+
17
+ (def prefix? (memoize increase-by-one?))
18
+
19
+ (defn mask [new indices]
20
+ (reduce (fn [mask pos]
21
+ (assoc mask pos (nth new pos)))
22
+ [nil nil nil nil]
23
+ indices))
24
+
25
+ (defn old-key
26
+ "Returns the old version of the given 'new' key if it exists in 'old-keys'.
27
+ 'indices' is a vector of integer indicating which positions in keys are significant,
28
+ i.e., [0 2] means that the first and third entry in the key are used for filtering."
29
+ [old-keys new indices]
30
+ (when (seq old-keys)
31
+ (let [mask (mask new indices)]
32
+ (when-let [candidates (subseq old-keys >= mask)]
33
+ (when (or (not (prefix? indices))
34
+ (diu/equals-on-indices? new (-> candidates first first) indices))
35
+ (let [res (->> candidates
36
+ (map first)
37
+ ;; Returns the key which has not been retracted.
38
+ ;; There will at most be one such key.
39
+ ;; Because of the ordering in keys, we know that
40
+ ;; when two successive keys have a positive
41
+ ;; :t value, then the second key is our answer,
42
+ ;; the one that has not been retracted."
43
+ (reduce (fn [prev-pos? k]
44
+ (let [curr-pos? (pos? (nth k 3))]
45
+ (if (and curr-pos?
46
+ prev-pos?
47
+ (diu/equals-on-indices? new k indices))
48
+ (reduced k)
49
+ curr-pos?)))
50
+ true))]
51
+ (if (boolean? res) nil res)))))))
52
+
53
+ (defn remove-old
54
+ "Removes old key from the 'kvs' map using 'remove-fn' function."
55
+ [kvs new remove-fn indices]
56
+ (when-let [old (old-key kvs new indices)]
57
+ (remove-fn old)))
58
+
59
+ (defrecord UpsertOp [key op-count indices version]
60
+ op/IOperation
61
+ (-insertion-ts [_] op-count)
62
+ (-affects-key [_] key)
63
+ (-apply-op-to-coll [_ kvs]
64
+ (-> (or (remove-old kvs key (partial dissoc kvs) indices) kvs)
65
+ (assoc key nil)))
66
+ (-apply-op-to-tree [_ tree]
67
+ (let [children (cond
68
+ (tree/data-node? tree) (:children tree)
69
+ :else (:children (peek (tree/lookup-path tree key))))]
70
+ (-> (or (remove-old children key (partial tree/delete tree) indices) tree)
71
+ (tree/insert key nil)))))
72
+
73
+ (defn old-retracted
74
+ "Returns a new datom to be inserted in the tree to signal the retraction of
75
+ its corresponding 'old' datom."
76
+ [kvs key old indices]
77
+ (let [[a b c _] old
78
+ [_ _ _ nt] key]
79
+ ;; '-' means it is retracted and 'nt' is the current transaction time.
80
+ [a b c (- nt)]))
81
+
82
+ (defrecord temporal-UpsertOp [key op-count indices version]
83
+ op/IOperation
84
+ (-insertion-ts [_] op-count)
85
+ (-affects-key [_] key)
86
+ (-apply-op-to-coll [_ kvs]
87
+ (if-let [old (old-key kvs key indices)]
88
+ (if (diu/equals-on-indices? key old [0 1 2])
89
+ kvs
90
+ (let [old-retracted (old-retracted kvs key old indices)]
91
+ (-> (assoc kvs old-retracted nil)
92
+ (assoc key nil))))
93
+ (assoc kvs key nil)))
94
+ (-apply-op-to-tree [_ tree]
95
+ (let [children (cond
96
+ (tree/data-node? tree) (:children tree)
97
+ :else (:children (peek (tree/lookup-path tree key))))
98
+ old (old-key children key indices)]
99
+ (if old
100
+ (if (diu/equals-on-indices? key old [0 1 2])
101
+ tree
102
+ (let [old-retracted (old-retracted children key old indices)]
103
+ (-> (tree/insert tree old-retracted nil)
104
+ (tree/insert key nil))))
105
+ (tree/insert tree key nil)))))
106
+
107
+ (defn new-UpsertOp [key op-count indices]
108
+ (UpsertOp. key op-count indices 0))
109
+
110
+ (defn new-temporal-UpsertOp [key op-count indices]
111
+ (temporal-UpsertOp. key op-count indices 0))
112
+
113
+ (defn add-upsert-handler
114
+ "Tells the store how to deserialize upsert related operations"
115
+ [store]
116
+ (swap! (:read-handlers store)
117
+ merge
118
+ {'datahike.index.hitchhiker_tree.upsert.UpsertOp
119
+ ;; TODO Remove ts when Wanderung is available.
120
+ (fn [{:keys [key value op-count ts indices]}]
121
+ (map->UpsertOp {:key key :value value :op-count (or op-count ts) :indices (or indices [0 1])
122
+ :version 0}))
123
+
124
+ 'datahike.index.hitchhiker_tree.upsert.temporal_UpsertOp
125
+ (fn [{:keys [key value op-count ts indices]}]
126
+ (map->temporal-UpsertOp {:key key :value value :op-count (or op-count ts) :indices (or indices [0 1])
127
+ :version 0}))})
128
+ store)
@@ -0,0 +1,213 @@
1
+ (ns ^:no-doc datahike.index.hitchhiker-tree
2
+ (:require [datahike.index.hitchhiker-tree.upsert :as ups]
3
+ [datahike.index.hitchhiker-tree.insert :as ins]
4
+ [datahike.index.utils :as diu]
5
+ [hitchhiker.tree.bootstrap.konserve :as hk]
6
+ [hitchhiker.tree.utils.async :as async]
7
+ [hitchhiker.tree.messaging :as hmsg]
8
+ [hitchhiker.tree.key-compare :as kc]
9
+ [hitchhiker.tree :as tree]
10
+ [datahike.array :refer [compare-arrays]]
11
+ [datahike.datom :as dd]
12
+ [datahike.constants :refer [e0 tx0 emax txmax]]
13
+ [clojure.spec.alpha :as s]
14
+ [datahike.index.interface :as di :refer [IIndex]])
15
+ #?(:clj (:import [clojure.lang AMapEntry]
16
+ [hitchhiker.tree DataNode IndexNode]
17
+ [datahike.datom Datom])))
18
+
19
+ (def ^:const default-index-b-factor 17)
20
+ (def ^:const default-index-data-node-size 300)
21
+ (def ^:const default-index-log-size (- 300 17))
22
+
23
+ (extend-protocol kc/IKeyCompare
24
+ clojure.lang.PersistentVector
25
+ (-compare [key1 key2]
26
+ (if-not (= (class key2) clojure.lang.PersistentVector)
27
+ (if (nil? key2)
28
+ +1 ;; Case for tuples. E.g. (compare [100 200] nil)
29
+ -1) ;; HACK for nil
30
+ (let [[a b c d] key1
31
+ [e f g h] key2]
32
+ (dd/combine-cmp
33
+ (kc/-compare a e)
34
+ (kc/-compare b f)
35
+ (kc/-compare c g)
36
+ (kc/-compare d h)))))
37
+ java.lang.String
38
+ (-compare [key1 key2]
39
+ (compare key1 key2))
40
+ clojure.lang.Keyword
41
+ (-compare [key1 key2]
42
+ (compare key1 key2))
43
+ nil
44
+ (-compare [key1 key2]
45
+ (if (nil? key2)
46
+ 0 -1)))
47
+
48
+ (extend-protocol kc/IKeyCompare
49
+ (Class/forName "[B")
50
+ (-compare [key1 key2]
51
+ (compare-arrays key1 key2)))
52
+
53
+ (defn- index-type->datom-fn [index-type]
54
+ (case index-type
55
+ :aevt (fn [a e v tx] (dd/datom e a v tx true))
56
+ :avet (fn [a v e tx] (dd/datom e a v tx true))
57
+ (fn [e a v tx] (dd/datom e a v tx true))))
58
+
59
+ (defn slice [tree from to index-type]
60
+ (let [[a b c d] (diu/datom-to-vec from index-type true)
61
+ cmp (diu/prefix-scan kc/-compare (diu/datom-to-vec to index-type false))
62
+ xf (comp
63
+ (take-while (fn [^AMapEntry kv] (cmp (.key kv))))
64
+ (map (fn [kv]
65
+ (let [[a b c d] (.key ^AMapEntry kv)]
66
+ ((index-type->datom-fn index-type) a b c d)))))]
67
+ (->> (sequence xf (hmsg/lookup-fwd-iter tree [a b c d]))
68
+ seq)))
69
+
70
+ (defn datom-seq [tree index-type]
71
+ (slice tree (dd/datom e0 nil nil tx0) (dd/datom emax nil nil txmax) index-type))
72
+
73
+ (defn datom-count [tree index-type]
74
+ (count (datom-seq tree index-type)))
75
+
76
+ (defn all-datoms [tree index-type]
77
+ (map
78
+ #(apply
79
+ (index-type->datom-fn index-type)
80
+ (first %))
81
+ (hmsg/lookup-fwd-iter tree [])))
82
+
83
+ (defn- datom->node [^Datom datom index-type]
84
+ (case index-type
85
+ :aevt [(.-a datom) (.-e datom) (.-v datom) (.-tx datom)]
86
+ :avet [(.-a datom) (.-v datom) (.-e datom) (.-tx datom)]
87
+ :eavt [(.-e datom) (.-a datom) (.-v datom) (.-tx datom)]
88
+ (throw (IllegalArgumentException. (str "Unknown index-type: " index-type)))))
89
+
90
+ (defn- index-type->indices [index-type]
91
+ (case index-type
92
+ :eavt [0 1]
93
+ :aevt [0 1]
94
+ :avet [0 2]
95
+ (throw (UnsupportedOperationException. "Unknown index type: " index-type))))
96
+
97
+ (defn insert [tree ^Datom datom index-type op-count]
98
+ (let [datom-as-vec (datom->node datom index-type)]
99
+ (async/<?? (hmsg/enqueue tree [(ins/new-InsertOp datom-as-vec op-count)]))))
100
+
101
+ (defn temporal-insert [tree ^Datom datom index-type op-count]
102
+ (let [datom-as-vec (datom->node datom index-type)]
103
+ (async/<?? (hmsg/enqueue tree [(ins/new-temporal-InsertOp datom-as-vec op-count)]))))
104
+
105
+ (defn upsert [tree ^Datom datom index-type op-count]
106
+ (let [datom-as-vec (datom->node datom index-type)]
107
+ (async/<?? (hmsg/enqueue tree [(ups/new-UpsertOp datom-as-vec op-count (index-type->indices index-type))]))))
108
+
109
+ (defn temporal-upsert [tree ^Datom datom index-type op-count]
110
+ (let [datom-as-vec (datom->node datom index-type)]
111
+ (async/<?? (hmsg/enqueue tree [(ups/new-temporal-UpsertOp datom-as-vec op-count (index-type->indices index-type))]))))
112
+
113
+ (defn remove-datom [tree ^Datom datom index-type op-count]
114
+ (async/<?? (hmsg/delete tree (datom->node datom index-type) op-count)))
115
+
116
+ (defn flush-tree [tree backend]
117
+ (:tree (async/<?? (tree/flush-tree-without-root tree backend))))
118
+
119
+ (defn mark [_tree]
120
+ (throw (ex-info "Mark phase not implemented for hitchhiker-tree."
121
+ {:type :gc-not-implemented})))
122
+
123
+ (extend-type DataNode
124
+ IIndex
125
+ (-all [eavt-tree]
126
+ (all-datoms eavt-tree :eavt))
127
+ (-seq [eavt-tree]
128
+ (datom-seq eavt-tree :eavt))
129
+ (-count [eavt-tree]
130
+ (datom-count eavt-tree :eavt))
131
+ (-insert [tree datom index-type op-count]
132
+ (insert tree datom index-type op-count))
133
+ (-temporal-insert [tree datom index-type op-count]
134
+ (temporal-insert tree datom index-type op-count))
135
+ (-upsert [tree datom index-type op-count _old-datom]
136
+ (upsert tree datom index-type op-count))
137
+ (-temporal-upsert [tree datom index-type op-count _old-datom]
138
+ (temporal-upsert tree datom index-type op-count))
139
+ (-remove [tree datom index-type op-count]
140
+ (remove-datom tree datom index-type op-count))
141
+ (-slice [tree from to index-type]
142
+ (slice tree from to index-type))
143
+ (-flush [tree backend]
144
+ (flush-tree tree backend))
145
+ (-transient [tree]
146
+ (identity tree))
147
+ (-persistent! [tree]
148
+ (identity tree))
149
+ (-mark [tree]
150
+ (mark tree)))
151
+
152
+ (extend-type IndexNode
153
+ IIndex
154
+ (-all [eavt-tree]
155
+ (all-datoms eavt-tree :eavt))
156
+ (-seq [eavt-tree]
157
+ (datom-seq eavt-tree :eavt))
158
+ (-count [eavt-tree]
159
+ (datom-count eavt-tree :eavt))
160
+ (-insert [tree datom index-type op-count]
161
+ (insert tree datom index-type op-count))
162
+ (-temporal-insert [index datom index-type op-count]
163
+ (temporal-insert index datom index-type op-count))
164
+ (-upsert [tree datom index-type op-count _old-datom]
165
+ (upsert tree datom index-type op-count))
166
+ (-temporal-upsert [tree datom index-type op-count _old-datom]
167
+ (temporal-upsert tree datom index-type op-count))
168
+ (-remove [tree datom index-type op-count]
169
+ (remove-datom tree datom index-type op-count))
170
+ (-slice [tree from to index-type]
171
+ (slice tree from to index-type))
172
+ (-flush [tree backend]
173
+ (flush-tree tree backend))
174
+ (-transient [tree]
175
+ (identity tree))
176
+ (-persistent! [tree]
177
+ (identity tree))
178
+ (-mark [tree]
179
+ (mark tree)))
180
+
181
+ (defn empty-tree [b-factor data-node-size log-size]
182
+ (async/<?? (tree/b-tree (tree/->Config b-factor data-node-size log-size))))
183
+
184
+ (defmethod di/empty-index :datahike.index/hitchhiker-tree
185
+ [_index-name _store _index-type {:keys [index-b-factor index-data-node-size index-log-size]}]
186
+ (empty-tree index-b-factor index-data-node-size index-log-size))
187
+
188
+ (defmethod di/init-index :datahike.index/hitchhiker-tree
189
+ [_index-name _store datoms index-type op-count {:keys [index-b-factor index-data-node-size index-log-size]}]
190
+ (async/<??
191
+ (async/reduce<
192
+ (fn [tree [idx datom]]
193
+ (insert tree datom index-type (+ idx op-count)))
194
+ (empty-tree index-b-factor index-data-node-size index-log-size)
195
+ (map-indexed (fn [idx datom] [idx datom]) (seq datoms)))))
196
+
197
+ (defmethod di/add-konserve-handlers :datahike.index/hitchhiker-tree [_config store]
198
+ (ups/add-upsert-handler
199
+ (ins/add-insert-handler
200
+ (hk/add-hitchhiker-tree-handlers
201
+ store))))
202
+
203
+ (defmethod di/konserve-backend :datahike.index/hitchhiker-tree [_index-name store]
204
+ (hk/->KonserveBackend store true))
205
+
206
+ (s/def ::index-b-factor long)
207
+ (s/def ::index-log-size long)
208
+ (s/def ::index-data-node-size long)
209
+
210
+ (defmethod di/default-index-config :datahike.index/hitchhiker-tree [_index-name]
211
+ {:index-b-factor default-index-b-factor
212
+ :index-log-size default-index-log-size
213
+ :index-data-node-size default-index-data-node-size})
@@ -0,0 +1,37 @@
1
+ (ns backward-test
2
+ (:require [datahike.api :as d]
3
+ [taoensso.timbre :as t]))
4
+
5
+ (def schema [{:db/ident :age
6
+ :db/cardinality :db.cardinality/one
7
+ :db/valueType :db.type/long}])
8
+ (def cfg {:store {:backend :file
9
+ :path "/tmp/datahike-backward-comp-test"
10
+ :id #uuid "550e8400-e29b-41d4-a716-446655440000"}
11
+ :keep-history? true
12
+ :schema-flexibility :write
13
+ :initial-tx schema})
14
+
15
+ (def size 10000)
16
+
17
+ (defn write [opt]
18
+ (t/info "Writing to db using latest released version of datahike ....")
19
+ (t/set-level! :warn)
20
+
21
+ (d/delete-database cfg)
22
+ (d/create-database cfg)
23
+ (let [conn (d/connect cfg)]
24
+ (d/transact conn
25
+ (vec (for [i (range size)]
26
+ [:db/add (inc i) :age i]))))
27
+ (t/info "Wrote " size " entries."))
28
+
29
+ (defn read [opt]
30
+ (t/info "Reading using latest code ....")
31
+ (let [conn (d/connect cfg)
32
+ res (first (d/q '[:find (count ?a)
33
+ :in $
34
+ :where [?e :age ?a]]
35
+ @conn))]
36
+ (assert (= [size] res))
37
+ (t/info "Read " (first res) " entries.")))
@@ -0,0 +1,14 @@
1
+ (ns datahike.integration-test.config-record-file-test
2
+ (:require [clojure.test :refer :all]
3
+ [datahike.integration-test :as it]))
4
+
5
+ (def config {:store {:backend :file :path "/tmp/file-test-1" :id #uuid "f11e0001-0000-0000-0000-000000000001"}})
6
+
7
+ (defn config-record-file-test-fixture [f]
8
+ (it/integration-test-fixture config)
9
+ (f))
10
+
11
+ (use-fixtures :once config-record-file-test-fixture)
12
+
13
+ (deftest ^:integration config-record-file-test []
14
+ (it/integration-test config))
@@ -0,0 +1,14 @@
1
+ (ns datahike.integration-test.config-record-test
2
+ (:require [clojure.test :refer :all]
3
+ [datahike.integration-test :as it]))
4
+
5
+ (def config {:store {:backend :memory :id #uuid "c0ff1c00-0000-0000-0000-000000000001"}})
6
+
7
+ (defn config-record-test-fixture [f]
8
+ (it/integration-test-fixture config)
9
+ (f))
10
+
11
+ (use-fixtures :once config-record-test-fixture)
12
+
13
+ (deftest ^:integration config-record-test []
14
+ (it/integration-test config))
@@ -0,0 +1,15 @@
1
+ (ns datahike.integration-test.depr-config-uri-test
2
+ (:require [clojure.test :refer :all]
3
+ [datahike.integration-test :as it]))
4
+
5
+ (def config "datahike:file:///tmp/file-test-3?id=5c6e0000-0000-0000-0000-000000000003")
6
+
7
+ (defn depr-config-uri-fixture [f]
8
+ (println "deprecated file uri config: " config)
9
+ (it/integration-test-fixture config)
10
+ (f))
11
+
12
+ (use-fixtures :once depr-config-uri-fixture)
13
+
14
+ (deftest ^:integration depr-config-uri-test []
15
+ (it/integration-test config))
@@ -0,0 +1,62 @@
1
+ (ns datahike.integration-test.return-map-test
2
+ (:require [clojure.test :refer [deftest is use-fixtures]]
3
+ [datahike.api :as d]))
4
+
5
+ (def config {:store {:backend :memory :id #uuid "0e7000a9-0000-0000-0000-000000000001"}})
6
+
7
+ (defn return-map-test-fixture [f]
8
+ (d/delete-database config)
9
+ (d/create-database config)
10
+ (def conn (d/connect config))
11
+ ;; the first transaction will be the schema we are using
12
+ (d/transact conn [{:db/ident :name
13
+ :db/valueType :db.type/string
14
+ :db/cardinality :db.cardinality/one}
15
+ {:db/ident :age
16
+ :db/valueType :db.type/long
17
+ :db/cardinality :db.cardinality/one}])
18
+
19
+ ;; lets add some data and wait for the transaction
20
+ (d/transact conn [{:name "Alice", :age 20}
21
+ {:name "Bob", :age 30}
22
+ {:name "Charlie", :age 40}])
23
+
24
+ (f))
25
+
26
+ (use-fixtures :once return-map-test-fixture)
27
+
28
+ (deftest return-keys-test
29
+ ;; search the data
30
+ (is (= [{:entity 4 :name "Bob" :age 30}
31
+ {:entity 5 :name "Charlie" :age 40}
32
+ {:entity 3 :name "Alice" :age 20}]
33
+ (d/q '[:find ?e ?n ?a
34
+ :keys entity name age
35
+ :where
36
+ [?e :name ?n]
37
+ [?e :age ?a]]
38
+ @conn))))
39
+
40
+ (deftest return-syms-test
41
+ ;; search the data
42
+ (is (= [{'entity 4 'name "Bob" 'age 30}
43
+ {'entity 5 'name "Charlie" 'age 40}
44
+ {'entity 3 'name "Alice" 'age 20}]
45
+ (d/q '[:find ?e ?n ?a
46
+ :syms entity name age
47
+ :where
48
+ [?e :name ?n]
49
+ [?e :age ?a]]
50
+ @conn))))
51
+
52
+ (deftest return-strs-test
53
+ ;; search the data
54
+ (is (= [{"entity" 4 "name" "Bob" "age" 30}
55
+ {"entity" 5 "name" "Charlie" "age" 40}
56
+ {"entity" 3 "name" "Alice" "age" 20}]
57
+ (d/q '[:find ?e ?n ?a
58
+ :strs entity name age
59
+ :where
60
+ [?e :name ?n]
61
+ [?e :age ?a]]
62
+ @conn))))
@@ -0,0 +1,67 @@
1
+ (ns ^:no-doc datahike.integration-test
2
+ "This namespace is the minimum test a Datahike backend needs to pass for compatibility assessment."
3
+ (:require [clojure.test :refer [is]]
4
+ [datahike.api :as d]
5
+ ;; Load hitchhiker-tree for backwards compatibility with existing test databases
6
+ #?(:clj [datahike.index.hitchhiker-tree])))
7
+
8
+ (defn integration-test-fixture [config]
9
+ (d/delete-database config)
10
+ (d/create-database config)
11
+ (let [conn (d/connect config)]
12
+ (d/transact conn [{:db/ident :name
13
+ :db/valueType :db.type/string
14
+ :db/cardinality :db.cardinality/one}
15
+ {:db/ident :age
16
+ :db/valueType :db.type/long
17
+ :db/cardinality :db.cardinality/one}])
18
+
19
+ ;; lets add some data and wait for the transaction
20
+ (d/transact conn [{:name "Alice", :age 20}
21
+ {:name "Bob", :age 30}
22
+ {:name "Charlie", :age 40}
23
+ {:age 15}])
24
+ (d/release conn)))
25
+
26
+ (defn integration-test [config]
27
+ (let [conn (d/connect config)]
28
+ ;; search the data
29
+ (is (= #{[3 "Alice" 20] [4 "Bob" 30] [5 "Charlie" 40]}
30
+ (d/q '[:find ?e ?n ?a
31
+ :where
32
+ [?e :name ?n]
33
+ [?e :age ?a]]
34
+ @conn)))
35
+
36
+ ;; add new entity data using a hash map
37
+ (d/transact conn {:tx-data [{:db/id 3 :age 25}]})
38
+
39
+ ;; if you want to work with queries like in
40
+ ;; https://grishaev.me/en/datomic-query/,
41
+ ;; you may use a hashmap
42
+ (is (= #{[5 "Charlie" 40] [4 "Bob" 30] [3 "Alice" 25]}
43
+ (d/q {:query '{:find [?e ?n ?a]
44
+ :where [[?e :name ?n]
45
+ [?e :age ?a]]}
46
+ :args [@conn]})))
47
+
48
+ ;; query the history of the data
49
+ (is (= #{[20] [25]}
50
+ (d/q '[:find ?a
51
+ :where
52
+ [?e :name "Alice"]
53
+ [?e :age ?a]]
54
+ (d/history @conn))))
55
+
56
+ ;; you might need to release the connection, e.g. for leveldb
57
+ (is (= nil (d/release conn)))
58
+
59
+ ;; database should exist
60
+ (is (d/database-exists? config))
61
+
62
+ ;; clean up the database if it is not needed any more
63
+ (d/delete-database config)
64
+
65
+ ;; database should not exist
66
+ (is (not (d/database-exists? config)))))
67
+
@@ -0,0 +1,124 @@
1
+ (ns datahike.norm.norm-test
2
+ (:require [clojure.test :refer [deftest is]]
3
+ [clojure.string :as string]
4
+ [clojure.java.io :as io]
5
+ [datahike.api :as d]
6
+ [datahike.norm.norm :as sut :refer [verify-checksums]]
7
+ [datahike.test.utils :as tu]))
8
+
9
+ (def ensure-norms #'sut/ensure-norms)
10
+
11
+ (deftest simple-test
12
+ (let [conn (tu/setup-db {} true)
13
+ _ (verify-checksums (io/file "test/datahike/norm/resources/simple-test"))
14
+ _ (ensure-norms conn (io/file "test/datahike/norm/resources/simple-test"))
15
+ schema (d/schema (d/db conn))]
16
+ (is (= #:db{:valueType :db.type/string, :cardinality :db.cardinality/one, :doc "Place of occupation", :ident :character/place-of-occupation}
17
+ (-> (schema :character/place-of-occupation)
18
+ (dissoc :db/id))))
19
+ (is (= #:db{:valueType :db.type/string, :cardinality :db.cardinality/one, :doc "Simpsons character name", :ident :character/name, :db/unique :db.unique/identity}
20
+ (-> (schema :character/name)
21
+ (dissoc :db/id))))
22
+ (is (= #:db{:ident :tx/norm, :valueType :db.type/keyword, :cardinality :db.cardinality/one}
23
+ (-> (schema :tx/norm)
24
+ (dissoc :db/id))))
25
+ (d/release conn)))
26
+
27
+ (defn tx-fn-test-fn [conn]
28
+ (-> (for [[eid value] (d/q '[:find ?e ?v
29
+ :where
30
+ [?e :character/place-of-occupation ?v]]
31
+ (d/db conn))]
32
+ [:db/add eid
33
+ :character/place-of-occupation (string/lower-case value)])
34
+ vec))
35
+
36
+ (deftest tx-fn-test
37
+ (let [conn (tu/setup-db {} true)
38
+ _ (verify-checksums (io/file "test/datahike/norm/resources/tx-fn-test/first"))
39
+ _ (ensure-norms conn (io/file "test/datahike/norm/resources/tx-fn-test/first"))
40
+ _ (d/transact conn {:tx-data [{:character/place-of-occupation "SPRINGFIELD ELEMENTARY SCHOOL"}
41
+ {:character/place-of-occupation "SPRINGFIELD NUCLEAR POWER PLANT"}]})
42
+ _ (verify-checksums (io/file "test/datahike/norm/resources/tx-fn-test/second"))
43
+ _ (ensure-norms conn (io/file "test/datahike/norm/resources/tx-fn-test/second"))]
44
+ (is (= #{["springfield elementary school"] ["springfield nuclear power plant"]}
45
+ (d/q '[:find ?v
46
+ :where
47
+ [_ :character/place-of-occupation ?v]]
48
+ (d/db conn))))
49
+ (d/release conn)))
50
+
51
+ (defn tx-data-and-tx-fn-test-fn [conn]
52
+ (-> (for [[eid]
53
+ (d/q '[:find ?e
54
+ :where
55
+ [?e :character/name]
56
+ (or-join [?e]
57
+ [?e :character/name "Homer Simpson"]
58
+ [?e :character/name "Marge Simpson"])]
59
+ (d/db conn))]
60
+ {:db/id eid
61
+ :character/children [[:character/name "Bart Simpson"]
62
+ [:character/name "Lisa Simpson"]
63
+ [:character/name "Maggie Simpson"]]})
64
+ vec))
65
+
66
+ (deftest tx-data-and-tx-fn-test
67
+ (let [conn (tu/setup-db {} true)
68
+ _ (verify-checksums (io/file "test/datahike/norm/resources/tx-data-and-tx-fn-test/first"))
69
+ _ (ensure-norms conn (io/file "test/datahike/norm/resources/tx-data-and-tx-fn-test/first"))
70
+ _ (d/transact conn {:tx-data [{:character/name "Homer Simpson"}
71
+ {:character/name "Marge Simpson"}
72
+ {:character/name "Bart Simpson"}
73
+ {:character/name "Lisa Simpson"}
74
+ {:character/name "Maggie Simpson"}]})
75
+ _ (verify-checksums (io/file "test/datahike/norm/resources/tx-data-and-tx-fn-test/second"))
76
+ _ (ensure-norms conn (io/file "test/datahike/norm/resources/tx-data-and-tx-fn-test/second"))
77
+ margehomer (d/q '[:find [?e ...]
78
+ :where
79
+ [?e :character/name]
80
+ (or-join [?e]
81
+ [?e :character/name "Homer Simpson"]
82
+ [?e :character/name "Marge Simpson"])]
83
+ (d/db conn))]
84
+ (is (= [#:character{:name "Homer Simpson",
85
+ :children
86
+ [#:character{:name "Bart Simpson"}
87
+ #:character{:name "Lisa Simpson"}
88
+ #:character{:name "Maggie Simpson"}]}
89
+ #:character{:name "Marge Simpson",
90
+ :children
91
+ [#:character{:name "Bart Simpson"}
92
+ #:character{:name "Lisa Simpson"}
93
+ #:character{:name "Maggie Simpson"}]}]
94
+ (d/pull-many (d/db conn) '[:character/name {:character/children [:character/name]}] margehomer)))
95
+ (d/release conn)))
96
+
97
+ (defn naming-and-sorting-test-fn [conn]
98
+ (-> (for [[eid] (d/q '[:find ?e
99
+ :where
100
+ [?e :character/name]
101
+ (or-join [?e]
102
+ [?e :character/name "Bart Simpson"]
103
+ [?e :character/name "Lisa Simpson"])]
104
+ (d/db conn))]
105
+ {:db/id eid
106
+ :character/occupation :student})
107
+ vec))
108
+
109
+ (deftest naming-and-sorting-test
110
+ (let [conn (tu/setup-db {} true)
111
+ _ (verify-checksums (io/file "test/datahike/norm/resources/naming-and-sorting-test"))
112
+ _ (sut/ensure-norms! conn (io/file "test/datahike/norm/resources/naming-and-sorting-test"))
113
+ lisabart (d/q '[:find [?e ...]
114
+ :where
115
+ [?e :character/occupation :student]]
116
+ (d/db conn))]
117
+ (is (= [{:db/id 10,
118
+ :character/name "Bart Simpson",
119
+ :character/occupation :student}
120
+ {:db/id 11,
121
+ :character/name "Lisa Simpson",
122
+ :character/occupation :student}]
123
+ (d/pull-many (d/db conn) '[*] lisabart)))
124
+ (d/release conn)))