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,370 @@
1
+ package datahike.java;
2
+
3
+ import clojure.java.api.Clojure;
4
+ import clojure.lang.PersistentHashSet;
5
+ import clojure.lang.APersistentMap;
6
+ import clojure.lang.APersistentVector;
7
+ import clojure.lang.PersistentVector;
8
+ import org.junit.Test;
9
+
10
+ import java.util.*;
11
+ import java.util.stream.Stream;
12
+
13
+ import static datahike.java.Datahike.deref;
14
+ import static datahike.java.Util.*;
15
+ import static org.junit.Assert.*;
16
+
17
+ import org.junit.runner.JUnitCore;
18
+ import org.junit.runner.Result;
19
+ import org.junit.runner.notification.Failure;
20
+
21
+
22
+
23
+ public class DatahikeTest {
24
+
25
+ private Object schema = Clojure.read(" [{:db/ident :name\n" +
26
+ " :db/valueType :db.type/string\n" +
27
+ " :db/unique :db.unique/identity\n" +
28
+ " :db/index true\n" +
29
+ " :db/cardinality :db.cardinality/one}\n" +
30
+ " {:db/ident :age\n" +
31
+ " :db/valueType :db.type/long\n" +
32
+ " :db/cardinality :db.cardinality/one}]");
33
+
34
+ private APersistentMap config() {
35
+ UUID connId = UUID.randomUUID();
36
+ return map(kwd(":store"), map(kwd(":backend"), kwd(":memory"),
37
+ kwd(":id"), connId),
38
+ kwd(":initial-tx"), this.schema);
39
+ }
40
+
41
+ private Date firstDate;
42
+ private String query;
43
+
44
+ private Object transactOnce() {
45
+ APersistentMap config = config();
46
+ Datahike.createDatabase(config);
47
+
48
+ Object conn = Datahike.connect(config);
49
+ query = "[:find ?n ?a :where [?e :name ?n] [?e :age ?a]]";
50
+
51
+ Datahike.transact(conn, vec(
52
+ map(kwd(":name"), "Alice", kwd(":age"), 25L),
53
+ map(kwd(":name"), "Bob", kwd(":age"), 30L)));
54
+ return conn;
55
+ }
56
+
57
+ @org.junit.Test
58
+ public void databaseExists() {
59
+ APersistentMap config = config();
60
+ Datahike.createDatabase(config);
61
+ assertTrue(Datahike.databaseExists(config));
62
+ APersistentMap configNotExisting = (APersistentMap)ednFromString("{:store {:backend :memory :id #uuid \"00000000-0000-0000-0000-000000000000\"}}");
63
+ assertFalse(Datahike.databaseExists(configNotExisting));
64
+ }
65
+
66
+ @org.junit.Test
67
+ public void queryWithDBAndInput() {
68
+ Object conn = transactOnce();
69
+ query = "[:find ?n ?a :in $ [?n] :where [?e :name ?n] [?e :age ?a]]";
70
+ Set<APersistentVector> res = (Set<APersistentVector>)Datahike.q(query, deref(conn), Clojure.read("[\"Alice\"]"));
71
+ Object[] names = res.stream().map(vec -> vec.get(0)).toArray();
72
+ assertTrue(names[0].equals("Alice"));
73
+ }
74
+
75
+ @org.junit.Test
76
+ public void queryWithJavaArrayInput() {
77
+ Object conn = transactOnce();
78
+ query = "[:find ?n ?a :in $ [?n] :where [?e :name ?n] [?e :age ?a]]";
79
+ Set<APersistentVector> res = (Set<APersistentVector>)Datahike.q(query, deref(conn), new String[] {"Alice"});
80
+ Object[] names = res.stream().map(vec -> vec.get(0)).toArray();
81
+ assertTrue(names[0].equals("Alice"));
82
+ }
83
+
84
+ @org.junit.Test
85
+ public void queryWithLocalInputDB() {
86
+ Object input = Clojure.read("[[1 :name 'Ivan'] [1 :age 19] [1 :aka \"dragon_killer_94\"] [1 :aka '-=autobot=-']]");
87
+ Set res = (Set)Datahike.q("[:find ?n ?a :where [?e :aka \"dragon_killer_94\"] [?e :name ?n] [?e :age ?a]]", input);
88
+ assertTrue(res.size() == 1);
89
+ }
90
+
91
+ @org.junit.Test
92
+ public void queryWithDB() {
93
+ APersistentMap config = config();
94
+ Datahike.createDatabase(config);
95
+ Object conn = Datahike.connect(config);
96
+
97
+ // Transacting new schema
98
+ Datahike.transact(conn, vec(map(kwd(":db/ident"), kwd(":name"),
99
+ kwd(":db/valueType"), kwd(":db.type/string"),
100
+ kwd(":db/cardinality"), kwd(":db.cardinality/one"))));
101
+
102
+ // Transacting with schema presence
103
+ Datahike.transact(conn, vec(map(kwd(":name"), "Alice")));
104
+
105
+ Object deref = Datahike.deref(conn);
106
+
107
+ Set res = (Set<APersistentVector>)Datahike.q("[:find ?e :where [?e :name]]", deref);
108
+ assertTrue(res.size() == 1);
109
+
110
+ res = (Set<APersistentVector>)Datahike.q("[:find ?v :where [_ :name ?v]]", deref);
111
+ assertEquals(PersistentHashSet.create(Arrays.asList(PersistentVector.create("Alice"))), res);
112
+ }
113
+
114
+ @org.junit.Test
115
+ public void history() {
116
+ Object conn = transactOnce();
117
+
118
+ Set<APersistentVector> res = (Set<APersistentVector>)Datahike.q((String) query, Datahike.history(deref(conn)));
119
+ Object[] names = res.stream().map(pv -> pv.get(0)).toArray();
120
+ assertArrayEquals(new String[] {"Alice", "Bob"}, names);
121
+ }
122
+
123
+ @Test
124
+ public void asOfAndSince() {
125
+ Object conn = transactOnce();
126
+
127
+ // Make sure transaction has older timestamp than firstDate
128
+ try {
129
+ Thread.sleep(10);
130
+ } catch (InterruptedException e) {
131
+ }
132
+
133
+ firstDate = new Date();
134
+ Datahike.transact(conn, vec(map(
135
+ kwd(":db/id"), vec(kwd(":name"), "Alice"),
136
+ kwd(":age"), 30L)));
137
+
138
+ Set res = (Set<APersistentVector>)Datahike.q(query, Datahike.asOf(deref(conn), firstDate));
139
+ assertEquals(2, res.size());
140
+
141
+ res = (Set<APersistentVector>)Datahike.q(query, Datahike.since(deref(conn), firstDate));
142
+ // 0, because :name was transacted before the first date
143
+ assertEquals(0, res.size());
144
+ }
145
+
146
+ @Test
147
+ public void pullAndPullMany() {
148
+ Object conn = transactOnce();
149
+
150
+ Datahike.transact(conn, vec(map(kwd(":db/id"), 10,
151
+ kwd(":name"), "Joe",
152
+ kwd(":age"), 50L)));
153
+ Map res = Datahike.pull(deref(conn), "[*]", 10);
154
+ assertEquals("Joe", res.get(kwd(":name")));
155
+
156
+ Datahike.transact(conn, vec(map(kwd(":db/id"), 20,
157
+ kwd(":name"), "Jane",
158
+ kwd(":age"), 25L)));
159
+ List list = Datahike.pullMany(deref(conn), "[*]", vec(10, 20));
160
+ assertEquals(2, list.size());
161
+ }
162
+
163
+ @Test
164
+ public void release() {
165
+ APersistentMap config = config();
166
+ Datahike.createDatabase(config);
167
+ Object conn = Datahike.connect(config);
168
+ Datahike.release(conn);
169
+ }
170
+
171
+ @Test
172
+ public void seekDatoms() {
173
+ APersistentMap config = config();
174
+ Datahike.createDatabase(config);
175
+ Object conn = Datahike.connect(config);
176
+
177
+ Datahike.transact(conn, (APersistentVector)Clojure.read("[{:db/id 10 :name \"Petr\" :age 44} {:db/id 20 :name \"Ivan\" :age 25} {:db/id 30 :name \"Sergey\" :age 11}]"));
178
+
179
+ // Test seekdatoms convenience method (component-based)
180
+ Object db = deref(conn);
181
+ Iterable<?> datomsResult = Datahike.seekdatoms(db, kwd(":eavt"), 10);
182
+ assertNotNull(datomsResult);
183
+
184
+ // Just verify the API works - detailed datom testing is covered elsewhere
185
+ boolean foundDatoms = false;
186
+ for (Object item : datomsResult) {
187
+ foundDatoms = true;
188
+ break; // At least one datom found
189
+ }
190
+ assertTrue(foundDatoms);
191
+ }
192
+
193
+ @Test
194
+ public void tempId() {
195
+ Object id = Datahike.tempid(kwd(":db.part/user"));
196
+ assertTrue(((Number)id).longValue() < 0);
197
+ id = Datahike.tempid(kwd(":db.part/user"), -10000);
198
+ assertEquals(-10000L, ((Number)id).longValue());
199
+ }
200
+
201
+ @Test
202
+ public void entity() {
203
+ Object conn = transactOnce();
204
+ Datahike.transact(conn, vec(map(kwd(":db/id"), 10,
205
+ kwd(":name"), "Joe",
206
+ kwd(":age"), 50L)));
207
+
208
+ IEntity entity = (IEntity) Datahike.entity(deref(conn), 10);
209
+ Object res = entity.valAt(kwd(":name"));
210
+ assertEquals("Joe", res);
211
+ }
212
+
213
+ @Test
214
+ public void entityDb() {
215
+ Object conn = transactOnce();
216
+ Datahike.transact(conn, vec(map(kwd(":db/id"), 10,
217
+ kwd(":name"), "Joe",
218
+ kwd(":age"), 50L)));
219
+ IEntity entity = (IEntity) Datahike.entity(deref(conn), 10);
220
+
221
+ Object db = Datahike.entityDb(entity);
222
+ assertNotNull(db);
223
+ }
224
+
225
+ @Test
226
+ public void filterAndIsFiltered() {
227
+ APersistentMap config = config();
228
+ Datahike.createDatabase(config);
229
+ Object conn = Datahike.connect(config);
230
+ assertFalse(Datahike.isFiltered(deref(conn)));
231
+
232
+ Datahike.transact(conn, (APersistentVector)Clojure.read("[{:db/id 10 :name \"Petr\" :age 44} {:db/id 20 :name \"Ivan\" :age 25} {:db/id 30 :name \"Sergey\" :age 11}]"));
233
+ Object filteredDB = Datahike.filter(deref(conn), Clojure.read("(fn [_ datom] (not= :age (:a datom)))"));
234
+ assertTrue(Datahike.isFiltered(filteredDB));
235
+ }
236
+
237
+ @Test
238
+ public void dbWith() {
239
+ APersistentMap config = config();
240
+ Datahike.createDatabase(config);
241
+ Object conn = Datahike.connect(config);
242
+ APersistentVector txData = (APersistentVector)Clojure.read("[{:db/id 10 :name \"Petr\" :age 44} {:db/id 20 :name \"Ivan\" :age 25} {:db/id 30 :name \"Sergey\" :age 11}]");
243
+ Object dbAfter = Datahike.dbWith(deref(conn), txData);
244
+ query = "[:find ?a :in $ :where [?e :age ?a]]";
245
+ Set res = (Set)Datahike.q(query, dbAfter);
246
+ assertTrue(res.size() == 3);
247
+ }
248
+
249
+ /* TODO: This requires a durable backend */
250
+ // @Test
251
+ // public void gcStorage() {
252
+ // APersistentMap config = config();
253
+ // Datahike.createDatabase(config);
254
+ // Object conn = Datahike.connect(config);
255
+ // Set<UUID> res = (Set<UUID>)deref(Datahike.gcStorage(conn));
256
+ // assertTrue(res.size() == 0);
257
+ // }
258
+
259
+ @Test
260
+ public void databaseBuilderMemoryWithUUID() {
261
+ UUID id = UUID.randomUUID();
262
+ Map<String, Object> config = Database.memory(id)
263
+ .keepHistory(true)
264
+ .build();
265
+
266
+ assertNotNull(config);
267
+ assertTrue(config.containsKey("store"));
268
+
269
+ @SuppressWarnings("unchecked")
270
+ Map<String, Object> store = (Map<String, Object>) config.get("store");
271
+ assertEquals(":memory", store.get("backend"));
272
+ assertEquals(id, store.get("id"));
273
+ assertEquals(true, config.get("keep-history?"));
274
+ }
275
+
276
+ @Test
277
+ public void databaseBuilderMemoryWithString() {
278
+ UUID id = UUID.randomUUID();
279
+ String idString = id.toString();
280
+
281
+ Map<String, Object> config = Database.memory(idString)
282
+ .schemaFlexibility(SchemaFlexibility.READ)
283
+ .build();
284
+
285
+ @SuppressWarnings("unchecked")
286
+ Map<String, Object> store = (Map<String, Object>) config.get("store");
287
+ assertEquals(id, store.get("id"));
288
+ assertEquals(":read", config.get("schema-flexibility"));
289
+ }
290
+
291
+ @Test
292
+ public void databaseBuilderFile() {
293
+ Map<String, Object> config = Database.file("/tmp/test-db")
294
+ .keepHistory(false)
295
+ .name("test-database")
296
+ .build();
297
+
298
+ @SuppressWarnings("unchecked")
299
+ Map<String, Object> store = (Map<String, Object>) config.get("store");
300
+ assertEquals(":file", store.get("backend"));
301
+ assertEquals("/tmp/test-db", store.get("path"));
302
+ assertEquals(false, config.get("keep-history?"));
303
+ assertEquals("test-database", config.get("name"));
304
+ }
305
+
306
+ @Test
307
+ public void databaseBuilderWithInitialTx() {
308
+ Object schema = vec(
309
+ map(kwd(":db/ident"), kwd(":test/attr"),
310
+ kwd(":db/valueType"), kwd(":db.type/string"),
311
+ kwd(":db/cardinality"), kwd(":db.cardinality/one"))
312
+ );
313
+
314
+ Map<String, Object> config = Database.memory(UUID.randomUUID())
315
+ .initialTx(schema)
316
+ .build();
317
+
318
+ assertNotNull(config.get("initial-tx"));
319
+ }
320
+
321
+ @Test
322
+ public void databaseBuilderCustomOption() {
323
+ Map<String, Object> config = Database.memory(UUID.randomUUID())
324
+ .option("temporal-index", true)
325
+ .option("attribute-refs?", false)
326
+ .build();
327
+
328
+ assertEquals(true, config.get("temporal-index"));
329
+ assertEquals(false, config.get("attribute-refs?"));
330
+ }
331
+
332
+ @Test
333
+ public void databaseBuilderIntegration() {
334
+ // Test that the builder output works with actual Datahike API
335
+ Map<String, Object> config = Database.memory(UUID.randomUUID())
336
+ .schemaFlexibility(SchemaFlexibility.READ)
337
+ .keepHistory(true)
338
+ .build();
339
+
340
+ Datahike.createDatabase(config);
341
+ assertTrue(Datahike.databaseExists(config));
342
+
343
+ Object conn = Datahike.connect(config);
344
+ assertNotNull(conn);
345
+
346
+ // Transact and query to verify the database works
347
+ Datahike.transact(conn, vec(map(kwd(":name"), "Test")));
348
+ Object result = Datahike.q("[:find ?n :where [?e :name ?n]]", deref(conn));
349
+ assertNotNull(result);
350
+
351
+ Datahike.deleteDatabase(config);
352
+ assertFalse(Datahike.databaseExists(config));
353
+ }
354
+
355
+ /**
356
+ * Called by Datahike's Clojure tests and runs the above Junit tests.
357
+ */
358
+ public static boolean run() {
359
+ Result result = JUnitCore.runClasses(DatahikeTest.class);
360
+
361
+ System.out.println("\n");
362
+ List<Failure> failures = result.getFailures();
363
+ for (Failure failure : failures) {
364
+ System.out.println("Junit Failure: " + failure.toString());
365
+ }
366
+ System.out.println("Java Bindings test failure count: " + failures.size());
367
+
368
+ return result.wasSuccessful();
369
+ }
370
+ }
@@ -0,0 +1,170 @@
1
+ package datahike.java;
2
+
3
+ import clojure.lang.Keyword;
4
+ import clojure.lang.Symbol;
5
+ import clojure.java.api.Clojure;
6
+ import clojure.lang.IFn;
7
+
8
+ /**
9
+ * EDN type helpers for explicit type construction.
10
+ *
11
+ * <p>This class provides static methods for creating EDN types when you need
12
+ * fine-grained control over conversion, or want to force a value to be treated
13
+ * as a specific EDN type regardless of automatic conversion rules.</p>
14
+ *
15
+ * <p>Example:</p>
16
+ * <pre>{@code
17
+ * import static datahike.java.EDN.*;
18
+ *
19
+ * Map<String, Object> schema = Map.of(
20
+ * "db/ident", keyword("person", "name"),
21
+ * "db/valueType", keyword("db.type", "string"),
22
+ * "db/cardinality", keyword("db.cardinality", "one"),
23
+ * "db/doc", forceString(":literal-colon-in-doc")
24
+ * );
25
+ * }</pre>
26
+ */
27
+ public class EDN {
28
+
29
+ private static final IFn readStringFn = Clojure.var("clojure.edn", "read-string");
30
+
31
+ /**
32
+ * Forbids instance creation.
33
+ */
34
+ private EDN() {}
35
+
36
+ /**
37
+ * Creates an EDN keyword from a name.
38
+ *
39
+ * <p>Example:</p>
40
+ * <pre>{@code
41
+ * keyword("name") // → :name
42
+ * }</pre>
43
+ *
44
+ * @param name keyword name
45
+ * @return Clojure keyword
46
+ */
47
+ public static Keyword keyword(String name) {
48
+ return Keyword.intern(name);
49
+ }
50
+
51
+ /**
52
+ * Creates a namespaced EDN keyword.
53
+ *
54
+ * <p>Example:</p>
55
+ * <pre>{@code
56
+ * keyword("person", "name") // → :person/name
57
+ * }</pre>
58
+ *
59
+ * @param namespace keyword namespace
60
+ * @param name keyword name
61
+ * @return Clojure keyword
62
+ */
63
+ public static Keyword keyword(String namespace, String name) {
64
+ return Keyword.intern(namespace, name);
65
+ }
66
+
67
+ /**
68
+ * Creates an EDN symbol from a name.
69
+ *
70
+ * <p>Symbols are used for function names and special forms in Clojure.
71
+ * Rarely needed in data transactions.</p>
72
+ *
73
+ * <p>Example:</p>
74
+ * <pre>{@code
75
+ * symbol("my-fn") // → my-fn
76
+ * }</pre>
77
+ *
78
+ * @param name symbol name
79
+ * @return Clojure symbol
80
+ */
81
+ public static Symbol symbol(String name) {
82
+ return Symbol.intern(name);
83
+ }
84
+
85
+ /**
86
+ * Creates a namespaced EDN symbol.
87
+ *
88
+ * <p>Example:</p>
89
+ * <pre>{@code
90
+ * symbol("clojure.core", "assoc") // → clojure.core/assoc
91
+ * }</pre>
92
+ *
93
+ * @param namespace symbol namespace
94
+ * @param name symbol name
95
+ * @return Clojure symbol
96
+ */
97
+ public static Symbol symbol(String namespace, String name) {
98
+ return Symbol.intern(namespace, name);
99
+ }
100
+
101
+ /**
102
+ * Creates an EDN UUID tagged literal.
103
+ *
104
+ * <p>Returns a string that will be parsed as #uuid when converted to EDN.</p>
105
+ *
106
+ * <p>Example:</p>
107
+ * <pre>{@code
108
+ * uuid("550e8400-e29b-41d4-a716-446655440000")
109
+ * // → #uuid "550e8400-e29b-41d4-a716-446655440000"
110
+ * }</pre>
111
+ *
112
+ * @param uuidString UUID string (with or without #uuid prefix)
113
+ * @return UUID tagged literal
114
+ */
115
+ public static Object uuid(String uuidString) {
116
+ // Strip #uuid prefix if present
117
+ String cleaned = uuidString.trim();
118
+ if (cleaned.startsWith("#uuid")) {
119
+ cleaned = cleaned.substring(5).trim().replaceAll("\"", "");
120
+ }
121
+ return readStringFn.invoke("#uuid \"" + cleaned + "\"");
122
+ }
123
+
124
+ /**
125
+ * Creates an EDN instant (timestamp) tagged literal.
126
+ *
127
+ * <p>Returns a string that will be parsed as #inst when converted to EDN.</p>
128
+ *
129
+ * <p>Example:</p>
130
+ * <pre>{@code
131
+ * inst("2024-01-01T00:00:00Z")
132
+ * // → #inst "2024-01-01T00:00:00Z"
133
+ * }</pre>
134
+ *
135
+ * @param isoTimestamp ISO 8601 timestamp string
136
+ * @return instant tagged literal
137
+ */
138
+ public static Object inst(String isoTimestamp) {
139
+ // Strip #inst prefix if present
140
+ String cleaned = isoTimestamp.trim();
141
+ if (cleaned.startsWith("#inst")) {
142
+ cleaned = cleaned.substring(5).trim().replaceAll("\"", "");
143
+ }
144
+ return readStringFn.invoke("#inst \"" + cleaned + "\"");
145
+ }
146
+
147
+ /**
148
+ * Forces a value to be treated as a string, even if it starts with ':'.
149
+ *
150
+ * <p>Use this to create strings that start with ':' without them becoming keywords.</p>
151
+ *
152
+ * <p>Example:</p>
153
+ * <pre>{@code
154
+ * forceString(":literal-colon")
155
+ * // → ":literal-colon" (string, not :literal-colon keyword)
156
+ * }</pre>
157
+ *
158
+ * <p>Note: This is equivalent to using backslash escaping: "\\:literal-colon"</p>
159
+ *
160
+ * @param value string value (can start with :)
161
+ * @return the string as-is (will not be converted to keyword)
162
+ */
163
+ public static String forceString(String value) {
164
+ // If value starts with ':', we need to escape it to prevent keyword conversion
165
+ if (value.startsWith(":")) {
166
+ return "\\" + value; // Add backslash escape
167
+ }
168
+ return value;
169
+ }
170
+ }
@@ -0,0 +1,11 @@
1
+ package datahike.java;
2
+
3
+ public interface IEntity {
4
+ /**
5
+ * Returns the value associated with keyword 'k' in this Entity.
6
+ *
7
+ * @param k a keyword
8
+ * @return the value associated with keyword 'k' in this Entity.
9
+ */
10
+ public Object valAt(Object k);
11
+ }