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,956 @@
1
+ (ns ^:no-doc datahike.db
2
+ (:refer-clojure :exclude [seqable?])
3
+ (:require
4
+ [clojure.data :as data]
5
+ [clojure.walk :refer [postwalk]]
6
+ #?(:clj [clojure.pprint :as pp])
7
+ [datahike.config :as dc]
8
+ [datahike.constants :as c :refer [ue0 e0 tx0 utx0 emax txmax system-schema]]
9
+ [datahike.datom :as dd :refer [datom datom-tx datom-added]]
10
+ [datahike.db.interface :as dbi]
11
+ [datahike.db.search :as dbs]
12
+ [datahike.db.utils :as dbu]
13
+ [datahike.index :as di]
14
+ [datahike.schema :as ds]
15
+ [datahike.store :as store]
16
+ [datahike.tools :as tools :refer [raise group-by-step #?(:clj meta-data)]]
17
+ [org.replikativ.persistent-sorted-set.arrays :as arrays]
18
+ [medley.core :as m]
19
+ [taoensso.timbre :refer [warn]])
20
+ #?(:cljs (:require-macros [datahike.db :refer [defrecord-updatable]]
21
+ [datahike.datom :refer [combine-cmp datom]]
22
+ [datahike.tools :refer [raise meta-data]]))
23
+ #?(:clj (:import [clojure.lang AMapEntry ITransientCollection IEditableCollection IPersistentCollection Seqable
24
+ IHashEq Associative IKeywordLookup ILookup]
25
+ [datahike.datom Datom]
26
+ [java.io Writer]
27
+ [java.util Date])))
28
+
29
+ (declare equiv-db empty-db)
30
+ #?(:cljs (declare pr-db))
31
+
32
+ ;; ----------------------------------------------------------------------------
33
+ ;; macros and funcs to support writing defrecords and updating
34
+ ;; (replacing) builtins, i.e., Object/hashCode, IHashEq hasheq, etc.
35
+ ;; code taken from prismatic:
36
+ ;; https://github.com/Prismatic/schema/commit/e31c419c56555c83ef9ee834801e13ef3c112597
37
+ ;;
38
+
39
+ ;; ----------------------------------------------------------------------------
40
+
41
+ #?(:cljs
42
+ (do
43
+ (def Exception js/Error)
44
+ (def IllegalArgumentException js/Error)
45
+ (def UnsupportedOperationException js/Error)))
46
+
47
+ ;; ----------------------------------------------------------------------------
48
+
49
+ (defn #?@(:clj [^Boolean seqable?]
50
+ :cljs [^boolean seqable?])
51
+ [x]
52
+ (and (not (string? x))
53
+ #?(:cljs (or (cljs.core/seqable? x)
54
+ (arrays/array? x))
55
+ :clj (or (seq? x)
56
+ (instance? Seqable x)
57
+ (nil? x)
58
+ (instance? Iterable x)
59
+ (arrays/array? x)
60
+ (instance? java.util.Map x)))))
61
+
62
+ (defn- cljs-env?
63
+ "Take the &env from a macro, and tell whether we are expanding into cljs."
64
+ [env]
65
+ (boolean (:ns env)))
66
+
67
+ #?(:clj
68
+ (defmacro if-cljs
69
+ "Return then if we are generating cljs code and else for Clojure code.
70
+ https://groups.google.com/d/msg/clojurescript/iBY5HaQda4A/w1lAQi9_AwsJ"
71
+ [then else]
72
+ (if (cljs-env? &env) then else)))
73
+
74
+ #?(:clj
75
+ (defn- get-sig [method]
76
+ ;; expects something like '(method-symbol [arg arg arg] ...)
77
+ ;; if the thing matches, returns [fully-qualified-symbol arity], otherwise nil
78
+ (and (sequential? method)
79
+ (symbol? (first method))
80
+ (vector? (second method))
81
+ (let [sym (first method)
82
+ ns (or (some->> sym resolve meta :ns str) "clojure.core")]
83
+ [(symbol ns (name sym)) (-> method second count)]))))
84
+
85
+ #?(:clj
86
+ (defn- dedupe-interfaces [deftype-form]
87
+ ;; get the interfaces list, remove any duplicates, similar to remove-nil-implements in potemkin
88
+ ;; verified w/ deftype impl in compiler:
89
+ ;; (deftype* tagname classname [fields] :implements [interfaces] :tag tagname methods*)
90
+ (let [[deftype* tagname classname fields implements interfaces & rest] deftype-form]
91
+ (when (or (not= deftype* 'deftype*) (not= implements :implements))
92
+ (throw (IllegalArgumentException. "deftype-form mismatch")))
93
+ (list* deftype* tagname classname fields implements (vec (distinct interfaces)) rest))))
94
+
95
+ #?(:clj
96
+ (defn- make-record-updatable-clj [name fields & impls]
97
+ (let [impl-map (->> impls (map (juxt get-sig identity)) (filter first) (into {}))
98
+ body (macroexpand-1 (list* 'defrecord name fields impls))]
99
+ (postwalk
100
+ (fn [form]
101
+ (if (and (sequential? form) (= 'deftype* (first form)))
102
+ (->> form
103
+ dedupe-interfaces
104
+ (remove (fn [method]
105
+ (when-let [impl (-> method get-sig impl-map)]
106
+ (not= method impl)))))
107
+ form))
108
+ body))))
109
+
110
+ ;; This doesn't work, it creates duplicate implementation warnings.
111
+ #_(:clj
112
+ (defn- make-record-updatable-cljs [name fields & impls]
113
+ `(defrecord ~name ~fields ~@impls)))
114
+
115
+ #?(:clj
116
+ (defn- make-record-updatable-cljs [name fields & impls]
117
+ `(do
118
+ (defrecord ~name ~fields)
119
+ (extend-type ~name ~@impls))))
120
+
121
+ #?(:clj
122
+ (defmacro defrecord-updatable [name fields & impls]
123
+ `(if-cljs
124
+ ~(apply make-record-updatable-cljs name fields impls)
125
+ ~(apply make-record-updatable-clj name fields impls))))
126
+
127
+ ;; TxReport
128
+
129
+ (defrecord TxReport [db-before db-after tx-data tempids tx-meta])
130
+
131
+ ;; DB
132
+
133
+ (defn- date? [d]
134
+ #?(:cljs (instance? js/Date d)
135
+ :clj (instance? Date d)))
136
+
137
+ (defn- date<= [^Date a ^Date b]
138
+ #?(:cljs (not (< (.getTime b) (.getTime a)))
139
+ :clj (not (.before b a))))
140
+
141
+ (defn- as-of-pred
142
+ "Create an as-of predicate, *including* the time-point"
143
+ [time-point]
144
+ (if (date? time-point)
145
+ (fn [^Datom d] (date<= (.-v d) time-point))
146
+ (fn [^Datom d] (<= (dd/datom-tx d) time-point))))
147
+
148
+ (defn- since-pred
149
+ "Create a since predicate, *excluding* the time-point. The opposite of `as-of-pred`."
150
+ [time-point]
151
+ (complement (as-of-pred time-point)))
152
+
153
+ (defn assemble-datoms-xform [db]
154
+ (mapcat
155
+ (fn [[[_ a] datoms]]
156
+ (if (dbu/multival? db a)
157
+ (->> datoms
158
+ (sort-by datom-tx)
159
+ (reduce (fn [current-datoms ^Datom datom]
160
+ (if (datom-added datom)
161
+ (assoc current-datoms (.-v datom) datom)
162
+ (dissoc current-datoms (.-v datom))))
163
+ {})
164
+ vals)
165
+ (let [last-ea-tx (apply max (map datom-tx datoms))
166
+ current-ea-datom (first (filter #(and (datom-added %) (= last-ea-tx (datom-tx %)))
167
+ datoms))]
168
+ (if current-ea-datom
169
+ [current-ea-datom]
170
+ []))))))
171
+
172
+ (defn temporal-datom-filter [datoms pred db]
173
+ (let [filtered-tx-ids (dbu/filter-txInstant datoms pred db)]
174
+ (filter (fn [^Datom d]
175
+ (contains? filtered-tx-ids
176
+ (datom-tx d))))))
177
+
178
+ (defn- post-process-datoms [datoms db context]
179
+ (let [xform (dbi/context-xform context)
180
+ time-pred (dbi/context-time-pred context)]
181
+ (cond
182
+
183
+ time-pred
184
+ (let [time-xform (temporal-datom-filter datoms time-pred db)]
185
+ (if (dbi/context-historical? context)
186
+ (into [] (dbi/nil-comp time-xform xform) datoms)
187
+ (->> datoms
188
+ (transduce time-xform
189
+ (group-by-step (fn [^Datom datom]
190
+ [(.-e datom) (.-a datom)])))
191
+ (into [] (dbi/nil-comp (assemble-datoms-xform db) xform)))))
192
+
193
+ xform (into [] xform datoms)
194
+
195
+ :else datoms)))
196
+
197
+ (defn db-transient [db]
198
+ (-> db
199
+ (update :eavt di/-transient)
200
+ (update :aevt di/-transient)
201
+ (update :avet di/-transient)))
202
+
203
+ (defn db-persistent! [db]
204
+ (-> db
205
+ (update :eavt di/-persistent!)
206
+ (update :aevt di/-persistent!)
207
+ (update :avet di/-persistent!)))
208
+
209
+ (defn contextual-search-fn [context]
210
+ (case (dbi/context-temporal? context)
211
+ true dbs/temporal-search
212
+ false dbs/search-current-indices))
213
+
214
+ (defn contextual-search [db pattern context]
215
+ (-> ((contextual-search-fn context) db pattern)
216
+ (post-process-datoms db context)))
217
+
218
+ (defn contextual-batch-search [db pattern-mask batch-fn context]
219
+ (-> ((contextual-search-fn context) db pattern-mask batch-fn)
220
+ (post-process-datoms db context)))
221
+
222
+ (defn contextual-datoms [db index-type cs context]
223
+ (-> (case (dbi/context-temporal? context)
224
+ true (dbu/temporal-datoms db index-type cs)
225
+ false (di/-slice
226
+ (get db index-type)
227
+ (dbu/components->pattern db index-type cs e0 tx0)
228
+ (dbu/components->pattern db index-type cs emax txmax)
229
+ index-type))
230
+ (post-process-datoms db context)))
231
+
232
+ (defn contextual-seek-datoms [db index-type cs context]
233
+ (-> (case (dbi/context-temporal? context)
234
+ true (dbs/temporal-seek-datoms db index-type cs)
235
+ false (di/-slice (get db index-type)
236
+ (dbu/components->pattern db index-type cs e0 tx0)
237
+ (datom emax nil nil txmax)
238
+ index-type))
239
+ (post-process-datoms db context)))
240
+
241
+ (defn contextual-rseek-datoms [db index-type cs context]
242
+ (-> (case (dbi/context-temporal? context)
243
+ true (dbs/temporal-rseek-datoms db index-type cs)
244
+ false (-> (di/-slice (get db index-type)
245
+ (dbu/components->pattern db index-type cs e0 tx0)
246
+ (datom emax nil nil txmax)
247
+ index-type)
248
+ vec
249
+ rseq))
250
+ (post-process-datoms db context)))
251
+
252
+ (defn contextual-index-range [db avet attr start end context]
253
+ (let [temporal? (dbi/context-temporal? context)
254
+ current-db (dbi/context-current-db context)]
255
+ (assert (or (not temporal?) current-db))
256
+ (-> (case temporal?
257
+ true (dbs/temporal-index-range db current-db attr start end)
258
+ false (do (when-not (dbu/indexing? db attr)
259
+ (raise "Attribute"
260
+ attr "should be marked as :db/index true" {}))
261
+
262
+ (dbu/validate-attr
263
+ attr (list '-index-range 'db attr start end) db)
264
+ (di/-slice
265
+ avet
266
+ (dbu/resolve-datom db nil attr start nil e0 tx0)
267
+ (dbu/resolve-datom db nil attr end nil emax txmax)
268
+ :avet)))
269
+ (post-process-datoms db context))))
270
+
271
+ (defn deeper-index-range [origin-db db attr start end context]
272
+ (dbi/-index-range origin-db
273
+ attr
274
+ start
275
+ end
276
+ (dbi/context-set-current-db-if-not-set context db)))
277
+
278
+ (defrecord-updatable DB [schema eavt aevt avet temporal-eavt temporal-aevt temporal-avet max-eid max-tx op-count rschema hash config system-entities ident-ref-map ref-ident-map meta]
279
+ #?@(:cljs
280
+ [IHash (-hash [db] (.-hash db))
281
+ IEquiv (-equiv [db other] (equiv-db db other))
282
+ ISeqable (-seq [db] (di/-seq (.-eavt db)))
283
+ IReversible (-rseq [db] (-rseq (.-eavt db)))
284
+ ICounted (-count [db] (count (.-eavt db)))
285
+ IEmptyableCollection (-empty [db] (empty-db (ds/get-user-schema db)))
286
+ IPrintWithWriter (-pr-writer [db w opts] (pr-db db w opts))
287
+ IEditableCollection (-as-transient [db] (db-transient db))
288
+ ITransientCollection (-conj! [db key] (throw (ex-info "datahike.DB/conj! is not supported" {})))
289
+ (-persistent! [db] (db-persistent! db))]
290
+
291
+ :clj
292
+ [Object (hashCode [db] hash)
293
+ clojure.lang.IHashEq (hasheq [db] hash)
294
+ Seqable (seq [db] (di/-seq eavt))
295
+ IPersistentCollection
296
+ (count [db] (di/-count eavt))
297
+ (equiv [db other] (equiv-db db other))
298
+ (empty [db] (empty-db (ds/get-user-schema db)))
299
+ IEditableCollection
300
+ (asTransient [db] (db-transient db))
301
+ ITransientCollection
302
+ (conj [db key] (throw (ex-info "datahike.DB/conj! is not supported" {})))
303
+ (persistent [db] (db-persistent! db))])
304
+
305
+ dbi/IDB
306
+ (-schema [db] (.-schema db))
307
+ (-rschema [db] (.-rschema db))
308
+ (-system-entities [db] (.-system-entities db))
309
+ (-attrs-by [db property] ((.-rschema db) property))
310
+ (-temporal-index? [db] (dbi/-keep-history? db))
311
+ (-keep-history? [db] (:keep-history? (.-config db)))
312
+ (-max-tx [db] (.-max-tx db))
313
+ (-max-eid [db] (.-max-eid db))
314
+ (-config [db] (.-config db))
315
+ (-ref-for [db a-ident]
316
+ (if (:attribute-refs? (.-config db))
317
+ (let [ref (get (.-ident-ref-map db) a-ident)]
318
+ (when (nil? ref)
319
+ (warn (str "Attribute " a-ident " has not been found in database")))
320
+ ref)
321
+ a-ident))
322
+ (-ident-for [db a-ref]
323
+ (if (:attribute-refs? (.-config db))
324
+ (let [a-ident (get (.-ref-ident-map db) a-ref)]
325
+ (when (nil? a-ident)
326
+ (warn (str "Attribute with reference number " a-ref " has not been found in database")))
327
+ a-ident)
328
+ a-ref))
329
+
330
+ dbi/ISearch
331
+ (-search-context [db] dbi/base-context)
332
+ (-search [db pattern context]
333
+ (contextual-search db pattern context))
334
+ (-batch-search [db pattern-mask batch-fn context]
335
+ (contextual-batch-search db pattern-mask batch-fn context))
336
+
337
+ dbi/IIndexAccess
338
+ (-datoms [db index-type cs context]
339
+ (contextual-datoms db index-type cs context))
340
+
341
+ (-seek-datoms [db index-type cs context]
342
+ (contextual-seek-datoms db index-type cs context))
343
+
344
+ (-rseek-datoms [db index-type cs context]
345
+ (contextual-rseek-datoms db index-type cs context))
346
+
347
+ (-index-range [db attr start end context]
348
+ (contextual-index-range db (.-avet db) attr start end context))
349
+
350
+ data/EqualityPartition
351
+ (equality-partition [x] :datahike/db)
352
+
353
+ data/Diff
354
+ (diff-similar [a b]
355
+ (let [datoms-a (di/-slice (:eavt a) (datom e0 nil nil tx0) (datom emax nil nil txmax) :eavt)
356
+ datoms-b (di/-slice (:eavt b) (datom e0 nil nil tx0) (datom emax nil nil txmax) :eavt)]
357
+ (dd/diff-sorted datoms-a datoms-b dd/cmp-datoms-eavt-quick))))
358
+
359
+ ;; FilteredDB
360
+
361
+ (defrecord-updatable FilteredDB [unfiltered-db pred]
362
+ #?@(:cljs
363
+ [IEquiv (-equiv [db other] (equiv-db db other))
364
+ ISeqable (-seq [db] (dbi/datoms db :eavt []))
365
+ ICounted (-count [db] (count (dbi/datoms db :eavt [])))
366
+ IPrintWithWriter (-pr-writer [db w opts] (pr-db db w opts))
367
+
368
+ IEmptyableCollection (-empty [_] (throw (js/Error. "-empty is not supported on FilteredDB")))
369
+
370
+ ILookup (-lookup ([_ _] (throw (js/Error. "-lookup is not supported on FilteredDB")))
371
+ ([_ _ _] (throw (js/Error. "-lookup is not supported on FilteredDB"))))
372
+
373
+ IAssociative
374
+ (-contains-key? [_ _] (throw (js/Error. "-contains-key? is not supported on FilteredDB")))
375
+ (-assoc [_ _ _] (throw (js/Error. "-assoc is not supported on FilteredDB")))]
376
+
377
+ :clj
378
+ [IPersistentCollection
379
+ (count [db] (count (dbi/datoms db :eavt [])))
380
+ (equiv [db o] (equiv-db db o))
381
+ (cons [db [k v]] (throw (UnsupportedOperationException. "cons is not supported on FilteredDB")))
382
+ (empty [db] (throw (UnsupportedOperationException. "empty is not supported on FilteredDB")))
383
+
384
+ Seqable (seq [db] (dbi/datoms db :eavt []))
385
+
386
+ clojure.lang.ILookup (valAt [db k] (throw (UnsupportedOperationException. "valAt/2 is not supported on FilteredDB")))
387
+ (valAt [db k nf] (throw (UnsupportedOperationException. "valAt/3 is not supported on FilteredDB")))
388
+ clojure.lang.IKeywordLookup (getLookupThunk [db k]
389
+ (throw (UnsupportedOperationException. "getLookupThunk is not supported on FilteredDB")))
390
+
391
+ Associative
392
+ (containsKey [e k] (throw (UnsupportedOperationException. "containsKey is not supported on FilteredDB")))
393
+ (entryAt [db k] (throw (UnsupportedOperationException. "entryAt is not supported on FilteredDB")))
394
+ (assoc [db k v] (throw (UnsupportedOperationException. "assoc is not supported on FilteredDB")))])
395
+
396
+ dbi/IDB
397
+ (-schema [db] (dbi/-schema (.-unfiltered-db db)))
398
+ (-rschema [db] (dbi/-rschema (.-unfiltered-db db)))
399
+ (-system-entities [db] (dbi/-system-entities (.-unfiltered-db db)))
400
+ (-attrs-by [db property] (dbi/-attrs-by (.-unfiltered-db db) property))
401
+ (-temporal-index? [db] (dbi/-keep-history? db))
402
+ (-keep-history? [db] (dbi/-keep-history? (.-unfiltered-db db)))
403
+ (-max-tx [db] (dbi/-max-tx (.-unfiltered-db db)))
404
+ (-max-eid [db] (dbi/-max-eid (.-unfiltered-db db)))
405
+ (-config [db] (dbi/-config (.-unfiltered-db db)))
406
+ (-ref-for [db a-ident] (dbi/-ref-for (.-unfiltered-db db) a-ident))
407
+ (-ident-for [db a-ref] (dbi/-ident-for (.-unfiltered-db db) a-ref))
408
+
409
+ dbi/ISearch
410
+ (-search-context [db] (dbi/context-with-xform-after
411
+ (dbi/-search-context (.-unfiltered-db db))
412
+ (filter (.-pred db))))
413
+ (-search [db pattern context]
414
+ (dbi/-search (.-unfiltered-db db) pattern context))
415
+ (-batch-search [db pattern-mask batch-fn context]
416
+ (dbi/-batch-search (.-unfiltered-db db) pattern-mask batch-fn context))
417
+
418
+ dbi/IIndexAccess
419
+ (-datoms [db index cs context]
420
+ (dbi/-datoms (.-unfiltered-db db) index cs context))
421
+
422
+ (-seek-datoms [db index cs context]
423
+ (dbi/-seek-datoms (.-unfiltered-db db) index cs context))
424
+
425
+ (-rseek-datoms [db index cs context]
426
+ (dbi/-rseek-datoms (.-unfiltered-db db) index cs context))
427
+
428
+ (-index-range [db attr start end context]
429
+ (deeper-index-range (.-unfiltered-db db)
430
+ db
431
+ attr
432
+ start end
433
+ context)))
434
+
435
+ ;; HistoricalDB
436
+
437
+ (defrecord-updatable HistoricalDB [origin-db]
438
+ #?@(:cljs
439
+ [IEquiv (-equiv [db other] (equiv-db db other))
440
+ ISeqable (-seq [db] (dbi/datoms db :eavt []))
441
+ ICounted (-count [db] (count (dbi/datoms db :eavt [])))
442
+ IPrintWithWriter (-pr-writer [db w opts] (pr-db db w opts))
443
+
444
+ IEmptyableCollection (-empty [_] (throw (js/Error. "-empty is not supported on HistoricalDB")))
445
+
446
+ ILookup (-lookup ([_ _] (throw (js/Error. "-lookup is not supported on HistoricalDB")))
447
+ ([_ _ _] (throw (js/Error. "-lookup is not supported on HistoricalDB"))))
448
+
449
+ IAssociative
450
+ (-contains-key? [_ _] (throw (js/Error. "-contains-key? is not supported on HistoricalDB")))
451
+ (-assoc [_ _ _] (throw (js/Error. "-assoc is not supported on HistoricalDB")))]
452
+ :clj
453
+ [IPersistentCollection
454
+ (count [db] (count (dbi/datoms db :eavt [])))
455
+ (equiv [db o] (equiv-db db o))
456
+ (cons [db [k v]] (throw (UnsupportedOperationException. "cons is not supported on HistoricalDB")))
457
+ (empty [db] (throw (UnsupportedOperationException. "empty is not supported on HistoricalDB")))
458
+
459
+ Seqable
460
+ (seq [db] (dbi/datoms db :eavt []))
461
+
462
+ Associative
463
+ (assoc [db k v] (throw (UnsupportedOperationException. "assoc is not supported on HistoricalDB")))])
464
+
465
+ dbi/IDB
466
+ (-schema [db] (dbi/-schema (.-origin-db db)))
467
+ (-rschema [db] (dbi/-rschema (.-origin-db db)))
468
+ (-system-entities [db] (dbi/-system-entities (.-origin-db db)))
469
+ (-attrs-by [db property] (dbi/-attrs-by (.-origin-db db) property))
470
+ (-temporal-index? [db] (dbi/-keep-history? (.-origin-db db)))
471
+ (-keep-history? [db] (dbi/-keep-history? (.-origin-db db)))
472
+ (-max-tx [db] (dbi/-max-tx (.-origin-db db)))
473
+ (-max-eid [db] (dbi/-max-eid (.-origin-db db)))
474
+ (-config [db] (dbi/-config (.-origin-db db)))
475
+ (-ref-for [db a-ident] (dbi/-ref-for (.-origin-db db) a-ident))
476
+ (-ident-for [db a-ref] (dbi/-ident-for (.-origin-db db) a-ref))
477
+
478
+ dbi/IHistory
479
+ (-time-point [db] nil)
480
+ (-origin [db] (.-origin-db db))
481
+
482
+ dbi/ISearch
483
+ (-search-context [db]
484
+ (-> (.-origin-db db)
485
+ dbi/-search-context
486
+ dbi/context-with-history))
487
+ (-search [db pattern context]
488
+ (dbi/-search (.-origin-db db) pattern context))
489
+ (-batch-search [db pattern-mask batch-fn context]
490
+ (dbi/-batch-search (.-origin-db db) pattern-mask batch-fn context))
491
+
492
+ dbi/IIndexAccess
493
+ (-datoms [db index-type cs context] (dbi/-datoms (.-origin-db db) index-type cs context))
494
+
495
+ (-seek-datoms [db index-type cs context] (dbi/-seek-datoms (.-origin-db db) index-type cs context))
496
+
497
+ (-rseek-datoms [db index-type cs context] (dbi/-rseek-datoms (.-origin-db db) index-type cs context))
498
+
499
+ (-index-range [db attr start end context] (deeper-index-range (.-origin-db db) db attr start end context)))
500
+
501
+ ;; AsOfDB
502
+
503
+ (defrecord-updatable AsOfDB [origin-db time-point]
504
+ #?@(:cljs
505
+ [IEquiv (-equiv [db other] (equiv-db db other))
506
+ ISeqable (-seq [db] (dbi/datoms db :eavt []))
507
+ ICounted (-count [db] (count (dbi/datoms db :eavt [])))
508
+ IPrintWithWriter (-pr-writer [db w opts] (pr-db db w opts))
509
+
510
+ IEmptyableCollection (-empty [_] (throw (js/Error. "-empty is not supported on AsOfDB")))
511
+
512
+ ILookup (-lookup ([_ _] (throw (js/Error. "-lookup is not supported on AsOfDB")))
513
+ ([_ _ _] (throw (js/Error. "-lookup is not supported on AsOfDB"))))
514
+
515
+ IAssociative
516
+ (-contains-key? [_ _] (throw (js/Error. "-contains-key? is not supported on AsOfDB")))
517
+ (-assoc [_ _ _] (throw (js/Error. "-assoc is not supported on AsOfDB")))]
518
+ :clj
519
+ [IPersistentCollection
520
+ (count [db] (count (dbi/datoms db :eavt [])))
521
+ (equiv [db o] (equiv-db db o))
522
+ (cons [db [k v]] (throw (UnsupportedOperationException. "cons is not supported on AsOfDB")))
523
+ (empty [db] (throw (UnsupportedOperationException. "empty is not supported on AsOfDB")))
524
+
525
+ Seqable
526
+ (seq [db] (dbi/datoms db :eavt []))
527
+
528
+ Associative
529
+ (assoc [db k v] (throw (UnsupportedOperationException. "assoc is not supported on AsOfDB")))])
530
+
531
+ dbi/IDB
532
+ (-schema [db] (dbi/-schema (.-origin-db db)))
533
+ (-rschema [db] (dbi/-rschema (.-origin-db db)))
534
+ (-system-entities [db] (dbi/-system-entities (.-origin-db db)))
535
+ (-attrs-by [db property] (dbi/-attrs-by (.-origin-db db) property))
536
+ (-temporal-index? [db] (dbi/-keep-history? (.-origin-db db)))
537
+ (-keep-history? [db] (dbi/-keep-history? (.-origin-db db)))
538
+ (-max-tx [db] (dbi/-max-tx (.-origin-db db)))
539
+ (-max-eid [db] (dbi/-max-eid (.-origin-db db)))
540
+ (-config [db] (dbi/-config (.-origin-db db)))
541
+ (-ref-for [db a-ident] (dbi/-ref-for (.-origin-db db) a-ident))
542
+ (-ident-for [db a-ref] (dbi/-ident-for (.-origin-db db) a-ref))
543
+
544
+ dbi/IHistory
545
+ (-time-point [db] (.-time-point db))
546
+ (-origin [db] (.-origin-db db))
547
+
548
+ dbi/ISearch
549
+ (-search-context [db] (dbi/context-with-temporal-timepred
550
+ (dbi/-search-context (.-origin-db db))
551
+ (as-of-pred (.-time-point db))))
552
+ (-search [db pattern context]
553
+ (dbi/-search (.-origin-db db) pattern context))
554
+ (-batch-search [db pattern batch-fn context]
555
+ (dbi/-batch-search (.-origin-db db) pattern batch-fn context))
556
+
557
+ dbi/IIndexAccess
558
+ (-datoms [db index-type cs context]
559
+ (dbi/-datoms (.-origin-db db) index-type cs context))
560
+
561
+ (-seek-datoms [db index-type cs context]
562
+ (dbi/-seek-datoms (.-origin-db db) index-type cs context))
563
+
564
+ (-rseek-datoms [db index-type cs context]
565
+ (dbi/-rseek-datoms (.-origin-db db) index-type cs context))
566
+
567
+ (-index-range [db attr start end context]
568
+ (deeper-index-range (.-origin-db db) db attr start end context)))
569
+
570
+ (defrecord-updatable SinceDB [origin-db time-point]
571
+ #?@(:cljs
572
+ [IEquiv (-equiv [db other] (equiv-db db other))
573
+ ISeqable (-seq [db] (dbi/datoms db :eavt []))
574
+ ICounted (-count [db] (count (dbi/datoms db :eavt [])))
575
+ IPrintWithWriter (-pr-writer [db w opts] (pr-db db w opts))
576
+
577
+ IEmptyableCollection (-empty [_] (throw (js/Error. "-empty is not supported on SinceDB")))
578
+
579
+ ILookup (-lookup ([_ _] (throw (js/Error. "-lookup is not supported on SinceDB")))
580
+ ([_ _ _] (throw (js/Error. "-lookup is not supported on SinceDB"))))
581
+
582
+ IAssociative
583
+ (-contains-key? [_ _] (throw (js/Error. "-contains-key? is not supported on SinceDB")))
584
+ (-assoc [_ _ _] (throw (js/Error. "-assoc is not supported on SinceDB")))]
585
+ :clj
586
+ [IPersistentCollection
587
+ (count [db] (count (dbi/datoms db :eavt [])))
588
+ (equiv [db o] (equiv-db db o))
589
+ (cons [db [k v]] (throw (UnsupportedOperationException. "cons is not supported on SinceDB")))
590
+ (empty [db] (throw (UnsupportedOperationException. "empty is not supported on SinceDB")))
591
+
592
+ Seqable
593
+ (seq [db] (dbi/datoms db :eavt []))
594
+
595
+ Associative
596
+ (assoc [db k v] (throw (UnsupportedOperationException. "assoc is not supported on SinceDB")))])
597
+
598
+ dbi/IDB
599
+ (-schema [db] (dbi/-schema (.-origin-db db)))
600
+ (-rschema [db] (dbi/-rschema (.-origin-db db)))
601
+ (-system-entities [db] (dbi/-system-entities (.-origin-db db)))
602
+ (-attrs-by [db property] (dbi/-attrs-by (.-origin-db db) property))
603
+ (-temporal-index? [db] (dbi/-keep-history? (.-origin-db db)))
604
+ (-keep-history? [db] (dbi/-keep-history? (.-origin-db db)))
605
+ (-max-tx [db] (dbi/-max-tx (.-origin-db db)))
606
+ (-max-eid [db] (dbi/-max-eid (.-origin-db db)))
607
+ (-config [db] (dbi/-config (.-origin-db db)))
608
+ (-ref-for [db a-ident] (dbi/-ref-for (.-origin-db db) a-ident))
609
+ (-ident-for [db a-ref] (dbi/-ident-for (.-origin-db db) a-ref))
610
+
611
+ dbi/IHistory
612
+ (-time-point [db] (.-time-point db))
613
+ (-origin [db] (.-origin-db db))
614
+
615
+ dbi/ISearch
616
+ (-search-context [db] (dbi/context-with-temporal-timepred
617
+ (dbi/-search-context (.-origin-db db))
618
+ (since-pred (.-time-point db))))
619
+ (-search [db pattern context]
620
+ (dbi/-search (.-origin-db db) pattern context))
621
+ (-batch-search [db pattern batch-fn context]
622
+ (dbi/-batch-search (.-origin-db db) pattern batch-fn context))
623
+
624
+ dbi/IIndexAccess
625
+ (dbi/-datoms [db index-type cs context]
626
+ (dbi/-datoms (.-origin-db db) index-type cs context))
627
+
628
+ (dbi/-seek-datoms [db index-type cs context]
629
+ (dbi/-seek-datoms (.-origin-db db) index-type cs context))
630
+
631
+ (dbi/-rseek-datoms [db index-type cs context]
632
+ (dbi/-rseek-datoms (.-origin-db db) index-type cs context))
633
+
634
+ (dbi/-index-range [db attr start end context]
635
+ (deeper-index-range (.-origin-db db)
636
+ db
637
+ attr
638
+ start end
639
+ context)))
640
+
641
+ (defn- equiv-db-index [x y]
642
+ (loop [xs (seq x)
643
+ ys (seq y)]
644
+ (cond
645
+ (nil? xs) (nil? ys)
646
+ (= (first xs) (first ys)) (recur (next xs) (next ys))
647
+ :else false)))
648
+
649
+ (defn- equiv-db [db other]
650
+ (and (or (instance? DB other) (instance? FilteredDB other))
651
+ (or (not (instance? DB other)) (= (hash db) (hash other)))
652
+ (= (dbi/-schema db) (dbi/-schema other))
653
+ (equiv-db-index (dbi/datoms db :eavt []) (dbi/datoms other :eavt []))))
654
+
655
+ #?(:cljs
656
+ (defn pr-db [db w opts]
657
+ (-write w "#datahike/DB {")
658
+ (-write w (str ":max-tx " (dbi/-max-tx db) " "))
659
+ (-write w (str ":max-eid " (dbi/-max-eid db) " "))
660
+ (-write w "}")))
661
+
662
+ #?(:clj
663
+ (do
664
+ (defn pr-db [db, ^Writer w]
665
+ (.write w (str "#datahike/DB {"))
666
+ (.write w ":store-id [")
667
+ (.write w (pr-str (store/store-identity (:store (dbi/-config db)))))
668
+ (.write w " ")
669
+ (.write w (pr-str (:branch (dbi/-config db))))
670
+ (.write w "] ")
671
+ (.write w (str ":commit-id " (pr-str (:datahike/commit-id (:meta db))) " "))
672
+ (.write w (str ":max-tx " (dbi/-max-tx db) " "))
673
+ (.write w (str ":max-eid " (dbi/-max-eid db)))
674
+ (.write w "}"))
675
+
676
+ (defn pr-hist-db [db ^Writer w flavor time-point?]
677
+ (.write w (str "#datahike/" flavor " {"))
678
+ (.write w ":origin ")
679
+ (binding [*out* w]
680
+ (pr (dbi/-origin db)))
681
+ (when time-point?
682
+ (.write w " :time-point ")
683
+ (binding [*out* w]
684
+ (pr (dbi/-time-point db))))
685
+ (.write w "}"))
686
+
687
+ (defmethod print-method DB [db w] (pr-db db w))
688
+ (defmethod print-method FilteredDB [db w] (pr-db db w)) ;; why not with "FilteredDB" ?
689
+ (defmethod print-method HistoricalDB [db w] (pr-hist-db db w "HistoricalDB" false))
690
+ (defmethod print-method AsOfDB [db w] (pr-hist-db db w "AsOfDB" true))
691
+ (defmethod print-method SinceDB [db w] (pr-hist-db db w "SinceDB" true))
692
+
693
+ (defmethod pp/simple-dispatch Datom [^Datom d]
694
+ (pp/pprint-logical-block :prefix "#datahike/Datom [" :suffix "]"
695
+ (pp/write-out (.-e d))
696
+ (.write ^Writer *out* " ")
697
+ (pp/pprint-newline :linear)
698
+ (pp/write-out (.-a d))
699
+ (.write ^Writer *out* " ")
700
+ (pp/pprint-newline :linear)
701
+ (pp/write-out (.-v d))
702
+ (.write ^Writer *out* " ")
703
+ (pp/pprint-newline :linear)
704
+ (pp/write-out (datom-tx d))))
705
+
706
+ (defn- pp-db [db ^Writer w]
707
+ (pp/pprint-logical-block :prefix "#datahike/DB {" :suffix "}"
708
+ (pp/pprint-logical-block
709
+ (pp/write-out :max-tx)
710
+ (.write ^Writer *out* " ")
711
+ (pp/pprint-newline :linear)
712
+ (pp/write-out (dbi/-max-tx db))
713
+ (.write ^Writer *out* " ")
714
+ (pp/pprint-newline :linear)
715
+ (pp/write-out :max-eid)
716
+ (.write ^Writer *out* " ")
717
+ (pp/pprint-newline :linear)
718
+ (pp/write-out (dbi/-max-eid db)))
719
+ (pp/pprint-newline :linear)))
720
+
721
+ (defmethod pp/simple-dispatch DB [db] (pp-db db *out*))
722
+ (defmethod pp/simple-dispatch FilteredDB [db] (pp-db db *out*))))
723
+
724
+ (defn- validate-schema-key [a k v expected]
725
+ (when-not (or (nil? v)
726
+ (contains? expected v))
727
+ (throw (ex-info (str "Bad attribute specification for " (pr-str {a {k v}}) ", expected one of " expected)
728
+ {:error :schema/validation
729
+ :attribute a
730
+ :key k
731
+ :value v}))))
732
+
733
+ (defn- validate-tuple-schema [a kv]
734
+ (when (= :db.type/tuple (:db/valueType kv))
735
+ (case (some #{:db/tupleAttrs :db/tupleTypes :db/tupleType} (keys kv))
736
+ :db/tupleAttrs (when (not (vector? (:db/tupleAttrs kv)))
737
+ (throw (ex-info (str "Bad attribute specification for " a ": {:db/tupleAttrs ...} should be a vector}")
738
+ {:error :schema/validation
739
+ :attribute a
740
+ :key :db/tupleAttrs})))
741
+ :db/tupleTypes (when (not (vector? (:db/tupleTypes kv)))
742
+ (throw (ex-info (str "Bad attribute specification for " a ": {:db/tupleTypes ...} should be a vector}")
743
+ {:error :schema/validation
744
+ :attribute a
745
+ :key :db/tupleTypes})))
746
+ :db/tupleType (when (not (keyword? (:db/tupleType kv)))
747
+ (throw (ex-info (str "Bad attribute specification for " a ": {:db/tupleType ...} should be a keyword}")
748
+ {:error :schema/validation
749
+ :attribute a
750
+ :key :db/tupleType}))))))
751
+
752
+ (defn- validate-schema [schema]
753
+ (doseq [[a-ident kv] schema]
754
+ (let [comp? (:db/isComponent kv false)]
755
+ (validate-schema-key a-ident :db/isComponent (:db/isComponent kv) #{true false})
756
+ (when (and comp? (not= (:db/valueType kv) :db.type/ref))
757
+ (throw (ex-info (str "Bad attribute specification for " a-ident ": {:db/isComponent true} should also have {:db/valueType :db.type/ref}")
758
+ {:error :schema/validation
759
+ :attribute a-ident
760
+ :key :db/isComponent}))))
761
+ (validate-schema-key a-ident :db/unique (:db/unique kv) #{:db.unique/value :db.unique/identity})
762
+ (validate-schema-key a-ident :db/valueType (:db/valueType kv) #{:db.type/ref :db.type/tuple})
763
+ (validate-schema-key a-ident :db/cardinality (:db/cardinality kv) #{:db.cardinality/one :db.cardinality/many})
764
+ (validate-tuple-schema a-ident kv)))
765
+
766
+ (defn to-old-schema [new-schema]
767
+ (if (or (vector? new-schema) (seq? new-schema))
768
+ (reduce
769
+ (fn [acc {:keys [:db/ident] :as schema-entity}]
770
+ (assoc acc ident schema-entity))
771
+ {}
772
+ new-schema)
773
+ new-schema))
774
+
775
+ (defn- validate-write-schema [schema]
776
+ (when-not (ds/old-schema-valid? schema)
777
+ (raise "Incomplete schema attributes, expected at least :db/valueType, :db/cardinality"
778
+ (ds/explain-old-schema schema))))
779
+
780
+ (defn init-max-eid [eavt]
781
+ ;; solved with reverse slice first in datascript
782
+ (if-let [datoms (di/-slice
783
+ eavt
784
+ (datom e0 nil nil tx0)
785
+ (datom (dec tx0) nil nil txmax)
786
+ :eavt)]
787
+ (-> datoms vec rseq first :e) ;; :e of last datom in slice
788
+ e0))
789
+
790
+ (defn get-max-tx [eavt]
791
+ (transduce (map (fn [^Datom d] (datom-tx d))) max tx0 (di/-all eavt)))
792
+
793
+ (def ref-datoms ;; maps enums as well
794
+ (let [idents (reduce (fn [m {:keys [db/ident db/id]}]
795
+ (assoc m ident id))
796
+ {}
797
+ system-schema)]
798
+ (->> system-schema
799
+ (mapcat
800
+ (fn [{:keys [db/id] :as i}]
801
+ (reduce-kv
802
+ (fn [coll k v]
803
+ (let [v-ref (idents v)
804
+ ;; datom val can be system schema eid (v-ref), or ident or regular (v)
805
+ d-val (if (and (not= k :db/ident) v-ref) v-ref v)]
806
+ (conj coll (dd/datom id (idents k) d-val tx0))))
807
+ []
808
+ (dissoc i :db/id))))
809
+ vec)))
810
+
811
+ (defn get-ident-ref-map
812
+ "Maps IDs of system entities to their names (keyword) and attribute names to the attribute's specification"
813
+ [schema]
814
+ (reduce
815
+ (fn [m [a {:keys [db/id]}]]
816
+ (when a
817
+ (assoc m a id)))
818
+ {}
819
+ schema))
820
+
821
+ (defn ^DB empty-db
822
+ "Prefer create-database in api, schema only in index for attribute reference database."
823
+ ([] (empty-db nil nil nil))
824
+ ([schema] (empty-db schema nil nil))
825
+ ([schema user-config] (empty-db schema user-config nil))
826
+ ([schema user-config store]
827
+ {:pre [(or (nil? schema) (map? schema) (coll? schema))]}
828
+ (let [complete-config (merge (dc/storeless-config) user-config)
829
+ _ (dc/validate-config complete-config)
830
+ complete-config (dc/remove-nils complete-config)
831
+ {:keys [keep-history? index schema-flexibility attribute-refs?]} complete-config
832
+ on-read? (= :read schema-flexibility)
833
+ schema (to-old-schema schema)
834
+ _ (if on-read?
835
+ (validate-schema schema)
836
+ (validate-write-schema schema))
837
+ complete-schema (merge schema
838
+ (if attribute-refs?
839
+ c/ref-implicit-schema
840
+ c/non-ref-implicit-schema))
841
+ rschema (dbu/rschema complete-schema)
842
+ ident-ref-map (if attribute-refs? (get-ident-ref-map complete-schema) {})
843
+ ref-ident-map (if attribute-refs? (clojure.set/map-invert ident-ref-map) {})
844
+ system-entities (if attribute-refs? c/system-entities #{})
845
+ indexed (if attribute-refs?
846
+ (set (map ident-ref-map (:db/index rschema)))
847
+ (:db/index rschema))
848
+ index-config (merge (:index-config complete-config)
849
+ {:indexed indexed})
850
+ eavt (if attribute-refs?
851
+ (di/init-index index store ref-datoms :eavt 0 index-config)
852
+ (di/empty-index index store :eavt index-config))
853
+ aevt (if attribute-refs?
854
+ (di/init-index index store ref-datoms :aevt 0 index-config)
855
+ (di/empty-index index store :aevt index-config))
856
+ indexed-datoms (filter (fn [[_ a _ _]] (contains? indexed a)) ref-datoms)
857
+ avet (if attribute-refs?
858
+ (di/init-index index store indexed-datoms :avet 0 index-config)
859
+ (di/empty-index index store :avet index-config))
860
+ max-eid (if attribute-refs? ue0 e0)
861
+ max-tx (if attribute-refs? utx0 tx0)]
862
+ (map->DB
863
+ (merge
864
+ {:schema complete-schema
865
+ :rschema rschema
866
+ :config complete-config
867
+ :eavt eavt
868
+ :aevt aevt
869
+ :avet avet
870
+ :max-eid max-eid
871
+ :max-tx max-tx
872
+ :hash 0
873
+ :system-entities system-entities
874
+ :ref-ident-map ref-ident-map
875
+ :ident-ref-map ident-ref-map
876
+ :meta (meta-data)
877
+ :op-count (if attribute-refs? (count ref-datoms) 0)}
878
+ (when keep-history? ;; no difference for attribute references since no update possible
879
+ {:temporal-eavt eavt
880
+ :temporal-aevt aevt
881
+ :temporal-avet avet}))))))
882
+
883
+ (defn ^DB init-db
884
+ ([datoms] (init-db datoms nil nil nil))
885
+ ([datoms schema] (init-db datoms schema nil nil))
886
+ ([datoms schema user-config] (init-db datoms schema user-config nil))
887
+ ([datoms schema user-config store]
888
+ (validate-schema schema)
889
+ (let [{:keys [index keep-history? attribute-refs?] :as complete-config} (merge (dc/storeless-config) user-config)
890
+ _ (dc/validate-config complete-config)
891
+ complete-schema (merge schema
892
+ (if attribute-refs?
893
+ c/ref-implicit-schema
894
+ c/non-ref-implicit-schema))
895
+ rschema (dbu/rschema complete-schema)
896
+ ident-ref-map (if attribute-refs? (get-ident-ref-map schema) {})
897
+ ref-ident-map (if attribute-refs? (clojure.set/map-invert ident-ref-map) {})
898
+ system-entities (if attribute-refs? c/system-entities #{})
899
+
900
+ indexed (if attribute-refs?
901
+ (set (map ident-ref-map (:db/index rschema)))
902
+ (:db/index rschema))
903
+ new-datoms (if attribute-refs? (concat ref-datoms datoms) datoms)
904
+ indexed-datoms (filter (fn [[_ a _ _]] (contains? indexed a)) new-datoms)
905
+ op-count 0
906
+ index-config (assoc (:index-config complete-config)
907
+ :indexed indexed)
908
+ avet (di/init-index index store indexed-datoms :avet op-count index-config)
909
+ eavt (di/init-index index store new-datoms :eavt op-count index-config)
910
+ aevt (di/init-index index store new-datoms :aevt op-count index-config)
911
+ max-eid (init-max-eid eavt)
912
+ max-tx (get-max-tx eavt)
913
+ op-count (count new-datoms)]
914
+ (map->DB (merge {:schema complete-schema
915
+ :rschema rschema
916
+ :config complete-config
917
+ :eavt eavt
918
+ :aevt aevt
919
+ :avet avet
920
+ :max-eid max-eid
921
+ :max-tx max-tx
922
+ :op-count op-count
923
+ :hash (reduce #(+ %1 (hash %2)) 0 datoms)
924
+ :system-entities system-entities
925
+ :meta (meta-data)
926
+ :ref-ident-map ref-ident-map
927
+ :ident-ref-map ident-ref-map}
928
+ (when keep-history?
929
+ {:temporal-eavt (di/empty-index index store :eavt index-config)
930
+ :temporal-aevt (di/empty-index index store :aevt index-config)
931
+ :temporal-avet (di/empty-index index store :avet index-config)}))))))
932
+
933
+ (defn metrics [^DB db]
934
+ (let [update-count-in (fn [m ks] (update-in m ks #(if % (inc %) 1)))
935
+ counts-map (->> (di/-seq (.-eavt db))
936
+ (reduce (fn [m ^Datom datom]
937
+ (-> m
938
+ (update-count-in [:per-attr-counts (dbi/-ident-for db (.-a datom))])
939
+ (update-count-in [:per-entity-counts (.-e datom)])))
940
+ {:per-attr-counts {}
941
+ :per-entity-counts {}}))
942
+ sum-indexed-attr-counts (fn [attr-counts] (->> attr-counts
943
+ (m/filter-keys #(contains? (:db/index (.-rschema db)) %))
944
+ vals
945
+ (reduce + 0)))]
946
+ (cond-> (merge counts-map
947
+ {:count (di/-count (.-eavt db))
948
+ :avet-count (->> (:per-attr-counts counts-map)
949
+ sum-indexed-attr-counts)})
950
+ (dbi/-keep-history? db)
951
+ (merge {:temporal-count (di/-count (.-temporal-eavt db))
952
+ :temporal-avet-count (->> (di/-seq (.-temporal-eavt db))
953
+ (reduce (fn [m ^Datom datom] (update-count-in m [(dbi/-ident-for db (.-a datom))]))
954
+ {})
955
+ sum-indexed-attr-counts)}))))
956
+