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,155 @@
1
+ (ns datahike.pod
2
+ "Babashka pod interface for Datahike.
3
+
4
+ This namespace provides the pod protocol implementation that allows
5
+ Datahike to be used from Babashka scripts.
6
+
7
+ The pod manages connections and database snapshots via ID-based references,
8
+ allowing immutable db values to be cached and released explicitly.
9
+
10
+ Functions are generated at compile-time from the API specification via
11
+ datahike.codegen.pod macros."
12
+ (:refer-clojure :exclude [read read-string])
13
+ (:require [bencode.core :as bencode]
14
+ [clojure.java.io :as io]
15
+ [cognitect.transit :as transit]
16
+ [datahike.api :as d]
17
+ [datahike.writing :as writing]
18
+ [datahike.codegen.pod :as codegen])
19
+ (:import [java.io PushbackInputStream]))
20
+
21
+ (set! *warn-on-reflection* true)
22
+
23
+ ;; =============================================================================
24
+ ;; I/O Infrastructure
25
+ ;; =============================================================================
26
+
27
+ (def stdin (PushbackInputStream. System/in))
28
+ (def stdout System/out)
29
+ (def stderr System/err)
30
+
31
+ (def debug? false)
32
+
33
+ (defn debug [& strs]
34
+ (when debug?
35
+ (binding [*out* (io/writer System/err)]
36
+ (apply prn strs))))
37
+
38
+ (defn write
39
+ ([v] (write stdout v))
40
+ ([stream v]
41
+ (debug :writing v)
42
+ (bencode/write-bencode stream v)
43
+ (flush)))
44
+
45
+ (defn write-err
46
+ ([v] (write stderr v))
47
+ ([stream v]
48
+ (debug :writing v)
49
+ (bencode/write-bencode stream v)
50
+ (flush)))
51
+
52
+ (defn read-string [^"[B" v]
53
+ (String. v))
54
+
55
+ (defn read [stream]
56
+ (bencode/read-bencode stream))
57
+
58
+ (defn read-transit [^String v]
59
+ (transit/read
60
+ (transit/reader
61
+ (java.io.ByteArrayInputStream. (.getBytes v "utf-8"))
62
+ :json)))
63
+
64
+ (defn write-transit [v]
65
+ (let [baos (java.io.ByteArrayOutputStream.)]
66
+ (transit/write (transit/writer baos :json) v)
67
+ (.toString baos "utf-8")))
68
+
69
+ ;; =============================================================================
70
+ ;; Generated Pod Runtime (atoms, helpers)
71
+ ;; =============================================================================
72
+
73
+ (codegen/defpod-runtime)
74
+
75
+ ;; =============================================================================
76
+ ;; Generated Pod Functions
77
+ ;; =============================================================================
78
+
79
+ (codegen/defpod-functions)
80
+
81
+ ;; =============================================================================
82
+ ;; Generated Pod Protocol Maps
83
+ ;; =============================================================================
84
+
85
+ (codegen/defpod-publics)
86
+
87
+ (codegen/defpod-describe-map)
88
+
89
+ (defn lookup
90
+ "Look up a function by name."
91
+ [var]
92
+ (get publics (symbol (name var))))
93
+
94
+ ;; =============================================================================
95
+ ;; Pod Runner
96
+ ;; =============================================================================
97
+
98
+ (defn run-pod
99
+ "Main pod event loop."
100
+ [_args]
101
+ (loop []
102
+ (let [message (try (read stdin)
103
+ (catch java.io.EOFException _
104
+ ::EOF))]
105
+ (when-not (identical? ::EOF message)
106
+ (let [op (get message "op")
107
+ op (read-string op)
108
+ op (keyword op)
109
+ id (some-> (get message "id")
110
+ read-string)
111
+ id (or id "unknown")]
112
+ (case op
113
+ :describe (do (write {"format" "transit+json"
114
+ "namespaces" [{"name" "datahike.pod"
115
+ "vars" describe-map}]
116
+ "id" id
117
+ "ops" {"shutdown" {}}})
118
+ (recur))
119
+ :invoke (do (try
120
+ (let [var (-> (get message "var")
121
+ read-string
122
+ symbol)
123
+ args (get message "args")
124
+ args (read-string args)
125
+ args (read-transit args)]
126
+ (if-let [f (lookup var)]
127
+ (do (debug f)
128
+ (debug args)
129
+ (let [result (apply f args)
130
+ _ (debug result)
131
+ value (write-transit result)
132
+ reply {"value" value
133
+ "id" id
134
+ "status" ["done"]}]
135
+ (write stdout reply)))
136
+ (throw (ex-info (str "Var not found: " var) {}))))
137
+ (catch Throwable e
138
+ (debug e)
139
+ (let [reply {"ex-message" (ex-message e)
140
+ "ex-data" (write-transit
141
+ (-> (ex-data e)
142
+ (update :argument-type str)
143
+ (assoc :type (str (class e)))))
144
+ "id" id
145
+ "status" ["done" "error"]}]
146
+ (write stdout reply))))
147
+ (recur))
148
+ :shutdown (System/exit 0)
149
+ (do
150
+ (let [reply {"ex-message" "Unknown op"
151
+ "ex-data" (pr-str {:op op})
152
+ "id" id
153
+ "status" ["done" "error"]}]
154
+ (write stdout reply))
155
+ (recur))))))))
@@ -0,0 +1,325 @@
1
+ (ns ^:no-doc datahike.pull-api
2
+ (:require
3
+ [datahike.db.utils :as dbu]
4
+ [datahike.db.interface :as dbi]
5
+ [datalog.parser.pull :as dpp #?@(:cljs [:refer [PullSpec]])])
6
+ #?(:clj
7
+ (:import
8
+ [datahike.datom Datom]
9
+ [datalog.parser.pull PullSpec])))
10
+
11
+ (defn- into!
12
+ [transient-coll items]
13
+ (reduce conj! transient-coll items))
14
+
15
+ (def ^:private ^:const +default-limit+ 1000)
16
+
17
+ (defn- initial-frame
18
+ "Creates an empty pattern frame according to pattern information."
19
+ [pattern eids multi?]
20
+ {:state :pattern
21
+ :pattern pattern
22
+ :wildcard? (:wildcard? pattern)
23
+ :specs (-> pattern :attrs seq)
24
+ :results (transient [])
25
+ :kvps (transient {})
26
+ :eids eids
27
+ :multi? multi?
28
+ :recursion {:depth {} :seen #{}}})
29
+
30
+ (defn subpattern-frame
31
+ "Returns frame specific for given attribute"
32
+ [pattern eids multi? attr]
33
+ (assoc (initial-frame pattern eids multi?) :attr attr))
34
+
35
+ (defn reset-frame
36
+ "Recalculate frame attributes from frame pattern and transfer end results to frame-specific result section"
37
+ [frame eids kvps]
38
+ (let [pattern (:pattern frame)]
39
+ (assoc frame
40
+ :eids eids
41
+ :specs (seq (:attrs pattern))
42
+ :wildcard? (:wildcard? pattern)
43
+ :kvps (transient {})
44
+ :results (cond-> (:results frame)
45
+ (seq kvps) (conj! kvps)))))
46
+
47
+ (defn push-recursion
48
+ "Push newly processed entity and increase recursion depth."
49
+ [rec attr eid]
50
+ (let [{:keys [depth seen]} rec]
51
+ (assoc rec
52
+ :depth (update depth attr (fnil inc 0))
53
+ :seen (conj seen eid))))
54
+
55
+ (defn seen-eid?
56
+ [frame eid]
57
+ (-> frame
58
+ (get-in [:recursion :seen] #{})
59
+ (contains? eid)))
60
+
61
+ (defn pull-seen-eid
62
+ "Add eid to result set if entity already seen. Else return nil."
63
+ [frame frames eid]
64
+ (when (seen-eid? frame eid)
65
+ (conj frames (update frame :results conj! {:db/id eid}))))
66
+
67
+ (defn single-frame-result
68
+ [key frame]
69
+ (some-> (:kvps frame) persistent! (get key)))
70
+
71
+ (defn recursion-result [frame]
72
+ (single-frame-result ::recursion frame))
73
+
74
+ (defn recursion-frame
75
+ [parent eid]
76
+ (let [attr (:attr parent)
77
+ rec (push-recursion (:recursion parent) attr eid)]
78
+ (assoc (subpattern-frame (:pattern parent) [eid] false ::recursion)
79
+ :recursion rec)))
80
+
81
+ (defn pull-recursion-frame
82
+ "Processes recursion for one entity ID or collects results.
83
+ Replaces current frame with
84
+ - one frame with remaining entiy IDs and
85
+ - one subpattern frame"
86
+ [db [frame & frames]]
87
+ (if-let [eids (seq (:eids frame))]
88
+ (let [frame (reset-frame frame (rest eids) (recursion-result frame))
89
+ eid (first eids)]
90
+ (or (pull-seen-eid frame frames eid)
91
+ (conj frames frame (recursion-frame frame eid))))
92
+ (let [kvps (recursion-result frame)
93
+ results (cond-> (:results frame)
94
+ (seq kvps) (conj! kvps))]
95
+ (conj frames (assoc frame :state :done :results results)))))
96
+
97
+ (defn recurse-attr
98
+ "Adds recursion frame to frame set if maximum recursion depth not reached"
99
+ [db attr multi? eids eid parent frames]
100
+ (let [{:keys [recursion pattern]} parent
101
+ depth (-> recursion (get :depth) (get attr 0))]
102
+ (if (-> pattern :attrs (get attr) :recursion (= depth))
103
+ (conj frames parent)
104
+ (pull-recursion-frame
105
+ db
106
+ (conj frames parent
107
+ {:state :recursion :pattern pattern
108
+ :attr attr :multi? multi? :eids eids
109
+ :recursion recursion
110
+ :results (transient [])})))))
111
+
112
+ (let [pattern (PullSpec. true {})] ;; For performance purposes?
113
+ (defn- expand-frame
114
+ [parent eid attr-key multi? eids]
115
+ (let [rec (push-recursion (:recursion parent) attr-key eid)]
116
+ (-> pattern
117
+ (subpattern-frame eids multi? attr-key)
118
+ (assoc :recursion rec)))))
119
+
120
+ (defn db-ident-and-id [db x]
121
+ (let [{:keys [ident ref]} (dbu/attr-info db x)]
122
+ (if (dbu/ident-name? ident)
123
+ {:db/id ref :db/ident ident}
124
+ {:db/id ref})))
125
+
126
+ (defn pull-attr-datoms
127
+ "Processes datoms found to requested pattern for given attribute, i.e.
128
+ - limits the result set to specified or default limit,
129
+ - renames attribute key if requested,
130
+ - adds default value on missing attributes if requested.
131
+ Adds frame if
132
+ - subpattern requested on attribute,
133
+ - recursion requested,
134
+ - attribute is reference.
135
+ Returns frame set."
136
+ [db attr-key attr eid forward? datoms opts [parent & frames]]
137
+ (let [limit (get opts :limit +default-limit+)
138
+ attr-key (or (:as opts) attr-key)
139
+ found (not-empty
140
+ (cond->> datoms
141
+ limit (into [] (take limit))))]
142
+ (if found
143
+ (let [ref? (dbu/ref? db attr)
144
+ system-attrib-ref? (dbu/system-attrib-ref? db attr)
145
+ component? (and ref? (dbu/component? db attr))
146
+ multi? (if forward? (dbu/multival? db attr)
147
+ (not component?))
148
+ datom-val (if forward? (fn [d] (.-v ^Datom d))
149
+ (fn [d] (.-e ^Datom d)))]
150
+
151
+ (cond
152
+ (contains? opts :subpattern)
153
+ (->> (subpattern-frame (:subpattern opts)
154
+ (mapv datom-val found)
155
+ multi? attr-key)
156
+ (conj frames parent))
157
+
158
+ (contains? opts :recursion)
159
+ (recurse-attr db attr-key multi?
160
+ (mapv datom-val found)
161
+ eid parent frames)
162
+
163
+ (and component? forward?)
164
+ (->> found
165
+ (mapv datom-val)
166
+ (expand-frame parent eid attr-key multi?)
167
+ (conj frames parent))
168
+
169
+ :else
170
+ (let [as-value (if (or ref? system-attrib-ref?)
171
+ #(db-ident-and-id db (datom-val %))
172
+ datom-val)
173
+ single? (not multi?)]
174
+ (->> (cond-> (into [] (map as-value) found)
175
+ single? first)
176
+ (update parent :kvps assoc! attr-key)
177
+ (conj frames)))))
178
+ (->> (cond-> parent
179
+ (contains? opts :default)
180
+ (update :kvps assoc! attr-key (:default opts)))
181
+ (conj frames)))))
182
+
183
+ (defn pull-attr
184
+ "Retrieve datoms for given entity id and specification from database"
185
+ [db spec eid frames]
186
+ (let [[attr-key opts] spec]
187
+ (if (= :db/id attr-key)
188
+ (if (not-empty (dbi/datoms db :eavt [eid]))
189
+ (conj (rest frames)
190
+ (update (first frames) :kvps assoc! :db/id eid))
191
+ frames)
192
+ (let [attr (:attr opts)
193
+ forward? (= attr-key attr)
194
+ a (if (and (:attribute-refs? (dbi/-config db))
195
+ (not (number? attr)))
196
+ (dbi/-ref-for db attr)
197
+ attr)
198
+ results (if (nil? a)
199
+ []
200
+ (if forward?
201
+ (dbi/datoms db :eavt [eid a])
202
+ (dbi/datoms db :avet [a eid])))]
203
+ (pull-attr-datoms db attr-key attr eid forward?
204
+ results opts frames)))))
205
+
206
+ (def ^:private filter-reverse-attrs
207
+ (filter (fn [[k v]] (not= k (:attr v)))))
208
+
209
+ (defn expand-reverse-subpattern-frame
210
+ [parent eid rattrs]
211
+ (-> (:pattern parent)
212
+ (assoc :attrs rattrs :wildcard? false)
213
+ (subpattern-frame [eid] false ::expand-rev)))
214
+
215
+ (defn expand-result
216
+ "Add intermediate result to frame next in line. Return frame set."
217
+ [frames kvps]
218
+ (->> kvps
219
+ (persistent!)
220
+ (update (first frames) :kvps into!)
221
+ (conj (rest frames))))
222
+
223
+ (defn pull-expand-reverse-frame
224
+ "Adds expand results of current frame to next frame in frame set."
225
+ [db [frame & frames]]
226
+ (->> (or (single-frame-result ::expand-rev frame) {})
227
+ (into! (:expand-kvps frame))
228
+ (expand-result frames)))
229
+
230
+ (defn pull-expand-frame
231
+ "Processes datoms for one attribute or changes frame state to process reverse attributes
232
+ and spawns new frame for subpattern."
233
+ [db [frame & frames]]
234
+ (if-let [datoms-by-attr (seq (:datoms frame))]
235
+ (let [[attr datoms] (first datoms-by-attr)
236
+ opts (-> frame
237
+ (get-in [:pattern :attrs])
238
+ (get attr {}))]
239
+ (pull-attr-datoms db attr attr (:eid frame) true datoms opts
240
+ (conj frames (update frame :datoms rest))))
241
+ (if-let [rattrs (->> (get-in frame [:pattern :attrs])
242
+ (into {} filter-reverse-attrs)
243
+ not-empty)]
244
+ (let [frame (assoc frame
245
+ :state :expand-rev
246
+ :expand-kvps (:kvps frame)
247
+ :kvps (transient {}))]
248
+ (->> rattrs
249
+ (expand-reverse-subpattern-frame frame (:eid frame))
250
+ (conj frames frame)))
251
+ (expand-result frames (:kvps frame)))))
252
+
253
+ (defn pull-wildcard-expand
254
+ [db frame frames eid pattern]
255
+ (let [datoms (group-by (fn [d] (if (:attribute-refs? (dbi/-config db))
256
+ (dbi/-ident-for db (.-a ^Datom d))
257
+ (.-a ^Datom d)))
258
+ (dbi/datoms db :eavt [eid]))
259
+ {:keys [attr recursion]} frame
260
+ rec (cond-> recursion
261
+ (some? attr) (push-recursion attr eid))]
262
+ (->> {:state :expand :kvps (transient {:db/id eid})
263
+ :eid eid :pattern pattern :datoms (seq datoms)
264
+ :recursion rec}
265
+ (conj frames frame)
266
+ (pull-expand-frame db))))
267
+
268
+ (defn pull-wildcard
269
+ [db frame frames]
270
+ (let [{:keys [eid pattern]} frame]
271
+ (or (pull-seen-eid frame frames eid)
272
+ (pull-wildcard-expand db frame frames eid pattern))))
273
+
274
+ (defn pull-pattern-frame
275
+ [db [frame & frames]]
276
+ (if-let [eids (seq (:eids frame))]
277
+ (if (:wildcard? frame)
278
+ (pull-wildcard db
279
+ (assoc frame
280
+ :specs []
281
+ :eid (first eids)
282
+ :wildcard? false)
283
+ frames)
284
+ (if-let [specs (seq (:specs frame))]
285
+ (let [spec (first specs)
286
+ new-frames (conj frames (assoc frame :specs (rest specs)))]
287
+ (pull-attr db spec (first eids) new-frames))
288
+ (->> frame :kvps persistent! not-empty
289
+ (reset-frame frame (rest eids))
290
+ (conj frames)
291
+ (recur db))))
292
+ (conj frames (assoc frame :state :done))))
293
+
294
+ (defn pull-pattern
295
+ [db frames]
296
+ (case (:state (first frames))
297
+ :expand (recur db (pull-expand-frame db frames))
298
+ :expand-rev (recur db (pull-expand-reverse-frame db frames))
299
+ :pattern (recur db (pull-pattern-frame db frames))
300
+ :recursion (recur db (pull-recursion-frame db frames))
301
+ :done (let [[f & remaining] frames
302
+ result (cond-> (persistent! (:results f))
303
+ (not (:multi? f)) first)]
304
+ (if (seq remaining)
305
+ (->> (cond-> (first remaining)
306
+ result (update :kvps assoc! (:attr f) result))
307
+ (conj (rest remaining))
308
+ (recur db))
309
+ result))))
310
+
311
+ (defn pull-spec
312
+ [db pattern eids multi?]
313
+ (let [eids (into [] (map #(dbu/entid-strict db %)) eids)]
314
+ (pull-pattern db (list (initial-frame pattern eids multi?)))))
315
+
316
+ (defn pull
317
+ ([db {:keys [selector eid]}]
318
+ (pull db selector eid))
319
+ ([db selector eid]
320
+ {:pre [(dbu/db? db)]}
321
+ (pull-spec db (dpp/parse-pull selector) [eid] false)))
322
+
323
+ (defn pull-many [db selector eids]
324
+ {:pre [(dbu/db? db)]}
325
+ (pull-spec db (dpp/parse-pull selector) eids true))