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,88 @@
1
+ (ns datahike.query-stats
2
+ (:require [clojure.set :as set]
3
+ [datahike.tools :as dt]))
4
+
5
+ (defn round [precision x]
6
+ #?(:clj (with-precision ^long precision ^java.math.BigDecimal x)
7
+ :cljs (let [y (Math/pow 10 precision)]
8
+ (/ (.round js/Math (* y x)) y))))
9
+
10
+ (defn compatible-abs [^long n]
11
+ #?(:clj (Math/abs n)
12
+ :cljs (js/Math.abs n)))
13
+
14
+ (defn get-stats [context]
15
+ {:rels (mapv (fn [rel] {:rows (count (:tuples rel))
16
+ :bound (set (keys (:attrs rel)))})
17
+ (:rels context))})
18
+
19
+ (defn update-ctx-with-stats
20
+ "update-fn must expect [context] as argument"
21
+ [context clause update-fn]
22
+ (if (:stats context)
23
+ (let [{:keys [res t]} (dt/timed #(update-fn context))
24
+ clause-stats (merge (get-stats res)
25
+ {:clause clause
26
+ :t t}
27
+ (:tmp-stats res))]
28
+ (-> res
29
+ (update :stats conj clause-stats)
30
+ (dissoc :tmp-stats)))
31
+ (update-fn context)))
32
+
33
+ (defn extend-stat
34
+ "Adds summarized row counts, bindings and clause time for convenience"
35
+ [{:keys [branches rels] :as stat}]
36
+ (assoc stat
37
+ :id (subs (str (compatible-abs (hash stat))) 0 6)
38
+ :t-branches (reduce #(+ %1 (:t %2)) 0.0 branches)
39
+ :rel-count (count rels)
40
+ :rows (reduce #(+ %1 (:rows %2)) 0 rels)
41
+ :bound (reduce #(set/union %1 (:bound %2)) #{} rels)
42
+ :branches (mapv extend-stat branches)))
43
+
44
+ (defn get-stat-diffs [parent-node prev-node {:keys [t t-branches rows bound] :as node}]
45
+ (let [extend-and-branches (fn [branches]
46
+ (mapv (partial get-stat-diffs node)
47
+ (cons prev-node branches)
48
+ branches))
49
+ extend-or-branches (fn [branches]
50
+ (mapv (partial get-stat-diffs node prev-node) branches))]
51
+ (-> node
52
+ (dissoc :rows :bound)
53
+ (assoc :prev (:id prev-node)
54
+ :parent (:id parent-node)
55
+ :t-diff (round 6 (- t t-branches))
56
+ :rows-in (:rows prev-node)
57
+ :rows-out rows
58
+ :rows-diff (- rows (:rows prev-node))
59
+ :bound-in (:bound prev-node)
60
+ :bound-out bound
61
+ :bound-diff (set/difference bound (:bound prev-node)))
62
+ (update :branches (case (:type node)
63
+ :and extend-and-branches
64
+ :or extend-or-branches
65
+ :or-join extend-or-branches
66
+ :rule extend-or-branches
67
+ :solve extend-and-branches
68
+ identity)))))
69
+
70
+ (defn extend-stats [stats]
71
+ (let [extended (map extend-stat stats)
72
+ root {:rows 0 :bound (set []) :id "_root_"}]
73
+ (mapv (partial get-stat-diffs root)
74
+ (cons root extended)
75
+ extended)))
76
+
77
+ (defn stats-table
78
+ ([stats]
79
+ (stats-table stats [:id :prev :parent :clause :type
80
+ :rows-in :rows-diff :bound-in :bound-diff
81
+ :t :t-diff :clauses]))
82
+ ([stats cols]
83
+ (->> stats
84
+ extend-stats
85
+ (hash-map :branches)
86
+ (tree-seq map? :branches)
87
+ rest
88
+ (map (apply juxt cols)))))
@@ -0,0 +1,62 @@
1
+ (ns datahike.readers
2
+ (:require [datahike.connections :refer [get-connection *connections*]]
3
+ [datahike.writing :as dw]
4
+ [datahike.datom :refer [datom] :as dd]
5
+ #?(:cljs [datahike.db :refer [HistoricalDB AsOfDB SinceDB]])
6
+ [datahike.impl.entity :as de]
7
+ [datahike.core :refer [init-db] :as dc]
8
+ [datahike.tools :refer [raise]]
9
+ [konserve.core :as k])
10
+ #?(:clj
11
+ (:import [datahike.datom Datom]
12
+ [datahike.db HistoricalDB AsOfDB SinceDB])))
13
+
14
+ (def tempid dc/tempid)
15
+
16
+ (def datom-from-reader dd/datom-from-reader)
17
+
18
+ (defn db-from-reader [{:keys [schema datoms store-id commit-id] :as raw-db}]
19
+ (if (and store-id commit-id)
20
+ #?(:cljs (throw (ex-info "Reader not supported." {:type :reader-not-supported
21
+ :raw-db raw-db}))
22
+ :clj
23
+ (if-let [conn (get-connection store-id)]
24
+ (let [store (:store @conn)]
25
+ (when-let [raw-db (k/get store commit-id nil {:sync? true})]
26
+ (dw/stored->db raw-db store)))
27
+ (raise (ex-info "Could not find active connection. Did you connect already?"
28
+ {:type :no-connection-for-db
29
+ :raw-db raw-db}))))
30
+ (init-db (map (fn [[e a v tx]] (datom e a v tx)) datoms) schema)))
31
+
32
+ (defn history-from-reader [{:keys [origin]}]
33
+ (HistoricalDB. origin))
34
+
35
+ (defn since-from-reader [{:keys [origin time-point]}]
36
+ (AsOfDB. origin time-point))
37
+
38
+ (defn as-of-from-reader [{:keys [origin time-point]}]
39
+ (SinceDB. origin time-point))
40
+
41
+ (defn connection-from-reader [conn-id]
42
+ (:conn (@*connections* conn-id)))
43
+
44
+ (defn entity-from-reader [{:keys [db eid]}]
45
+ (de/entity db eid))
46
+
47
+ (def ^{:doc "Data readers for EDN readers. In CLJS they’re registered automatically. In CLJ, if `data_readers.clj` do not work, you can always do
48
+
49
+ ```
50
+ (clojure.edn/read-string {:readers data-readers} \"...\")
51
+ ```"}
52
+ edn-readers
53
+ {'datahike/Datom datahike.readers/datom-from-reader
54
+ 'datahike/DB datahike.readers/db-from-reader
55
+ 'datahike/HistoricalDB datahike.readers/history-from-reader
56
+ 'datahike/SinceDB datahike.readers/since-from-reader
57
+ 'datahike/AsOfDB datahike.readers/as-of-from-reader
58
+ 'datahike/Connection datahike.readers/connection-from-reader
59
+ 'db/id datahike.readers/tempid})
60
+
61
+ #?(:cljs
62
+ (doseq [[tag cb] edn-readers] (cljs.reader/register-tag-parser! tag cb)))
@@ -0,0 +1,218 @@
1
+ (ns datahike.remote
2
+ "Literals that can function as lightweight remote pointers to connections and
3
+ dbs."
4
+ (:require [cognitect.transit :as transit]
5
+ [jsonista.core :as j]
6
+ [jsonista.tagged :as jt]
7
+ [clojure.edn :as edn]
8
+ [datahike.json :refer [json-base-handlers]]
9
+ [datahike.datom :as dd])
10
+ #?(:clj
11
+ (:import [clojure.lang IDeref]
12
+ [datahike.datom Datom]
13
+ [com.fasterxml.jackson.core JsonGenerator])))
14
+
15
+ ;; https://github.com/thi-ng/color/issues/10
16
+ ;; fixes lein repl / Cloure 1.10.0
17
+ (prefer-method print-method java.util.Map clojure.lang.IDeref)
18
+
19
+ ;; fixes lein repl / Clojure 1.10.1
20
+ (prefer-method print-method clojure.lang.IPersistentMap clojure.lang.IDeref)
21
+
22
+ ;; fixes CIDER / Clojure 1.9.0 / 1.10.0 / 1.10.1
23
+ (prefer-method clojure.pprint/simple-dispatch clojure.lang.IPersistentMap clojure.lang.IDeref)
24
+
25
+ ;; Remote peer currently operated on. This is used to allow the tagged literal
26
+ ;; readers to attach the remote again.
27
+ (def ^:dynamic *remote-peer* nil)
28
+
29
+ (defmulti remote-deref (fn [{:keys [remote-peer]}] (:backend remote-peer)))
30
+
31
+ (defprotocol PRemotePeer
32
+ (-remote-peer [_] "Retrieve remote peer."))
33
+
34
+ (extend-protocol PRemotePeer
35
+ Object
36
+ (-remote-peer [_] nil))
37
+
38
+ (defn remote-peer [obj] (-remote-peer obj))
39
+
40
+ (defrecord RemoteConnection [store-id remote-peer]
41
+ #?@(:clj
42
+ [IDeref
43
+ (deref [conn] (remote-deref conn))
44
+ PRemotePeer
45
+ (-remote-peer [_] remote-peer)]))
46
+
47
+ (defn remote-connection [store-id]
48
+ (RemoteConnection. store-id *remote-peer*))
49
+
50
+ #?(:clj
51
+ (defmethod print-method RemoteConnection
52
+ [^RemoteConnection conn ^java.io.Writer w]
53
+ (.write w "#datahike/RemoteConnection")
54
+ (.write w (pr-str (:store-id conn)))))
55
+
56
+ (defrecord RemoteDB [store-id max-tx max-eid commit-id remote-peer]
57
+ PRemotePeer
58
+ (-remote-peer [_] remote-peer))
59
+
60
+ (defn remote-db [m]
61
+ (assoc (map->RemoteDB m) :remote-peer *remote-peer*))
62
+
63
+ #?(:clj
64
+ (defmethod print-method RemoteDB
65
+ [^RemoteDB db ^java.io.Writer w]
66
+ (.write w "#datahike/RemoteDB")
67
+ (.write w (pr-str (into {} (dissoc db :remote-peer))))))
68
+
69
+ (defrecord RemoteHistoricalDB [origin remote-peer]
70
+ PRemotePeer
71
+ (-remote-peer [_] remote-peer))
72
+
73
+ (defn remote-historical-db [m]
74
+ (assoc (map->RemoteHistoricalDB m) :remote-peer *remote-peer*))
75
+
76
+ #?(:clj
77
+ (defmethod print-method RemoteHistoricalDB
78
+ [^RemoteDB db ^java.io.Writer w]
79
+ (.write w "#datahike/RemoteHistoricalDB")
80
+ (.write w (pr-str (into {} (dissoc db :remote-peer))))))
81
+
82
+ (defrecord RemoteSinceDB [origin time-point remote-peer]
83
+ PRemotePeer
84
+ (-remote-peer [_] remote-peer))
85
+
86
+ (defn remote-since-db [m]
87
+ (assoc (map->RemoteSinceDB m) :remote-peer *remote-peer*))
88
+
89
+ #?(:clj
90
+ (defmethod print-method RemoteSinceDB
91
+ [^RemoteDB db ^java.io.Writer w]
92
+ (.write w "#datahike/RemoteSinceDB")
93
+ (.write w (pr-str (into {} (dissoc db :remote-peer))))))
94
+
95
+ (defrecord RemoteAsOfDB [origin time-point remote-peer]
96
+ PRemotePeer
97
+ (-remote-peer [_] remote-peer))
98
+
99
+ (defn remote-as-of-db [m]
100
+ (assoc (map->RemoteAsOfDB m) :remote-peer *remote-peer*))
101
+
102
+ #?(:clj
103
+ (defmethod print-method RemoteAsOfDB
104
+ [^RemoteDB db ^java.io.Writer w]
105
+ (.write w "#datahike/RemoteAsOfDB")
106
+ (.write w (pr-str (into {} (dissoc db :remote-peer))))))
107
+
108
+ (defrecord RemoteEntity [db eid remote-peer]
109
+ PRemotePeer
110
+ (-remote-peer [_] remote-peer))
111
+
112
+ (defn remote-entity [m]
113
+ (assoc (map->RemoteEntity m) :remote-peer *remote-peer*))
114
+
115
+ #?(:clj
116
+ (defmethod print-method RemoteEntity
117
+ [^RemoteEntity e ^java.io.Writer w]
118
+ (.write w "#datahike/RemoteEntity")
119
+ (.write w (pr-str (dissoc (into {} e) :remote-peer)))))
120
+
121
+ (defn edn-replace-remote-literals [s]
122
+ (reduce (fn [^String s [^String from ^String to]]
123
+ (.replace s from to))
124
+ s
125
+ [["#datahike/RemoteConnection" "#datahike/Connection"]
126
+ ["#datahike/RemoteDB" "#datahike/DB"]
127
+ ["#datahike/RemoteHistoricalDB" "#datahike/HistoricalDB"]
128
+ ["#datahike/RemoteSinceDB" "#datahike/SinceDB"]
129
+ ["#datahike/RemoteAsOfDB" "#datahike/AsOfDB"]]))
130
+
131
+ (def edn-readers {'datahike/Connection remote-connection
132
+ 'datahike/DB remote-db
133
+ 'datahike/HistoricalDB remote-historical-db
134
+ 'datahike/AsOfDB remote-as-of-db
135
+ 'datahike/SinceDB remote-since-db
136
+ 'datahike/Datom datahike.datom/datom-from-reader
137
+ 'datahike.db.TxReport datahike.db/map->TxReport})
138
+
139
+ (defn map-without-remote [r]
140
+ (dissoc (into {} r) :remote-peer))
141
+
142
+ (defn datom-as-vec [^Datom d]
143
+ [(.-e d) (.-a d) (.-v d) (dd/datom-tx d) (dd/datom-added d)])
144
+
145
+ (defn datom-from-vec [v] (apply dd/datom v))
146
+
147
+ (def transit-write-handlers {datahike.remote.RemoteConnection (transit/write-handler "datahike/Connection" #(:store-id %))
148
+ datahike.datom.Datom (transit/write-handler "datahike/Datom" datom-as-vec)
149
+ datahike.remote.RemoteDB (transit/write-handler "datahike/DB" map-without-remote)
150
+ datahike.remote.RemoteHistoricalDB (transit/write-handler "datahike/HistoricalDB" map-without-remote)
151
+ datahike.remote.RemoteSinceDB (transit/write-handler "datahike/SinceDB" map-without-remote)
152
+ datahike.remote.RemoteAsOfDB (transit/write-handler "datahike/AsOfDB" map-without-remote)
153
+ datahike.remote.RemoteEntity (transit/write-handler "datahike/Entity" #(into {} %))})
154
+
155
+ (def transit-read-handlers {"datahike/Connection" (transit/read-handler remote-connection)
156
+ "datahike/Datom" (transit/read-handler datom-from-vec)
157
+ "datahike/TxReport" (transit/read-handler datahike.db/map->TxReport)
158
+ "datahike/DB" (transit/read-handler remote-db)
159
+ "datahike/HistoricalDB" (transit/read-handler remote-historical-db)
160
+ "datahike/SinceDB" (transit/read-handler remote-since-db)
161
+ "datahike/AsOfDB" (transit/read-handler remote-as-of-db)
162
+ "datahike/Entity" (transit/read-handler remote-entity)})
163
+
164
+ (declare json-mapper)
165
+
166
+ (defn write-to-generator [f]
167
+ (fn [x ^JsonGenerator gen]
168
+ (let [json-out (j/write-value-as-string (f x) json-mapper)]
169
+ (.writeRawValue gen json-out))))
170
+
171
+ (def json-mapper-opts
172
+ {:encode-key-fn true
173
+ :decode-key-fn true
174
+ :modules [(jt/module
175
+ {:handlers
176
+ (merge
177
+ json-base-handlers
178
+ {datahike.remote.RemoteConnection
179
+ {:tag "!datahike/Connection"
180
+ :encode (write-to-generator :store-id)
181
+ :decode remote-connection}
182
+
183
+ datahike.datom.Datom
184
+ {:tag "!datahike/Datom"
185
+ :encode (write-to-generator datom-as-vec)
186
+ :decode datom-from-vec}
187
+
188
+ datahike.db.TxReport
189
+ {:tag "!datahike/TxReport"
190
+ :encode (write-to-generator #(into {} %))
191
+ :decode datahike.db/map->TxReport}
192
+
193
+ datahike.remote.RemoteDB
194
+ {:tag "!datahike/DB"
195
+ :encode (write-to-generator map-without-remote)
196
+ :decode remote-db}
197
+
198
+ datahike.remote.RemoteHistoricalDB
199
+ {:tag "!datahike/HistoricalDB"
200
+ :encode (write-to-generator map-without-remote)
201
+ :decode remote-historical-db}
202
+
203
+ datahike.remote.RemoteSinceDB
204
+ {:tag "!datahike/SinceDB"
205
+ :encode (write-to-generator map-without-remote)
206
+ :decode remote-since-db}
207
+
208
+ datahike.remote.RemoteAsOfDB
209
+ {:tag "!datahike/AsOfDB"
210
+ :encode (write-to-generator map-without-remote)
211
+ :decode remote-as-of-db}
212
+
213
+ datahike.remote.RemoteEntity
214
+ {:tag "!datahike/Entity"
215
+ :encode (write-to-generator #(into {} %))
216
+ :decode remote-entity}})})]})
217
+
218
+ (def json-mapper (j/object-mapper json-mapper-opts))
@@ -0,0 +1,228 @@
1
+ (ns ^:no-doc datahike.schema
2
+ (:require [clojure.spec.alpha :as s]
3
+ [datahike.datom])
4
+ #?(:clj (:import [datahike.datom Datom])))
5
+
6
+ (s/def :db.type/id #?(:clj #(or (= (class %) java.lang.Long) string?)
7
+ :cljs #(or (and (number? %)
8
+ (js/Number.isSafeInteger %))
9
+ string?)))
10
+
11
+ ;; db types
12
+ (s/def :db.type/bigdec #?(:cljs (complement any?) ; feels more appropriate than hiding key -pat
13
+ :clj decimal?))
14
+ (s/def :db.type/bigint #?(:clj integer?
15
+ :cljs #(or (integer? %)
16
+ (= js/BigInt (type %)))))
17
+ (s/def :db.type/boolean boolean?)
18
+ (s/def :db.type/bytes #?(:clj bytes?
19
+ :cljs #(and (some->> (.-buffer %) (instance? js/ArrayBuffer))
20
+ (some->> (.-byteLength %) (number?)))))
21
+ (s/def :db.type/double double?)
22
+ (s/def :db.type/float float?)
23
+ (s/def :db.type/number number?)
24
+ (s/def :db.type/instant #?(:clj #(= (class %) java.util.Date)
25
+ :cljs inst?))
26
+ (s/def :db.type/keyword keyword?)
27
+ (s/def :db.type/long #?(:clj #(= (class %) java.lang.Long)
28
+ :cljs #(js/Number.isSafeInteger %)))
29
+ (s/def :db.type/ref :db.type/id)
30
+ (s/def :db.type/string string?)
31
+ (s/def :db.type/symbol symbol?)
32
+ (s/def :db.type/uuid uuid?)
33
+ (s/def :db.type/tuple vector?)
34
+
35
+ (s/def :db.type/value
36
+ #{:db.type/bigdec
37
+ :db.type/bigint
38
+ :db.type/boolean
39
+ :db.type/bytes
40
+ :db.type/double
41
+ :db.type/float
42
+ :db.type/number
43
+ :db.type/instant
44
+ :db.type/keyword
45
+ :db.type/long
46
+ :db.type/ref
47
+ :db.type/string
48
+ :db.type/symbol
49
+ :db.type/uuid
50
+ :db.type/value
51
+ :db.type/tuple
52
+ :db.type/cardinality
53
+ :db.type.install/attribute
54
+ :db.type/valueType
55
+ :db.type/unique})
56
+
57
+ ;; TODO: add bytes
58
+
59
+ (s/def :db.type/cardinality #{:db.cardinality/one :db.cardinality/many})
60
+ (s/def :db.type/unique #{:db.unique/identity :db.unique/value})
61
+
62
+ ;; only for old datomic compliance, will be part of partioning in the future
63
+ (s/def :db.type.install/_attribute #{:db.part/tx :db.part/db :db.part/user})
64
+
65
+ (s/def ::schema-attribute #{:db/id :db/ident :db/isComponent :db/noHistory :db/valueType :db/cardinality :db/unique :db/index :db.install/_attribute :db/doc :db/tupleAttrs :db/tupleType :db/tupleTypes})
66
+
67
+ (s/def ::entity-spec-attribute #{:db/ensure :db.entity/attrs :db.entity/preds})
68
+ (s/def ::meta-attribute #{:db/txInstant :db/retracted :db/noCommit})
69
+
70
+ (s/def ::schema (s/keys :req [:db/ident :db/valueType :db/cardinality]
71
+ :opt [:db/id :db/unique :db/index :db.install/_attribute :db/doc :db/noHistory :db/tupleType :db/tupleTypes]))
72
+
73
+ (s/def ::entity-spec (s/keys :opt [:db.entity/attrs :db.entity/preds]))
74
+
75
+ (s/def ::enum (s/keys :req [:db/ident]))
76
+
77
+ (def required-keys #{:db/ident :db/valueType :db/cardinality})
78
+
79
+ (def ^:const implicit-schema-spec {:db/ident {:db/valueType :db.type/keyword
80
+ :db/unique :db.unique/identity
81
+ :db/cardinality :db.cardinality/one}
82
+ :db/valueType {:db/valueType :db.type/value
83
+ :db/unique :db.unique/identity
84
+ :db/cardinality :db.cardinality/one}
85
+ :db/id {:db/valueType :db.type/id
86
+ :db/unique :db.unique/identity
87
+ :db/cardinality :db.cardinality/one}
88
+ :db/cardinality {:db/valueType :db.type/cardinality
89
+ :db/unique :db.unique/identity
90
+ :db/cardinality :db.cardinality/one}
91
+ :db/index {:db/valueType :db.type/boolean
92
+ :db/unique :db.unique/identity
93
+ :db/cardinality :db.cardinality/one}
94
+ :db/unique {:db/valueType :db.type/unique
95
+ :db/unique :db.unique/identity
96
+ :db/cardinality :db.cardinality/one}
97
+ :db/isComponent {:db/valueType :db.type/boolean
98
+ :db/unique :db.unique/identity
99
+ :db/cardinality :db.cardinality/one}
100
+ :db/noHistory {:db/valueType :db.type/boolean
101
+ :db/unique :db.unique/identity
102
+ :db/cardinality :db.cardinality/one}
103
+ :db/txInstant {:db/valueType :db.type/instant
104
+ :db/unique :db.unique/identity
105
+ :db/index true
106
+ :db/cardinality :db.cardinality/one}
107
+ :db/noCommit {:db/valueType :db.type/boolean
108
+ :db/unique :db.unique/identity
109
+ :db/cardinality :db.cardinality/one}
110
+ :db/retracted {:db/valueType :db.type/long
111
+ :db/unique :db.unique/identity
112
+ :db/cardinality :db.cardinality/many}
113
+ :db/ensure {:db/valueType :db.type/keyword
114
+ :db/cardinality :db.cardinality/one}
115
+ :db.entity/attrs {:db/valueType :db.type/keyword
116
+ :db/cardinality :db.cardinality/many}
117
+ :db.entity/preds {:db/valueType :db.type/symbol
118
+ :db/cardinality :db.cardinality/many}
119
+ :db/doc {:db/valueType :db.type/string
120
+ :db/index true
121
+ :db/cardinality :db.cardinality/one}
122
+ :db.install/_attribute {:db/valueType :db.type.install/_attribute
123
+ :db/unique :db.unique/identity
124
+ :db/cardinality :db.cardinality/one}
125
+ :db/tupleType {:db/valueType :db.type/value
126
+ :db/cardinality :db.cardinality/one}
127
+ :db/tupleTypes {:db/valueType :db.type/tuple
128
+ :db/cardinality :db.cardinality/one}
129
+ :db/tupleAttrs {:db/valueType :db.type/tuple
130
+ :db/cardinality :db.cardinality/one}})
131
+ (s/def :db/helpers #{:db.install/attribute :db})
132
+ (s/def :db.part/types #{:db.part/tx :db.part/sys :db.part/user})
133
+
134
+ (s/def :db.meta/attributes #{:db/txInstant})
135
+
136
+ (s/def ::sys-idents (s/or :value :db.type/value
137
+ :cardinality :db.type/cardinality
138
+ :parts :db.part/types
139
+ :helpers :db/helpers
140
+ :meta :db.meta/attributes
141
+ :unique :db.type/unique))
142
+
143
+ (def schema-keys #{:db/ident :db/isComponent :db/noHistory :db/valueType :db/cardinality :db/unique :db/index :db.install/_attribute :db/doc :db/tupleType :db/tupleTypes :db/tupleAttrs})
144
+
145
+ (s/def ::old-schema-val (s/keys :req [:db/valueType :db/cardinality]
146
+ :opt [:db/ident :db/unique :db/index :db.install/_attribute :db/doc :db/noHistory]))
147
+
148
+ (s/def ::old-schema-key keyword?)
149
+
150
+ (s/def ::old-schema (s/nilable (s/map-of ::old-schema-key ::old-schema-val)))
151
+
152
+ (defn old-schema-valid? [schema]
153
+ (s/valid? ::old-schema schema))
154
+
155
+ (defn explain-old-schema [schema]
156
+ (s/explain-data ::old-schema schema))
157
+
158
+ (defn meta-attr? [a-ident]
159
+ (s/valid? ::meta-attribute a-ident))
160
+
161
+ (defn schema-attr? [a-ident]
162
+ (s/valid? ::schema-attribute a-ident))
163
+
164
+ (defn sys-ident? [a-ident]
165
+ (s/valid? ::sys-idents a-ident))
166
+
167
+ (defn entity-spec-attr? [a-ident]
168
+ (s/valid? ::entity-spec-attribute a-ident))
169
+
170
+ (defn value-valid? [a-ident v-ident schema]
171
+ (let [schema (if (or (meta-attr? a-ident) (schema-attr? a-ident) (entity-spec-attr? a-ident))
172
+ implicit-schema-spec
173
+ schema)
174
+ value-type (get-in schema [a-ident :db/valueType])]
175
+ (s/valid? value-type v-ident)))
176
+
177
+ (defn instant? [db ^Datom datom schema]
178
+ (let [a-ident (if (:attribute-refs? (:config db))
179
+ ((:ref-ident-map db) (.-a datom))
180
+ (.-a datom))
181
+ schema (if (or (meta-attr? a-ident) (schema-attr? a-ident))
182
+ implicit-schema-spec
183
+ schema)]
184
+ (= (get-in schema [a-ident :db/valueType]) :db.type/instant)))
185
+
186
+ (defn schema-entity? [entity]
187
+ (some #(contains? entity %) schema-keys))
188
+
189
+ (defn schema? [schema]
190
+ (s/valid? ::schema schema))
191
+
192
+ (defn describe-type [schema-type]
193
+ (s/describe schema-type))
194
+
195
+ (defn find-invalid-schema-updates [entity attr-schema]
196
+ (reduce-kv
197
+ (fn [m attr-def new-value]
198
+ (let [old-value (get-in attr-schema [attr-def])]
199
+ (when (not= old-value new-value)
200
+ (case attr-def
201
+ :db/cardinality
202
+ ;; Prohibit update from :db.cardinality/one to :db.cardinality/many, if there is a :db/unique constraint.
203
+ (when (and (= new-value :db.cardinality/many)
204
+ (#{:db.unique/value :db.unique/identity} (:db/unique attr-schema)))
205
+ (assoc m attr-def [old-value new-value]))
206
+
207
+ :db/unique
208
+ (when (or (not (:db/unique attr-schema))
209
+ (not= :db.cardinality/one (:db/cardinality attr-schema)))
210
+ (assoc m attr-def [old-value new-value]))
211
+
212
+ ;; Always allow these attributes to be updated.
213
+ :db/doc nil
214
+ :db/noHistory nil
215
+ :db/isComponent nil
216
+
217
+ (assoc m attr-def [old-value new-value])))))
218
+ {}
219
+ (dissoc entity :db/id)))
220
+
221
+ (defn is-system-keyword? [value]
222
+ (and (or (keyword? value) (string? value))
223
+ (if-let [ns (namespace (keyword value))]
224
+ (= "db" (first (clojure.string/split ns #"\.")))
225
+ false)))
226
+
227
+ (defn get-user-schema [{:keys [schema] :as db}]
228
+ (into {} (filter #(not (is-system-keyword? (key %))) schema)))
@@ -0,0 +1,42 @@
1
+ (ns datahike.schema-cache
2
+ (:require #?(:clj [clojure.core.cache.wrapped :as cw]
3
+ :cljs [cljs.cache.wrapped :as cw])
4
+ [datahike.config :as dc]
5
+ [datahike.store :as ds]))
6
+
7
+ ;; Shared schema read cache across all stores
8
+ (def schema-meta-cache (cw/lru-cache-factory {} :threshold dc/*schema-meta-cache-size*))
9
+
10
+ ;; LRU cache of LRU caches for write operations, one per store
11
+ (def schema-write-caches
12
+ (cw/lru-cache-factory {} :threshold dc/*schema-write-cache-max-db-count*))
13
+
14
+ (defn- get-or-create-write-cache [store-config]
15
+ (let [store-id (ds/store-identity store-config)]
16
+ (if (cw/has? schema-write-caches store-id)
17
+ (cw/lookup schema-write-caches store-id)
18
+ (let [new-cache (cw/lru-cache-factory {} :threshold dc/*schema-meta-cache-size*)]
19
+ (cw/miss schema-write-caches store-id new-cache)
20
+ new-cache))))
21
+
22
+ (defn cache-has? [schema-meta-key]
23
+ (cw/has? schema-meta-cache schema-meta-key))
24
+
25
+ (defn cache-lookup [schema-meta-key]
26
+ (cw/lookup schema-meta-cache schema-meta-key))
27
+
28
+ (defn cache-miss [schema-meta-key schema-meta]
29
+ (cw/miss schema-meta-cache schema-meta-key schema-meta))
30
+
31
+ (defn write-cache-has? [store-config schema-meta-key]
32
+ (let [write-cache (get-or-create-write-cache store-config)]
33
+ (cw/has? write-cache schema-meta-key)))
34
+
35
+ (defn add-to-write-cache [store-config schema-meta-key]
36
+ (let [write-cache (get-or-create-write-cache store-config)]
37
+ (cw/miss write-cache schema-meta-key true)))
38
+
39
+ (defn clear-write-cache [store-config]
40
+ (let [store-id (ds/store-identity store-config)]
41
+ (cw/evict schema-write-caches store-id)))
42
+