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,85 @@
|
|
|
1
|
+
# Schema Migration
|
|
2
|
+
|
|
3
|
+
Schema migration with Datahike is the evolution of your current schema into a future schema.
|
|
4
|
+
|
|
5
|
+
## Why using the schema migration tool?
|
|
6
|
+
You could use the `transact`-fn of the api-ns to apply your schema, but with our
|
|
7
|
+
`norm`-ns you can define your migrations centrally and they will be applied once and only
|
|
8
|
+
once to your database.
|
|
9
|
+
|
|
10
|
+
This helps when your production database has limited accessibility from your developer
|
|
11
|
+
machines and you want to apply the migrations from a server next to your production code.
|
|
12
|
+
In case you are setting up your database from scratch for e.g. development purpose you can
|
|
13
|
+
rely on your schema to be up-to-date with your production environment because you are
|
|
14
|
+
keeping your original schema along with your migrations in a central repository.
|
|
15
|
+
|
|
16
|
+
## How to migrate a database schema
|
|
17
|
+
When we are speaking of changes to your schema, these should always add new definitions and
|
|
18
|
+
never change existing definitions. In case you want to change existing data to a new format
|
|
19
|
+
you will have to create a new schema and transact your existing data transformed again. A
|
|
20
|
+
good intro to this topic [can be found here](https://docs.datomic.com/cloud/schema/schema-change.html).
|
|
21
|
+
|
|
22
|
+
## Transaction-functions
|
|
23
|
+
Your transaction functions need to be on your classpath to be called and they need to take
|
|
24
|
+
one argument, the connection to your database. Each function needs to return a vector of
|
|
25
|
+
transactions so that they can be applied during migration.
|
|
26
|
+
|
|
27
|
+
Please be aware that with transaction-functions you will create transactions that need to be
|
|
28
|
+
held in memory. Very large migrations might exceed your memory.
|
|
29
|
+
|
|
30
|
+
## Norms?
|
|
31
|
+
Like [conformity for Datomic](https://github.com/avescodes/conformity) we are using the term
|
|
32
|
+
norm for our tool. You can use it to declare expectations about the state of your database
|
|
33
|
+
and enforce those idempotently without repeatedly transacting schema. These expectations
|
|
34
|
+
can be the form of your schema, data in a certain format or pre-transacted data for e.g.
|
|
35
|
+
a development database.
|
|
36
|
+
|
|
37
|
+
## Migration folder
|
|
38
|
+
Preferably create a folder in your project resources called `migrations`. You can however
|
|
39
|
+
use any folder you like even outside your resources. If you don't want to package the
|
|
40
|
+
migrations into a jar you can just run the migration-functions with a path as string passed.
|
|
41
|
+
In your migration-folder you store your migration-files. Be aware that your chosen
|
|
42
|
+
migration-folder will include all subfolders for reading the migrations. Don't store
|
|
43
|
+
other files in your migration-folder besides your migrations!
|
|
44
|
+
|
|
45
|
+
## How to migrate
|
|
46
|
+
|
|
47
|
+
1. Create a folder of your choice, for now let's call it `migrations`. In this folder you
|
|
48
|
+
create a new file with an edn-extension like `001-my-first-norm.edn`. Preferably you name the
|
|
49
|
+
file beginning with a number. Please be aware that the name of your file will be the id of
|
|
50
|
+
your migration. Taking into account that you might create some more migrations in the future
|
|
51
|
+
you should left-pad the names with zeros to keep a proper sorting. Keep in mind that your
|
|
52
|
+
migrations are transacted sorted after your chosen ids one after another. Spaces will be
|
|
53
|
+
replaced with dashes to compose the id.
|
|
54
|
+
|
|
55
|
+
2. Write the transactions itself into your newly created file. The content of the file needs
|
|
56
|
+
to be an edn-map with one or both of the keys `:tx-data` and `tx-fn`. `:tx-data` is just
|
|
57
|
+
transaction data in the form of a vector, `:tx-fn` is a function that you can run during the
|
|
58
|
+
execution to migrate data from one attribute to another for example. This function needs to
|
|
59
|
+
be qualified and callable from the classpath. It will be evaluated during the migration and
|
|
60
|
+
needs to return transactions. These transactions will be transacted with `:tx-data` together
|
|
61
|
+
in one transaction.
|
|
62
|
+
|
|
63
|
+
Example of a migration:
|
|
64
|
+
```clojure
|
|
65
|
+
{:tx-data [{:db/doc "Place of occupation"
|
|
66
|
+
:db/ident :character/place-of-occupation
|
|
67
|
+
:db/valueType :db.type/string
|
|
68
|
+
:db/cardinality :db.cardinality/one}]
|
|
69
|
+
:tx-fn my-transactions.my-project/my-first-tx-fn}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
3. When you are sufficiently confident that your migrations will work you usually want to store
|
|
73
|
+
it in some kind of version control system. To avoid conflicts with fellow colleagues we
|
|
74
|
+
implemented a security net. Run the function `update-checksums!` from the `datahike.norm.norm`
|
|
75
|
+
namespace to create or update a `checksums.edn` file inside your migrations-folder. This file
|
|
76
|
+
contains the names and checksums of your migration-files. In case a colleague of yours
|
|
77
|
+
checked in a migration that you have not been aware of, your VCS should avoid merging the
|
|
78
|
+
conflicting `checksums.edn` file.
|
|
79
|
+
|
|
80
|
+
4. To apply your migrations you most likely want to package the migrations into a jar together
|
|
81
|
+
with datahike and a piece of code that actually runs your migrations and run it on a server.
|
|
82
|
+
You should check the correctness of the checksums with `datahike.norm.norm/verify-checksums`
|
|
83
|
+
and finally run the `datahike.norm.norm/ensure-norms!` function to apply your migrations. For
|
|
84
|
+
each migration that is already applied there will be a `:tx/norm` attribute stored with the
|
|
85
|
+
id of your migration so it will not be applied twice.
|
package/doc/schema.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Schema
|
|
2
|
+
|
|
3
|
+
Datahike supports two approaches to data validation: **schema-on-read** (flexible, validate later) and **schema-on-write** (strict, validate immediately). Choose at database creation time - this cannot be changed later.
|
|
4
|
+
|
|
5
|
+
## When to Use Each Approach
|
|
6
|
+
|
|
7
|
+
| Aspect | Schema-on-read (`:read`) | Schema-on-write (`:write`, default) |
|
|
8
|
+
|--------|-------------------------|-------------------------------------|
|
|
9
|
+
| **Validation** | None - accepts any data | Enforces types and structure |
|
|
10
|
+
| **Use when** | Prototyping, evolving schemas, heterogeneous data | Production systems, data integrity critical |
|
|
11
|
+
| **Similar to** | MongoDB, Redis, JSON documents | PostgreSQL, Datomic, traditional RDBMS |
|
|
12
|
+
| **Trade-off** | Flexibility vs. runtime errors | Safety vs. schema migration complexity |
|
|
13
|
+
|
|
14
|
+
**Default:** Datahike uses `:write` (schema-on-write) by default since version 0.2.0.
|
|
15
|
+
|
|
16
|
+
## Schema-on-read
|
|
17
|
+
|
|
18
|
+
Schema-on-read accepts any data without validation. Set `:schema-flexibility :read` at database creation to enable this mode.
|
|
19
|
+
|
|
20
|
+
```clojure
|
|
21
|
+
(require '[datahike.api :as d])
|
|
22
|
+
|
|
23
|
+
(def cfg {:store {:backend :memory :id #uuid "550e8400-e29b-41d4-a716-446655440010"} :schema-flexibility :read})
|
|
24
|
+
|
|
25
|
+
(d/create-database cfg)
|
|
26
|
+
|
|
27
|
+
(def conn (d/connect cfg))
|
|
28
|
+
|
|
29
|
+
;; now you can add any arbitrary data
|
|
30
|
+
(d/transact conn {:tx-data [{:any "Data"}]})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Schema-on-write
|
|
34
|
+
|
|
35
|
+
Schema-on-write (the default) enforces type safety and structure. Define your schema before adding data. The schema itself is stored in the database, so you transact it like any other data.
|
|
36
|
+
|
|
37
|
+
```clojure
|
|
38
|
+
(require '[datahike.api :as d])
|
|
39
|
+
|
|
40
|
+
;; since the :write approach is the default value we may also skip the setting
|
|
41
|
+
(def cfg {:store {:backend :memory :id #uuid "550e8400-e29b-41d4-a716-446655440011"} :schema-flexibility :write})
|
|
42
|
+
|
|
43
|
+
(d/create-database cfg)
|
|
44
|
+
|
|
45
|
+
(def conn (d/connect cfg))
|
|
46
|
+
|
|
47
|
+
;; define a simple schema
|
|
48
|
+
(def schema [{:db/ident :name :db/valueType :db.type/string :db/cardinality :db.cardinality/one}])
|
|
49
|
+
|
|
50
|
+
;; transact it
|
|
51
|
+
(d/transact conn {:tx-data schema})
|
|
52
|
+
|
|
53
|
+
;; now we can transact data based on the provided schema
|
|
54
|
+
(d/transact conn {:tx-data [{:name "Alice"}]})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The schema definition is for the most part compliant with Datomic's
|
|
58
|
+
[approach](https://docs.datomic.com/on-prem/schema.html). Required are three
|
|
59
|
+
attributes:
|
|
60
|
+
|
|
61
|
+
- `:db/ident`: the name of the attribute, defined as a keyword with optional
|
|
62
|
+
namespace, e.g. `:user/name`
|
|
63
|
+
- `:db/valueType`: the type of the value associated with an attribute, e.g. `db.type/string`, see
|
|
64
|
+
[below](#supported-value-types) for supported types
|
|
65
|
+
- `:db/cardinality`: the cardinality of the value, whether the value is a single
|
|
66
|
+
value or a set of values, can be either `:db.cardinality/one` or `db.cardinality/many`
|
|
67
|
+
|
|
68
|
+
Additionally, the following optional attributes are supported:
|
|
69
|
+
|
|
70
|
+
- `db/doc`: the documentation for the attribute as a string
|
|
71
|
+
- `db/unique`: a uniqueness constraint on the attribute for a given value, can
|
|
72
|
+
be either `db.unique/value` (only one entity with this attribute can have the same value) or `db.unique/identity`(only one entity can have
|
|
73
|
+
the value for this attribute with upsert enabled)
|
|
74
|
+
- `db/index`: indicates whether an index for the attribute's value should be
|
|
75
|
+
created as a boolean
|
|
76
|
+
- `db/isComponent`: indicates that an attribute of type `:db.type/ref` references a subcomponent of the entity that has the attribute (for cascading retractions)
|
|
77
|
+
- if `:db/valueType` is `:db.type/tuple`, one of:
|
|
78
|
+
- `db/tupleAttrs`: a collection of attributes that make up the tuple (for [composite tuples](https://docs.datomic.com/on-prem/schema/schema.html#composite-tuples))
|
|
79
|
+
- `db/tupleTypes`: a collection of 2-8 types that make up the tuple (for [heterogeneous fixed length tuples](https://docs.datomic.com/on-prem/schema/schema.html#heterogeneous-tuples))
|
|
80
|
+
- `db/tupleType`: the type of the tuple elements (for [homogeneous variable length tuples](https://docs.datomic.com/on-prem/schema/schema.html#homogeneous-tuples))
|
|
81
|
+
|
|
82
|
+
### Supported value types
|
|
83
|
+
|
|
84
|
+
The following types are currently support in datahike:
|
|
85
|
+
|
|
86
|
+
| Value Type | Corresponding Type |
|
|
87
|
+
| ----------------- | -------------------- |
|
|
88
|
+
| `db.type/bigdec` | java.math.BigDecimal |
|
|
89
|
+
| `db.type/bigint` | java.math.BigInteger |
|
|
90
|
+
| `db.type/boolean` | Boolean |
|
|
91
|
+
| `db.type/double` | Double |
|
|
92
|
+
| `db.type/float` | Double or Float |
|
|
93
|
+
| `db.type/instant` | java.util.Date |
|
|
94
|
+
| `db.type/keyword` | clojure.lang.Keyword |
|
|
95
|
+
| `db.type/long` | java.lang.Long |
|
|
96
|
+
| `db.type/ref` | java.lang.Long |
|
|
97
|
+
| `db.type/string` | String |
|
|
98
|
+
| `db.type/symbol` | clojure.lang.Symbol |
|
|
99
|
+
| `db.type/uuid` | java.util.UUID |
|
|
100
|
+
| `db.type/tuple` | clojure.lang.Vector |
|
|
101
|
+
|
|
102
|
+
The schema is validated using [clojure.spec](https://clojure.org/guides/spec). For additional validation beyond schema, see [Entity Specs](entity_spec.md).
|
|
103
|
+
|
|
104
|
+
### Tuple Examples
|
|
105
|
+
|
|
106
|
+
Tuples store multiple values together as a single attribute. Datahike supports three tuple types:
|
|
107
|
+
|
|
108
|
+
#### Composite Tuples
|
|
109
|
+
Composite tuples combine existing attributes into a compound key:
|
|
110
|
+
|
|
111
|
+
```clojure
|
|
112
|
+
;; Define the component attributes
|
|
113
|
+
(def schema [{:db/ident :user/first-name :db/valueType :db.type/string :db/cardinality :db.cardinality/one}
|
|
114
|
+
{:db/ident :user/last-name :db/valueType :db.type/string :db/cardinality :db.cardinality/one}
|
|
115
|
+
;; Composite tuple combining first and last name
|
|
116
|
+
{:db/ident :user/full-name
|
|
117
|
+
:db/valueType :db.type/tuple
|
|
118
|
+
:db/tupleAttrs [:user/first-name :user/last-name]
|
|
119
|
+
:db/cardinality :db.cardinality/one
|
|
120
|
+
:db/unique :db.unique/identity}])
|
|
121
|
+
|
|
122
|
+
(d/transact conn {:tx-data schema})
|
|
123
|
+
(d/transact conn {:tx-data [{:user/first-name "Alice" :user/last-name "Smith"}]})
|
|
124
|
+
|
|
125
|
+
;; Query by the composite tuple
|
|
126
|
+
(d/q '[:find ?e :where [?e :user/full-name ["Alice" "Smith"]]] @conn)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Heterogeneous Fixed-Length Tuples
|
|
130
|
+
Fixed-length tuples with different types for each position:
|
|
131
|
+
|
|
132
|
+
```clojure
|
|
133
|
+
;; Geographic coordinate: [latitude longitude elevation]
|
|
134
|
+
(def schema [{:db/ident :location/coordinates
|
|
135
|
+
:db/valueType :db.type/tuple
|
|
136
|
+
:db/tupleTypes [:db.type/double :db.type/double :db.type/long]
|
|
137
|
+
:db/cardinality :db.cardinality/one}])
|
|
138
|
+
|
|
139
|
+
(d/transact conn {:tx-data schema})
|
|
140
|
+
(d/transact conn {:tx-data [{:location/coordinates [37.7749 -122.4194 52]}]})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Homogeneous Variable-Length Tuples
|
|
144
|
+
Variable-length tuples where all elements have the same type:
|
|
145
|
+
|
|
146
|
+
```clojure
|
|
147
|
+
;; RGB color values
|
|
148
|
+
(def schema [{:db/ident :color/rgb
|
|
149
|
+
:db/valueType :db.type/tuple
|
|
150
|
+
:db/tupleType :db.type/long
|
|
151
|
+
:db/cardinality :db.cardinality/one}])
|
|
152
|
+
|
|
153
|
+
(d/transact conn {:tx-data schema})
|
|
154
|
+
(d/transact conn {:tx-data [{:color/rgb [255 128 0]}]})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Schema Migration
|
|
158
|
+
|
|
159
|
+
Updating existing schema is discouraged as it may cause data inconsistencies. Only updates to `:db/cardinality` and `:db/unique` are supported.
|
|
160
|
+
|
|
161
|
+
**Recommended migration strategies:**
|
|
162
|
+
|
|
163
|
+
1. **Add new attributes** - Create a new attribute and migrate data, deprecating the old one
|
|
164
|
+
2. **Export and reimport** - Export data, create new database with updated schema, transform and import data
|
|
165
|
+
3. **Use norms** - For systematic schema changes across environments, use [Norms (Database Migrations)](norms.md)
|
|
166
|
+
|
|
167
|
+
## Common Schema Patterns
|
|
168
|
+
|
|
169
|
+
### User Profile
|
|
170
|
+
|
|
171
|
+
```clojure
|
|
172
|
+
(def user-schema
|
|
173
|
+
[{:db/ident :user/id
|
|
174
|
+
:db/valueType :db.type/uuid
|
|
175
|
+
:db/cardinality :db.cardinality/one
|
|
176
|
+
:db/unique :db.unique/identity
|
|
177
|
+
:db/doc "Unique user identifier"}
|
|
178
|
+
|
|
179
|
+
{:db/ident :user/email
|
|
180
|
+
:db/valueType :db.type/string
|
|
181
|
+
:db/cardinality :db.cardinality/one
|
|
182
|
+
:db/unique :db.unique/identity
|
|
183
|
+
:db/doc "User email address"}
|
|
184
|
+
|
|
185
|
+
{:db/ident :user/name
|
|
186
|
+
:db/valueType :db.type/string
|
|
187
|
+
:db/cardinality :db.cardinality/one}
|
|
188
|
+
|
|
189
|
+
{:db/ident :user/roles
|
|
190
|
+
:db/valueType :db.type/keyword
|
|
191
|
+
:db/cardinality :db.cardinality/many
|
|
192
|
+
:db/doc "User roles (admin, editor, viewer)"}
|
|
193
|
+
|
|
194
|
+
{:db/ident :user/created-at
|
|
195
|
+
:db/valueType :db.type/instant
|
|
196
|
+
:db/cardinality :db.cardinality/one
|
|
197
|
+
:db/index true}])
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Blog Post with References
|
|
201
|
+
|
|
202
|
+
```clojure
|
|
203
|
+
(def blog-schema
|
|
204
|
+
[{:db/ident :post/id
|
|
205
|
+
:db/valueType :db.type/uuid
|
|
206
|
+
:db/cardinality :db.cardinality/one
|
|
207
|
+
:db/unique :db.unique/identity}
|
|
208
|
+
|
|
209
|
+
{:db/ident :post/title
|
|
210
|
+
:db/valueType :db.type/string
|
|
211
|
+
:db/cardinality :db.cardinality/one}
|
|
212
|
+
|
|
213
|
+
{:db/ident :post/content
|
|
214
|
+
:db/valueType :db.type/string
|
|
215
|
+
:db/cardinality :db.cardinality/one}
|
|
216
|
+
|
|
217
|
+
{:db/ident :post/author
|
|
218
|
+
:db/valueType :db.type/ref
|
|
219
|
+
:db/cardinality :db.cardinality/one
|
|
220
|
+
:db/doc "Reference to user entity"}
|
|
221
|
+
|
|
222
|
+
{:db/ident :post/tags
|
|
223
|
+
:db/valueType :db.type/string
|
|
224
|
+
:db/cardinality :db.cardinality/many}
|
|
225
|
+
|
|
226
|
+
{:db/ident :post/published-at
|
|
227
|
+
:db/valueType :db.type/instant
|
|
228
|
+
:db/cardinality :db.cardinality/one
|
|
229
|
+
:db/index true}])
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Hierarchical Data (Organization Chart)
|
|
233
|
+
|
|
234
|
+
```clojure
|
|
235
|
+
(def org-schema
|
|
236
|
+
[{:db/ident :employee/id
|
|
237
|
+
:db/valueType :db.type/uuid
|
|
238
|
+
:db/cardinality :db.cardinality/one
|
|
239
|
+
:db/unique :db.unique/identity}
|
|
240
|
+
|
|
241
|
+
{:db/ident :employee/name
|
|
242
|
+
:db/valueType :db.type/string
|
|
243
|
+
:db/cardinality :db.cardinality/one}
|
|
244
|
+
|
|
245
|
+
{:db/ident :employee/manager
|
|
246
|
+
:db/valueType :db.type/ref
|
|
247
|
+
:db/cardinality :db.cardinality/one
|
|
248
|
+
:db/doc "Reference to manager (also an employee)"}
|
|
249
|
+
|
|
250
|
+
{:db/ident :employee/department
|
|
251
|
+
:db/valueType :db.type/ref
|
|
252
|
+
:db/cardinality :db.cardinality/one
|
|
253
|
+
:db/doc "Reference to department entity"}
|
|
254
|
+
|
|
255
|
+
{:db/ident :department/name
|
|
256
|
+
:db/valueType :db.type/string
|
|
257
|
+
:db/cardinality :db.cardinality/one
|
|
258
|
+
:db/unique :db.unique/identity}])
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Component Entities (Cascading Deletion)
|
|
262
|
+
|
|
263
|
+
```clojure
|
|
264
|
+
(def order-schema
|
|
265
|
+
[{:db/ident :order/id
|
|
266
|
+
:db/valueType :db.type/uuid
|
|
267
|
+
:db/cardinality :db.cardinality/one
|
|
268
|
+
:db/unique :db.unique/identity}
|
|
269
|
+
|
|
270
|
+
{:db/ident :order/items
|
|
271
|
+
:db/valueType :db.type/ref
|
|
272
|
+
:db/cardinality :db.cardinality/many
|
|
273
|
+
:db/isComponent true
|
|
274
|
+
:db/doc "Line items are components - deleted when order is deleted"}
|
|
275
|
+
|
|
276
|
+
{:db/ident :item/product-id
|
|
277
|
+
:db/valueType :db.type/string
|
|
278
|
+
:db/cardinality :db.cardinality/one}
|
|
279
|
+
|
|
280
|
+
{:db/ident :item/quantity
|
|
281
|
+
:db/valueType :db.type/long
|
|
282
|
+
:db/cardinality :db.cardinality/one}
|
|
283
|
+
|
|
284
|
+
{:db/ident :item/price
|
|
285
|
+
:db/valueType :db.type/bigdec
|
|
286
|
+
:db/cardinality :db.cardinality/one}])
|
|
287
|
+
```
|