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,161 @@
|
|
|
1
|
+
package datahike.java;
|
|
2
|
+
|
|
3
|
+
import clojure.lang.Keyword;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Pre-defined Datahike keyword constants.
|
|
7
|
+
*
|
|
8
|
+
* <p>Use these constants for common Datahike schema and transaction attributes
|
|
9
|
+
* to avoid typos and get IDE autocompletion.</p>
|
|
10
|
+
*
|
|
11
|
+
* <p>Example:</p>
|
|
12
|
+
* <pre>{@code
|
|
13
|
+
* import static datahike.java.Keywords.*;
|
|
14
|
+
* import static datahike.java.EDN.*;
|
|
15
|
+
*
|
|
16
|
+
* Map<String, Object> schema = Map.of(
|
|
17
|
+
* DB_IDENT, keyword("person", "name"),
|
|
18
|
+
* DB_VALUE_TYPE, STRING,
|
|
19
|
+
* DB_CARDINALITY, ONE,
|
|
20
|
+
* DB_DOC, "Person's full name"
|
|
21
|
+
* );
|
|
22
|
+
* }</pre>
|
|
23
|
+
*/
|
|
24
|
+
public class Keywords {
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Forbids instance creation.
|
|
28
|
+
*/
|
|
29
|
+
private Keywords() {}
|
|
30
|
+
|
|
31
|
+
// =========================================================================
|
|
32
|
+
// Entity Attributes
|
|
33
|
+
// =========================================================================
|
|
34
|
+
|
|
35
|
+
/** Entity ID: :db/id */
|
|
36
|
+
public static final Keyword DB_ID = Keyword.intern("db", "id");
|
|
37
|
+
|
|
38
|
+
/** Entity identifier: :db/ident */
|
|
39
|
+
public static final Keyword DB_IDENT = Keyword.intern("db", "ident");
|
|
40
|
+
|
|
41
|
+
// =========================================================================
|
|
42
|
+
// Schema Attributes
|
|
43
|
+
// =========================================================================
|
|
44
|
+
|
|
45
|
+
/** Value type: :db/valueType */
|
|
46
|
+
public static final Keyword DB_VALUE_TYPE = Keyword.intern("db", "valueType");
|
|
47
|
+
|
|
48
|
+
/** Cardinality: :db/cardinality */
|
|
49
|
+
public static final Keyword DB_CARDINALITY = Keyword.intern("db", "cardinality");
|
|
50
|
+
|
|
51
|
+
/** Documentation: :db/doc */
|
|
52
|
+
public static final Keyword DB_DOC = Keyword.intern("db", "doc");
|
|
53
|
+
|
|
54
|
+
/** Uniqueness constraint: :db/unique */
|
|
55
|
+
public static final Keyword DB_UNIQUE = Keyword.intern("db", "unique");
|
|
56
|
+
|
|
57
|
+
/** Component attribute: :db/isComponent */
|
|
58
|
+
public static final Keyword DB_IS_COMPONENT = Keyword.intern("db", "isComponent");
|
|
59
|
+
|
|
60
|
+
/** Disable history: :db/noHistory */
|
|
61
|
+
public static final Keyword DB_NO_HISTORY = Keyword.intern("db", "noHistory");
|
|
62
|
+
|
|
63
|
+
/** Index attribute: :db/index */
|
|
64
|
+
public static final Keyword DB_INDEX = Keyword.intern("db", "index");
|
|
65
|
+
|
|
66
|
+
/** Fulltext index: :db/fulltext */
|
|
67
|
+
public static final Keyword DB_FULLTEXT = Keyword.intern("db", "fulltext");
|
|
68
|
+
|
|
69
|
+
// =========================================================================
|
|
70
|
+
// Value Types
|
|
71
|
+
// =========================================================================
|
|
72
|
+
|
|
73
|
+
/** String type: :db.type/string */
|
|
74
|
+
public static final Keyword STRING = Keyword.intern("db.type", "string");
|
|
75
|
+
|
|
76
|
+
/** Boolean type: :db.type/boolean */
|
|
77
|
+
public static final Keyword BOOLEAN = Keyword.intern("db.type", "boolean");
|
|
78
|
+
|
|
79
|
+
/** Long type: :db.type/long */
|
|
80
|
+
public static final Keyword LONG = Keyword.intern("db.type", "long");
|
|
81
|
+
|
|
82
|
+
/** Big integer type: :db.type/bigint */
|
|
83
|
+
public static final Keyword BIGINT = Keyword.intern("db.type", "bigint");
|
|
84
|
+
|
|
85
|
+
/** Float type: :db.type/float */
|
|
86
|
+
public static final Keyword FLOAT = Keyword.intern("db.type", "float");
|
|
87
|
+
|
|
88
|
+
/** Double type: :db.type/double */
|
|
89
|
+
public static final Keyword DOUBLE = Keyword.intern("db.type", "double");
|
|
90
|
+
|
|
91
|
+
/** Big decimal type: :db.type/bigdec */
|
|
92
|
+
public static final Keyword BIGDEC = Keyword.intern("db.type", "bigdec");
|
|
93
|
+
|
|
94
|
+
/** Instant type: :db.type/instant */
|
|
95
|
+
public static final Keyword INSTANT = Keyword.intern("db.type", "instant");
|
|
96
|
+
|
|
97
|
+
/** UUID type: :db.type/uuid */
|
|
98
|
+
public static final Keyword UUID_TYPE = Keyword.intern("db.type", "uuid");
|
|
99
|
+
|
|
100
|
+
/** Keyword type: :db.type/keyword */
|
|
101
|
+
public static final Keyword KEYWORD_TYPE = Keyword.intern("db.type", "keyword");
|
|
102
|
+
|
|
103
|
+
/** Symbol type: :db.type/symbol */
|
|
104
|
+
public static final Keyword SYMBOL_TYPE = Keyword.intern("db.type", "symbol");
|
|
105
|
+
|
|
106
|
+
/** Reference type: :db.type/ref */
|
|
107
|
+
public static final Keyword REF = Keyword.intern("db.type", "ref");
|
|
108
|
+
|
|
109
|
+
/** Bytes type: :db.type/bytes */
|
|
110
|
+
public static final Keyword BYTES = Keyword.intern("db.type", "bytes");
|
|
111
|
+
|
|
112
|
+
// =========================================================================
|
|
113
|
+
// Cardinality Values
|
|
114
|
+
// =========================================================================
|
|
115
|
+
|
|
116
|
+
/** Cardinality one: :db.cardinality/one */
|
|
117
|
+
public static final Keyword ONE = Keyword.intern("db.cardinality", "one");
|
|
118
|
+
|
|
119
|
+
/** Cardinality many: :db.cardinality/many */
|
|
120
|
+
public static final Keyword MANY = Keyword.intern("db.cardinality", "many");
|
|
121
|
+
|
|
122
|
+
// =========================================================================
|
|
123
|
+
// Uniqueness Values
|
|
124
|
+
// =========================================================================
|
|
125
|
+
|
|
126
|
+
/** Unique value constraint: :db.unique/value */
|
|
127
|
+
public static final Keyword UNIQUE_VALUE = Keyword.intern("db.unique", "value");
|
|
128
|
+
|
|
129
|
+
/** Unique identity constraint: :db.unique/identity */
|
|
130
|
+
public static final Keyword UNIQUE_IDENTITY = Keyword.intern("db.unique", "identity");
|
|
131
|
+
|
|
132
|
+
// =========================================================================
|
|
133
|
+
// Transaction Metadata
|
|
134
|
+
// =========================================================================
|
|
135
|
+
|
|
136
|
+
/** Transaction entity: :db/tx */
|
|
137
|
+
public static final Keyword TX = Keyword.intern("db", "tx");
|
|
138
|
+
|
|
139
|
+
/** Transaction timestamp: :db/txInstant */
|
|
140
|
+
public static final Keyword TX_INSTANT = Keyword.intern("db", "txInstant");
|
|
141
|
+
|
|
142
|
+
// =========================================================================
|
|
143
|
+
// Schema Flexibility Values
|
|
144
|
+
// =========================================================================
|
|
145
|
+
|
|
146
|
+
/** Schema flexibility read mode: :read */
|
|
147
|
+
public static final Keyword SCHEMA_READ = Keyword.intern("read");
|
|
148
|
+
|
|
149
|
+
/** Schema flexibility write mode: :write */
|
|
150
|
+
public static final Keyword SCHEMA_WRITE = Keyword.intern("write");
|
|
151
|
+
|
|
152
|
+
// =========================================================================
|
|
153
|
+
// Storage Backends
|
|
154
|
+
// =========================================================================
|
|
155
|
+
|
|
156
|
+
/** Memory backend: :memory */
|
|
157
|
+
public static final Keyword BACKEND_MEMORY = Keyword.intern("memory");
|
|
158
|
+
|
|
159
|
+
/** File backend: :file */
|
|
160
|
+
public static final Keyword BACKEND_FILE = Keyword.intern("file");
|
|
161
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
package datahike.java;
|
|
2
|
+
|
|
3
|
+
import clojure.lang.Keyword;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Schema flexibility modes for Datahike databases.
|
|
7
|
+
*
|
|
8
|
+
* <p>Controls how the database handles attributes not defined in the schema:</p>
|
|
9
|
+
* <ul>
|
|
10
|
+
* <li>{@link #READ} - Strict mode: Only allow reads of undefined attributes, reject writes</li>
|
|
11
|
+
* <li>{@link #WRITE} - Flexible mode: Allow both reads and writes of undefined attributes</li>
|
|
12
|
+
* </ul>
|
|
13
|
+
*
|
|
14
|
+
* @see <a href="https://github.com/replikativ/datahike/blob/main/doc/schema.md">Schema Documentation</a>
|
|
15
|
+
*/
|
|
16
|
+
public enum SchemaFlexibility {
|
|
17
|
+
/**
|
|
18
|
+
* Read-only flexibility: Allow reading undefined attributes but reject writes.
|
|
19
|
+
* This is the recommended mode for production use with schemaless data.
|
|
20
|
+
*/
|
|
21
|
+
READ(Keywords.SCHEMA_READ),
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Write flexibility: Allow both reading and writing undefined attributes.
|
|
25
|
+
* Use this for fully schemaless databases or during prototyping.
|
|
26
|
+
*/
|
|
27
|
+
WRITE(Keywords.SCHEMA_WRITE);
|
|
28
|
+
|
|
29
|
+
private final Keyword keyword;
|
|
30
|
+
|
|
31
|
+
SchemaFlexibility(Keyword keyword) {
|
|
32
|
+
this.keyword = keyword;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Returns the Clojure keyword representation.
|
|
37
|
+
*
|
|
38
|
+
* @return the keyword for this schema flexibility mode
|
|
39
|
+
*/
|
|
40
|
+
public Keyword toKeyword() {
|
|
41
|
+
return keyword;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns the string representation suitable for EDN/config maps.
|
|
46
|
+
*
|
|
47
|
+
* @return the string representation (e.g., ":read", ":write")
|
|
48
|
+
*/
|
|
49
|
+
public String toEDNString() {
|
|
50
|
+
return keyword.toString();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
package datahike.java;
|
|
2
|
+
|
|
3
|
+
import clojure.java.api.Clojure;
|
|
4
|
+
import clojure.lang.IFn;
|
|
5
|
+
import clojure.lang.APersistentMap;
|
|
6
|
+
import clojure.lang.APersistentVector;
|
|
7
|
+
import clojure.lang.Keyword;
|
|
8
|
+
import clojure.lang.RT;
|
|
9
|
+
|
|
10
|
+
public class Util {
|
|
11
|
+
public static final IFn derefFn = Clojure.var("clojure.core", "deref");
|
|
12
|
+
private static final IFn hashMapFn = Clojure.var("clojure.core", "hash-map");
|
|
13
|
+
private static final IFn vectorFn = Clojure.var("clojure.core", "vec");
|
|
14
|
+
private static final IFn readStringFn = Clojure.var("clojure.edn", "read-string");
|
|
15
|
+
|
|
16
|
+
/** Converts a keyword given as a string into a clojure keyword */
|
|
17
|
+
public static Keyword kwd(String str) {
|
|
18
|
+
return (Keyword)Clojure.read(str);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Creates a new clojure HashMap from the arguments of the form: key1, val1, key2, val2, ... */
|
|
22
|
+
public static APersistentMap map(Object... keyVals) {
|
|
23
|
+
Object[] converted = new Object[keyVals.length];
|
|
24
|
+
for (int i = 0; i < keyVals.length; i += 2) {
|
|
25
|
+
// Convert keys (always keywordize)
|
|
26
|
+
Object key = keyVals[i];
|
|
27
|
+
if (key instanceof String) {
|
|
28
|
+
String strKey = (String) key;
|
|
29
|
+
converted[i] = strKey.startsWith(":") ? kwd(strKey) : Keyword.intern(strKey);
|
|
30
|
+
} else {
|
|
31
|
+
converted[i] = key;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Convert values (apply EDN rules)
|
|
35
|
+
if (i + 1 < keyVals.length) {
|
|
36
|
+
converted[i + 1] = convertValue(keyVals[i + 1]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return (APersistentMap) hashMapFn.applyTo(RT.seq(converted));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Creates a new clojure vector with EDN conversion applied to items */
|
|
43
|
+
public static APersistentVector vec(Object... items) {
|
|
44
|
+
// Convert each item using EDN rules
|
|
45
|
+
Object[] converted = new Object[items.length];
|
|
46
|
+
for (int i = 0; i < items.length; i++) {
|
|
47
|
+
converted[i] = convertValue(items[i]);
|
|
48
|
+
}
|
|
49
|
+
return vecRaw(converted);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Creates a new clojure vector without conversion (internal use) */
|
|
53
|
+
private static APersistentVector vecRaw(Object... items) {
|
|
54
|
+
// No need to use 'applyTo here, as 'vectorFn taking a collection as an argument will produce a clj vector
|
|
55
|
+
// containing *each* of the collection elements.
|
|
56
|
+
return (APersistentVector) vectorFn.invoke(items);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Converts a value following universal EDN conversion rules:
|
|
61
|
+
* - String starting with ":" → keyword
|
|
62
|
+
* - String starting with "\\:" → literal string with ":" (escaped)
|
|
63
|
+
* - String without ":" → string
|
|
64
|
+
* - Numbers, booleans, null → as-is
|
|
65
|
+
* - Maps → recursively convert
|
|
66
|
+
* - Lists/Arrays → recursively convert
|
|
67
|
+
*
|
|
68
|
+
* This is public to allow reuse from Clojure interop layer.
|
|
69
|
+
*/
|
|
70
|
+
public static Object convertValue(Object value) {
|
|
71
|
+
if (value == null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Handle strings with EDN conversion rules
|
|
76
|
+
if (value instanceof String) {
|
|
77
|
+
String str = (String) value;
|
|
78
|
+
|
|
79
|
+
// Escaped colon - strip backslash and return as string
|
|
80
|
+
if (str.startsWith("\\:")) {
|
|
81
|
+
return str.substring(1); // Return ":literal" from "\\:literal"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Colon prefix - convert to keyword
|
|
85
|
+
if (str.startsWith(":")) {
|
|
86
|
+
return kwd(str);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Regular string - return as-is
|
|
90
|
+
return str;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Recursively convert nested maps
|
|
94
|
+
if (value instanceof java.util.Map && !(value instanceof APersistentMap)) {
|
|
95
|
+
return mapToPersistentMap((java.util.Map<String, Object>) value);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Recursively convert lists/arrays
|
|
99
|
+
if (value instanceof java.util.List) {
|
|
100
|
+
java.util.List<?> list = (java.util.List<?>) value;
|
|
101
|
+
Object[] converted = new Object[list.size()];
|
|
102
|
+
for (int i = 0; i < list.size(); i++) {
|
|
103
|
+
converted[i] = convertValue(list.get(i));
|
|
104
|
+
}
|
|
105
|
+
return vecRaw(converted);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (value instanceof Object[]) {
|
|
109
|
+
Object[] arr = (Object[]) value;
|
|
110
|
+
Object[] converted = new Object[arr.length];
|
|
111
|
+
for (int i = 0; i < arr.length; i++) {
|
|
112
|
+
converted[i] = convertValue(arr[i]);
|
|
113
|
+
}
|
|
114
|
+
return vecRaw(converted);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Numbers, booleans, and other types - return as-is
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Converts a Java Map to a Clojure persistent map */
|
|
122
|
+
public static APersistentMap mapToPersistentMap(java.util.Map<String, Object> javaMap) {
|
|
123
|
+
if (javaMap == null) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
Object[] keyVals = new Object[javaMap.size() * 2];
|
|
127
|
+
int i = 0;
|
|
128
|
+
for (java.util.Map.Entry<String, Object> entry : javaMap.entrySet()) {
|
|
129
|
+
Object key = entry.getKey();
|
|
130
|
+
// If key is already a Keyword, use it as-is
|
|
131
|
+
if (key instanceof Keyword) {
|
|
132
|
+
keyVals[i++] = key;
|
|
133
|
+
} else if (key instanceof String) {
|
|
134
|
+
String strKey = (String) key;
|
|
135
|
+
// Convert string keys to keywords (auto-prefix with : if not present)
|
|
136
|
+
keyVals[i++] = strKey.startsWith(":") ? kwd(strKey) : Keyword.intern(strKey);
|
|
137
|
+
} else {
|
|
138
|
+
// Use key as-is for other types
|
|
139
|
+
keyVals[i++] = key;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Convert values using universal EDN rules
|
|
143
|
+
keyVals[i++] = convertValue(entry.getValue());
|
|
144
|
+
}
|
|
145
|
+
return (APersistentMap) hashMapFn.applyTo(RT.seq(keyVals));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Convert Clojure persistent map to Java HashMap.
|
|
150
|
+
* Used for return values that need to be Java-friendly.
|
|
151
|
+
*
|
|
152
|
+
* @param clojureMap Clojure persistent map
|
|
153
|
+
* @return Java HashMap with string keys
|
|
154
|
+
*/
|
|
155
|
+
public static java.util.Map<String, Object> clojureMapToJavaMap(APersistentMap clojureMap) {
|
|
156
|
+
if (clojureMap == null) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
java.util.Map<String, Object> javaMap = new java.util.HashMap<>();
|
|
160
|
+
for (Object entry : clojureMap) {
|
|
161
|
+
java.util.Map.Entry<?, ?> e = (java.util.Map.Entry<?, ?>) entry;
|
|
162
|
+
String key = e.getKey().toString();
|
|
163
|
+
javaMap.put(key, e.getValue());
|
|
164
|
+
}
|
|
165
|
+
return javaMap;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Normalize Java collections to Clojure collections for API processing.
|
|
170
|
+
*
|
|
171
|
+
* <p><b>Escape hatch (automatic):</b> If data is already a Clojure persistent
|
|
172
|
+
* collection, returns immediately with O(1) instanceof check. Advanced users
|
|
173
|
+
* can use {@link #vec} and {@link #map} for zero-overhead calls.</p>
|
|
174
|
+
*
|
|
175
|
+
* <p><b>Conversion rules (applied recursively):</b></p>
|
|
176
|
+
* <ul>
|
|
177
|
+
* <li>java.util.List → clojure.lang.PersistentVector</li>
|
|
178
|
+
* <li>java.util.Map → clojure.lang.PersistentHashMap</li>
|
|
179
|
+
* <li>Map keys (String) → keywords ("name" → :name, ":name" → :name)</li>
|
|
180
|
+
* <li>Values (String) → keywords only if prefixed with ":"</li>
|
|
181
|
+
* <li>Primitives, Clojure types → unchanged</li>
|
|
182
|
+
* </ul>
|
|
183
|
+
*
|
|
184
|
+
* <p>This function is general and consistent - applied uniformly to all
|
|
185
|
+
* Java API method parameters that accept collections.</p>
|
|
186
|
+
*
|
|
187
|
+
* @param data The data to normalize (List, Map, or other types)
|
|
188
|
+
* @return Clojure-compatible data structure
|
|
189
|
+
*/
|
|
190
|
+
public static Object normalizeCollections(Object data) {
|
|
191
|
+
// Escape hatch: already Clojure persistent collection - O(1) check
|
|
192
|
+
if (data instanceof clojure.lang.IPersistentCollection) {
|
|
193
|
+
return data;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Java List → Clojure vector with recursive conversion
|
|
197
|
+
if (data instanceof java.util.List) {
|
|
198
|
+
java.util.List<?> list = (java.util.List<?>) data;
|
|
199
|
+
Object[] converted = new Object[list.size()];
|
|
200
|
+
for (int i = 0; i < list.size(); i++) {
|
|
201
|
+
converted[i] = convertValue(list.get(i));
|
|
202
|
+
}
|
|
203
|
+
return vecRaw(converted);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Java Map → Clojure map with recursive conversion
|
|
207
|
+
if (data instanceof java.util.Map && !(data instanceof APersistentMap)) {
|
|
208
|
+
return mapToPersistentMap((java.util.Map<String, Object>) data);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Other types → apply EDN value conversion rules
|
|
212
|
+
return convertValue(data);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Read string into edn data structure. */
|
|
216
|
+
public static Object ednFromString(String str) {
|
|
217
|
+
return readStringFn.invoke(str);
|
|
218
|
+
}
|
|
219
|
+
}
|
package/karma.conf.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module.exports = function (config) {
|
|
2
|
+
config.set({
|
|
3
|
+
browsers: ['ChromeHeadless'],
|
|
4
|
+
basePath: 'target',
|
|
5
|
+
files: ['browser-ci.js'],
|
|
6
|
+
frameworks: ['cljs-test'],
|
|
7
|
+
plugins: ['karma-cljs-test', 'karma-chrome-launcher'],
|
|
8
|
+
colors: true,
|
|
9
|
+
logLevel: config.LOG_INFO,
|
|
10
|
+
client: {
|
|
11
|
+
args: ["shadow.test.karma.init"]
|
|
12
|
+
},
|
|
13
|
+
singleRun: true,
|
|
14
|
+
// Integration tests need longer timeouts due to database ops and network calls
|
|
15
|
+
browserDisconnectTimeout: 180000, // 3 minutes
|
|
16
|
+
browserNoActivityTimeout: 180000, // 3 minutes
|
|
17
|
+
captureTimeout: 300000 // 5 minutes
|
|
18
|
+
})
|
|
19
|
+
};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
package datahike.impl;
|
|
2
|
+
|
|
3
|
+
import org.graalvm.nativeimage.c.function.CFunctionPointer;
|
|
4
|
+
import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer;
|
|
5
|
+
import org.graalvm.nativeimage.c.type.CCharPointer;
|
|
6
|
+
import org.graalvm.nativeimage.c.type.CCharPointerPointer;
|
|
7
|
+
import org.graalvm.nativeimage.c.type.CConst;
|
|
8
|
+
import org.graalvm.nativeimage.c.type.CTypeConversion;
|
|
9
|
+
import datahike.java.Datahike;
|
|
10
|
+
import datahike.java.Util;
|
|
11
|
+
import datahike.impl.libdatahike;
|
|
12
|
+
import clojure.lang.APersistentMap;
|
|
13
|
+
import clojure.lang.Keyword;
|
|
14
|
+
import java.io.StringWriter;
|
|
15
|
+
import java.io.PrintWriter;
|
|
16
|
+
import java.util.Date;
|
|
17
|
+
import java.util.Base64;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Base infrastructure for native C bindings.
|
|
21
|
+
*
|
|
22
|
+
* This class provides the core utilities for:
|
|
23
|
+
* - Exception handling and formatting
|
|
24
|
+
* - Input format parsing (db, history, since, asof, json, edn, cbor)
|
|
25
|
+
* - Output format serialization (json, edn, cbor)
|
|
26
|
+
* - C type conversions
|
|
27
|
+
*
|
|
28
|
+
* The actual C entry points are generated in LibDatahike.java.
|
|
29
|
+
*/
|
|
30
|
+
public class LibDatahikeBase {
|
|
31
|
+
|
|
32
|
+
// =========================================================================
|
|
33
|
+
// Callback Interface
|
|
34
|
+
// =========================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* C function pointer interface for reading return values.
|
|
38
|
+
* All native entry points use this callback pattern to return results.
|
|
39
|
+
*/
|
|
40
|
+
public interface OutputReader extends CFunctionPointer {
|
|
41
|
+
@InvokeCFunctionPointer
|
|
42
|
+
void call(@CConst CCharPointer output);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// =========================================================================
|
|
46
|
+
// Exception Handling
|
|
47
|
+
// =========================================================================
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Format an exception as a C string for callback.
|
|
51
|
+
* Format: "exception:{message}\nStacktrace:\n{stacktrace}"
|
|
52
|
+
*/
|
|
53
|
+
protected static @CConst CCharPointer toException(Exception e) {
|
|
54
|
+
StringWriter sw = new StringWriter();
|
|
55
|
+
e.printStackTrace(new PrintWriter(sw));
|
|
56
|
+
String st = sw.toString();
|
|
57
|
+
return toCCharPointer("exception:".concat(e.toString()).concat("\nStacktrace:\n").concat(st));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// =========================================================================
|
|
61
|
+
// C Type Conversions
|
|
62
|
+
// =========================================================================
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Parse EDN configuration string to Clojure map.
|
|
66
|
+
*/
|
|
67
|
+
public static APersistentMap readConfig(CCharPointer db_config) {
|
|
68
|
+
return (APersistentMap) Util.ednFromString(CTypeConversion.toJavaString(db_config));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Convert Java String to C char pointer.
|
|
73
|
+
*/
|
|
74
|
+
public static @CConst CCharPointer toCCharPointer(String result) {
|
|
75
|
+
CTypeConversion.CCharPointerHolder holder = CTypeConversion.toCString(result);
|
|
76
|
+
CCharPointer value = holder.get();
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Convert byte array to Base64-encoded C char pointer.
|
|
82
|
+
* Used for CBOR output format.
|
|
83
|
+
*/
|
|
84
|
+
public static @CConst CCharPointer toCCharPointer(byte[] result) {
|
|
85
|
+
CTypeConversion.CCharPointerHolder holder = CTypeConversion.toCBytes(Base64.getEncoder().encode(result));
|
|
86
|
+
CCharPointer value = holder.get();
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// =========================================================================
|
|
91
|
+
// Input Format Handling
|
|
92
|
+
// =========================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Load input based on format specification.
|
|
96
|
+
*
|
|
97
|
+
* Supported formats:
|
|
98
|
+
* - "db" : Connect and deref to get current database
|
|
99
|
+
* - "history" : Get full history database
|
|
100
|
+
* - "since:{timestamp_ms}" : Get database since timestamp
|
|
101
|
+
* - "asof:{timestamp_ms}" : Get database as-of timestamp
|
|
102
|
+
* - "json" : Parse as JSON
|
|
103
|
+
* - "edn" : Parse as EDN
|
|
104
|
+
* - "cbor" : Parse as CBOR (base64 encoded)
|
|
105
|
+
*/
|
|
106
|
+
protected static Object loadInput(@CConst CCharPointer input_format,
|
|
107
|
+
@CConst CCharPointer raw_input) {
|
|
108
|
+
String format = CTypeConversion.toJavaString(input_format);
|
|
109
|
+
String formats[] = format.split(":");
|
|
110
|
+
switch (formats[0]) {
|
|
111
|
+
case "db":
|
|
112
|
+
return Datahike.deref(Datahike.connect(readConfig(raw_input)));
|
|
113
|
+
case "history":
|
|
114
|
+
return Datahike.history(Datahike.deref(Datahike.connect(readConfig(raw_input))));
|
|
115
|
+
case "since":
|
|
116
|
+
return Datahike.since(Datahike.deref(Datahike.connect(readConfig(raw_input))),
|
|
117
|
+
new Date(Long.parseLong(formats[1])));
|
|
118
|
+
case "asof":
|
|
119
|
+
return Datahike.asOf(Datahike.deref(Datahike.connect(readConfig(raw_input))),
|
|
120
|
+
new Date(Long.parseLong(formats[1])));
|
|
121
|
+
case "json":
|
|
122
|
+
return libdatahike.parseJSON(CTypeConversion.toJavaString(raw_input));
|
|
123
|
+
case "edn":
|
|
124
|
+
return libdatahike.parseEdn(CTypeConversion.toJavaString(raw_input));
|
|
125
|
+
case "cbor":
|
|
126
|
+
return libdatahike.parseCBOR(CTypeConversion.toJavaString(raw_input).getBytes());
|
|
127
|
+
default:
|
|
128
|
+
throw new IllegalArgumentException("Input format not supported: " + format);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Load multiple inputs for query operations.
|
|
134
|
+
*/
|
|
135
|
+
protected static Object[] loadInputs(@CConst long num_inputs,
|
|
136
|
+
@CConst CCharPointerPointer input_formats,
|
|
137
|
+
@CConst CCharPointerPointer raw_inputs) {
|
|
138
|
+
Object[] inputs = new Object[(int) num_inputs];
|
|
139
|
+
for (int i = 0; i < num_inputs; i++) {
|
|
140
|
+
inputs[i] = loadInput(input_formats.read(i), raw_inputs.read(i));
|
|
141
|
+
}
|
|
142
|
+
return inputs;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// =========================================================================
|
|
146
|
+
// Output Format Handling
|
|
147
|
+
// =========================================================================
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Serialize output based on format specification.
|
|
151
|
+
*
|
|
152
|
+
* Supported formats:
|
|
153
|
+
* - "json" : Serialize as JSON string
|
|
154
|
+
* - "edn" : Serialize as EDN string
|
|
155
|
+
* - "cbor" : Serialize as CBOR (base64 encoded)
|
|
156
|
+
*/
|
|
157
|
+
protected static @CConst CCharPointer toOutput(@CConst CCharPointer output_format,
|
|
158
|
+
Object output) {
|
|
159
|
+
String format = CTypeConversion.toJavaString(output_format);
|
|
160
|
+
switch (format) {
|
|
161
|
+
case "json":
|
|
162
|
+
return toCCharPointer(libdatahike.toJSONString(output));
|
|
163
|
+
case "edn":
|
|
164
|
+
return toCCharPointer(libdatahike.toEdnString(output));
|
|
165
|
+
case "cbor":
|
|
166
|
+
return toCCharPointer(libdatahike.toCBOR(output));
|
|
167
|
+
default:
|
|
168
|
+
throw new IllegalArgumentException("Output format not supported: " + format);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// =========================================================================
|
|
173
|
+
// Helper Methods for Generated Code
|
|
174
|
+
// =========================================================================
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Parse keyword from EDN string (e.g., ":eavt" -> Keyword).
|
|
178
|
+
*/
|
|
179
|
+
protected static Keyword parseKeyword(CCharPointer kwd_edn) {
|
|
180
|
+
return Util.kwd(CTypeConversion.toJavaString(kwd_edn));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Parse EDN to Iterable (for eids, etc).
|
|
185
|
+
*/
|
|
186
|
+
protected static Iterable<?> parseIterable(CCharPointer edn) {
|
|
187
|
+
return (Iterable<?>) libdatahike.parseEdn(CTypeConversion.toJavaString(edn));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Convert datoms to vectors for serialization.
|
|
192
|
+
*/
|
|
193
|
+
protected static Iterable<?> datomsToVecs(Iterable<?> datoms) {
|
|
194
|
+
return libdatahike.datomsToVecs(datoms);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Convert entity to map for serialization.
|
|
199
|
+
*/
|
|
200
|
+
protected static Object entityToMap(Object entity) {
|
|
201
|
+
return libdatahike.intoMap(entity);
|
|
202
|
+
}
|
|
203
|
+
}
|