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.
- package/.circleci/config.yml +405 -0
- package/.circleci/scripts/gen_ci.clj +194 -0
- package/.cirrus.yml +60 -0
- package/.clj-kondo/babashka/sci/config.edn +1 -0
- package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
- package/.clj-kondo/config.edn +95 -0
- package/.dir-locals.el +2 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
- package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
- package/.github/ISSUE_TEMPLATE/config.yml +6 -0
- package/.github/pull_request_template.md +24 -0
- package/.github/workflows/native-image.yml +84 -0
- package/LICENSE +203 -0
- package/README.md +273 -0
- package/bb/deps.edn +9 -0
- package/bb/resources/github-fingerprints +3 -0
- package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
- package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
- package/bb/resources/native-image-tests/run-native-image-tests +74 -0
- package/bb/resources/native-image-tests/run-python-tests +22 -0
- package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
- package/bb/resources/native-image-tests/testconfig.edn +5 -0
- package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
- package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
- package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
- package/bb/resources/template/pom.xml +22 -0
- package/bb/src/tools/build.clj +132 -0
- package/bb/src/tools/clj_kondo.clj +32 -0
- package/bb/src/tools/deploy.clj +26 -0
- package/bb/src/tools/examples.clj +19 -0
- package/bb/src/tools/npm.clj +100 -0
- package/bb/src/tools/python.clj +14 -0
- package/bb/src/tools/release.clj +94 -0
- package/bb/src/tools/test.clj +148 -0
- package/bb/src/tools/version.clj +47 -0
- package/bb.edn +269 -0
- package/benchmark/src/benchmark/cli.clj +195 -0
- package/benchmark/src/benchmark/compare.clj +157 -0
- package/benchmark/src/benchmark/config.clj +316 -0
- package/benchmark/src/benchmark/measure.clj +187 -0
- package/benchmark/src/benchmark/store.clj +190 -0
- package/benchmark/test/benchmark/measure_test.clj +156 -0
- package/build.clj +30 -0
- package/config.edn +49 -0
- package/deps.edn +138 -0
- package/dev/sandbox.clj +82 -0
- package/dev/sandbox.cljs +127 -0
- package/dev/sandbox_benchmarks.clj +27 -0
- package/dev/sandbox_client.clj +87 -0
- package/dev/sandbox_transact_bench.clj +109 -0
- package/dev/user.clj +79 -0
- package/doc/README.md +96 -0
- package/doc/adl/README.md +6 -0
- package/doc/adl/adr-000-adr.org +28 -0
- package/doc/adl/adr-001-attribute-references.org +15 -0
- package/doc/adl/adr-002-build-tooling.org +54 -0
- package/doc/adl/adr-003-db-meta-data.md +52 -0
- package/doc/adl/adr-004-github-flow.md +40 -0
- package/doc/adl/adr-XYZ-template.md +30 -0
- package/doc/adl/index.org +3 -0
- package/doc/assets/datahike-logo.svg +3 -0
- package/doc/assets/datahiking-invoice.org +85 -0
- package/doc/assets/hhtree2.png +0 -0
- package/doc/assets/network_topology.svg +624 -0
- package/doc/assets/perf.png +0 -0
- package/doc/assets/schema_mindmap.mm +132 -0
- package/doc/assets/schema_mindmap.svg +970 -0
- package/doc/assets/temporal_index.mm +74 -0
- package/doc/backend-development.md +78 -0
- package/doc/bb-pod.md +89 -0
- package/doc/benchmarking.md +360 -0
- package/doc/bindings/edn-conversion.md +383 -0
- package/doc/cli.md +162 -0
- package/doc/cljdoc.edn +27 -0
- package/doc/cljs-support.md +133 -0
- package/doc/config.md +406 -0
- package/doc/contributing.md +114 -0
- package/doc/datalog-vs-sql.md +210 -0
- package/doc/datomic_differences.md +109 -0
- package/doc/development/pull-api-ns.md +186 -0
- package/doc/development/pull-frame-state-diagram.jpg +0 -0
- package/doc/distributed.md +566 -0
- package/doc/entity_spec.md +92 -0
- package/doc/gc.md +273 -0
- package/doc/java-api.md +808 -0
- package/doc/javascript-api.md +421 -0
- package/doc/libdatahike.md +86 -0
- package/doc/logging_and_error_handling.md +43 -0
- package/doc/norms.md +66 -0
- package/doc/schema-migration.md +85 -0
- package/doc/schema.md +287 -0
- package/doc/storage-backends.md +363 -0
- package/doc/store-id-refactoring.md +596 -0
- package/doc/time_variance.md +325 -0
- package/doc/unstructured.md +167 -0
- package/doc/versioning.md +261 -0
- package/examples/basic/README.md +19 -0
- package/examples/basic/deps.edn +6 -0
- package/examples/basic/docker-compose.yml +13 -0
- package/examples/basic/src/examples/core.clj +60 -0
- package/examples/basic/src/examples/schema.clj +155 -0
- package/examples/basic/src/examples/store.clj +60 -0
- package/examples/basic/src/examples/time_travel.clj +185 -0
- package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
- package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
- package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
- package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
- package/examples/java/README.md +162 -0
- package/examples/java/pom.xml +62 -0
- package/examples/java/src/main/java/examples/QuickStart.java +115 -0
- package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
- package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
- package/flake.lock +27 -0
- package/flake.nix +27 -0
- package/http-server/datahike/http/middleware.clj +75 -0
- package/http-server/datahike/http/server.clj +269 -0
- package/java/src/datahike/java/Database.java +274 -0
- package/java/src/datahike/java/Datahike.java +281 -0
- package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
- package/java/src/datahike/java/DatahikeTest.java +370 -0
- package/java/src/datahike/java/EDN.java +170 -0
- package/java/src/datahike/java/IEntity.java +11 -0
- package/java/src/datahike/java/Keywords.java +161 -0
- package/java/src/datahike/java/SchemaFlexibility.java +52 -0
- package/java/src/datahike/java/Util.java +219 -0
- package/karma.conf.js +19 -0
- package/libdatahike/compile-cpp +7 -0
- package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
- package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
- package/libdatahike/src/test_cpp.cpp +61 -0
- package/npm-package/PUBLISHING.md +140 -0
- package/npm-package/README.md +226 -0
- package/npm-package/package.template.json +34 -0
- package/npm-package/test-isomorphic.ts +281 -0
- package/npm-package/test.js +557 -0
- package/npm-package/typescript-test.ts +70 -0
- package/package.json +16 -0
- package/pydatahike/README.md +569 -0
- package/pydatahike/pyproject.toml +91 -0
- package/pydatahike/setup.py +42 -0
- package/pydatahike/src/datahike/__init__.py +134 -0
- package/pydatahike/src/datahike/_native.py +250 -0
- package/pydatahike/src/datahike/_version.py +2 -0
- package/pydatahike/src/datahike/database.py +722 -0
- package/pydatahike/src/datahike/edn.py +311 -0
- package/pydatahike/src/datahike/py.typed +0 -0
- package/pydatahike/tests/conftest.py +17 -0
- package/pydatahike/tests/test_basic.py +170 -0
- package/pydatahike/tests/test_database.py +51 -0
- package/pydatahike/tests/test_edn_conversion.py +299 -0
- package/pydatahike/tests/test_query.py +99 -0
- package/pydatahike/tests/test_schema.py +55 -0
- package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
- package/resources/example_server.edn +4 -0
- package/shadow-cljs.edn +56 -0
- package/src/data_readers.clj +7 -0
- package/src/datahike/api/impl.cljc +176 -0
- package/src/datahike/api/specification.cljc +633 -0
- package/src/datahike/api/types.cljc +261 -0
- package/src/datahike/api.cljc +41 -0
- package/src/datahike/array.cljc +99 -0
- package/src/datahike/cli.clj +166 -0
- package/src/datahike/cljs.cljs +6 -0
- package/src/datahike/codegen/cli.clj +406 -0
- package/src/datahike/codegen/clj_kondo.clj +291 -0
- package/src/datahike/codegen/java.clj +403 -0
- package/src/datahike/codegen/naming.cljc +33 -0
- package/src/datahike/codegen/native.clj +559 -0
- package/src/datahike/codegen/pod.clj +488 -0
- package/src/datahike/codegen/python.clj +838 -0
- package/src/datahike/codegen/report.clj +55 -0
- package/src/datahike/codegen/typescript.clj +262 -0
- package/src/datahike/codegen/validation.clj +145 -0
- package/src/datahike/config.cljc +294 -0
- package/src/datahike/connections.cljc +16 -0
- package/src/datahike/connector.cljc +265 -0
- package/src/datahike/constants.cljc +142 -0
- package/src/datahike/core.cljc +297 -0
- package/src/datahike/datom.cljc +459 -0
- package/src/datahike/db/interface.cljc +119 -0
- package/src/datahike/db/search.cljc +305 -0
- package/src/datahike/db/transaction.cljc +937 -0
- package/src/datahike/db/utils.cljc +338 -0
- package/src/datahike/db.cljc +956 -0
- package/src/datahike/experimental/unstructured.cljc +126 -0
- package/src/datahike/experimental/versioning.cljc +172 -0
- package/src/datahike/externs.js +31 -0
- package/src/datahike/gc.cljc +69 -0
- package/src/datahike/http/client.clj +188 -0
- package/src/datahike/http/writer.clj +79 -0
- package/src/datahike/impl/entity.cljc +218 -0
- package/src/datahike/index/interface.cljc +93 -0
- package/src/datahike/index/persistent_set.cljc +469 -0
- package/src/datahike/index/utils.cljc +44 -0
- package/src/datahike/index.cljc +32 -0
- package/src/datahike/js/api.cljs +172 -0
- package/src/datahike/js/api_macros.clj +22 -0
- package/src/datahike/js.cljs +163 -0
- package/src/datahike/json.cljc +209 -0
- package/src/datahike/lru.cljc +146 -0
- package/src/datahike/migrate.clj +39 -0
- package/src/datahike/norm/norm.clj +245 -0
- package/src/datahike/online_gc.cljc +252 -0
- package/src/datahike/pod.clj +155 -0
- package/src/datahike/pull_api.cljc +325 -0
- package/src/datahike/query.cljc +1945 -0
- package/src/datahike/query_stats.cljc +88 -0
- package/src/datahike/readers.cljc +62 -0
- package/src/datahike/remote.cljc +218 -0
- package/src/datahike/schema.cljc +228 -0
- package/src/datahike/schema_cache.cljc +42 -0
- package/src/datahike/spec.cljc +101 -0
- package/src/datahike/store.cljc +80 -0
- package/src/datahike/tools.cljc +308 -0
- package/src/datahike/transit.cljc +80 -0
- package/src/datahike/writer.cljc +239 -0
- package/src/datahike/writing.cljc +362 -0
- package/src/deps.cljs +1 -0
- package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
- package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
- package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
- package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
- package/test/datahike/integration_test/config_record_file_test.clj +14 -0
- package/test/datahike/integration_test/config_record_test.clj +14 -0
- package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
- package/test/datahike/integration_test/return_map_test.clj +62 -0
- package/test/datahike/integration_test.cljc +67 -0
- package/test/datahike/norm/norm_test.clj +124 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
- package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
- package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
- package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
- package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
- package/test/datahike/test/api_test.cljc +895 -0
- package/test/datahike/test/array_test.cljc +40 -0
- package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
- package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
- package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
- package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
- package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
- package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
- package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
- package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
- package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
- package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
- package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
- package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
- package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
- package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
- package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
- package/test/datahike/test/attribute_refs/utils.cljc +128 -0
- package/test/datahike/test/cache_test.cljc +38 -0
- package/test/datahike/test/components_test.cljc +92 -0
- package/test/datahike/test/config_test.cljc +158 -0
- package/test/datahike/test/core_test.cljc +105 -0
- package/test/datahike/test/datom_test.cljc +44 -0
- package/test/datahike/test/db_test.cljc +54 -0
- package/test/datahike/test/entity_spec_test.cljc +159 -0
- package/test/datahike/test/entity_test.cljc +103 -0
- package/test/datahike/test/explode_test.cljc +143 -0
- package/test/datahike/test/filter_test.cljc +75 -0
- package/test/datahike/test/gc_test.cljc +159 -0
- package/test/datahike/test/http/server_test.clj +192 -0
- package/test/datahike/test/http/writer_test.clj +86 -0
- package/test/datahike/test/ident_test.cljc +32 -0
- package/test/datahike/test/index_test.cljc +345 -0
- package/test/datahike/test/insert.cljc +125 -0
- package/test/datahike/test/java_bindings_test.clj +6 -0
- package/test/datahike/test/listen_test.cljc +41 -0
- package/test/datahike/test/lookup_refs_test.cljc +266 -0
- package/test/datahike/test/lru_test.cljc +27 -0
- package/test/datahike/test/migrate_test.clj +297 -0
- package/test/datahike/test/model/core.cljc +376 -0
- package/test/datahike/test/model/invariant.cljc +142 -0
- package/test/datahike/test/model/rng.cljc +82 -0
- package/test/datahike/test/model_test.clj +217 -0
- package/test/datahike/test/nodejs_test.cljs +262 -0
- package/test/datahike/test/online_gc_test.cljc +475 -0
- package/test/datahike/test/pod_test.clj +369 -0
- package/test/datahike/test/pull_api_test.cljc +474 -0
- package/test/datahike/test/purge_test.cljc +144 -0
- package/test/datahike/test/query_aggregates_test.cljc +101 -0
- package/test/datahike/test/query_find_specs_test.cljc +52 -0
- package/test/datahike/test/query_fns_test.cljc +523 -0
- package/test/datahike/test/query_interop_test.cljc +47 -0
- package/test/datahike/test/query_not_test.cljc +189 -0
- package/test/datahike/test/query_or_test.cljc +158 -0
- package/test/datahike/test/query_pull_test.cljc +147 -0
- package/test/datahike/test/query_rules_test.cljc +248 -0
- package/test/datahike/test/query_stats_test.cljc +218 -0
- package/test/datahike/test/query_test.cljc +984 -0
- package/test/datahike/test/schema_test.cljc +424 -0
- package/test/datahike/test/specification_test.cljc +30 -0
- package/test/datahike/test/store_test.cljc +78 -0
- package/test/datahike/test/stress_test.cljc +57 -0
- package/test/datahike/test/time_variance_test.cljc +518 -0
- package/test/datahike/test/tools_test.clj +134 -0
- package/test/datahike/test/transact_test.cljc +518 -0
- package/test/datahike/test/tuples_test.cljc +564 -0
- package/test/datahike/test/unstructured_test.cljc +291 -0
- package/test/datahike/test/upsert_impl_test.cljc +205 -0
- package/test/datahike/test/upsert_test.cljc +363 -0
- package/test/datahike/test/utils.cljc +110 -0
- package/test/datahike/test/validation_test.cljc +48 -0
- package/test/datahike/test/versioning_test.cljc +56 -0
- package/test/datahike/test.cljc +66 -0
- 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
|
+
}
|