From 854c1ff6c3884e491c79a1855e4b482ae0ce05ea Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Mon, 21 Feb 2022 12:24:54 +0100 Subject: [PATCH 01/14] Remove Spec Namespaces from Production Namespaces We don't like to require spec namespaces from production namespaces because function specs are only used in test and dev. --- modules/cql/src/blaze/elm/compiler/external_data.clj | 1 - modules/cql/src/blaze/elm/compiler/library.clj | 1 - modules/cql/src/blaze/elm/compiler/library_spec.clj | 1 + modules/cql/src/blaze/elm/compiler/queries.clj | 1 - .../src/blaze/db/resource_store/cassandra.clj | 1 - modules/db-resource-store/src/blaze/db/resource_store/kv.clj | 1 - modules/db/src/blaze/db/api.clj | 1 - modules/db/src/blaze/db/impl/search_param.clj | 1 - modules/db/src/blaze/db/impl/search_param/composite.clj | 1 - modules/db/src/blaze/db/impl/search_param/composite/common.clj | 1 - .../src/blaze/db/impl/search_param/composite/token_quantity.clj | 1 - .../db/src/blaze/db/impl/search_param/composite/token_token.clj | 1 - modules/db/src/blaze/db/impl/search_param/date.clj | 1 - modules/db/src/blaze/db/impl/search_param/has.clj | 1 - modules/db/src/blaze/db/impl/search_param/number.clj | 1 - modules/db/src/blaze/db/impl/search_param/quantity.clj | 1 - modules/db/src/blaze/db/impl/search_param/string.clj | 1 - modules/db/src/blaze/db/impl/search_param/token.clj | 1 - modules/db/src/blaze/db/node.clj | 1 - modules/db/src/blaze/db/node/transaction.clj | 1 - modules/db/src/blaze/db/node/tx_indexer/verify.clj | 1 - modules/fhir-client/src/blaze/fhir_client/impl.clj | 1 - modules/fhir-path/src/blaze/fhir_path.clj | 1 - modules/fhir-structure/src/blaze/fhir/spec.clj | 1 - modules/fhir-structure/src/blaze/fhir/spec/type/system.clj | 1 - modules/interaction/src/blaze/interaction/history/util.clj | 1 - modules/interaction/src/blaze/interaction/search/params.clj | 1 - .../interaction/src/blaze/interaction/search/params/include.clj | 1 - modules/interaction/src/blaze/interaction/search_compartment.clj | 1 - modules/interaction/src/blaze/interaction/search_type.clj | 1 - modules/interaction/src/blaze/interaction/transaction.clj | 1 - .../src/blaze/fhir/operation/evaluate_measure/cql.clj | 1 - .../src/blaze/fhir/operation/evaluate_measure/measure.clj | 1 - .../blaze/fhir/operation/evaluate_measure/measure/population.clj | 1 - .../blaze/fhir/operation/evaluate_measure/measure/stratifier.clj | 1 - .../blaze/fhir/operation/evaluate_measure/middleware/params.clj | 1 - modules/page-store-cassandra/src/blaze/page_store/cassandra.clj | 1 - .../src/blaze/page_store/cassandra/codec.clj | 1 - modules/rest-api/src/blaze/rest_api/middleware/resource.clj | 1 - 39 files changed, 1 insertion(+), 38 deletions(-) diff --git a/modules/cql/src/blaze/elm/compiler/external_data.clj b/modules/cql/src/blaze/elm/compiler/external_data.clj index 6880d771c..2ff3c73c4 100644 --- a/modules/cql/src/blaze/elm/compiler/external_data.clj +++ b/modules/cql/src/blaze/elm/compiler/external_data.clj @@ -6,7 +6,6 @@ (:require [blaze.anomaly :as ba :refer [if-ok]] [blaze.db.api :as d] - [blaze.db.api-spec] [blaze.elm.compiler.core :as core] [blaze.elm.spec] [blaze.elm.util :as elm-util] diff --git a/modules/cql/src/blaze/elm/compiler/library.clj b/modules/cql/src/blaze/elm/compiler/library.clj index 7e0a56704..f78367791 100644 --- a/modules/cql/src/blaze/elm/compiler/library.clj +++ b/modules/cql/src/blaze/elm/compiler/library.clj @@ -1,7 +1,6 @@ (ns blaze.elm.compiler.library (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.elm.compiler :as compiler] [blaze.elm.deps-infer :as deps-infer] [blaze.elm.equiv-relationships :as equiv-relationships] diff --git a/modules/cql/src/blaze/elm/compiler/library_spec.clj b/modules/cql/src/blaze/elm/compiler/library_spec.clj index 51cf584be..f39cced8a 100644 --- a/modules/cql/src/blaze/elm/compiler/library_spec.clj +++ b/modules/cql/src/blaze/elm/compiler/library_spec.clj @@ -1,5 +1,6 @@ (ns blaze.elm.compiler.library-spec (:require + [blaze.anomaly-spec] [blaze.elm.compiler-spec] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.library :as library] diff --git a/modules/cql/src/blaze/elm/compiler/queries.clj b/modules/cql/src/blaze/elm/compiler/queries.clj index 8414a431e..e57d76775 100644 --- a/modules/cql/src/blaze/elm/compiler/queries.clj +++ b/modules/cql/src/blaze/elm/compiler/queries.clj @@ -9,7 +9,6 @@ [blaze.coll.core :as coll] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.structured-values :as structured-values] - [blaze.elm.expression-spec] [blaze.elm.protocols :as p] [blaze.fhir.spec]) (:import diff --git a/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj b/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj index 5e0168dff..dc56aada4 100644 --- a/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj +++ b/modules/db-resource-store-cassandra/src/blaze/db/resource_store/cassandra.clj @@ -1,7 +1,6 @@ (ns blaze.db.resource-store.cassandra (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.byte-string :as bs] [blaze.cassandra :as cass] diff --git a/modules/db-resource-store/src/blaze/db/resource_store/kv.clj b/modules/db-resource-store/src/blaze/db/resource_store/kv.clj index 046a48824..b4a4fe0f2 100644 --- a/modules/db-resource-store/src/blaze/db/resource_store/kv.clj +++ b/modules/db-resource-store/src/blaze/db/resource_store/kv.clj @@ -2,7 +2,6 @@ "A resource store implementation that uses a kev-value store as backend." (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac] [blaze.byte-string :as bs] [blaze.coll.core :as coll] diff --git a/modules/db/src/blaze/db/api.clj b/modules/db/src/blaze/db/api.clj index d577232f4..c7f1798e4 100644 --- a/modules/db/src/blaze/db/api.clj +++ b/modules/db/src/blaze/db/api.clj @@ -8,7 +8,6 @@ (:refer-clojure :exclude [sync]) (:require [blaze.anomaly :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.resource-handle :as rh] diff --git a/modules/db/src/blaze/db/impl/search_param.clj b/modules/db/src/blaze/db/impl/search_param.clj index b7b65e2aa..721b560cf 100644 --- a/modules/db/src/blaze/db/impl/search_param.clj +++ b/modules/db/src/blaze/db/impl/search_param.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.compartment.search-param-value-resource :as c-sp-vr] diff --git a/modules/db/src/blaze/db/impl/search_param/composite.clj b/modules/db/src/blaze/db/impl/search_param/composite.clj index 428d595f9..845ce0d5f 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.composite (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.db.impl.codec :as codec] [blaze.db.impl.search-param.composite.token-quantity :as tq] [blaze.db.impl.search-param.composite.token-token :as tt] diff --git a/modules/db/src/blaze/db/impl/search_param/composite/common.clj b/modules/db/src/blaze/db/impl/search_param/composite/common.clj index d688c211d..d7c725f6b 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite/common.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite/common.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.composite.common (:require [blaze.anomaly :refer [when-ok]] - [blaze.anomaly-spec] [blaze.byte-string :as bs] [blaze.coll.core :as coll] [blaze.db.impl.protocols :as p] diff --git a/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj b/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj index 706202af8..967386e38 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite/token_quantity.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.composite.token-quantity (:require [blaze.anomaly :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.byte-string :as bs] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] diff --git a/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj b/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj index c5b5a3086..8c3900c2e 100644 --- a/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj +++ b/modules/db/src/blaze/db/impl/search_param/composite/token_token.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.composite.token-token (:require [blaze.anomaly :refer [when-ok]] - [blaze.anomaly-spec] [blaze.byte-string :as bs] [blaze.coll.core :as coll] [blaze.db.impl.protocols :as p] diff --git a/modules/db/src/blaze/db/impl/search_param/date.clj b/modules/db/src/blaze/db/impl/search_param/date.clj index 0b1dda7bb..dbe630d3f 100644 --- a/modules/db/src/blaze/db/impl/search_param/date.clj +++ b/modules/db/src/blaze/db/impl/search_param/date.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.date (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.byte-string :as bs] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] diff --git a/modules/db/src/blaze/db/impl/search_param/has.clj b/modules/db/src/blaze/db/impl/search_param/has.clj index 20d34babd..29fd2828b 100644 --- a/modules/db/src/blaze/db/impl/search_param/has.clj +++ b/modules/db/src/blaze/db/impl/search_param/has.clj @@ -2,7 +2,6 @@ "https://www.hl7.org/fhir/search.html#has" (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.resource-search-param-value :as r-sp-v] diff --git a/modules/db/src/blaze/db/impl/search_param/number.clj b/modules/db/src/blaze/db/impl/search_param/number.clj index bb5338f98..f72314879 100644 --- a/modules/db/src/blaze/db/impl/search_param/number.clj +++ b/modules/db/src/blaze/db/impl/search_param/number.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.number (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] [blaze.db.impl.protocols :as p] diff --git a/modules/db/src/blaze/db/impl/search_param/quantity.clj b/modules/db/src/blaze/db/impl/search_param/quantity.clj index 5835093eb..89cbf16fb 100644 --- a/modules/db/src/blaze/db/impl/search_param/quantity.clj +++ b/modules/db/src/blaze/db/impl/search_param/quantity.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.quantity (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.byte-string :as bs] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] diff --git a/modules/db/src/blaze/db/impl/search_param/string.clj b/modules/db/src/blaze/db/impl/search_param/string.clj index 6113b1df7..e8f9d9125 100644 --- a/modules/db/src/blaze/db/impl/search_param/string.clj +++ b/modules/db/src/blaze/db/impl/search_param/string.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.string (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.compartment.search-param-value-resource :as c-sp-vr] diff --git a/modules/db/src/blaze/db/impl/search_param/token.clj b/modules/db/src/blaze/db/impl/search_param/token.clj index 3abb8e794..049b4a758 100644 --- a/modules/db/src/blaze/db/impl/search_param/token.clj +++ b/modules/db/src/blaze/db/impl/search_param/token.clj @@ -1,7 +1,6 @@ (ns blaze.db.impl.search-param.token (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.coll.core :as coll] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.compartment.search-param-value-resource :as c-sp-vr] diff --git a/modules/db/src/blaze/db/node.clj b/modules/db/src/blaze/db/node.clj index 645aa0081..a88114823 100644 --- a/modules/db/src/blaze/db/node.clj +++ b/modules/db/src/blaze/db/node.clj @@ -2,7 +2,6 @@ "Local Database Node" (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.db.impl.batch-db :as batch-db] [blaze.db.impl.codec :as codec] diff --git a/modules/db/src/blaze/db/node/transaction.clj b/modules/db/src/blaze/db/node/transaction.clj index 97f2aada4..d5474ecf6 100644 --- a/modules/db/src/blaze/db/node/transaction.clj +++ b/modules/db/src/blaze/db/node/transaction.clj @@ -5,7 +5,6 @@ [blaze.db.impl.index.tx-error :as tx-error] [blaze.db.impl.index.tx-success :as tx-success] [blaze.fhir.hash :as hash] - [blaze.fhir.hash-spec] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type :as type])) diff --git a/modules/db/src/blaze/db/node/tx_indexer/verify.clj b/modules/db/src/blaze/db/node/tx_indexer/verify.clj index afaa8f785..5f00a0d89 100644 --- a/modules/db/src/blaze/db/node/tx_indexer/verify.clj +++ b/modules/db/src/blaze/db/node/tx_indexer/verify.clj @@ -1,7 +1,6 @@ (ns blaze.db.node.tx-indexer.verify (:require [blaze.anomaly :as ba :refer [throw-anom]] - [blaze.anomaly-spec] [blaze.byte-string :as bs] [blaze.db.api :as d] [blaze.db.impl.codec :as codec] diff --git a/modules/fhir-client/src/blaze/fhir_client/impl.clj b/modules/fhir-client/src/blaze/fhir_client/impl.clj index 8ac93cf2c..b8a8f31bb 100644 --- a/modules/fhir-client/src/blaze/fhir_client/impl.clj +++ b/modules/fhir-client/src/blaze/fhir_client/impl.clj @@ -2,7 +2,6 @@ (:refer-clojure :exclude [update]) (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac] [blaze.async.flow :as flow] [blaze.fhir.spec :as fhir-spec] diff --git a/modules/fhir-path/src/blaze/fhir_path.clj b/modules/fhir-path/src/blaze/fhir_path.clj index bb7b59fff..47cc6d565 100644 --- a/modules/fhir-path/src/blaze/fhir_path.clj +++ b/modules/fhir-path/src/blaze/fhir_path.clj @@ -2,7 +2,6 @@ (:refer-clojure :exclude [compile eval resolve]) (:require [blaze.anomaly :as ba :refer [throw-anom]] - [blaze.anomaly-spec] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type :as type] [blaze.fhir.spec.type.system :as system] diff --git a/modules/fhir-structure/src/blaze/fhir/spec.clj b/modules/fhir-structure/src/blaze/fhir/spec.clj index 948162c1e..7005a2970 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.spec (:require [blaze.anomaly :as ba] - [blaze.anomaly-spec] [blaze.fhir.hash.spec] [blaze.fhir.spec.impl :as impl] [blaze.fhir.spec.spec] diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type/system.clj b/modules/fhir-structure/src/blaze/fhir/spec/type/system.clj index af304c7df..93f991053 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type/system.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type/system.clj @@ -12,7 +12,6 @@ (:refer-clojure :exclude [boolean? decimal? integer? string? type]) (:require [blaze.anomaly :as ba] - [blaze.anomaly-spec] [cognitect.anomalies :as anom] [java-time.core :as time-core]) (:import diff --git a/modules/interaction/src/blaze/interaction/history/util.clj b/modules/interaction/src/blaze/interaction/history/util.clj index 41892143a..0d1923d7e 100644 --- a/modules/interaction/src/blaze/interaction/history/util.clj +++ b/modules/interaction/src/blaze/interaction/history/util.clj @@ -1,6 +1,5 @@ (ns blaze.interaction.history.util (:require - [blaze.db.api-spec] [blaze.fhir.spec.type :as type] [blaze.handler.fhir.util :as fhir-util] [blaze.interaction.util :as iu] diff --git a/modules/interaction/src/blaze/interaction/search/params.clj b/modules/interaction/src/blaze/interaction/search/params.clj index 60f6b92a4..fc816f2ce 100644 --- a/modules/interaction/src/blaze/interaction/search/params.clj +++ b/modules/interaction/src/blaze/interaction/search/params.clj @@ -1,7 +1,6 @@ (ns blaze.interaction.search.params (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.handler.fhir.util :as fhir-util] [blaze.interaction.search.params.include :as include] diff --git a/modules/interaction/src/blaze/interaction/search/params/include.clj b/modules/interaction/src/blaze/interaction/search/params/include.clj index 220e42f17..a2e00c1bd 100644 --- a/modules/interaction/src/blaze/interaction/search/params/include.clj +++ b/modules/interaction/src/blaze/interaction/search/params/include.clj @@ -1,7 +1,6 @@ (ns blaze.interaction.search.params.include (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.handler.fhir.util :as fhir-util] [clojure.string :as str])) diff --git a/modules/interaction/src/blaze/interaction/search_compartment.clj b/modules/interaction/src/blaze/interaction/search_compartment.clj index c09023bc1..1e14c8448 100644 --- a/modules/interaction/src/blaze/interaction/search_compartment.clj +++ b/modules/interaction/src/blaze/interaction/search_compartment.clj @@ -1,7 +1,6 @@ (ns blaze.interaction.search-compartment (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.db.api :as d] [blaze.db.spec] diff --git a/modules/interaction/src/blaze/interaction/search_type.clj b/modules/interaction/src/blaze/interaction/search_type.clj index fe8072e62..33ff3936d 100644 --- a/modules/interaction/src/blaze/interaction/search_type.clj +++ b/modules/interaction/src/blaze/interaction/search_type.clj @@ -4,7 +4,6 @@ https://www.hl7.org/fhir/http.html#search" (:require [blaze.anomaly :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.db.api :as d] [blaze.db.spec] diff --git a/modules/interaction/src/blaze/interaction/transaction.clj b/modules/interaction/src/blaze/interaction/transaction.clj index 854d90cda..36e3ad9a0 100644 --- a/modules/interaction/src/blaze/interaction/transaction.clj +++ b/modules/interaction/src/blaze/interaction/transaction.clj @@ -4,7 +4,6 @@ https://www.hl7.org/fhir/http.html#transaction" (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.db.api :as d] [blaze.executors :as ex] diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj index 5a0f5de72..2df079a91 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.operation.evaluate-measure.cql (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.db.api :as d] [blaze.elm.expression :as expr] [blaze.fhir.spec :as fhir-spec] diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj index 396e710f7..8df4ffd3d 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.operation.evaluate-measure.measure (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.coll.core :as coll] [blaze.cql-translator :as cql-translator] [blaze.db.api :as d] diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/population.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/population.clj index 52d242271..d97c29dee 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/population.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/population.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.operation.evaluate-measure.measure.population (:require [blaze.anomaly :refer [when-ok]] - [blaze.anomaly-spec] [blaze.fhir.operation.evaluate-measure.cql :as cql] [blaze.fhir.operation.evaluate-measure.measure.util :as u])) diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj index c99512a9b..3490676a7 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.operation.evaluate-measure.measure.stratifier (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.fhir.operation.evaluate-measure.cql :as cql] [blaze.fhir.operation.evaluate-measure.measure.util :as u] [blaze.fhir.spec.type :as type])) diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj index f528ac346..db481b77d 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.operation.evaluate-measure.middleware.params (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac] [blaze.fhir.operation.evaluate-measure.measure.spec] [blaze.fhir.spec :as fhir-spec] diff --git a/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj b/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj index a0955992a..e1d66522f 100644 --- a/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj +++ b/modules/page-store-cassandra/src/blaze/page_store/cassandra.clj @@ -1,7 +1,6 @@ (ns blaze.page-store.cassandra (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac :refer [do-sync]] [blaze.cassandra :as cass] [blaze.cassandra.spec] diff --git a/modules/page-store-cassandra/src/blaze/page_store/cassandra/codec.clj b/modules/page-store-cassandra/src/blaze/page_store/cassandra/codec.clj index 809fd83b1..7afae8bb0 100644 --- a/modules/page-store-cassandra/src/blaze/page_store/cassandra/codec.clj +++ b/modules/page-store-cassandra/src/blaze/page_store/cassandra/codec.clj @@ -1,7 +1,6 @@ (ns blaze.page-store.cassandra.codec (:require [blaze.anomaly :as ba] - [blaze.anomaly-spec] [cognitect.anomalies :as anom] [jsonista.core :as j]) (:import diff --git a/modules/rest-api/src/blaze/rest_api/middleware/resource.clj b/modules/rest-api/src/blaze/rest_api/middleware/resource.clj index bbe739c4b..81cd69344 100644 --- a/modules/rest-api/src/blaze/rest_api/middleware/resource.clj +++ b/modules/rest-api/src/blaze/rest_api/middleware/resource.clj @@ -2,7 +2,6 @@ "JSON/XML deserialization middleware." (:require [blaze.anomaly :as ba :refer [when-ok]] - [blaze.anomaly-spec] [blaze.async.comp :as ac] [blaze.fhir.spec :as fhir-spec] [clojure.data.xml :as xml] From 865d152bd3f569963d715d902731168a9f66f1d3 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Sun, 20 Feb 2022 22:51:22 +0100 Subject: [PATCH 02/14] Improve FHIRPath Performance Especially long chains of union expressions are about twice as fast now. A real world import of 10.000 Synthea bundles showed the following results as output of blazectl v0.8.6. Before this commit: Found 10000 bundles in total (from 10000 JSON files and from 0 NDJSON files) Uploads [total, concurrency] 10000, 4 Success [ratio] 100.00 % Duration [total] 14m45s Requ. Latencies [mean, 50, 95, 99, max] 353ms, 292ms, 787ms, 1.182s 4.156s Proc. Latencies [mean, 50, 95, 99, max] 353ms, 292ms, 787ms, 1.182s 4.156s Bytes In [total, mean] 476.75 MiB, 48.82 KiB Bytes Out [total, mean] 3.98 GiB, 417.01 KiB Status Codes [code:count] 200:10000 After this commit: Found 10000 bundles in total (from 10000 JSON files and from 0 NDJSON files) Uploads [total, concurrency] 10000, 4 Success [ratio] 100.00 % Duration [total] 14m14s Requ. Latencies [mean, 50, 95, 99, max] 341ms, 282ms, 758ms, 1.202s 3.866s Proc. Latencies [mean, 50, 95, 99, max] 341ms, 282ms, 758ms, 1.202s 3.866s Bytes In [total, mean] 476.75 MiB, 48.82 KiB Bytes Out [total, mean] 3.98 GiB, 417.01 KiB Status Codes [code:count] 200:10000 The number of imported resources was the following: Condition : 130563 Observation : 2716495 Patient : 10000 ------------------------------------------- total : 2857058 So the performance improvement is about 3.5 %. --- modules/db/Makefile | 2 +- modules/db/src/blaze/db/impl/search_param.clj | 13 +-- .../src/blaze/db/impl/search_param/token.clj | 14 +-- .../src/blaze/db/impl/search_param/util.clj | 10 ++ modules/db/src/blaze/db/node.clj | 1 + .../db/src/blaze/db/node/resource_indexer.clj | 15 ++- .../db/src/blaze/db/search_param_registry.clj | 20 ++-- .../blaze/db/search_param_registry_spec.clj | 6 +- .../db/test-perf/blaze/db/api_test_perf.clj | 3 +- .../db/search_param_registry_test_perf.clj | 37 +++++++ .../blaze/db/impl/search_param/token_test.clj | 52 ++++++++-- .../test/blaze/db/impl/search_param_spec.clj | 2 +- .../blaze/db/node/resource_indexer_test.clj | 28 ++++++ .../blaze/db/search_param_registry_test.clj | 27 ++++- modules/fhir-path/src/blaze/fhir_path.clj | 98 +++++++++++-------- .../fhir-path/test/blaze/fhir_path_test.clj | 47 +++++++-- .../src/blaze/fhir/spec/type.clj | 8 +- .../fhir/operation/evaluate_measure/cql.clj | 4 +- modules/rest-util/src/blaze/handler/util.clj | 2 +- 19 files changed, 284 insertions(+), 105 deletions(-) create mode 100644 modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj diff --git a/modules/db/Makefile b/modules/db/Makefile index 5c978eb5d..74eadf807 100644 --- a/modules/db/Makefile +++ b/modules/db/Makefile @@ -1,5 +1,5 @@ lint: - clj-kondo --lint src test deps.edn + clj-kondo --lint src test test-perf deps.edn test: clojure -M:test --profile :ci diff --git a/modules/db/src/blaze/db/impl/search_param.clj b/modules/db/src/blaze/db/impl/search_param.clj index 721b560cf..4448225fe 100644 --- a/modules/db/src/blaze/db/impl/search_param.clj +++ b/modules/db/src/blaze/db/impl/search_param.clj @@ -17,8 +17,7 @@ [blaze.db.impl.search-param.token] [blaze.db.impl.search-param.util :as u] [blaze.fhir-path :as fhir-path] - [blaze.fhir.spec :as fhir-spec] - [clojure.spec.alpha :as s])) + [blaze.fhir.spec :as fhir-spec])) (set! *warn-on-reflection* true) @@ -105,17 +104,15 @@ (p/-matches? search-param context resource-handle modifier compiled-values)) -(def stub-resolver +(def ^:private stub-resolver "A resolver which only returns a resource stub with type and id from the local reference itself." (reify fhir-path/Resolver (-resolve [_ uri] - (let [res (s/conform :blaze.fhir/local-ref uri)] - (when-not (s/invalid? res) - (let [[type id] res] - {:fhir/type (keyword "fhir" type) - :id id})))))) + (when-let [[type id] (some-> uri u/split-literal-ref)] + {:fhir/type (keyword "fhir" type) + :id id})))) (defn compartment-ids diff --git a/modules/db/src/blaze/db/impl/search_param/token.clj b/modules/db/src/blaze/db/impl/search_param/token.clj index 049b4a758..2c7876468 100644 --- a/modules/db/src/blaze/db/impl/search_param/token.clj +++ b/modules/db/src/blaze/db/impl/search_param/token.clj @@ -104,19 +104,9 @@ (identifier-entries nil identifier)) -(defn- split-literal-ref [^String s] - (let [idx (.indexOf s 47)] - (when (pos? idx) - (let [type (.substring s 0 idx)] - (when (.matches (re-matcher #"[A-Z]([A-Za-z0-9_]){0,254}" type)) - (let [id (.substring s (unchecked-inc-int idx))] - (when (.matches (re-matcher #"[A-Za-z0-9\-\.]{1,64}" id)) - [type id]))))))) - - (defn- literal-reference-entries [reference] (when-let [value (type/value reference)] - (if-let [[type id] (split-literal-ref value)] + (if-let [[type id] (u/split-literal-ref value)] [[nil (codec/v-hash id)] [nil (codec/v-hash (str type "/" id))] [nil (codec/tid-id (codec/tid type) @@ -199,7 +189,7 @@ (fn [value] (when (identical? :fhir/Reference (fhir-spec/fhir-type value)) (when-let [reference (:reference value)] - (nth (split-literal-ref reference) 1))))) + (nth (u/split-literal-ref reference) 1))))) values))) (-index-values [search-param resolver resource] diff --git a/modules/db/src/blaze/db/impl/search_param/util.clj b/modules/db/src/blaze/db/impl/search_param/util.clj index 044ae9836..147299d6f 100644 --- a/modules/db/src/blaze/db/impl/search_param/util.clj +++ b/modules/db/src/blaze/db/impl/search_param/util.clj @@ -93,3 +93,13 @@ (filter #(= ^long tid (bb/get-int! %))) (map bs/from-byte-buffer) (keep #(non-deleted-resource-handle resource-handle tid %))))) + + +(defn split-literal-ref [^String s] + (let [idx (.indexOf s 47)] + (when (pos? idx) + (let [type (.substring s 0 idx)] + (when (.matches (re-matcher #"[A-Z]([A-Za-z0-9_]){0,254}" type)) + (let [id (.substring s (unchecked-inc-int idx))] + (when (.matches (re-matcher #"[A-Za-z0-9\-\.]{1,64}" id)) + [type id]))))))) diff --git a/modules/db/src/blaze/db/node.clj b/modules/db/src/blaze/db/node.clj index a88114823..1d80b6e24 100644 --- a/modules/db/src/blaze/db/node.clj +++ b/modules/db/src/blaze/db/node.clj @@ -153,6 +153,7 @@ (log/trace "done indexing all resources") (catch Exception e (log/error "Error while resource indexing: " (ex-message (ex-cause e))) + (log/error e) (throw e)) (finally (prom/observe-duration! timer)))) diff --git a/modules/db/src/blaze/db/node/resource_indexer.clj b/modules/db/src/blaze/db/node/resource_indexer.clj index 8f3d80121..47211daf8 100644 --- a/modules/db/src/blaze/db/node/resource_indexer.clj +++ b/modules/db/src/blaze/db/node/resource_indexer.clj @@ -1,6 +1,6 @@ (ns blaze.db.node.resource-indexer (:require - [blaze.anomaly :as ba] + [blaze.anomaly :as ba :refer [if-ok]] [blaze.async.comp :as ac] [blaze.byte-string :as bs] [blaze.db.impl.codec :as codec] @@ -84,13 +84,22 @@ res))) +(defn- linked-compartments [search-param-registry hash resource] + (if-ok [compartments (sr/linked-compartments search-param-registry resource)] + compartments + (fn [e] + (log/warn "Skip indexing compartments of resource with hash " + (bs/hex hash) " because of:" (::anom/message e)) + []))) + + (defn- conj-index-entries! [search-param-registry last-updated res [hash resource]] - (log/trace "index-resource with hash" (bs/hex hash)) + (log/trace "Index resource with hash" (bs/hex hash)) (with-open [_ (prom/timer duration-seconds "calc-search-params")] (let [resource (update resource :meta (fnil assoc #fhir/Meta{}) :lastUpdated last-updated) - compartments (sr/linked-compartments search-param-registry resource)] + compartments (linked-compartments search-param-registry hash resource)] (transduce (mapcat #(index-entries % compartments hash resource)) conj! diff --git a/modules/db/src/blaze/db/search_param_registry.clj b/modules/db/src/blaze/db/search_param_registry.clj index b9552abb2..835aaeb42 100644 --- a/modules/db/src/blaze/db/search_param_registry.clj +++ b/modules/db/src/blaze/db/search_param_registry.clj @@ -1,8 +1,7 @@ (ns blaze.db.search-param-registry (:refer-clojure :exclude [get]) (:require - [blaze.anomaly :refer [if-ok when-ok]] - [blaze.anomaly-spec] + [blaze.anomaly :as ba :refer [if-ok when-ok]] [blaze.coll.core :as coll] [blaze.db.impl.search-param :as search-param] [blaze.db.impl.search-param.core :as sc] @@ -59,13 +58,18 @@ (into (map val) (index type)))) (-linked-compartments [_ resource] - (into + (transduce + (comp + (map + (fn [{:keys [def-code search-param]}] + (when-ok [compartment-ids (search-param/compartment-ids search-param resource)] + (coll/eduction + (map (fn [id] [def-code id])) + compartment-ids)))) + (halt-when ba/anomaly?) + cat) + conj #{} - (mapcat - (fn [{:keys [def-code search-param]}] - (coll/eduction - (map (fn [id] [def-code id])) - (search-param/compartment-ids search-param resource)))) (compartment-index (name (fhir-spec/fhir-type resource)))))) diff --git a/modules/db/src/blaze/db/search_param_registry_spec.clj b/modules/db/src/blaze/db/search_param_registry_spec.clj index 1bdbf974e..6ce5b2ea5 100644 --- a/modules/db/src/blaze/db/search_param_registry_spec.clj +++ b/modules/db/src/blaze/db/search_param_registry_spec.clj @@ -3,7 +3,8 @@ [blaze.db.search-param-registry :as sr] [blaze.db.search-param-registry.spec] [blaze.fhir.spec] - [clojure.spec.alpha :as s])) + [clojure.spec.alpha :as s] + [cognitect.anomalies :as anom])) (s/fdef sr/get @@ -21,4 +22,5 @@ (s/fdef sr/linked-compartments :args (s/cat :search-param-registry :blaze.db/search-param-registry :resource :blaze/resource) - :ret (s/coll-of (s/tuple string? :blaze.resource/id))) + :ret (s/or :compartments (s/coll-of (s/tuple string? :blaze.resource/id)) + :anomaly ::anom/anomaly)) diff --git a/modules/db/test-perf/blaze/db/api_test_perf.clj b/modules/db/test-perf/blaze/db/api_test_perf.clj index 26d6af5cb..2ffa66934 100644 --- a/modules/db/test-perf/blaze/db/api_test_perf.clj +++ b/modules/db/test-perf/blaze/db/api_test_perf.clj @@ -1,6 +1,5 @@ (ns blaze.db.api-test-perf (:require - [blaze.anomaly :refer [ex-anom]] [blaze.db.api :as d] [blaze.db.kv :as kv] [blaze.db.kv.mem] @@ -15,7 +14,7 @@ [blaze.fhir.structure-definition-repo] [blaze.log] [blaze.test-util :refer [with-system]] - [clojure.test :refer [deftest is testing]] + [clojure.test :refer [deftest]] [criterium.core :as criterium] [integrant.core :as ig] [java-time :as time] diff --git a/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj b/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj new file mode 100644 index 000000000..067a95fbf --- /dev/null +++ b/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj @@ -0,0 +1,37 @@ +(ns blaze.db.search-param-registry-test-perf + (:require + [blaze.db.search-param-registry :as sr] + [blaze.fhir.structure-definition-repo] + [blaze.test-util :refer [with-system]] + [clojure.test :refer [deftest testing]] + [criterium.core :as criterium] + [integrant.core :as ig] + [taoensso.timbre :as log])) + + +(log/set-level! :info) + + +(def system + {:blaze.fhir/structure-definition-repo {} + :blaze.db/search-param-registry + {:structure-definition-repo (ig/ref :blaze.fhir/structure-definition-repo)}}) + + +(deftest linked-compartments-test + (with-system [{:blaze.db/keys [search-param-registry]} system] + ;; 1.6 µs - Mac mini M1 + (testing "Condition subject" + (criterium/quick-bench + (sr/linked-compartments + search-param-registry + {:fhir/type :fhir/Condition :id "0" + :subject #fhir/Reference{:reference "Patient/1"}})) + + ;; 700 ns - Mac mini M1 + (testing "Observation subject" + (criterium/quick-bench + (sr/linked-compartments + search-param-registry + {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/1"}})))))) diff --git a/modules/db/test/blaze/db/impl/search_param/token_test.clj b/modules/db/test/blaze/db/impl/search_param/token_test.clj index 60ab376ce..84504b54b 100644 --- a/modules/db/test/blaze/db/impl/search_param/token_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/token_test.clj @@ -631,24 +631,56 @@ (sr/get search-param-registry "subject" "Observation")) +(defn patient-param [search-param-registry] + (sr/get search-param-registry "patient" "Condition")) + + (defn compartment-ids [search-param resource] (into [] (search-param/compartment-ids search-param resource))) (deftest compartment-ids-test (with-system [{:blaze.db/keys [search-param-registry]} system] - (let [subject-param (subject-param search-param-registry)] + (testing "Observation" + (let [subject-param (subject-param search-param-registry)] + + (testing "with literal reference" + (let [observation {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}] + (is (= ["0"] (compartment-ids subject-param observation))))) + + (testing "without reference" + (let [observation {:fhir/type :fhir/Observation :id "0"}] + (is (empty? (compartment-ids subject-param observation))))) - (testing "with literal reference" - (let [observation {:fhir/type :fhir/Observation :id "0" + (testing "with reference without reference value" + (let [observation {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:display "foo"}}] + (is (empty? (compartment-ids subject-param observation))))) + + (testing "with absolute reference" + (let [observation {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "http://server.org/Patient/0"}}] + (is (empty? (compartment-ids subject-param observation))))))) + + (testing "Condition" + (let [patient-param (patient-param search-param-registry)] + + (testing "with literal reference" + (let [condition {:fhir/type :fhir/Condition :id "0" :subject #fhir/Reference{:reference "Patient/0"}}] - (is (= ["0"] (compartment-ids subject-param observation))))) + (is (= ["0"] (compartment-ids patient-param condition))))) + + (testing "without reference" + (let [condition {:fhir/type :fhir/Condition :id "0"}] + (is (empty? (compartment-ids patient-param condition))))) - (testing "without reference" - (let [observation {:fhir/type :fhir/Observation :id "0"}] - (is (empty? (compartment-ids subject-param observation))))) + (testing "with reference without reference value" + (let [condition {:fhir/type :fhir/Condition :id "0" + :subject #fhir/Reference{:display "foo"}}] + (is (empty? (compartment-ids patient-param condition))))) - (testing "with absolute reference" - (let [observation {:fhir/type :fhir/Observation :id "0" + (testing "with absolute reference" + (let [condition {:fhir/type :fhir/Condition :id "0" :subject #fhir/Reference{:reference "http://server.org/Patient/0"}}] - (is (empty? (compartment-ids subject-param observation)))))))) + (is (empty? (compartment-ids patient-param condition))))))))) diff --git a/modules/db/test/blaze/db/impl/search_param_spec.clj b/modules/db/test/blaze/db/impl/search_param_spec.clj index e0dd0f7e6..9d649f3f5 100644 --- a/modules/db/test/blaze/db/impl/search_param_spec.clj +++ b/modules/db/test/blaze/db/impl/search_param_spec.clj @@ -64,7 +64,7 @@ (s/fdef search-param/compartment-ids :args (s/cat :search-param :blaze.db/search-param :resource :blaze/resource) - :ret (s/coll-of :blaze.resource/id)) + :ret (s/or :ids (s/coll-of :blaze.resource/id) :anomaly ::anom/anomaly)) (s/fdef search-param/index-entries diff --git a/modules/db/test/blaze/db/node/resource_indexer_test.clj b/modules/db/test/blaze/db/node/resource_indexer_test.clj index 557f8453f..c9d1c42b9 100644 --- a/modules/db/test/blaze/db/node/resource_indexer_test.clj +++ b/modules/db/test/blaze/db/node/resource_indexer_test.clj @@ -16,6 +16,7 @@ [blaze.db.resource-store :as rs] [blaze.db.resource-store.kv :as rs-kv] [blaze.db.search-param-registry] + [blaze.fhir-path :as fhir-path] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec.type] @@ -94,6 +95,33 @@ ::anom/message := "msg-200802"))))) +(deftest skips-on-failing-fhir-path-eval-test + (with-system [{kv-store ::kv/mem resource-store ::rs/kv + :blaze.db/keys [search-param-registry]} system] + (let [observation {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "foo"}} + hash (hash/generate observation) + resource-indexer (resource-indexer/new-resource-indexer + search-param-registry kv-store) + context + {:resource-store resource-store + :resource-indexer resource-indexer}] + (with-redefs [fhir-path/eval (fn [_ _ _] {::anom/category ::anom/fault})] + @(resource-indexer/index-resources + context + {:t 0 + :instant Instant/EPOCH + :tx-cmds + [{:op "put" + :type "Observation" + :id "0" + :hash hash}] + :local-payload + {hash observation}})) + + (is (empty? (sp-vr-tu/decode-index-entries kv-store :id)))))) + + (deftest index-condition-resource-test (with-system [{kv-store ::kv/mem resource-store ::rs/kv :blaze.db/keys [search-param-registry]} system] diff --git a/modules/db/test/blaze/db/search_param_registry_test.clj b/modules/db/test/blaze/db/search_param_registry_test.clj index 83e4d28fd..e5adca49d 100644 --- a/modules/db/test/blaze/db/search_param_registry_test.clj +++ b/modules/db/test/blaze/db/search_param_registry_test.clj @@ -2,11 +2,13 @@ (:require [blaze.db.search-param-registry :as sr] [blaze.db.search-param-registry-spec] + [blaze.fhir-path :as fhir-path] [blaze.fhir.spec.type] [blaze.fhir.structure-definition-repo] [blaze.test-util :refer [with-system]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] + [cognitect.anomalies :as anom] [integrant.core :as ig] [juxt.iota :refer [given]] [taoensso.timbre :as log])) @@ -49,6 +51,14 @@ count := 1 [0] := ["Patient" "1"])) + (testing "Observation subject" + (given (sr/linked-compartments + search-param-registry + {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/1"}}) + count := 1 + [0] := ["Patient" "1"])) + (testing "MedicationAdministration subject" (given (sr/linked-compartments search-param-registry @@ -78,4 +88,19 @@ [{:fhir/type :fhir.MedicationAdministration/performer :actor #fhir/Reference{:reference "Patient/1"}}]}) count := 1 - [0] := ["Patient" "1"])))) + [0] := ["Patient" "1"])) + + (testing "with FHIRPath eval error" + (with-redefs [fhir-path/eval + (fn [_ _ _] + {::anom/category ::anom/fault + ::anom/message "msg-121005" + ::x ::y})] + (given + (sr/linked-compartments + search-param-registry + {:fhir/type :fhir/Condition :id "0" + :subject #fhir/Reference{:reference "Patient/1"}}) + ::anom/category := ::anom/fault + ::anom/message := "msg-121005" + ::x := ::y))))) diff --git a/modules/fhir-path/src/blaze/fhir_path.clj b/modules/fhir-path/src/blaze/fhir_path.clj index 47cc6d565..cf253d423 100644 --- a/modules/fhir-path/src/blaze/fhir_path.clj +++ b/modules/fhir-path/src/blaze/fhir_path.clj @@ -9,7 +9,7 @@ [cuerdas.core :as str] [taoensso.timbre :as log]) (:import - [clojure.lang Counted PersistentVector] + [clojure.lang Counted PersistentVector IReduceInit] [java.io StringReader] [org.antlr.v4.runtime CharStreams CommonTokenStream] [org.antlr.v4.runtime.tree TerminalNode] @@ -108,7 +108,7 @@ (identical? :fhir/boolean type) true :else (throw-anom (ba/incorrect (singleton-evaluation-msg coll))))) - 0 [] + 0 coll (throw-anom (ba/incorrect (singleton-evaluation-msg coll))))) @@ -119,24 +119,32 @@ coll)) -(defrecord TypedStartExpression [spec] +(defrecord TypedStartExpression [rf] Expression (-eval [_ _ coll] - (filterv #(identical? spec (fhir-spec/fhir-type %)) coll))) + (.reduce ^IReduceInit coll rf []))) -(defrecord GetChildrenExpression [key] +(defn- typed-start-expression [type-name] + (let [fhir-type (keyword "fhir" type-name) + pred #(identical? fhir-type (fhir-spec/fhir-type %))] + (->TypedStartExpression ((filter pred) conj)))) + + +(defrecord GetChildrenExpression [f] Expression (-eval [_ _ coll] - (reduce - (fn [res x] - (let [val (get x key)] - (cond - (sequential? val) (into res val) - (some? val) (conj res val) - :else res))) - [] - coll))) + (.reduce ^IReduceInit coll f []))) + + +(defn- get-children-expression [key] + (->GetChildrenExpression + (fn [res item] + (let [val (get item key)] + (cond + (instance? IReduceInit val) (.reduce ^IReduceInit val conj res) + (some? val) (conj res val) + :else res))))) (defrecord InvocationExpression [expression invocation] @@ -174,7 +182,7 @@ (-eval [_ context coll] (let [coll (-eval expression context coll)] (case (.count ^Counted coll) - 0 [] + 0 coll 1 [(identical? type-specifier (fhir-spec/fhir-type (nth coll 0)))] @@ -191,7 +199,7 @@ (-eval [_ context coll] (let [coll (-eval expression context coll)] (case (.count ^Counted coll) - 0 [] + 0 coll 1 (if (identical? type-specifier (fhir-spec/fhir-type (nth coll 0))) coll @@ -269,7 +277,7 @@ Expression (-eval [_ _ coll] (case (.count ^Counted coll) - 0 [] + 0 coll 1 (if (identical? type-specifier (fhir-spec/fhir-type (nth coll 0))) coll @@ -296,12 +304,13 @@ (throw-anom (ba/unsupported "unsupported `exists` function")))) -(defmulti resolve (fn [_ item] (fhir-spec/fhir-type item))) +(defmulti ^IReduceInit resolve (fn [_ item] (fhir-spec/fhir-type item))) (defn- resolve* [resolver uri] - (when-let [resource (-resolve resolver uri)] - [resource])) + (if-let [resource (-resolve resolver uri)] + [resource] + [])) (defmethod resolve :fhir/string [{:keys [resolver]} uri] @@ -313,14 +322,15 @@ (defmethod resolve :default [_ item] - (log/debug (format "Skip resolving %s `%s`." (name (fhir-spec/fhir-type item)) - (pr-str item)))) + (log/warn (format "Skip resolving %s `%s`." (name (fhir-spec/fhir-type item)) + (pr-str item))) + []) (defrecord ResolveFunctionExpression [] Expression (-eval [_ context coll] - (reduce #(reduce conj %1 (resolve context %2)) [] coll))) + (.reduce ^IReduceInit coll #(.reduce (resolve context %2) conj %1) []))) (defprotocol FPCompiler @@ -354,28 +364,34 @@ (pr-str x))) -(defrecord WhereFunctionExpression [criteria] +(defrecord WhereFunctionExpression [where-rf] Expression (-eval [_ context coll] - (filterv - (fn [item] - (let [coll (-eval criteria context [item])] - (case (.count ^Counted coll) - 0 false + (.reduce ^IReduceInit coll (where-rf context) []))) + + +(defn- where-function-expr [criteria] + (->WhereFunctionExpression + (fn [context] + ((filter + (fn [item] + (let [coll (-eval criteria context [item])] + (case (.count ^Counted coll) + 0 false - 1 (let [first (nth coll 0)] - (if (identical? :system/boolean (system/type first)) - first - (throw-anom (ba/incorrect (non-boolean-result-msg first))))) + 1 (let [first (nth coll 0)] + (if (identical? :system/boolean (system/type first)) + first + (throw-anom (ba/incorrect (non-boolean-result-msg first))))) - (throw-anom (ba/incorrect (multiple-result-msg coll)))))) - coll))) + (throw-anom (ba/incorrect (multiple-result-msg coll))))))) + conj)))) (defmethod function-expression "where" [_ ^fhirpathParser$ParamListContext paramsCtx] (if-let [criteria-ctx (some-> paramsCtx (.expression 0))] - (->WhereFunctionExpression (-compile criteria-ctx)) + (where-function-expr (-compile criteria-ctx)) (throw-anom (ba/incorrect "missing criteria in `where` function")))) @@ -396,17 +412,17 @@ ;; Additional functions (https://www.hl7.org/fhir/fhirpath.html#functions) -(defrecord ExtensionFunctionExpression [xf] +(defrecord ExtensionFunctionExpression [rf] Expression (-eval [_ _ coll] - (into [] xf coll))) + (.reduce ^IReduceInit coll rf []))) (defmethod function-expression "extension" [_ ^fhirpathParser$ParamListContext paramsCtx] (let [url-pred (set (some-> paramsCtx (.expression 0) -compile)) xf (comp (mapcat :extension) (filter (comp url-pred :url)))] - (->ExtensionFunctionExpression xf))) + (->ExtensionFunctionExpression (xf conj)))) (defmethod function-expression "resolve" @@ -538,8 +554,8 @@ (if (Character/isUpperCase ^char first-char) (if (= "Resource" identifier) (->StartExpression) - (->TypedStartExpression (keyword "fhir" identifier))) - (->GetChildrenExpression (keyword identifier))))) + (typed-start-expression identifier)) + (get-children-expression (keyword identifier))))) (-compile-as-type-specifier [ctx] (let [type (-compile (.identifier ctx))] (if (fhir-spec/type-exists? type) diff --git a/modules/fhir-path/test/blaze/fhir_path_test.clj b/modules/fhir-path/test/blaze/fhir_path_test.clj index 857dc7cf9..3926b1d23 100644 --- a/modules/fhir-path/test/blaze/fhir_path_test.clj +++ b/modules/fhir-path/test/blaze/fhir_path_test.clj @@ -206,20 +206,47 @@ ;; 5. Functions (deftest resolve-function-test - (let [resolver - (reify - fhir-path/Resolver - (-resolve [_ uri] - (when (= "reference-180039" uri) - {:fhir/type :fhir/Patient - :id "id-164737"})))] + (testing "Specimen with reference to Patient" + (let [resolver + (reify + fhir-path/Resolver + (-resolve [_ uri] + (when (= "reference-180039" uri) + {:fhir/type :fhir/Patient + :id "id-164737"})))] + (given + (eval + "Specimen.subject.where(resolve() is Patient)" + resolver + {:fhir/type :fhir/Specimen :id "foo" + :subject #fhir/Reference{:reference "reference-180039"}}) + [0 :reference] := "reference-180039"))) + + (testing "Specimen with display only reference" (given (eval "Specimen.subject.where(resolve() is Patient)" resolver - {:fhir/type :fhir/Specimen :id "id-175250" - :subject #fhir/Reference{:reference "reference-180039"}}) - [0 :reference] := "reference-180039"))) + {:fhir/type :fhir/Specimen :id "foo" + :subject #fhir/Reference{:display "foo"}}) + count := 0)) + + (testing "Resolving on unsupported data type is skipped" + (given + (eval + "Patient.gender.where(resolve())" + resolver + {:fhir/type :fhir/Patient :id "foo" + :gender #fhir/code"unknown"}) + count := 0)) + + (testing "Resolving string" + (given + (eval + "Patient.id.where(resolve())" + resolver + {:fhir/type :fhir/Patient :id "foo"}) + count := 0))) ;; 5.1. Existence diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type.clj b/modules/fhir-structure/src/blaze/fhir/spec/type.clj index db7ce1ca8..43bbb40ea 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type.clj @@ -12,7 +12,7 @@ (:import [blaze.fhir.spec.type.system DateTimeYear DateTimeYearMonth DateTimeYearMonthDay] - [clojure.lang Keyword] + [clojure.lang IPersistentMap Keyword] [com.fasterxml.jackson.core JsonGenerator] [com.fasterxml.jackson.databind JsonSerializer SerializerProvider] [com.fasterxml.jackson.databind.module SimpleModule] @@ -26,7 +26,7 @@ Instant LocalDate LocalDateTime LocalTime OffsetDateTime Year YearMonth ZoneOffset] [java.time.format DateTimeFormatter DateTimeParseException] - [java.util List Map UUID])) + [java.util List UUID])) (xml-name/alias-uri 'f "http://hl7.org/fhir") @@ -1113,9 +1113,9 @@ (-hash-into [k sink] (.putInt ^PrimitiveSink sink (.hasheq k))) (-references [_]) - Map + IPersistentMap (-type [m] - (:fhir/type m)) + (.valAt m :fhir/type)) (-value [_]) (-hash-into [m sink] (.putByte ^PrimitiveSink sink (byte 37)) diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj index 2df079a91..3f12a2d19 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj @@ -36,7 +36,9 @@ (try (expr/eval context (get library-context expression-name) subject-handle) (catch Exception e - (log/error (log/stacktrace e)) + (log/error (format "Error while evaluating the expression `%s`:" + expression-name) (ex-message (ex-cause e))) + (log/error e) (ba/fault (ex-message e) :fhir/issue "exception" diff --git a/modules/rest-util/src/blaze/handler/util.clj b/modules/rest-util/src/blaze/handler/util.clj index 41fb5a8be..ae4bb1deb 100644 --- a/modules/rest-util/src/blaze/handler/util.clj +++ b/modules/rest-util/src/blaze/handler/util.clj @@ -135,7 +135,7 @@ (ex-data error)) f) (do - (log/error (log/stacktrace error)) + (log/error error) (error-response* (ba/fault (ex-message error) From 3fe82a6e50f17505065870fb6d64ac76e9ace450 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Mon, 21 Feb 2022 22:31:20 +0100 Subject: [PATCH 03/14] Improve CQL Quantity Creation Performance The number narrowing of the default number system is unnecessary and costly. With that change, the CQL expression: define InInitialPopulation: exists from [Observation: Code {system: 'http://loinc.org', code: '39156-5'}] O where O.value as Quantity > 30 'kg/m2' Is over 10 times faster with the following Synthea resource counts: Condition : 130563 Observation : 2716495 Patient : 10000 ------------------------------------------- total : 2857058 --- modules/cql/src/blaze/elm/decimal.clj | 7 +------ modules/cql/src/blaze/elm/integer.clj | 9 ++++----- modules/cql/src/blaze/elm/quantity.clj | 7 +++++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/modules/cql/src/blaze/elm/decimal.clj b/modules/cql/src/blaze/elm/decimal.clj index 64aab93b9..c6dc001c9 100644 --- a/modules/cql/src/blaze/elm/decimal.clj +++ b/modules/cql/src/blaze/elm/decimal.clj @@ -12,8 +12,7 @@ [blaze.anomaly :as ba :refer [throw-anom]] [blaze.elm.protocols :as p]) (:import - [java.math RoundingMode] - [tech.units.indriya.function RationalNumber])) + [java.math RoundingMode])) (set! *warn-on-reflection* true) @@ -284,10 +283,6 @@ BigDecimal (to-decimal [x] x) - RationalNumber - (to-decimal [x] - (.bigDecimalValue x)) - String (to-decimal [s] (when-let [d (try (BigDecimal. s) (catch Exception _))] diff --git a/modules/cql/src/blaze/elm/integer.clj b/modules/cql/src/blaze/elm/integer.clj index b512f755c..cde2597b1 100644 --- a/modules/cql/src/blaze/elm/integer.clj +++ b/modules/cql/src/blaze/elm/integer.clj @@ -86,9 +86,6 @@ ;; 16.13. Modulo (extend-protocol p/Modulo - nil - (modulo [_ _]) - Number (modulo [x div] (try @@ -172,7 +169,8 @@ ;; 22.25. ToInteger (extend-protocol p/ToInteger Integer - (to-integer [x] x) + (to-integer [x] + (long x)) Long (to-integer [x] x) @@ -187,7 +185,8 @@ ;; 22.27. ToLong (extend-protocol p/ToLong Integer - (to-long [x] (long x)) + (to-long [x] + (long x)) Long (to-long [x] x) diff --git a/modules/cql/src/blaze/elm/quantity.clj b/modules/cql/src/blaze/elm/quantity.clj index f855f01a3..7792a56a9 100644 --- a/modules/cql/src/blaze/elm/quantity.clj +++ b/modules/cql/src/blaze/elm/quantity.clj @@ -12,12 +12,19 @@ [javax.measure.format UnitFormat] [javax.measure.spi ServiceProvider] [tech.units.indriya ComparableQuantity] + [tech.units.indriya.function Calculus DefaultNumberSystem] [tech.units.indriya.quantity Quantities])) (set! *warn-on-reflection* true) +(Calculus/setCurrentNumberSystem + (proxy [DefaultNumberSystem] [] + (narrow [number] + number))) + + (def ^:private ^UnitFormat ucum-format (.getUnitFormat (.getFormatService (ServiceProvider/current)) "CASE_SENSITIVE")) From fd7336072df999040480ea76bd09e7b6f9cfec4f Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Wed, 23 Feb 2022 20:55:06 +0100 Subject: [PATCH 04/14] Provide Reader Literal #fhir/instant --- .../fhir-structure/resources/data_readers.clj | 1 + .../src/blaze/fhir/spec/type.clj | 24 ++++++++++- .../test/blaze/fhir/spec/type_test.clj | 40 +++++++++++-------- .../test/blaze/fhir/spec_test.clj | 10 +++-- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/modules/fhir-structure/resources/data_readers.clj b/modules/fhir-structure/resources/data_readers.clj index a1ce9a725..75f2aed21 100644 --- a/modules/fhir-structure/resources/data_readers.clj +++ b/modules/fhir-structure/resources/data_readers.clj @@ -4,6 +4,7 @@ fhir/url blaze.fhir.spec.type/->Url fhir/canonical blaze.fhir.spec.type/->Canonical fhir/base64Binary blaze.fhir.spec.type/->Base64Binary + fhir/instant blaze.fhir.spec.type/->Instant fhir/date blaze.fhir.spec.type/->Date fhir/dateTime blaze.fhir.spec.type/->DateTime fhir/time blaze.fhir.spec.type/->Time diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type.clj b/modules/fhir-structure/src/blaze/fhir/spec/type.clj index 43bbb40ea..b18d2619c 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type.clj @@ -382,12 +382,12 @@ ;; ---- instant --------------------------------------------------------------- -(defn- format-offset-date-time [date-time] +(defn- format-offset-date-time ^String [date-time] (.format DateTimeFormatter/ISO_DATE_TIME date-time)) ;; Implementation of a FHIR instant with a variable ZoneOffset. -(deftype OffsetInstant [^OffsetDateTime value] +(deftype OffsetInstant [value] p/FhirType (-type [_] :fhir/instant) (-value [_] value) @@ -413,6 +413,12 @@ (.serialize OffsetDateTimeSerializer/INSTANCE (.value offset-instant) gen provider)))) +(defmethod print-method OffsetInstant [^OffsetInstant instant ^Writer w] + (.write w "#fhir/instant\"") + (.write w (format-offset-date-time (.value instant))) + (.write w "\"")) + + (extend-protocol p/FhirType Instant (-type [_] :fhir/instant) @@ -425,6 +431,12 @@ (-references [_])) +(defmethod print-method Instant [^Instant instant ^Writer w] + (.write w "#fhir/instant\"") + (.write w (str instant)) + (.write w "\"")) + + (defn ->Instant [s] (cond (str/ends-with? s "Z") (Instant/parse s) @@ -1341,6 +1353,14 @@ (.write w ")")) +(defmethod print-dup Instant [^Instant instant ^Writer w] + (.write w "#=(java.time.Instant/ofEpochSecond ") + (.write w (str (.getEpochSecond instant))) + (.write w " ") + (.write w (str (.getNano instant))) + (.write w ")")) + + (defmethod print-dup YearMonth [^YearMonth yearMonth ^Writer w] (.write w "#=(java.time.YearMonth/of ") (.write w (str (.getYear yearMonth))) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj index c88e728ba..8e9608e65 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj @@ -428,49 +428,55 @@ (is (= Instant/EPOCH (type/xml->Instant (sexp [nil {:value "1970-01-01T00:00:00Z"}]))))) (testing "from JSON" - (is (= Instant/EPOCH (type/->Instant "1970-01-01T00:00:00Z")))) + (is (= Instant/EPOCH #fhir/instant"1970-01-01T00:00:00Z"))) (testing "type" (is (= :fhir/instant - (type/type (type/->Instant "2020-01-01T00:00:00+02:00")))) + (type/type #fhir/instant"2020-01-01T00:00:00+02:00"))) (is (= :fhir/instant (type/type Instant/EPOCH)))) (testing "value is a System.DateTime which is a OffsetDateTime" (is (= (OffsetDateTime/of 2020 1 1 0 0 0 0 (ZoneOffset/ofHours 2)) - (type/value (type/->Instant "2020-01-01T00:00:00+02:00")))) + (type/value #fhir/instant"2020-01-01T00:00:00+02:00"))) (is (= (OffsetDateTime/of 1970 1 1 0 0 0 0 ZoneOffset/UTC) (type/value Instant/EPOCH)))) (testing "to-json" (are [instant json] (= json (gen-json-string instant)) - (type/->Instant "2020-01-01T00:00:00+02:00") "\"2020-01-01T00:00:00+02:00\"" + #fhir/instant"2020-01-01T00:00:00+02:00" "\"2020-01-01T00:00:00+02:00\"" Instant/EPOCH "\"1970-01-01T00:00:00Z\"")) (testing "to-xml" (is (= (sexp [nil {:value "2020-01-01T00:00:00+02:00"}]) - (type/to-xml (type/->Instant "2020-01-01T00:00:00+02:00")))) + (type/to-xml #fhir/instant"2020-01-01T00:00:00+02:00"))) (is (= (sexp [nil {:value "1970-01-01T00:00:00Z"}]) (type/to-xml Instant/EPOCH)))) (testing "equals" - (is (= (type/->Instant "2020-01-01T00:00:00+02:00") - (type/->Instant "2020-01-01T00:00:00+02:00"))) - (is (not= (type/->Instant "2020-01-01T00:00:00+01:00") - (type/->Instant "2020-01-01T00:00:00+02:00"))) - (is (= Instant/EPOCH (type/->Instant "1970-01-01T00:00:00Z"))) - (is (= Instant/EPOCH (type/->Instant "1970-01-01T00:00:00+00:00")))) + (is (= #fhir/instant"2020-01-01T00:00:00+02:00" + #fhir/instant"2020-01-01T00:00:00+02:00")) + (is (not= #fhir/instant"2020-01-01T00:00:00+01:00" + #fhir/instant"2020-01-01T00:00:00+02:00")) + (is (= Instant/EPOCH #fhir/instant"1970-01-01T00:00:00Z")) + (is (= Instant/EPOCH #fhir/instant"1970-01-01T00:00:00+00:00"))) (testing "instance size" (testing "backed by OffsetDateTime, taking into account shared offsets" - (is (= 112 (- (total-size (type/->Instant "2020-01-01T00:00:00+02:00")) + (is (= 112 (- (total-size #fhir/instant"2020-01-01T00:00:00+02:00") (total-size ZoneOffset/UTC))))) (testing "backed by java.time.Instant" (is (= 24 (total-size Instant/EPOCH))))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) - (type/->Instant "2020-01-01T00:00:00+00:00") "d81f6bc2" - (type/->Instant "2020-01-01T00:00:00+01:00") "4225df0d" - (type/->Instant "2020-01-01T00:00:00Z") "d81f6bc2" - (type/->Instant "1970-01-01T00:00:00Z") "93344244" + #fhir/instant"2020-01-01T00:00:00+00:00" "d81f6bc2" + #fhir/instant"2020-01-01T00:00:00+01:00" "4225df0d" + #fhir/instant"2020-01-01T00:00:00Z" "d81f6bc2" + #fhir/instant"1970-01-01T00:00:00Z" "93344244" Instant/EPOCH "93344244")) (testing "references" (are [x refs] (= refs (type/references x)) Instant/EPOCH - nil))) + nil)) + (testing "print" + (are [i s] (= s (pr-str i)) + #fhir/instant"2020-01-01T00:00:00Z" + "#fhir/instant\"2020-01-01T00:00:00Z\"" + #fhir/instant"2020-01-01T00:00:00+01:00" + "#fhir/instant\"2020-01-01T00:00:00+01:00\""))) (deftest date-test diff --git a/modules/fhir-structure/test/blaze/fhir/spec_test.clj b/modules/fhir-structure/test/blaze/fhir/spec_test.clj index 61d4071d2..14a1a79d9 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec_test.clj @@ -4,6 +4,7 @@ [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec-spec] [blaze.fhir.spec.type :as type] + [blaze.test-util :as tu] [clojure.alpha.spec :as s2] [clojure.data.xml.name :as xml-name] [clojure.data.xml.node :as xml-node] @@ -24,6 +25,7 @@ (st/instrument) +(tu/init-fhir-specs) (defn- fixture [f] @@ -717,7 +719,7 @@ (deftest fhir-instant (testing "FHIR spec" (are [s] (s2/valid? :fhir/instant s) - (type/->Instant "2015-02-07T13:28:17.239+02:00"))) + #fhir/instant"2015-02-07T13:28:17.239+02:00")) (testing "JSON spec" (are [s] (s2/valid? :fhir.json/instant s) @@ -727,14 +729,14 @@ (testing "JSON" (are [json fhir] (= fhir (s2/conform :fhir.json/instant json)) "2015-02-07T13:28:17.239+02:00" - (type/->Instant "2015-02-07T13:28:17.239+02:00")))) + #fhir/instant"2015-02-07T13:28:17.239+02:00"))) (testing "unforming" (testing "JSON" (are [fhir json] (= json (unform-json fhir)) - (type/->Instant "2015-02-07T13:28:17.239+02:00") + #fhir/instant"2015-02-07T13:28:17.239+02:00" "\"2015-02-07T13:28:17.239+02:00\"" - (type/->Instant "2015-02-07T13:28:17.239Z") + #fhir/instant"2015-02-07T13:28:17.239Z" "\"2015-02-07T13:28:17.239Z\"")))) From d5514b71b4684dc917d1b3e9e0ec7fd57dde1817 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Thu, 24 Feb 2022 19:23:23 +0100 Subject: [PATCH 05/14] Start Implementing Compiled Query Forms The ELM compiler compiles ELM data structures into data structures that can be evaluated on a database. That compiled data structures consisted mostly of Clojure records. Printing that data structures can be useful in order to see something like a query plan. However, Clojure records don't always print very nice and some used opaque functions do not print at all. So we introduce compiled query forms that can be obtained by calling the -form method for now and a form function later. The forms are modeled in the LISP tradition and can be printed or even pretty-printed. The implementation is far from complete now. --- .../scripts/evaluate-measure-subject-list.sh | 2 +- .github/workflows/build.yml | 64 ++- modules/cql/src/blaze/cql_translator_spec.clj | 5 +- modules/cql/src/blaze/elm/compiler.clj | 4 + .../elm/compiler/arithmetic_operators.clj | 18 +- modules/cql/src/blaze/elm/compiler/core.clj | 15 +- .../src/blaze/elm/compiler/external_data.clj | 12 +- .../blaze/elm/compiler/interval_operators.clj | 7 +- .../blaze/elm/compiler/logical_operators.clj | 238 ++++----- modules/cql/src/blaze/elm/compiler/macros.clj | 168 +++--- .../cql/src/blaze/elm/compiler/parameters.clj | 4 +- .../cql/src/blaze/elm/compiler/queries.clj | 23 +- .../src/blaze/elm/compiler/reusing_logic.clj | 22 +- .../blaze/elm/compiler/structured_values.clj | 12 +- .../src/blaze/elm/compiler/type_operators.clj | 35 +- modules/cql/src/blaze/elm/date_time.clj | 13 +- modules/cql/src/blaze/elm/decimal.clj | 3 +- .../elm/compiler/aggregate_operators_test.clj | 76 +-- .../compiler/arithmetic_operators_test.clj | 481 ++++++++++-------- .../elm/compiler/clinical_operators_test.clj | 8 +- .../elm/compiler/clinical_values_test.clj | 48 +- .../compiler/comparison_operators_test.clj | 388 ++++---------- .../compiler/conditional_operators_test.clj | 12 +- .../elm/compiler/date_time_operators_test.clj | 279 +++++----- .../blaze/elm/compiler/external_data_test.clj | 44 +- .../elm/compiler/interval_operators_test.clj | 394 +++++++------- .../elm/compiler/list_operators_test.clj | 116 +++-- .../elm/compiler/logical_operators_test.clj | 251 +++++---- .../compiler/nullological_operators_test.clj | 42 +- .../blaze/elm/compiler/parameters_test.clj | 13 +- .../test/blaze/elm/compiler/queries_test.clj | 166 +++--- .../blaze/elm/compiler/reusing_logic_test.clj | 120 +++-- .../blaze/elm/compiler/simple_values_test.clj | 42 +- .../elm/compiler/string_operators_test.clj | 168 +++--- .../elm/compiler/structured_values_test.clj | 25 +- .../cql/test/blaze/elm/compiler/test_util.clj | 71 ++- .../elm/compiler/type_operators_test.clj | 162 ++++-- modules/cql/test/blaze/elm/literal.clj | 130 ++++- modules/cql/test/blaze/elm/literal_spec.clj | 212 ++++---- .../cql/test/blaze/elm/normalizer_test.clj | 1 + modules/cql/test/blaze/elm/spec_test.clj | 36 +- modules/cql/test/data_readers.clj | 12 + .../blaze/db/impl/search_param/date_test.clj | 3 +- 43 files changed, 2216 insertions(+), 1729 deletions(-) diff --git a/.github/scripts/evaluate-measure-subject-list.sh b/.github/scripts/evaluate-measure-subject-list.sh index 128d2ab65..b4506f737 100755 --- a/.github/scripts/evaluate-measure-subject-list.sh +++ b/.github/scripts/evaluate-measure-subject-list.sh @@ -103,7 +103,7 @@ evaluate-measure() { } fetch-patients() { - curl -s "$1/Patient?_list=$2&_count=100" + curl -s "$1/Patient?_list=$2&_count=200" } BASE="http://localhost:8080/fhir" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1d10f2986..08da2488d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -304,7 +304,7 @@ jobs: run: .github/scripts/check-total-number-of-resources.sh 92114 - name: Count Resources - run: blazectl --no-progress --server http://localhost:8080/fhir count-resources + run: blazectl count-resources --server http://localhost:8080/fhir - name: Download Patient Resources run: .github/scripts/download-resources.sh Patient @@ -372,6 +372,12 @@ jobs: - name: Evaluate CQL Query 2 - Subject List run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q2-query.cql 42 + - name: Evaluate CQL Query 4 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q4-query.cql 0 + + - name: Evaluate CQL Query 4 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q4-query.cql 0 + - name: Evaluate CQL Query 7 run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q7-query.cql 81 @@ -384,6 +390,30 @@ jobs: - name: Evaluate CQL Query 14 - Subject List run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q14-query.cql 96 + - name: Evaluate CQL Query 15 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q15-query.cql 31 + + - name: Evaluate CQL Query 15 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q15-query.cql 31 + + - name: Evaluate CQL Query 17 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q17-query.cql 120 + + - name: Evaluate CQL Query 17 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q17-query.cql 120 + + - name: Evaluate CQL Query 36 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q36-parameter-query.cql 86 + + - name: Evaluate CQL Query 36 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q36-parameter-query.cql 86 + + - name: Evaluate CQL Query 34 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q37-overlaps-query.cql 24 + + - name: Evaluate CQL Query 34 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q37-overlaps-query.cql 24 + - name: Forwarded Header HTTPS run: .github/scripts/forwarded-header.sh https @@ -658,7 +688,7 @@ jobs: run: .github/scripts/check-total-number-of-resources.sh 92114 - name: Count Resources - run: blazectl --no-progress --server http://localhost:8080/fhir count-resources + run: blazectl count-resources --server http://localhost:8080/fhir - name: Download Patient Resources run: .github/scripts/download-resources.sh Patient @@ -726,6 +756,12 @@ jobs: - name: Evaluate CQL Query 2 - Subject List run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q2-query.cql 42 + - name: Evaluate CQL Query 4 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q4-query.cql 0 + + - name: Evaluate CQL Query 4 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q4-query.cql 0 + - name: Evaluate CQL Query 7 run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q7-query.cql 81 @@ -738,6 +774,30 @@ jobs: - name: Evaluate CQL Query 14 - Subject List run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q14-query.cql 96 + - name: Evaluate CQL Query 15 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q15-query.cql 31 + + - name: Evaluate CQL Query 15 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q15-query.cql 31 + + - name: Evaluate CQL Query 17 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q17-query.cql 120 + + - name: Evaluate CQL Query 17 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q17-query.cql 120 + + - name: Evaluate CQL Query 36 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q36-parameter-query.cql 86 + + - name: Evaluate CQL Query 36 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q36-parameter-query.cql 86 + + - name: Evaluate CQL Query 34 + run: .github/scripts/evaluate-measure.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q37-overlaps-query.cql 24 + + - name: Evaluate CQL Query 34 - Subject List + run: .github/scripts/evaluate-measure-subject-list.sh modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q37-overlaps-query.cql 24 + - name: Forwarded Header HTTPS run: .github/scripts/forwarded-header.sh https diff --git a/modules/cql/src/blaze/cql_translator_spec.clj b/modules/cql/src/blaze/cql_translator_spec.clj index acbb573e0..a4f3c4193 100644 --- a/modules/cql/src/blaze/cql_translator_spec.clj +++ b/modules/cql/src/blaze/cql_translator_spec.clj @@ -3,9 +3,10 @@ [blaze.anomaly-spec] [blaze.cql-translator :as cql-translator] [blaze.elm.spec] - [clojure.spec.alpha :as s])) + [clojure.spec.alpha :as s] + [cognitect.anomalies :as anom])) (s/fdef cql-translator/translate :args (s/cat :cql string? :opts (s/* some?)) - :ret :elm/library) + :ret (s/or :library :elm/library :anomaly ::anom/anomaly)) diff --git a/modules/cql/src/blaze/elm/compiler.clj b/modules/cql/src/blaze/elm/compiler.clj index 2b766f22d..5f3679dce 100644 --- a/modules/cql/src/blaze/elm/compiler.clj +++ b/modules/cql/src/blaze/elm/compiler.clj @@ -42,3 +42,7 @@ Use `compile-library` to compile a whole library." [context expression] (core/compile* context expression)) + + +(defn form [expression] + (core/-form expression)) diff --git a/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj b/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj index c4c650e8c..ee9dc7197 100644 --- a/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj @@ -129,20 +129,20 @@ ;; 16.19. Round -(defrecord RoundOperatorExpression [operand precision] - core/Expression - (-eval [_ context resource scope] - (p/round (core/-eval operand context resource scope) - (core/-eval precision context resource scope)))) - - (defmethod core/compile* :elm.compiler.type/round [context {:keys [operand precision]}] (let [operand (core/compile* context operand) - precision (or (some->> precision (core/compile* context)) 0)] + precision (some->> precision (core/compile* context))] (if (and (core/static? operand) (core/static? precision)) (p/round operand precision) - (->RoundOperatorExpression operand precision)))) + (reify core/Expression + (-eval [_ context resource scope] + (p/round (core/-eval operand context resource scope) + (core/-eval precision context resource scope))) + (-form [_] + (->> (some-> (core/-form precision) list) + (cons (core/-form operand)) + (cons 'round))))))) ;; 16.20. Subtract diff --git a/modules/cql/src/blaze/elm/compiler/core.clj b/modules/cql/src/blaze/elm/compiler/core.clj index 50e7b7ad8..ef4694cd7 100644 --- a/modules/cql/src/blaze/elm/compiler/core.clj +++ b/modules/cql/src/blaze/elm/compiler/core.clj @@ -14,7 +14,8 @@ (defprotocol Expression (-eval [expression context resource scope] "Evaluates `expression` on `resource` using `context` and optional `scope` - for scoped expressions like inside queries.")) + for scoped expressions like inside queries.") + (-form [expression])) (defn expr? [x] @@ -23,12 +24,16 @@ (extend-protocol Expression nil - (-eval [this _ _ _] - this) + (-eval [expr _ _ _] + expr) + (-form [_] + 'nil) Object - (-eval [this _ _ _] - this)) + (-eval [expr _ _ _] + expr) + (-form [expr] + expr)) (defn static? [x] diff --git a/modules/cql/src/blaze/elm/compiler/external_data.clj b/modules/cql/src/blaze/elm/compiler/external_data.clj index 2ff3c73c4..6ec02e6e4 100644 --- a/modules/cql/src/blaze/elm/compiler/external_data.clj +++ b/modules/cql/src/blaze/elm/compiler/external_data.clj @@ -21,10 +21,12 @@ (d/list-compartment-resource-handles db context id data-type))) -(defrecord CompartmentQueryRetrieveExpression [query] +(defrecord CompartmentQueryRetrieveExpression [query data-type clauses] core/Expression (-eval [_ {:keys [db]} {:keys [id]} _] - (d/execute-query db query id))) + (d/execute-query db query id)) + (-form [_] + `(~'compartment-query-retrieve ~data-type ~clauses))) (defn- code->clause-value [{:keys [system code]}] @@ -45,7 +47,7 @@ [node context data-type property codes] (let [clauses [(into [property] (map code->clause-value) codes)] query (d/compile-compartment-query node context data-type clauses)] - (->CompartmentQueryRetrieveExpression query))) + (->CompartmentQueryRetrieveExpression query data-type clauses))) (defn- split-reference [s] @@ -155,7 +157,9 @@ (if (empty? codes) (reify core/Expression (-eval [_ {:keys [db]} _ _] - (into [] (d/type-list db data-type)))) + (into [] (d/type-list db data-type))) + (-form [_] + `(~'retrieve ~data-type))) (let [clauses [(into [code-property] (map code->clause-value) codes)]] (if-ok [query (d/compile-type-query node data-type clauses)] (reify core/Expression diff --git a/modules/cql/src/blaze/elm/compiler/interval_operators.clj b/modules/cql/src/blaze/elm/compiler/interval_operators.clj index 355d2eb7c..c680697cc 100644 --- a/modules/cql/src/blaze/elm/compiler/interval_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/interval_operators.clj @@ -118,7 +118,7 @@ ;; 19.7. Ends -(defbinop ends [x y _] +(defbinopp ends [x y _] (and (p/greater-or-equal (:start x) (:start y)) (p/equal (:end x) (:end y)))) @@ -128,6 +128,9 @@ (p/except x y)) +;; TODO 19.11. Expand + + ;; 19.12. In (defmethod core/compile* :elm.compiler.type/in [_ _] @@ -221,7 +224,7 @@ ;; 19.30. Starts -(defbinop starts [x y _] +(defbinopp starts [x y _] (and (p/equal (:start x) (:start y)) (p/less-or-equal (:end x) (:end y)))) diff --git a/modules/cql/src/blaze/elm/compiler/logical_operators.clj b/modules/cql/src/blaze/elm/compiler/logical_operators.clj index 81abbf626..a7dc5ff92 100644 --- a/modules/cql/src/blaze/elm/compiler/logical_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/logical_operators.clj @@ -9,50 +9,53 @@ ;; 13.1. And - -;; static-a is either true or nil but not false -(defrecord StaticAndOperatorExpression [static-a b] - core/Expression - (-eval [_ context resource scope] - (let [b (core/-eval b context resource scope)] - (cond - (false? b) false - (and (true? static-a) (true? b)) true)))) - - -(defn- and-static [static-a b] - (if (core/static? b) - (cond - (false? b) false - (and (true? static-a) (true? b)) true) - (->StaticAndOperatorExpression static-a b))) - - -(defrecord AndOperatorExpression [a b] - core/Expression - (-eval [_ context resource scope] - (let [a (core/-eval a context resource scope)] - (if (false? a) - false - (let [b (core/-eval b context resource scope)] - (cond - (false? b) false - (and (true? a) (true? b)) true)))))) +(defn- nil-and-expr [x] + (reify core/Expression + (-eval [_ context resource scope] + (when (false? (core/-eval x context resource scope)) + false)) + (-form [_] + (list 'and nil (core/-form x))))) + + +(defn- nil-and + "Creates an and-expression where one operand is known to be nil." + [x] + (case x + (true nil) nil + false false + (nil-and-expr x))) + + +(defn- dynamic-and + "Creates an and-expression where `a` is known to be dynamic and `b` could be + static or dynamic." + [a b] + (case b + true a + false false + nil (nil-and-expr a) + (reify core/Expression + (-eval [_ context resource scope] + (let [a (core/-eval a context resource scope)] + (if (false? a) + false + (let [b (core/-eval b context resource scope)] + (cond + (false? b) false + (and (true? a) (true? b)) true))))) + (-form [_] + (list 'and (core/-form a) (core/-form b)))))) (defmethod core/compile* :elm.compiler.type/and [context {[a b] :operand}] (let [a (core/compile* context a)] - (if (core/static? a) - (if (false? a) - false - (and-static a (core/compile* context b))) - (let [b (core/compile* context b)] - (if (core/static? b) - (if (false? b) - false - (and-static b a)) - (->AndOperatorExpression a b)))))) + (case a + true (core/compile* context b) + false false + nil (nil-and (core/compile* context b)) + (dynamic-and a (core/compile* context b))))) ;; 13.2 Implies @@ -68,104 +71,85 @@ ;; 13.4. Or - -;; static-a is either false or nil but not true -(defrecord StaticOrOperatorExpression [static-a b] - core/Expression - (-eval [_ context resource scope] - (let [b (core/-eval b context resource scope)] - (cond - (true? b) true - (and (false? static-a) (false? b)) false)))) - - -(defn- or-static [static-a b] - (if (core/static? b) - (cond - (true? b) true - (and (false? static-a) (false? b)) false) - (->StaticOrOperatorExpression static-a b))) - - -(defrecord OrOperatorExpression [a b] - core/Expression - (-eval [_ context resource scope] - (let [a (core/-eval a context resource scope)] - (if (true? a) - true - (let [b (core/-eval b context resource scope)] - (cond - (true? b) true - (and (false? a) (false? b)) false)))))) +(defn- nil-or-expr [x] + (reify core/Expression + (-eval [_ context resource scope] + (when (true? (core/-eval x context resource scope)) + true)) + (-form [_] + (list 'or nil (core/-form x))))) + + +(defn- nil-or + "Creates an or-expression where one operand is known to be nil." + [x] + (case x + true true + (false nil) nil + (nil-or-expr x))) + + +(defn- dynamic-or + "Creates an or-expression where `a` is known to be dynamic and `b` could be + static or dynamic." + [a b] + (case b + true true + false a + nil (nil-or-expr a) + (reify core/Expression + (-eval [_ context resource scope] + (let [a (core/-eval a context resource scope)] + (if (true? a) + true + (let [b (core/-eval b context resource scope)] + (cond + (true? b) true + (and (false? a) (false? b)) false))))) + (-form [_] + (list 'or (core/-form a) (core/-form b)))))) (defmethod core/compile* :elm.compiler.type/or [context {[a b] :operand}] (let [a (core/compile* context a)] - (if (core/static? a) - (if (true? a) - true - (or-static a (core/compile* context b))) - (let [operand-2 (core/compile* context b)] - (if (core/static? operand-2) - (if (true? operand-2) - true - (or-static operand-2 a)) - (->OrOperatorExpression a operand-2)))))) + (case a + true true + false (core/compile* context b) + nil (nil-or (core/compile* context b)) + (dynamic-or a (core/compile* context b))))) ;; 13.5 Xor -(defrecord StaticXOrOperatorExpression [static-a b] - core/Expression - (-eval [_ context resource scope] - (let [b (core/-eval b context resource scope)] - (cond - (or (and (true? static-a) (true? b)) - (and (false? static-a) (false? b))) - false - (or (and (true? static-a) (false? b)) - (and (false? static-a) (true? b))) - true)))) - - -(defn- xor-static [static-a b] - (if (core/static? b) - (cond - (or (and (true? static-a) (true? b)) - (and (false? static-a) (false? b))) - false - (or (and (true? static-a) (false? b)) - (and (false? static-a) (true? b))) - true) - (->StaticXOrOperatorExpression static-a b))) - - -(defrecord XOrOperatorExpression [a b] - core/Expression - (-eval [_ context resource scope] - (let [a (core/-eval a context resource scope)] - (if (nil? a) - nil - (let [b (core/-eval b context resource scope)] - (cond - (or (and (true? a) (true? b)) - (and (false? a) (false? b))) - false - (or (and (true? a) (false? b)) - (and (false? a) (true? b))) - true)))))) +(defn- dynamic-xor + "Creates an xor-expression where `a` is known to be dynamic and `b` could be + static or dynamic." + [a b] + (case b + true + (reify core/Expression + (-eval [_ context resource scope] + (let [a (core/-eval a context resource scope)] + (when (some? a) + (not a)))) + (-form [_] + (list 'not (core/-form a)))) + false a + nil nil + (reify core/Expression + (-eval [_ context resource scope] + (when-some [a (core/-eval a context resource scope)] + (when-some [b (core/-eval b context resource scope)] + (if a (not b) b)))) + (-form [_] + (list 'xor (core/-form a) (core/-form b)))))) (defmethod core/compile* :elm.compiler.type/xor [context {[a b] :operand}] (let [a (core/compile* context a)] - (if (core/static? a) - (if (nil? a) - nil - (xor-static a (core/compile* context b))) - (let [b (core/compile* context b)] - (if (core/static? b) - (if (nil? b) - nil - (xor-static b a)) - (->XOrOperatorExpression a b)))))) + (case a + true (core/compile* context {:type "Not" :operand b}) + false (core/compile* context b) + nil nil + (dynamic-xor a (core/compile* context b))))) diff --git a/modules/cql/src/blaze/elm/compiler/macros.clj b/modules/cql/src/blaze/elm/compiler/macros.clj index 982ab29a5..b20cce95d 100644 --- a/modules/cql/src/blaze/elm/compiler/macros.clj +++ b/modules/cql/src/blaze/elm/compiler/macros.clj @@ -1,11 +1,6 @@ (ns blaze.elm.compiler.macros (:require - [blaze.elm.compiler.core :as core] - [cuerdas.core :as cuerdas])) - - -(defn- record-name [s] - (str (cuerdas/capital (cuerdas/camel (name s))) "OperatorExpression")) + [blaze.elm.compiler.core :as core])) (defmacro defunop @@ -14,30 +9,33 @@ (let [attr-map (when (map? (first more)) (first more)) more (if (map? (first more)) (next more) more) [[operand-binding expr-binding] & body] more] - `(do - ~(if expr-binding - `(defrecord ~(symbol (record-name name)) [~'operand ~'expr] - core/Expression - (-eval [~'_ context# resource# scope#] - (let [~operand-binding (core/-eval ~'operand context# resource# scope#) - ~expr-binding ~'expr] - ~@body))) - `(defrecord ~(symbol (record-name name)) [~'operand] - core/Expression - (-eval [~'_ context# resource# scope#] - (let [~operand-binding (core/-eval ~'operand context# resource# scope#)] - ~@body)))) - - (defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) - [context# ~'expr] - (let [~'operand (core/compile* (merge context# ~attr-map) (:operand ~'expr))] - (if (core/static? ~'operand) - (let [~operand-binding ~'operand - ~(or expr-binding '_) ~'expr] + (if expr-binding + `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + [context# expr#] + (let [operand# (core/compile* (merge context# ~attr-map) (:operand expr#))] + (if (core/static? operand#) + (let [~operand-binding operand# + ~expr-binding expr#] ~@body) - ~(if expr-binding - `(~(symbol (str "->" (record-name name))) ~'operand ~'expr) - `(~(symbol (str "->" (record-name name))) ~'operand)))))))) + (reify core/Expression + (-eval [~'_ context# resource# scope#] + (let [~operand-binding (core/-eval operand# context# resource# scope#) + ~expr-binding expr#] + ~@body)) + (-form [~'_] + (list (quote ~name) (core/-form operand#))))))) + `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + [context# expr#] + (let [operand# (core/compile* (merge context# ~attr-map) (:operand expr#))] + (if (core/static? operand#) + (let [~operand-binding operand#] + ~@body) + (reify core/Expression + (-eval [~'_ context# resource# scope#] + (let [~operand-binding (core/-eval operand# context# resource# scope#)] + ~@body)) + (-form [~'_] + (list (quote ~name) (core/-form operand#)))))))))) (defmacro defbinop @@ -46,22 +44,22 @@ (let [attr-map (when (map? (first more)) (first more)) more (if (map? (first more)) (next more) more) [[op-1-binding op-2-binding] & body] more] - `(do - (defrecord ~(symbol (record-name name)) [~'operand-1 ~'operand-2] - core/Expression - (-eval [~'_ context# resource# scope#] - (let [~op-1-binding (core/-eval ~'operand-1 context# resource# scope#) - ~op-2-binding (core/-eval ~'operand-2 context# resource# scope#)] - ~@body))) - - (defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) - [context# {[operand-1# operand-2#] :operand}] - (let [context# (merge context# ~attr-map) - ~op-1-binding (core/compile* context# operand-1#) - ~op-2-binding (core/compile* context# operand-2#)] - (if (and (core/static? ~op-1-binding) (core/static? ~op-2-binding)) - ~@body - (~(symbol (str "->" (record-name name))) ~op-1-binding ~op-2-binding))))))) + `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + [context# {[operand-1# operand-2#] :operand}] + (let [context# (merge context# ~attr-map) + operand-1# (core/compile* context# operand-1#) + operand-2# (core/compile* context# operand-2#)] + (if (and (core/static? operand-1#) (core/static? operand-2#)) + (let [~op-1-binding operand-1# + ~op-2-binding operand-2#] + ~@body) + (reify core/Expression + (-eval [~'_ context# resource# scope#] + (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) + ~op-2-binding (core/-eval operand-2# context# resource# scope#)] + ~@body)) + (-form [~'_] + (list (quote ~name) (core/-form operand-1#) (core/-form operand-2#))))))))) (defmacro defternop @@ -83,17 +81,13 @@ (defmacro defnaryop {:arglists '([name bindings & body])} [name [operands-binding] & body] - `(do - (defrecord ~(symbol (record-name name)) [~'operands] - core/Expression - (-eval [~'_ context# resource# scope#] - (let [~operands-binding (mapv #(core/-eval % context# resource# scope#) ~'operands)] - ~@body))) - - (defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) - [context# {~'operands :operand}] - (let [~'operands (mapv #(core/compile* context# %) ~'operands)] - (~(symbol (str "->" (record-name name))) ~'operands))))) + `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + [context# {operands# :operand}] + (let [operands# (mapv #(core/compile* context# %) operands#)] + (reify core/Expression + (-eval [~'_ context# resource# scope#] + (let [~operands-binding (mapv #(core/-eval % context# resource# scope#) operands#)] + ~@body)))))) (defmacro defaggop @@ -108,36 +102,6 @@ ~@body)))))) -(defmacro defbinopp - {:arglists '([name attr-map? bindings & body])} - [name & more] - (let [attr-map (when (map? (first more)) (first more)) - more (if (map? (first more)) (next more) more) - [[op-1-binding op-2-binding precision-binding] & body] more] - `(do - (defrecord ~(symbol (record-name name)) [~'operand-1 ~'operand-2 ~'precision] - core/Expression - (-eval [~'_ context# resource# scope#] - (let [~op-1-binding (core/-eval ~'operand-1 context# resource# scope#) - ~op-2-binding (core/-eval ~'operand-2 context# resource# scope#) - ~precision-binding ~'precision] - ~@body))) - - (defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) - [context# {[operand-1# operand-2#] :operand precision# :precision}] - (let [context# (merge context# ~attr-map) - operand-1# (core/compile* context# operand-1#) - operand-2# (core/compile* context# operand-2#) - precision# (some-> precision# core/to-chrono-unit)] - (if (and (core/static? operand-1#) (core/static? operand-2#)) - (let [~op-1-binding operand-1# - ~op-2-binding operand-2# - ~precision-binding precision#] - ~@body) - (~(symbol (str "->" (record-name name))) - operand-1# operand-2# precision#))))))) - - (defmacro defunopp {:arglists '([name bindings & body])} [name [operand-binding precision-binding expr-binding] & body] @@ -149,4 +113,34 @@ (reify core/Expression (-eval [~'_ context# resource# scope#] (let [~operand-binding (core/-eval operand# context# resource# scope#)] - ~@body)))))) + ~@body)) + (-form [~'_] + (list (quote ~name) (core/-form operand#) precision#)))))) + + +(defmacro defbinopp + {:arglists '([name attr-map? bindings & body])} + [name & more] + (let [attr-map (when (map? (first more)) (first more)) + more (if (map? (first more)) (next more) more) + [[op-1-binding op-2-binding precision-binding] & body] more] + `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + [context# {[operand-1# operand-2#] :operand precision# :precision}] + (let [context# (merge context# ~attr-map) + operand-1# (core/compile* context# operand-1#) + operand-2# (core/compile* context# operand-2#) + chrono-precision# (some-> precision# core/to-chrono-unit)] + (if (and (core/static? operand-1#) (core/static? operand-2#)) + (let [~op-1-binding operand-1# + ~op-2-binding operand-2# + ~precision-binding chrono-precision#] + ~@body) + (reify core/Expression + (-eval [~'_ context# resource# scope#] + (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) + ~op-2-binding (core/-eval operand-2# context# resource# scope#) + ~precision-binding chrono-precision#] + ~@body)) + (-form [~'_] + (list (quote ~name) (core/-form operand-1#) (core/-form operand-2#) + precision#)))))))) diff --git a/modules/cql/src/blaze/elm/compiler/parameters.clj b/modules/cql/src/blaze/elm/compiler/parameters.clj index 100ecbe53..2789f37ce 100644 --- a/modules/cql/src/blaze/elm/compiler/parameters.clj +++ b/modules/cql/src/blaze/elm/compiler/parameters.clj @@ -26,7 +26,9 @@ (let [value (get parameters name ::not-found)] (if (identical? ::not-found value) (throw-anom (parameter-value-not-found-anom context name)) - value)))) + value))) + (-form [_] + `(~'param-ref ~name))) (defn- find-parameter-def diff --git a/modules/cql/src/blaze/elm/compiler/queries.clj b/modules/cql/src/blaze/elm/compiler/queries.clj index e57d76775..fcf465382 100644 --- a/modules/cql/src/blaze/elm/compiler/queries.clj +++ b/modules/cql/src/blaze/elm/compiler/queries.clj @@ -20,7 +20,8 @@ (defprotocol XformFactory (-create [_ context resource] - "Creates a xform which filters and/or shapes query sources.")) + "Creates a xform which filters and/or shapes query sources.") + (-form [_])) (defrecord WithXformFactory @@ -56,7 +57,9 @@ (defrecord WhereXformFactory [expr] XformFactory (-create [_ context resource] - (filter #(core/-eval expr context resource %)))) + (filter #(core/-eval expr context resource %))) + (-form [_] + `(~'where ~(core/-form expr)))) (defn- where-xform-factory [expr] @@ -72,7 +75,9 @@ (defrecord DistinctXformFactory [] XformFactory (-create [_ _ _] - (distinct))) + (distinct)) + (-form [_] + 'distinct)) (defrecord ComposedDistinctXformFactory [xform-factory] @@ -96,7 +101,9 @@ (defrecord ComposedXformFactory [factories] XformFactory (-create [_ context resource] - (transduce (map #(-create % context resource)) comp factories))) + (transduce (map #(-create % context resource)) comp factories)) + (-form [_] + `(~'comp ~@(map -form factories)))) (defn- xform-factory @@ -125,7 +132,9 @@ (-eval [_ context resource scope] (coll/eduction (-create xform-factory context resource) - (core/-eval source context resource scope)))) + (core/-eval source context resource scope))) + (-form [_] + `(~'eduction-query ~(-form xform-factory) ~(core/-form source)))) (defn- eduction-expr [xform-factory source] @@ -138,7 +147,9 @@ (into [] (-create xform-factory context resource) - (core/-eval source context resource scope)))) + (core/-eval source context resource scope))) + (-form [_] + `(~'vector-query ~(-form xform-factory) ~(core/-form source)))) (defn- into-vector-expr [xform-factory source] diff --git a/modules/cql/src/blaze/elm/compiler/reusing_logic.clj b/modules/cql/src/blaze/elm/compiler/reusing_logic.clj index cbc23cd32..8100b5678 100644 --- a/modules/cql/src/blaze/elm/compiler/reusing_logic.clj +++ b/modules/cql/src/blaze/elm/compiler/reusing_logic.clj @@ -35,7 +35,9 @@ (let [expr (get library-context name ::not-found)] (if (identical? ::not-found expr) (throw-anom (expression-not-found-anom context name)) - (core/-eval expr context resource nil))))) + (core/-eval expr context resource nil)))) + (-form [_] + `(~'expr-ref ~name))) (defn- find-expression-def @@ -98,7 +100,9 @@ (defrecord ToQuantityFunctionExpression [operand] core/Expression (-eval [_ context resource scope] - (-to-quantity (core/-eval operand context resource scope)))) + (-to-quantity (core/-eval operand context resource scope))) + (-form [_] + `(~'call "ToQuantity" ~(core/-form operand)))) (defrecord ToCodeFunctionExpression [operand] @@ -117,13 +121,17 @@ (defrecord ToDateTimeFunctionExpression [operand] core/Expression (-eval [_ {:keys [now] :as context} resource scope] - (p/to-date-time (core/-eval operand context resource scope) now))) + (p/to-date-time (core/-eval operand context resource scope) now)) + (-form [_] + `(~'call "ToDateTime" ~(core/-form operand)))) (defrecord ToStringFunctionExpression [operand] core/Expression (-eval [_ context resource scope] - (str (core/-eval operand context resource scope)))) + (str (core/-eval operand context resource scope))) + (-form [_] + `(~'call "ToString" ~(core/-form operand)))) (defprotocol ToInterval @@ -144,14 +152,16 @@ (defrecord ToIntervalFunctionExpression [operand] core/Expression (-eval [_ context resource scope] - (-to-interval (core/-eval operand context resource scope) context))) + (-to-interval (core/-eval operand context resource scope) context)) + (-form [_] + `(~'call "ToInterval" ~(core/-form operand)))) ;; 9.4. FunctionRef (defmethod core/compile* :elm.compiler.type/function-ref [context {:keys [name] operands :operand}] ;; TODO: look into other libraries (:libraryName) - (let [operands (mapv #(core/compile* context %) operands)] + (let [operands (map #(core/compile* context %) operands)] (case name "ToQuantity" (->ToQuantityFunctionExpression (first operands)) diff --git a/modules/cql/src/blaze/elm/compiler/structured_values.clj b/modules/cql/src/blaze/elm/compiler/structured_values.clj index f7336297f..e86e738f3 100644 --- a/modules/cql/src/blaze/elm/compiler/structured_values.clj +++ b/modules/cql/src/blaze/elm/compiler/structured_values.clj @@ -92,19 +92,25 @@ (defrecord SourcePropertyExpression [source key] core/Expression (-eval [_ {:keys [db] :as context} resource scope] - (get-property db key (core/-eval source context resource scope)))) + (get-property db key (core/-eval source context resource scope))) + (-form [_] + `(~key ~(core/-form source)))) (defrecord SingleScopePropertyExpression [key] core/Expression (-eval [_ {:keys [db]} _ value] - (get-property db key value))) + (get-property db key value)) + (-form [_] + `(~key ~'default))) (defrecord ScopePropertyExpression [scope-key key] core/Expression (-eval [_ {:keys [db]} _ scope] - (get-property db key (get scope scope-key)))) + (get-property db key (get scope scope-key))) + (-form [_] + `(~key ~(symbol (name scope-key))))) (defn- path->key [path] diff --git a/modules/cql/src/blaze/elm/compiler/type_operators.clj b/modules/cql/src/blaze/elm/compiler/type_operators.clj index 36d25b899..1aad04a51 100644 --- a/modules/cql/src/blaze/elm/compiler/type_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/type_operators.clj @@ -16,27 +16,22 @@ ;; 22.1. As -;; -;; The As operator allows the result of an expression to be cast as a given -;; target type. This allows expressions to be written that are statically typed -;; against the expected run-time type of the argument. If the argument is not of -;; the specified type, and the strict attribute is false (the default), the -;; result is null. If the argument is not of the specified type and the strict -;; attribute is true, an exception is thrown. -(defrecord AsExpression [operand matches-type?] +(defrecord AsExpression [operand type pred] core/Expression (-eval [_ context resource scope] (let [value (core/-eval operand context resource scope)] - (when (matches-type? value) - value)))) + (when (pred value) + value))) + (-form [_] + `(~'as ~type ~(core/-form operand)))) (defn- matches-elm-named-type-fn [type-name] (case type-name - "Boolean" boolean? - "Integer" int? - "DateTime" date-time/temporal? - "Quantity" quantity/quantity? + "Boolean" ['elm/boolean boolean?] + "Integer" ['elm/integer int?] + "DateTime" ['elm/date-time date-time/temporal?] + "Quantity" ['elm/quantity quantity/quantity?] (throw-anom (ba/unsupported (format "Unsupported ELM type `%s` in As expression." type-name) @@ -47,7 +42,7 @@ (let [[type-ns type-name] (elm-util/parse-qualified-name type-name)] (case type-ns "http://hl7.org/fhir" - (comp #{(keyword "fhir" type-name)} fhir-spec/fhir-type) + [(symbol "fhir" type-name) (comp #{(keyword "fhir" type-name)} fhir-spec/fhir-type)] "urn:hl7-org:elm-types:r1" (matches-elm-named-type-fn type-name) (throw-anom @@ -62,9 +57,10 @@ (matches-named-type-fn (:name as-type-specifier)) "ListTypeSpecifier" - (let [pred (matches-type-specifier-fn (:elementType as-type-specifier))] - (fn matches-type? [x] - (every? pred x))) + (let [[type pred] (matches-type-specifier-fn (:elementType as-type-specifier))] + [`(~'list ~type) + (fn matches-type? [x] + (every? pred x))]) (throw-anom (ba/unsupported @@ -92,7 +88,8 @@ (defmethod core/compile* :elm.compiler.type/as [context {:keys [operand] :as expression}] (when-some [operand (core/compile* context operand)] - (->AsExpression operand (matches-type-fn expression)))) + (let [[type pred] (matches-type-fn expression)] + (->AsExpression operand type pred)))) ;; TODO 22.2. CanConvert diff --git a/modules/cql/src/blaze/elm/date_time.clj b/modules/cql/src/blaze/elm/date_time.clj index 15e8bf2ad..bd8670094 100644 --- a/modules/cql/src/blaze/elm/date_time.clj +++ b/modules/cql/src/blaze/elm/date_time.clj @@ -6,11 +6,13 @@ (:require [blaze.anomaly :as ba :refer [throw-anom]] [blaze.elm.protocols :as p] + [blaze.fhir.spec.type] [blaze.fhir.spec.type.system :as system] [java-time :as time]) (:import + [blaze.fhir.spec.type OffsetInstant] [blaze.fhir.spec.type.system DateTimeYear DateTimeYearMonth DateTimeYearMonthDay] - [java.time LocalDate LocalDateTime LocalTime OffsetDateTime Year YearMonth] + [java.time LocalDate LocalDateTime LocalTime OffsetDateTime Year YearMonth Instant] [java.time.temporal ChronoField ChronoUnit Temporal TemporalAccessor] [java.util Map])) @@ -1279,6 +1281,15 @@ nil (to-date-time [_ _]) + Instant + (to-date-time [this now] + (-> (.atOffset this (.getOffset ^OffsetDateTime now)) + (.toLocalDateTime))) + + OffsetInstant + (to-date-time [this now] + (p/to-date-time (.value this) now)) + Year (to-date-time [this _] (DateTimeYear. this)) diff --git a/modules/cql/src/blaze/elm/decimal.clj b/modules/cql/src/blaze/elm/decimal.clj index c6dc001c9..f95830bca 100644 --- a/modules/cql/src/blaze/elm/decimal.clj +++ b/modules/cql/src/blaze/elm/decimal.clj @@ -232,7 +232,8 @@ (extend-protocol p/Round BigDecimal (round [x precision] - (.setScale x ^long precision RoundingMode/HALF_UP))) + (let [new-scale (or precision 0)] + (.setScale x ^int new-scale RoundingMode/HALF_UP)))) ;; 16.20. Subtract diff --git a/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj b/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj index d71ab22d0..b1261bee7 100644 --- a/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj @@ -42,9 +42,9 @@ (deftest compile-all-true-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/all-true source)) {} nil nil)) - #elm/list [#elm/boolean"true" #elm/boolean"false"] false - #elm/list [#elm/boolean"false"] false - #elm/list [#elm/boolean"true"] true + #elm/list [#elm/boolean "true" #elm/boolean "false"] false + #elm/list [#elm/boolean "false"] false + #elm/list [#elm/boolean "true"] true #elm/list [{:type "Null"}] true #elm/list [] true @@ -64,9 +64,9 @@ (deftest compile-any-true-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/any-true source)) {} nil nil)) - #elm/list [#elm/boolean"true" #elm/boolean"false"] true - #elm/list [#elm/boolean"false"] false - #elm/list [#elm/boolean"true"] true + #elm/list [#elm/boolean "true" #elm/boolean "false"] true + #elm/list [#elm/boolean "false"] false + #elm/list [#elm/boolean "true"] true #elm/list [{:type "Null"}] false #elm/list [] false @@ -86,9 +86,9 @@ (deftest compile-avg-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/avg source)) {} nil nil)) - #elm/list [#elm/decimal"1" #elm/decimal"2"] 1.5M - #elm/list [#elm/integer"1" #elm/integer"2"] 1.5M - #elm/list [#elm/integer"1"] 1M + #elm/list [#elm/decimal "1" #elm/decimal "2"] 1.5M + #elm/list [#elm/integer "1" #elm/integer "2"] 1.5M + #elm/list [#elm/integer "1"] 1M #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -108,8 +108,8 @@ (deftest compile-count-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/count source)) {} nil nil)) - #elm/list [#elm/integer"1"] 1 - #elm/list [#elm/integer"1" #elm/integer"1"] 2 + #elm/list [#elm/integer "1"] 1 + #elm/list [#elm/integer "1" #elm/integer "1"] 2 #elm/list [{:type "Null"}] 0 #elm/list [] 0 @@ -130,9 +130,9 @@ (deftest compile-geometric-mean-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/geometric-mean source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"8"] 4M - #elm/list [#elm/integer"2" #elm/integer"8"] 4M - #elm/list [#elm/integer"1"] 1M + #elm/list [#elm/decimal "2" #elm/decimal "8"] 4M + #elm/list [#elm/integer "2" #elm/integer "8"] 4M + #elm/list [#elm/integer "1"] 1M #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -153,9 +153,9 @@ (deftest compile-product-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/product source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"8"] 16M - #elm/list [#elm/integer"2" #elm/integer"8"] 16 - #elm/list [#elm/integer"1"] 1 + #elm/list [#elm/decimal "2" #elm/decimal "8"] 16M + #elm/list [#elm/integer "2" #elm/integer "8"] 16 + #elm/list [#elm/integer "1"] 1 #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -177,9 +177,9 @@ (deftest compile-max-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/max source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"8"] 8M - #elm/list [#elm/integer"2" #elm/integer"8"] 8 - #elm/list [#elm/integer"1"] 1 + #elm/list [#elm/decimal "2" #elm/decimal "8"] 8M + #elm/list [#elm/integer "2" #elm/integer "8"] 8 + #elm/list [#elm/integer "1"] 1 #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -199,10 +199,10 @@ (deftest compile-median-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/median source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"10" #elm/decimal"8"] 8M - #elm/list [#elm/integer"2" #elm/integer"10" #elm/integer"8"] 8 - #elm/list [#elm/integer"1" #elm/integer"2"] 1.5M - #elm/list [#elm/integer"1"] 1 + #elm/list [#elm/decimal "2" #elm/decimal "10" #elm/decimal "8"] 8M + #elm/list [#elm/integer "2" #elm/integer "10" #elm/integer "8"] 8 + #elm/list [#elm/integer "1" #elm/integer "2"] 1.5M + #elm/list [#elm/integer "1"] 1 #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -224,9 +224,9 @@ (deftest compile-min-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/min source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"8"] 2M - #elm/list [#elm/integer"2" #elm/integer"8"] 2 - #elm/list [#elm/integer"1"] 1 + #elm/list [#elm/decimal "2" #elm/decimal "8"] 2M + #elm/list [#elm/integer "2" #elm/integer "8"] 2 + #elm/list [#elm/integer "1"] 1 #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -246,10 +246,10 @@ (deftest compile-mode-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/mode source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"2" #elm/decimal"8"] 2M - #elm/list [#elm/integer"2" #elm/integer"2" #elm/integer"8"] 2 - #elm/list [#elm/integer"1"] 1 - #elm/list [#elm/integer"1" {:type "Null"} {:type "Null"}] 1 + #elm/list [#elm/decimal "2" #elm/decimal "2" #elm/decimal "8"] 2M + #elm/list [#elm/integer "2" #elm/integer "2" #elm/integer "8"] 2 + #elm/list [#elm/integer "1"] 1 + #elm/list [#elm/integer "1" {:type "Null"} {:type "Null"}] 1 #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -270,7 +270,7 @@ (deftest compile-population-variance-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/population-variance source)) {} nil nil)) - #elm/list [#elm/decimal"1" #elm/decimal"2" #elm/decimal"3" #elm/decimal"4" #elm/decimal"5"] 2M + #elm/list [#elm/decimal "1" #elm/decimal "2" #elm/decimal "3" #elm/decimal "4" #elm/decimal "5"] 2M #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -291,7 +291,7 @@ (deftest compile-population-std-dev-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/population-std-dev source)) {} nil nil)) - #elm/list [#elm/decimal"1" #elm/decimal"2" #elm/decimal"3" #elm/decimal"4" #elm/decimal"5"] 1.41421356M + #elm/list [#elm/decimal "1" #elm/decimal "2" #elm/decimal "3" #elm/decimal "4" #elm/decimal "5"] 1.41421356M #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -311,9 +311,9 @@ (deftest compile-sum-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/sum source)) {} nil nil)) - #elm/list [#elm/decimal"2" #elm/decimal"8"] 10M - #elm/list [#elm/integer"2" #elm/integer"8"] 10 - #elm/list [#elm/integer"1"] 1 + #elm/list [#elm/decimal "2" #elm/decimal "8"] 10M + #elm/list [#elm/integer "2" #elm/integer "8"] 10 + #elm/list [#elm/integer "1"] 1 #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -334,7 +334,7 @@ (deftest compile-std-dev-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/std-dev source)) {} nil nil)) - #elm/list [#elm/decimal"1" #elm/decimal"2" #elm/decimal"3" #elm/decimal"4" #elm/decimal"5"] 1.58113883M + #elm/list [#elm/decimal "1" #elm/decimal "2" #elm/decimal "3" #elm/decimal "4" #elm/decimal "5"] 1.58113883M #elm/list [{:type "Null"}] nil #elm/list [] nil @@ -355,7 +355,7 @@ (deftest compile-variance-test (testing "Without path" (are [source res] (= res (core/-eval (c/compile {} (elm/variance source)) {} nil nil)) - #elm/list [#elm/decimal"1" #elm/decimal"2" #elm/decimal"3" #elm/decimal"4" #elm/decimal"5"] 2.5M + #elm/list [#elm/decimal "1" #elm/decimal "2" #elm/decimal "3" #elm/decimal "4" #elm/decimal "5"] 2.5M #elm/list [{:type "Null"}] nil #elm/list [] nil diff --git a/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj b/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj index 3a4bd6c34..63f0bb4a5 100644 --- a/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj @@ -86,7 +86,9 @@ [0M "m"] (quantity/quantity 0M "m") [1M "m"] (quantity/quantity 1M "m")))) - (tu/testing-unary-null elm/abs)) + (tu/testing-unary-null elm/abs) + + (tu/testing-unary-form elm/abs)) ;; 16.2. Add @@ -137,25 +139,25 @@ "1" "0" 1 "1" "1" 2)) - (tu/testing-binary-null elm/add #elm/integer"1")) + (tu/testing-binary-null elm/add #elm/integer "1")) (testing "Adding zero integer to any integer or decimal doesn't change it" (satisfies-prop 100 (prop/for-all [operand (s/gen (s/or :i :elm/integer :d :elm/decimal))] - (let [elm (elm/equal [(elm/add [operand #elm/integer"0"]) operand])] + (let [elm (elm/equal [(elm/add [operand #elm/integer "0"]) operand])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) (testing "Adding zero decimal to any decimal doesn't change it" (satisfies-prop 100 (prop/for-all [operand (s/gen :elm/decimal)] - (let [elm (elm/equal [(elm/add [operand #elm/decimal"0"]) operand])] + (let [elm (elm/equal [(elm/add [operand #elm/decimal "0"]) operand])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) (testing "Adding identical integers equals multiplying the same integer by two" (satisfies-prop 100 (prop/for-all [integer (s/gen :elm/integer)] (let [elm (elm/equivalent [(elm/add [integer integer]) - (elm/multiply [integer #elm/integer"2"])])] + (elm/multiply [integer #elm/integer "2"])])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) (testing "Decimal" @@ -167,37 +169,37 @@ "1.1" "0" 1.1M "1.1" "1.1" 2.2M) - (tu/testing-binary-null elm/add #elm/decimal"1.1")) + (tu/testing-binary-null elm/add #elm/decimal "1.1")) (testing "Mix with integer" (are [x y res] (= res (c/compile {} (elm/add [x y]))) - #elm/decimal"1.1" #elm/integer"1" 2.1M - #elm/integer"1" #elm/decimal"1.1" 2.1M) + #elm/decimal "1.1" #elm/integer "1" 2.1M + #elm/integer "1" #elm/decimal "1.1" 2.1M) - (tu/testing-binary-null elm/add #elm/integer"1" #elm/decimal"1.1") - (tu/testing-binary-null elm/add #elm/decimal"1.1" #elm/integer"1")) + (tu/testing-binary-null elm/add #elm/integer "1" #elm/decimal "1.1") + (tu/testing-binary-null elm/add #elm/decimal "1.1" #elm/integer "1")) (testing "Trailing zeros are preserved" (are [x y res] (= res (str (core/-eval (c/compile {} (elm/add [x y])) {} nil nil))) - #elm/decimal"1.23" #elm/decimal"1.27" "2.50")) + #elm/decimal "1.23" #elm/decimal "1.27" "2.50")) (testing "Arithmetic overflow results in nil" (are [x y] (nil? (core/-eval (c/compile {} (elm/add [x y])) {} nil nil)) - #elm/decimal"99999999999999999999" #elm/decimal"1" - #elm/decimal"99999999999999999999.99999999" #elm/decimal"1"))) + #elm/decimal "99999999999999999999" #elm/decimal "1" + #elm/decimal "99999999999999999999.99999999" #elm/decimal "1"))) (testing "Adding identical decimals equals multiplying the same decimal by two" (satisfies-prop 100 (prop/for-all [decimal (s/gen :elm/decimal)] (let [elm (elm/equal [(elm/add [decimal decimal]) - (elm/multiply [decimal #elm/integer"2"])])] + (elm/multiply [decimal #elm/integer "2"])])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) (testing "Adding identical decimals and dividing by two results in the same decimal" (satisfies-prop 100 (prop/for-all [decimal (s/gen :elm/decimal)] (let [elm (elm/equal [(elm/divide [(elm/add [decimal decimal]) - #elm/integer"2"]) + #elm/integer "2"]) decimal])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) @@ -228,7 +230,7 @@ 100 (prop/for-all [quantity (gen/such-that :value (s/gen :elm/quantity) 100)] (let [elm (elm/equal [(elm/add [quantity quantity]) - (elm/multiply [quantity #elm/integer"2"])])] + (elm/multiply [quantity #elm/integer "2"])])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) (testing "Adding identical quantities and dividing by two results in the same quantity" @@ -236,24 +238,24 @@ 100 (prop/for-all [quantity (gen/such-that :value (s/gen :elm/quantity) 100)] (let [elm (elm/equal [(elm/divide [(elm/add [quantity quantity]) - #elm/integer"2"]) + #elm/integer "2"]) quantity])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) (testing "Date + Quantity" (are [x y res] (= res (core/-eval (c/compile {} (elm/add [x y])) {} nil nil)) - #elm/date"2019" #elm/quantity[1 "year"] (system/date 2020) - #elm/date"2019" #elm/quantity[13 "months"] (system/date 2020) + #elm/date "2019" #elm/quantity [1 "year"] (system/date 2020) + #elm/date "2019" #elm/quantity [13 "months"] (system/date 2020) - #elm/date"2019-01" #elm/quantity[1 "month"] (system/date 2019 2) - #elm/date"2019-01" #elm/quantity[12 "month"] (system/date 2020 1) - #elm/date"2019-01" #elm/quantity[13 "month"] (system/date 2020 2) - #elm/date"2019-01" #elm/quantity[1 "year"] (system/date 2020 1) + #elm/date "2019-01" #elm/quantity [1 "month"] (system/date 2019 2) + #elm/date "2019-01" #elm/quantity [12 "month"] (system/date 2020 1) + #elm/date "2019-01" #elm/quantity [13 "month"] (system/date 2020 2) + #elm/date "2019-01" #elm/quantity [1 "year"] (system/date 2020 1) - #elm/date"2019-01-01" #elm/quantity[1 "year"] (system/date 2020 1 1) - #elm/date"2012-02-29" #elm/quantity[1 "year"] (system/date 2013 2 28) - #elm/date"2019-01-01" #elm/quantity[1 "month"] (system/date 2019 2 1) - #elm/date"2019-01-01" #elm/quantity[1 "day"] (system/date 2019 1 2))) + #elm/date "2019-01-01" #elm/quantity [1 "year"] (system/date 2020 1 1) + #elm/date "2012-02-29" #elm/quantity [1 "year"] (system/date 2013 2 28) + #elm/date "2019-01-01" #elm/quantity [1 "month"] (system/date 2019 2 1) + #elm/date "2019-01-01" #elm/quantity [1 "day"] (system/date 2019 1 2))) (testing "Adding a positive amount of years to a year makes it greater" (satisfies-prop 100 @@ -336,19 +338,21 @@ (testing "DateTime + Quantity" (are [x y res] (= res (core/-eval (c/compile {} (elm/add [x y])) {} nil nil)) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "year"] (system/date-time 2020 1 1 0 0 0) - #elm/date-time"2012-02-29T00" #elm/quantity[1 "year"] (system/date-time 2013 2 28 0 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "month"] (system/date-time 2019 2 1 0 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "day"] (system/date-time 2019 1 2 0 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "hour"] (system/date-time 2019 1 1 1 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "minute"] (system/date-time 2019 1 1 0 1 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "second"] (system/date-time 2019 1 1 0 0 1))) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "year"] (system/date-time 2020 1 1 0 0 0) + #elm/date-time "2012-02-29T00" #elm/quantity [1 "year"] (system/date-time 2013 2 28 0 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "month"] (system/date-time 2019 2 1 0 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "day"] (system/date-time 2019 1 2 0 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "hour"] (system/date-time 2019 1 1 1 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "minute"] (system/date-time 2019 1 1 0 1 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "second"] (system/date-time 2019 1 1 0 0 1))) (testing "Time + Quantity" (are [x y res] (= res (core/-eval (c/compile {} (elm/add [x y])) {} nil nil)) - #elm/time"00:00:00" #elm/quantity[1 "hour"] (date-time/local-time 1 0 0) - #elm/time"00:00:00" #elm/quantity[1 "minute"] (date-time/local-time 0 1 0) - #elm/time"00:00:00" #elm/quantity[1 "second"] (date-time/local-time 0 0 1)))) + #elm/time "00:00:00" #elm/quantity [1 "hour"] (date-time/local-time 1 0 0) + #elm/time "00:00:00" #elm/quantity [1 "minute"] (date-time/local-time 0 1 0) + #elm/time "00:00:00" #elm/quantity [1 "second"] (date-time/local-time 0 0 1))) + + (tu/testing-binary-form elm/add)) ;; 16.3. Ceiling @@ -359,10 +363,12 @@ ;; If the argument is null, the result is null. (deftest compile-ceiling-test (are [x res] (= res (c/compile {} (elm/ceiling x))) - #elm/integer"1" 1 - #elm/decimal"1.1" 2) + #elm/integer "1" 1 + #elm/decimal "1.1" 2) + + (tu/testing-unary-null elm/ceiling) - (tu/testing-unary-null elm/ceiling)) + (tu/testing-unary-form elm/ceiling)) ;; 16.4. Divide @@ -391,7 +397,7 @@ "1" "0" nil "1" "0.0" nil)) - (tu/testing-binary-null elm/divide #elm/decimal"1.1")) + (tu/testing-binary-null elm/divide #elm/decimal "1.1")) (testing "Integer" (testing "Static" @@ -401,7 +407,7 @@ "1" "0" nil)) - (tu/testing-binary-null elm/divide #elm/integer"1")) + (tu/testing-binary-null elm/divide #elm/integer "1")) (testing "Decimal/Integer" (testing "Static" @@ -410,7 +416,7 @@ "1" "0" nil)) - (tu/testing-binary-null elm/divide #elm/decimal"1.1" #elm/integer"1")) + (tu/testing-binary-null elm/divide #elm/decimal "1.1" #elm/integer "1")) (testing "Integer/Decimal" (testing "Static" @@ -420,7 +426,7 @@ "1" "0" nil "1" "0.0" nil)) - (tu/testing-binary-null elm/divide #elm/integer"1" #elm/decimal"1.1")) + (tu/testing-binary-null elm/divide #elm/integer "1" #elm/decimal "1.1")) (testing "Quantity" (testing "Static" @@ -430,27 +436,29 @@ [12 "cm2"] [3 "cm"] (quantity/quantity 4 "cm"))) - (tu/testing-binary-null elm/divide #elm/quantity[1])) + (tu/testing-binary-null elm/divide #elm/quantity [1])) (testing "Quantity/Integer" (testing "Static" (are [x y res] (p/equal res (tu/compile-binop elm/divide elm/quantity elm/integer x y)) [1M "m"] "2" (quantity/quantity 0.5M "m"))) - (tu/testing-binary-null elm/divide #elm/quantity[1] #elm/integer"1")) + (tu/testing-binary-null elm/divide #elm/quantity [1] #elm/integer "1")) (testing "Quantity/Decimal" (testing "Static" (are [x y res] (p/equal res (tu/compile-binop elm/divide elm/quantity elm/decimal x y)) [2.5M "m"] "2.5" (quantity/quantity 1M "m"))) - (tu/testing-binary-null elm/divide #elm/quantity[1] #elm/decimal"1.1")) + (tu/testing-binary-null elm/divide #elm/quantity [1] #elm/decimal "1.1")) (testing "(d / d) * d = d" (satisfies-prop 100 (prop/for-all [decimal (s/gen :elm/non-zero-decimal)] (let [elm (elm/equal [(elm/multiply [(elm/divide [decimal decimal]) decimal]) decimal])] - (true? (core/-eval (c/compile {} elm) {} nil nil))))))) + (true? (core/-eval (c/compile {} elm) {} nil nil)))))) + + (tu/testing-binary-form elm/divide)) ;; 16.5. Exp @@ -460,10 +468,12 @@ ;; If the argument is null, the result is null. (deftest compile-exp-test (are [x res] (= res (c/compile {} (elm/exp x))) - #elm/integer"0" 1M - #elm/decimal"0" 1M) + #elm/integer "0" 1M + #elm/decimal "0" 1M) + + (tu/testing-unary-null elm/exp) - (tu/testing-unary-null elm/exp)) + (tu/testing-unary-form elm/exp)) ;; 16.6. Floor @@ -474,10 +484,12 @@ ;; If the argument is null, the result is null. (deftest compile-floor-test (are [x res] (= res (c/compile {} (elm/floor x))) - #elm/integer"1" 1 - #elm/decimal"1.1" 1) + #elm/integer "1" 1 + #elm/decimal "1.1" 1) - (tu/testing-unary-null elm/floor)) + (tu/testing-unary-null elm/floor) + + (tu/testing-unary-form elm/floor)) ;; 16.7. HighBoundary @@ -506,20 +518,22 @@ (deftest compile-log-test (testing "Integer" (are [x base res] (= res (c/compile {} (elm/log [x base]))) - #elm/integer"16" #elm/integer"2" 4M + #elm/integer "16" #elm/integer "2" 4M - #elm/integer"0" #elm/integer"2" nil) + #elm/integer "0" #elm/integer "2" nil) - (tu/testing-binary-null elm/log #elm/integer"1")) + (tu/testing-binary-null elm/log #elm/integer "1")) (testing "Decimal" (are [x base res] (= res (c/compile {} (elm/log [x base]))) - #elm/decimal"100" #elm/decimal"10" 2M - #elm/decimal"1" #elm/decimal"1" nil + #elm/decimal "100" #elm/decimal "10" 2M + #elm/decimal "1" #elm/decimal "1" nil + + #elm/decimal "0" #elm/integer "2" nil) - #elm/decimal"0" #elm/integer"2" nil) + (tu/testing-binary-null elm/log #elm/decimal "1.1")) - (tu/testing-binary-null elm/log #elm/decimal"1.1"))) + (tu/testing-binary-form elm/log)) ;; 16.9. LowBoundary @@ -548,20 +562,22 @@ ;; If the result of the operation cannot be represented, the result is null. (deftest compile-ln-test (are [x res] (= res (c/compile {} (elm/ln x))) - #elm/integer"1" 0M - #elm/integer"2" 0.69314718M - #elm/integer"3" 1.09861229M + #elm/integer "1" 0M + #elm/integer "2" 0.69314718M + #elm/integer "3" 1.09861229M + + #elm/decimal "1" 0M + #elm/decimal "1.1" 0.09531018M - #elm/decimal"1" 0M - #elm/decimal"1.1" 0.09531018M + #elm/integer "0" nil + #elm/decimal "0" nil - #elm/integer"0" nil - #elm/decimal"0" nil + #elm/integer "-1" nil + #elm/decimal "-1" nil) - #elm/integer"-1" nil - #elm/decimal"-1" nil) + (tu/testing-unary-null elm/ln) - (tu/testing-unary-null elm/ln)) + (tu/testing-unary-form elm/ln)) ;; 16.11. MaxValue @@ -671,7 +687,7 @@ "3" "2" 1 "5" "3" 2) - (tu/testing-binary-null elm/modulo #elm/integer"1")) + (tu/testing-binary-null elm/modulo #elm/integer "1")) (testing "Decimal" (are [x div res] (= res (tu/compile-binop elm/modulo elm/decimal x div)) @@ -681,12 +697,14 @@ "2.5" "2" 0.5M) - (tu/testing-binary-null elm/modulo #elm/decimal"1.1")) + (tu/testing-binary-null elm/modulo #elm/decimal "1.1")) (testing "Mixed Integer and Decimal" (are [x div res] (= res (core/-eval (c/compile {} (elm/modulo [x div])) {} nil nil)) - #elm/integer"1" #elm/integer"0" nil - #elm/decimal"1" #elm/decimal"0" nil))) + #elm/integer "1" #elm/integer "0" nil + #elm/decimal "1" #elm/decimal "0" nil)) + + (tu/testing-binary-form elm/modulo)) ;; 16.14. Multiply @@ -707,7 +725,7 @@ "1" "2" 2 "2" "2" 4) - (tu/testing-binary-null elm/multiply #elm/integer"1")) + (tu/testing-binary-null elm/multiply #elm/integer "1")) (testing "Decimal" (testing "Decimal" @@ -715,7 +733,7 @@ "1" "2" 2M "1.23456" "1.23456" 1.52413839M) - (tu/testing-binary-null elm/multiply #elm/decimal"1.1")) + (tu/testing-binary-null elm/multiply #elm/decimal "1.1")) (testing "Arithmetic overflow results in nil" (are [x y] (nil? (tu/compile-binop elm/multiply elm/decimal x y)) @@ -724,10 +742,12 @@ (testing "Quantity" (are [x y res] (p/equal res (core/-eval (c/compile {} (elm/multiply [x y])) {} nil nil)) - #elm/quantity[1 "m"] #elm/integer"2" (quantity/quantity 2 "m") - #elm/quantity[1 "m"] #elm/quantity[2 "m"] (quantity/quantity 2 "m2")) + #elm/quantity [1 "m"] #elm/integer "2" (quantity/quantity 2 "m") + #elm/quantity [1 "m"] #elm/quantity [2 "m"] (quantity/quantity 2 "m2")) + + (tu/testing-binary-null elm/multiply #elm/quantity [1])) - (tu/testing-binary-null elm/multiply #elm/quantity[1]))) + (tu/testing-binary-form elm/multiply)) ;; 16.15. Negate @@ -750,12 +770,14 @@ (testing "Quantity" (are [x res] (= res (c/compile {} (elm/negate x))) - #elm/quantity[1] (quantity/quantity -1 "1") - #elm/quantity[1M] (quantity/quantity -1M "1") - #elm/quantity[1 "m"] (quantity/quantity -1 "m") - #elm/quantity[1M "m"] (quantity/quantity -1M "m"))) + #elm/quantity [1] (quantity/quantity -1 "1") + #elm/quantity [1M] (quantity/quantity -1M "1") + #elm/quantity [1 "m"] (quantity/quantity -1 "m") + #elm/quantity [1M "m"] (quantity/quantity -1M "m"))) - (tu/testing-unary-null elm/negate)) + (tu/testing-unary-null elm/negate) + + (tu/testing-unary-form elm/negate)) ;; 16.16. Power @@ -773,7 +795,7 @@ "10" "2" 100 "2" "-2" 0.25M) - (tu/testing-binary-null elm/power #elm/integer"1")) + (tu/testing-binary-null elm/power #elm/integer "1")) (testing "Decimal" (are [x y res] (= res (tu/compile-binop elm/power elm/decimal x y)) @@ -781,13 +803,15 @@ "10" "2" 100M "4" "0.5" 2M) - (tu/testing-binary-null elm/power #elm/decimal"1.1")) + (tu/testing-binary-null elm/power #elm/decimal "1.1")) (testing "Mixed" (are [x y res] (= res (c/compile {} (elm/power [x y]))) - #elm/decimal"2.5" #elm/integer"2" 6.25M - #elm/decimal"10" #elm/integer"2" 100M - #elm/decimal"10" #elm/integer"2" 100M))) + #elm/decimal "2.5" #elm/integer "2" 6.25M + #elm/decimal "10" #elm/integer "2" 100M + #elm/decimal "10" #elm/integer "2" 100M)) + + (tu/testing-binary-form elm/power)) ;; 16.17. Precision @@ -831,50 +855,52 @@ (deftest compile-predecessor-test (testing "Integer" (are [x res] (= res (c/compile {} (elm/predecessor x))) - #elm/integer"0" -1)) + #elm/integer "0" -1)) (testing "Decimal" (are [x res] (= res (c/compile {} (elm/predecessor x))) - #elm/decimal"0" -1E-8M)) + #elm/decimal "0" -1E-8M)) (testing "Date" (are [x res] (= res (c/compile {} (elm/predecessor x))) - #elm/date"2019" (system/date 2018) - #elm/date"2019-01" (system/date 2018 12) - #elm/date"2019-01-01" (system/date 2018 12 31))) + #elm/date "2019" (system/date 2018) + #elm/date "2019-01" (system/date 2018 12) + #elm/date "2019-01-01" (system/date 2018 12 31))) (testing "DateTime" (are [x res] (= res (c/compile {} (elm/predecessor x))) - #elm/date-time"2019" (system/date-time 2018) - #elm/date-time"2019-01" (system/date-time 2018 12) - #elm/date-time"2019-01-01" (system/date-time 2018 12 31) - #elm/date-time"2019-01-01T00" (system/date-time 2018 12 31 23 59 59 999))) + #elm/date-time "2019" (system/date-time 2018) + #elm/date-time "2019-01" (system/date-time 2018 12) + #elm/date-time "2019-01-01" (system/date-time 2018 12 31) + #elm/date-time "2019-01-01T00" (system/date-time 2018 12 31 23 59 59 999))) (testing "Time" (are [x res] (= res (c/compile {} (elm/predecessor x))) - #elm/time"12:00" (date-time/local-time 11 59))) + #elm/time "12:00" (date-time/local-time 11 59))) (testing "Quantity" (are [x res] (= res (c/compile {} (elm/predecessor x))) - #_#_#elm/quantity[0 "m"] (quantity/quantity -1 "m") ; TODO: implement - #elm/quantity[0M "m"] (quantity/quantity -1E-8M "m"))) + #_#_#elm/quantity [0 "m"] (quantity/quantity -1 "m") ; TODO: implement + #elm/quantity [0M "m"] (quantity/quantity -1E-8M "m"))) (tu/testing-unary-null elm/predecessor) + (tu/testing-unary-form elm/predecessor) + (testing "throws error if the argument is already the minimum value" (are [x] (= ::anom/incorrect (::anom/category (ba/try-anomaly (c/compile {} (elm/predecessor x))))) (elm/decimal (str decimal/min)) - #elm/date"0001" - #elm/date"0001-01" - #elm/date"0001-01-01" - #elm/time"00:00:00.0" - #elm/date-time"0001" - #elm/date-time"0001-01" - #elm/date-time"0001-01-01" - #elm/date-time"0001-01-01T00:00:00.0" + #elm/date "0001" + #elm/date "0001-01" + #elm/date "0001-01-01" + #elm/time "00:00:00.0" + #elm/date-time "0001" + #elm/date-time "0001-01" + #elm/date-time "0001-01-01" + #elm/date-time "0001-01-01T00:00:00.0" (elm/quantity [decimal/min])))) @@ -889,40 +915,49 @@ ;; Precision determines the decimal place at which the rounding will occur. If ;; precision is not specified or null, 0 is assumed. (deftest compile-round-test - (testing "Without precision" - (testing "Static" + (testing "without precision" + (testing "static" (are [x res] (= res (c/compile {} (elm/round [x]))) - #elm/integer"1" 1M - #elm/decimal"1" 1M - #elm/decimal"0.5" 1M - #elm/decimal"0.4" 0M - #elm/decimal"-0.4" 0M - #elm/decimal"-0.5" -1M - #elm/decimal"-0.6" -1M - #elm/decimal"-1.1" -1M - #elm/decimal"-1.5" -2M - #elm/decimal"-1.6" -2M + #elm/integer "1" 1M + #elm/decimal "1" 1M + #elm/decimal "0.5" 1M + #elm/decimal "0.4" 0M + #elm/decimal "-0.4" 0M + #elm/decimal "-0.5" -1M + #elm/decimal "-0.6" -1M + #elm/decimal "-1.1" -1M + #elm/decimal "-1.5" -2M + #elm/decimal "-1.6" -2M {:type "Null"} nil)) - (testing "Dynamic Null" + (testing "dynamic null" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/round[#elm/parameter-ref"x"] + elm #elm/round [#elm/parameter-ref "x"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"x" nil}}] (is (nil? (core/-eval expr eval-ctx nil nil)))))) - (testing "With precision" + (testing "with precision" (testing "Static" (are [x precision res] (= res (c/compile {} (elm/round [x precision]))) - #elm/decimal"3.14159" #elm/integer"3" 3.142M - {:type "Null"} #elm/integer"3" nil)) + #elm/decimal "3.14159" #elm/integer "3" 3.142M + {:type "Null"} #elm/integer "3" nil)) - (testing "Dynamic Null" + (testing "dynamic null" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/round[#elm/parameter-ref"x" #elm/integer"3"] + elm #elm/round [#elm/parameter-ref "x" #elm/integer "3"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"x" nil}}] - (is (nil? (core/-eval expr eval-ctx nil nil))))))) + (is (nil? (core/-eval expr eval-ctx nil nil)))))) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}}] + (are [elm form] (= form (core/-form (c/compile compile-ctx elm))) + #elm/round [#elm/parameter-ref "x"] + '(round (param-ref "x")) + + #elm/round [#elm/parameter-ref "x" #elm/integer "3"] + '(round (param-ref "x") 3))))) ;; 16.20. Subtract @@ -960,14 +995,14 @@ (deftest compile-subtract-test (testing "Integer" (are [x y res] (= res (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/integer"-1" #elm/integer"-1" 0 - #elm/integer"-1" #elm/integer"0" -1 - #elm/integer"1" #elm/integer"1" 0 - #elm/integer"1" #elm/integer"0" 1 - #elm/integer"1" #elm/integer"-1" 2 + #elm/integer "-1" #elm/integer "-1" 0 + #elm/integer "-1" #elm/integer "0" -1 + #elm/integer "1" #elm/integer "1" 0 + #elm/integer "1" #elm/integer "0" 1 + #elm/integer "1" #elm/integer "-1" 2 - {:type "Null"} #elm/integer"1" nil - #elm/integer"1" {:type "Null"} nil)) + {:type "Null"} #elm/integer "1" nil + #elm/integer "1" {:type "Null"} nil)) (testing "Subtracting identical integers results in zero" (satisfies-prop 100 @@ -977,23 +1012,23 @@ (testing "Decimal" (testing "Decimal" (are [x y res] (= res (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/decimal"-1" #elm/decimal"-1" 0M - #elm/decimal"-1" #elm/decimal"0" -1M - #elm/decimal"1" #elm/decimal"1" 0M - #elm/decimal"1" #elm/decimal"0" 1M - #elm/decimal"1" #elm/decimal"-1" 2M + #elm/decimal "-1" #elm/decimal "-1" 0M + #elm/decimal "-1" #elm/decimal "0" -1M + #elm/decimal "1" #elm/decimal "1" 0M + #elm/decimal "1" #elm/decimal "0" 1M + #elm/decimal "1" #elm/decimal "-1" 2M - {:type "Null"} #elm/decimal"1.1" nil - #elm/decimal"1.1" {:type "Null"} nil)) + {:type "Null"} #elm/decimal "1.1" nil + #elm/decimal "1.1" {:type "Null"} nil)) (testing "Mix with integer" (are [x y res] (= res (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/decimal"1" #elm/integer"1" 0M)) + #elm/decimal "1" #elm/integer "1" 0M)) (testing "Arithmetic overflow results in nil" (are [x y] (nil? (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/decimal"-99999999999999999999" #elm/decimal"1" - #elm/decimal"-99999999999999999999.99999999" #elm/decimal"1"))) + #elm/decimal "-99999999999999999999" #elm/decimal "1" + #elm/decimal "-99999999999999999999.99999999" #elm/decimal "1"))) (testing "Subtracting identical decimals results in zero" (satisfies-prop 100 @@ -1002,25 +1037,25 @@ (testing "Time-based quantity" (are [x y res] (= res (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/quantity[1 "year"] #elm/quantity[1 "year"] (date-time/period 0 0 0) - #elm/quantity[1 "year"] #elm/quantity[1 "month"] (date-time/period 0 11 0) - #elm/quantity[1 "year"] #elm/quantity[1 "day"] (date-time/period 1 0 (- (* 24 3600 1000))) + #elm/quantity [1 "year"] #elm/quantity [1 "year"] (date-time/period 0 0 0) + #elm/quantity [1 "year"] #elm/quantity [1 "month"] (date-time/period 0 11 0) + #elm/quantity [1 "year"] #elm/quantity [1 "day"] (date-time/period 1 0 (- (* 24 3600 1000))) - #elm/quantity[1 "day"] #elm/quantity[1 "day"] (date-time/period 0 0 0) - #elm/quantity[1 "day"] #elm/quantity[1 "hour"] (date-time/period 0 0 (* 23 3600 1000)) + #elm/quantity [1 "day"] #elm/quantity [1 "day"] (date-time/period 0 0 0) + #elm/quantity [1 "day"] #elm/quantity [1 "hour"] (date-time/period 0 0 (* 23 3600 1000)) - #elm/quantity[1 "year"] #elm/quantity[1.1M "year"] (date-time/period -0.1M 0 0) - #elm/quantity[1 "year"] #elm/quantity[13.1M "month"] (date-time/period 0 -1.1M 0))) + #elm/quantity [1 "year"] #elm/quantity [1.1M "year"] (date-time/period -0.1M 0 0) + #elm/quantity [1 "year"] #elm/quantity [13.1M "month"] (date-time/period 0 -1.1M 0))) (testing "UCUM quantity" (are [x y res] (p/equal res (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/quantity[1 "m"] #elm/quantity[1 "m"] (quantity/quantity 0 "m") - #elm/quantity[1 "m"] #elm/quantity[1 "cm"] (quantity/quantity 0.99 "m"))) + #elm/quantity [1 "m"] #elm/quantity [1 "m"] (quantity/quantity 0 "m") + #elm/quantity [1 "m"] #elm/quantity [1 "cm"] (quantity/quantity 0.99 "m"))) (testing "Incompatible UCUM Quantity Subtractions" (are [x y] (thrown? UnconvertibleException (core/-eval (c/compile {} (elm/subtract [x y])) {} nil nil)) - #elm/quantity[1 "cm2"] #elm/quantity[1 "cm"] - #elm/quantity[1 "m"] #elm/quantity[1 "s"])) + #elm/quantity [1 "cm2"] #elm/quantity [1 "cm"] + #elm/quantity [1 "m"] #elm/quantity [1 "s"])) (testing "Subtracting identical quantities results in zero" (satisfies-prop @@ -1034,18 +1069,18 @@ (testing "Date - Quantity" (are [x y res] (= res (c/compile {} (elm/subtract [x y]))) - #elm/date"2019" #elm/quantity[1 "year"] (system/date 2018) - #elm/date"2019" #elm/quantity[13 "months"] (system/date 2018) + #elm/date "2019" #elm/quantity [1 "year"] (system/date 2018) + #elm/date "2019" #elm/quantity [13 "months"] (system/date 2018) - #elm/date"2019-01" #elm/quantity[1 "month"] (system/date 2018 12) - #elm/date"2019-01" #elm/quantity[12 "month"] (system/date 2018 1) - #elm/date"2019-01" #elm/quantity[13 "month"] (system/date 2017 12) - #elm/date"2019-01" #elm/quantity[1 "year"] (system/date 2018 1) + #elm/date "2019-01" #elm/quantity [1 "month"] (system/date 2018 12) + #elm/date "2019-01" #elm/quantity [12 "month"] (system/date 2018 1) + #elm/date "2019-01" #elm/quantity [13 "month"] (system/date 2017 12) + #elm/date "2019-01" #elm/quantity [1 "year"] (system/date 2018 1) - #elm/date"2019-01-01" #elm/quantity[1 "year"] (system/date 2018 1 1) - #elm/date"2012-02-29" #elm/quantity[1 "year"] (system/date 2011 2 28) - #elm/date"2019-01-01" #elm/quantity[1 "month"] (system/date 2018 12 1) - #elm/date"2019-01-01" #elm/quantity[1 "day"] (system/date 2018 12 31))) + #elm/date "2019-01-01" #elm/quantity [1 "year"] (system/date 2018 1 1) + #elm/date "2012-02-29" #elm/quantity [1 "year"] (system/date 2011 2 28) + #elm/date "2019-01-01" #elm/quantity [1 "month"] (system/date 2018 12 1) + #elm/date "2019-01-01" #elm/quantity [1 "day"] (system/date 2018 12 31))) ;; TODO: find a solution to avoid overflow #_(testing "Subtracting a positive amount of years from a year makes it smaller" @@ -1097,31 +1132,33 @@ (testing "DateTime - Quantity" (are [x y res] (= res (c/compile {} (elm/subtract [x y]))) - #elm/date-time"2019" #elm/quantity[1 "year"] (system/date-time 2018) - #elm/date-time"2019" #elm/quantity[13 "months"] (system/date-time 2018) - - #elm/date-time"2019-01" #elm/quantity[1 "month"] (system/date-time 2018 12) - #elm/date-time"2019-01" #elm/quantity[12 "month"] (system/date-time 2018 1) - #elm/date-time"2019-01" #elm/quantity[13 "month"] (system/date-time 2017 12) - #elm/date-time"2019-01" #elm/quantity[1 "year"] (system/date-time 2018 1) - - #elm/date-time"2019-01-01" #elm/quantity[1 "year"] (system/date-time 2018 1 1) - #elm/date-time"2012-02-29" #elm/quantity[1 "year"] (system/date-time 2011 2 28) - #elm/date-time"2019-01-01" #elm/quantity[1 "month"] (system/date-time 2018 12 1) - #elm/date-time"2019-01-01" #elm/quantity[1 "day"] (system/date-time 2018 12 31) - - #elm/date-time"2019-01-01T00" #elm/quantity[1 "year"] (system/date-time 2018 1 1 0 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "month"] (system/date-time 2018 12 1 0 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "day"] (system/date-time 2018 12 31 0 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "hour"] (system/date-time 2018 12 31 23 0 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "minute"] (system/date-time 2018 12 31 23 59 0) - #elm/date-time"2019-01-01T00" #elm/quantity[1 "second"] (system/date-time 2018 12 31 23 59 59))) + #elm/date-time "2019" #elm/quantity [1 "year"] (system/date-time 2018) + #elm/date-time "2019" #elm/quantity [13 "months"] (system/date-time 2018) + + #elm/date-time "2019-01" #elm/quantity [1 "month"] (system/date-time 2018 12) + #elm/date-time "2019-01" #elm/quantity [12 "month"] (system/date-time 2018 1) + #elm/date-time "2019-01" #elm/quantity [13 "month"] (system/date-time 2017 12) + #elm/date-time "2019-01" #elm/quantity [1 "year"] (system/date-time 2018 1) + + #elm/date-time "2019-01-01" #elm/quantity [1 "year"] (system/date-time 2018 1 1) + #elm/date-time "2012-02-29" #elm/quantity [1 "year"] (system/date-time 2011 2 28) + #elm/date-time "2019-01-01" #elm/quantity [1 "month"] (system/date-time 2018 12 1) + #elm/date-time "2019-01-01" #elm/quantity [1 "day"] (system/date-time 2018 12 31) + + #elm/date-time "2019-01-01T00" #elm/quantity [1 "year"] (system/date-time 2018 1 1 0 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "month"] (system/date-time 2018 12 1 0 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "day"] (system/date-time 2018 12 31 0 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "hour"] (system/date-time 2018 12 31 23 0 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "minute"] (system/date-time 2018 12 31 23 59 0) + #elm/date-time "2019-01-01T00" #elm/quantity [1 "second"] (system/date-time 2018 12 31 23 59 59))) (testing "Time - Quantity" (are [x y res] (= res (c/compile {} (elm/subtract [x y]))) - #elm/time"00:00:00" #elm/quantity[1 "hour"] (date-time/local-time 23 0 0) - #elm/time"00:00:00" #elm/quantity[1 "minute"] (date-time/local-time 23 59 0) - #elm/time"00:00:00" #elm/quantity[1 "second"] (date-time/local-time 23 59 59)))) + #elm/time "00:00:00" #elm/quantity [1 "hour"] (date-time/local-time 23 0 0) + #elm/time "00:00:00" #elm/quantity [1 "minute"] (date-time/local-time 23 59 0) + #elm/time "00:00:00" #elm/quantity [1 "second"] (date-time/local-time 23 59 59))) + + (tu/testing-binary-form elm/subtract)) ;; 16.21. Successor @@ -1152,46 +1189,48 @@ (deftest compile-successor-test (testing "Integer" (are [x res] (= res (c/compile {} (elm/successor x))) - #elm/integer"0" 1)) + #elm/integer "0" 1)) (testing "Decimal" (are [x res] (= res (c/compile {} (elm/successor x))) - #elm/decimal"0" 1E-8M)) + #elm/decimal "0" 1E-8M)) (testing "Date" (are [x res] (= res (c/compile {} (elm/successor x))) - #elm/date"2019" (system/date 2020) - #elm/date"2019-01" (system/date 2019 2) - #elm/date"2019-01-01" (system/date 2019 1 2))) + #elm/date "2019" (system/date 2020) + #elm/date "2019-01" (system/date 2019 2) + #elm/date "2019-01-01" (system/date 2019 1 2))) (testing "DateTime" (are [x res] (= res (c/compile {} (elm/successor x))) - #elm/date-time"2019" (system/date-time 2020) - #elm/date-time"2019-01" (system/date-time 2019 2) - #elm/date-time"2019-01-01" (system/date-time 2019 1 2) - #elm/date-time"2019-01-01T00" (system/date-time 2019 1 1 0 0 0 1))) + #elm/date-time "2019" (system/date-time 2020) + #elm/date-time "2019-01" (system/date-time 2019 2) + #elm/date-time "2019-01-01" (system/date-time 2019 1 2) + #elm/date-time "2019-01-01T00" (system/date-time 2019 1 1 0 0 0 1))) (testing "Time" (are [x res] (= res (c/compile {} (elm/successor x))) - #elm/time"00:00:00" (date-time/local-time 0 0 1))) + #elm/time "00:00:00" (date-time/local-time 0 0 1))) (testing "Quantity" (are [x res] (= res (c/compile {} (elm/successor x))) - #_#_#elm/quantity[0 "m"] (quantity/quantity 1 "m") ; TODO: implement - #elm/quantity[0M "m"] (quantity/quantity 1E-8M "m"))) + #_#_#elm/quantity [0 "m"] (quantity/quantity 1 "m") ; TODO: implement + #elm/quantity [0M "m"] (quantity/quantity 1E-8M "m"))) (tu/testing-unary-null elm/successor) (are [x] (thrown? Exception (core/-eval (c/compile {} (elm/successor x)) {} nil nil)) (elm/decimal (str decimal/max)) - #elm/date"9999" - #elm/date"9999-12" - #elm/date"9999-12-31" - #elm/time"23:59:59.999" - #elm/date-time"9999" - #elm/date-time"9999-12" - #elm/date-time"9999-12-31" - #elm/date-time"9999-12-31T23:59:59.999")) + #elm/date "9999" + #elm/date "9999-12" + #elm/date "9999-12-31" + #elm/time "23:59:59.999" + #elm/date-time "9999" + #elm/date-time "9999-12" + #elm/date-time "9999-12-31" + #elm/date-time "9999-12-31T23:59:59.999") + + (tu/testing-unary-form elm/successor)) ;; 16.22. Truncate @@ -1202,10 +1241,12 @@ (deftest compile-truncate-test (testing "Static" (are [x res] (= res (c/compile {} (elm/truncate x))) - #elm/integer"1" 1 - #elm/decimal"1.1" 1)) + #elm/integer "1" 1 + #elm/decimal "1.1" 1)) - (tu/testing-unary-null elm/truncate)) + (tu/testing-unary-null elm/truncate) + + (tu/testing-unary-form elm/truncate)) ;; 16.23. TruncatedDivide @@ -1228,7 +1269,7 @@ "1" "0" nil "1" "0.0" nil)) - (tu/testing-binary-null elm/truncated-divide #elm/decimal"1.1")) + (tu/testing-binary-null elm/truncated-divide #elm/decimal "1.1")) (testing "Integer" (testing "Static" @@ -1239,7 +1280,7 @@ "1" "0" nil)) - (tu/testing-binary-null elm/truncated-divide #elm/integer"1")) + (tu/testing-binary-null elm/truncated-divide #elm/integer "1")) (testing "Decimal/Integer" (testing "Static" @@ -1250,8 +1291,8 @@ "1" "0" nil)) - (tu/testing-binary-null elm/truncated-divide #elm/decimal"1.1" - #elm/integer"1")) + (tu/testing-binary-null elm/truncated-divide #elm/decimal "1.1" + #elm/integer "1")) (testing "Integer/Decimal" (testing "Static" @@ -1263,5 +1304,7 @@ "1" "0" nil "1" "0.0" nil)) - (tu/testing-binary-null elm/truncated-divide #elm/integer"1" - #elm/decimal"1.1"))) + (tu/testing-binary-null elm/truncated-divide #elm/integer "1" + #elm/decimal "1.1")) + + (tu/testing-binary-form elm/truncated-divide)) diff --git a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj index ed7885509..997a14cdc 100644 --- a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj @@ -58,18 +58,18 @@ (deftest compile-calculate-age-at-test (testing "Year" (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) - {:type "CalculateAgeAt" :operand [#elm/date"2018" #elm/date"2019"] + {:type "CalculateAgeAt" :operand [#elm/date "2018" #elm/date "2019"] :precision "Year"} 1 - {:type "CalculateAgeAt" :operand [#elm/date"2018" #elm/date"2018"] + {:type "CalculateAgeAt" :operand [#elm/date "2018" #elm/date "2018"] :precision "Year"} 0 - {:type "CalculateAgeAt" :operand [#elm/date"2018" #elm/date"2018"] + {:type "CalculateAgeAt" :operand [#elm/date "2018" #elm/date "2018"] :precision "Month"} nil)) - (tu/testing-binary-null elm/calculate-age-at #elm/date"2018")) + (tu/testing-binary-null elm/calculate-age-at #elm/date "2018")) ;; 23.5. Equal diff --git a/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj b/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj index 5c3a14aea..e036f8c87 100644 --- a/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj +++ b/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj @@ -49,7 +49,7 @@ {:library {:codeSystems {:def [{:name "sys-def-115852" :id "system-115910"}]}}}] - (given (c/compile context #elm/code["sys-def-115852" "code-115927"]) + (given (c/compile context #elm/code ["sys-def-115852" "code-115927"]) type := Code :system := "system-115910" :code := "code-115927"))) @@ -62,7 +62,7 @@ [{:name "sys-def-120434" :id "system-120411" :version "version-120408"}]}}}] - (given (c/compile context #elm/code["sys-def-120434" "code-120416"]) + (given (c/compile context #elm/code ["sys-def-120434" "code-120416"]) type := Code :system := "system-120411" :version := "version-120408" @@ -70,7 +70,7 @@ (testing "missing code system" (let [context {:library {:codeSystems {:def []}}}] - (given (ba/try-anomaly (c/compile context #elm/code["sys-def-112249" "code-112253"])) + (given (ba/try-anomaly (c/compile context #elm/code ["sys-def-112249" "code-112253"])) ::anom/category := ::anom/not-found ::anom/message := "Can't find the code system `sys-def-112249`.")))) @@ -97,7 +97,7 @@ [{:name "code-def-125054" :id "code-125340" :codeSystem {:name "sys-def-125149"}}]}}}] - (given (c/compile context #elm/code-ref"code-def-125054") + (given (c/compile context #elm/code-ref "code-def-125054") type := Code :system := "system-name-125213" :code := "code-125340"))) @@ -115,7 +115,7 @@ [{:name "code-def-125054" :id "code-125354" :codeSystem {:name "sys-def-125149"}}]}}}] - (given (c/compile context #elm/code-ref"code-def-125054") + (given (c/compile context #elm/code-ref "code-def-125054") type := Code :system := "system-name-125213" :version := "version-125222" @@ -147,25 +147,25 @@ (testing "Examples" (are [elm res] (= res (c/compile {} elm)) {:type "Quantity"} nil - #elm/quantity[1] (quantity/quantity 1 "") - #elm/quantity[1 "year"] (date-time/period 1 0 0) - #elm/quantity[2 "years"] (date-time/period 2 0 0) - #elm/quantity[1 "month"] (date-time/period 0 1 0) - #elm/quantity[2 "months"] (date-time/period 0 2 0) - #elm/quantity[1 "week"] (date-time/period 0 0 (* 7 24 60 60 1000)) - #elm/quantity[2 "weeks"] (date-time/period 0 0 (* 2 7 24 60 60 1000)) - #elm/quantity[1 "day"] (date-time/period 0 0 (* 24 60 60 1000)) - #elm/quantity[2 "days"] (date-time/period 0 0 (* 2 24 60 60 1000)) - #elm/quantity[1 "hour"] (date-time/period 0 0 (* 60 60 1000)) - #elm/quantity[2 "hours"] (date-time/period 0 0 (* 2 60 60 1000)) - #elm/quantity[1 "minute"] (date-time/period 0 0 (* 60 1000)) - #elm/quantity[2 "minutes"] (date-time/period 0 0 (* 2 60 1000)) - #elm/quantity[1 "second"] (date-time/period 0 0 1000) - #elm/quantity[2 "seconds"] (date-time/period 0 0 2000) - #elm/quantity[1 "millisecond"] (date-time/period 0 0 1) - #elm/quantity[2 "milliseconds"] (date-time/period 0 0 2) - #elm/quantity[1 "s"] (quantity/quantity 1 "s") - #elm/quantity[1 "cm2"] (quantity/quantity 1 "cm2"))) + #elm/quantity [1] (quantity/quantity 1 "") + #elm/quantity [1 "year"] (date-time/period 1 0 0) + #elm/quantity [2 "years"] (date-time/period 2 0 0) + #elm/quantity [1 "month"] (date-time/period 0 1 0) + #elm/quantity [2 "months"] (date-time/period 0 2 0) + #elm/quantity [1 "week"] (date-time/period 0 0 (* 7 24 60 60 1000)) + #elm/quantity [2 "weeks"] (date-time/period 0 0 (* 2 7 24 60 60 1000)) + #elm/quantity [1 "day"] (date-time/period 0 0 (* 24 60 60 1000)) + #elm/quantity [2 "days"] (date-time/period 0 0 (* 2 24 60 60 1000)) + #elm/quantity [1 "hour"] (date-time/period 0 0 (* 60 60 1000)) + #elm/quantity [2 "hours"] (date-time/period 0 0 (* 2 60 60 1000)) + #elm/quantity [1 "minute"] (date-time/period 0 0 (* 60 1000)) + #elm/quantity [2 "minutes"] (date-time/period 0 0 (* 2 60 1000)) + #elm/quantity [1 "second"] (date-time/period 0 0 1000) + #elm/quantity [2 "seconds"] (date-time/period 0 0 2000) + #elm/quantity [1 "millisecond"] (date-time/period 0 0 1) + #elm/quantity [2 "milliseconds"] (date-time/period 0 0 2) + #elm/quantity [1 "s"] (quantity/quantity 1 "s") + #elm/quantity [1 "cm2"] (quantity/quantity 1 "cm2"))) (testing "Periods" (satisfies-prop 100 diff --git a/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj b/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj index 595fa13bb..2908208f5 100644 --- a/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj @@ -83,7 +83,7 @@ "1" "2" false "2" "1" false) - (tu/testing-binary-null elm/equal #elm/integer"1")) + (tu/testing-binary-null elm/equal #elm/integer "1")) (testing "Decimal" (are [x y res] (= res (tu/compile-binop elm/equal elm/decimal x y)) @@ -94,22 +94,22 @@ "1.1" "1.10" true "1.10" "1.1" true) - (tu/testing-binary-null elm/equal #elm/decimal"1.1")) + (tu/testing-binary-null elm/equal #elm/decimal "1.1")) (testing "Mixed Integer Decimal" (are [x y res] (= res (c/compile {} (elm/equal [x y]))) - #elm/integer"1" #elm/decimal"1" true - #elm/decimal"1" #elm/integer"1" true)) + #elm/integer "1" #elm/decimal "1" true + #elm/decimal "1" #elm/integer "1" true)) (testing "Mixed Integer String" (are [x y res] (= res (c/compile {} (elm/equal [x y]))) - #elm/integer"1" #elm/string"1" false - #elm/string"1" #elm/integer"1" false)) + #elm/integer "1" #elm/string "1" false + #elm/string "1" #elm/integer "1" false)) (testing "Mixed Decimal String" (are [x y res] (= res (c/compile {} (elm/equal [x y]))) - #elm/decimal"1" #elm/string"1" false - #elm/string"1" #elm/decimal"1" false)) + #elm/decimal "1" #elm/string "1" false + #elm/string "1" #elm/decimal "1" false)) (testing "String" (are [x y res] (= res (tu/compile-binop elm/equal elm/string x y)) @@ -130,39 +130,39 @@ [1 "s"] [2 "s"] false [1 "s"] [1 "m"] false) - (tu/testing-binary-null elm/equal #elm/quantity[1])) + (tu/testing-binary-null elm/equal #elm/quantity [1])) ;; TODO: Ratio (testing "Tuple" (are [x y res] (= res (tu/compile-binop elm/equal elm/tuple x y)) {} {} true - {"id" #elm/string"1"} {"id" #elm/string"1"} true - {"id" #elm/string"1"} {"id" #elm/string"2"} false - {"id" #elm/string"1"} {"foo" #elm/string"1"} false)) + {"id" #elm/string "1"} {"id" #elm/string "1"} true + {"id" #elm/string "1"} {"id" #elm/string "2"} false + {"id" #elm/string "1"} {"foo" #elm/string "1"} false)) (testing "List" (are [x y res] (= res (tu/compile-binop elm/equal elm/list x y)) - [#elm/integer"1"] [#elm/integer"1"] true + [#elm/integer "1"] [#elm/integer "1"] true [] [] true - [#elm/integer"1"] [] false - [#elm/integer"1"] [#elm/integer"2"] false - [#elm/integer"1" #elm/integer"1"] - [#elm/integer"1" #elm/integer"2"] false + [#elm/integer "1"] [] false + [#elm/integer "1"] [#elm/integer "2"] false + [#elm/integer "1" #elm/integer "1"] + [#elm/integer "1" #elm/integer "2"] false - [#elm/integer"1" {:type "Null"}] [#elm/integer"1" {:type "Null"}] nil + [#elm/integer "1" {:type "Null"}] [#elm/integer "1" {:type "Null"}] nil [{:type "Null"}] [{:type "Null"}] nil - [#elm/date"2019"] [#elm/date"2019-01"] nil) + [#elm/date "2019"] [#elm/date "2019-01"] nil) (tu/testing-binary-null elm/equal #elm/list [])) (testing "Interval" (are [x y res] (= res (tu/compile-binop elm/equal elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] - [#elm/integer"1" #elm/integer"2"] true) + [#elm/integer "1" #elm/integer "2"] + [#elm/integer "1" #elm/integer "2"] true) - (tu/testing-binary-null elm/equal #elm/interval [#elm/integer"1" #elm/integer"2"])) + (tu/testing-binary-null elm/equal #elm/interval [#elm/integer "1" #elm/integer "2"])) (testing "Date with year precision" (are [x y res] (= res (tu/compile-binop elm/equal elm/date x y)) @@ -170,7 +170,7 @@ "2012" "2013" false "2013" "2012" false) - (tu/testing-binary-null elm/equal #elm/date"2013")) + (tu/testing-binary-null elm/equal #elm/date "2013")) (testing "Date with year-month precision" (are [x y res] (= res (tu/compile-binop elm/equal elm/date x y)) @@ -178,7 +178,7 @@ "2013-01" "2013-02" false "2013-02" "2013-01" false) - (tu/testing-binary-null elm/equal #elm/date"2013-01")) + (tu/testing-binary-null elm/equal #elm/date "2013-01")) (testing "Date with full precision" (are [x y res] (= res (tu/compile-binop elm/equal elm/date x y)) @@ -186,7 +186,7 @@ "2013-01-01" "2013-01-02" false "2013-01-02" "2013-01-01" false) - (tu/testing-binary-null elm/equal #elm/date"2013-01-01")) + (tu/testing-binary-null elm/equal #elm/date "2013-01-01")) (testing "Date with differing precisions" (are [x y res] (= res (tu/compile-binop elm/equal elm/date x y)) @@ -204,7 +204,7 @@ "2013-01-01T00" "2013-01-01T00:00:00" true) - (tu/testing-binary-null elm/equal #elm/date-time"2013-01-01")) + (tu/testing-binary-null elm/equal #elm/date-time "2013-01-01")) (testing "Time" (are [x y res] (= res (tu/compile-binop elm/equal elm/time x y)) @@ -216,7 +216,7 @@ "12:00" "12" nil) - (tu/testing-binary-null elm/equal #elm/time"12:30:15")) + (tu/testing-binary-null elm/equal #elm/time "12:30:15")) (testing "Code" (are [x y res] (= res (core/-eval (c/compile {} (elm/equal [x y])) {} nil nil)) @@ -230,7 +230,9 @@ (tu/code "a" "2010" "0") (tu/code "a" "2020" "0") false (tu/code "a" "2020" "0") (tu/code "a" "2010" "0") false) - (tu/testing-binary-null elm/equal (tu/code "a" "0")))) + (tu/testing-binary-null elm/equal (tu/code "a" "0"))) + + (tu/testing-binary-form elm/equal)) ;; 12.2. Equivalent @@ -296,64 +298,64 @@ (testing "Boolean" (are [x y res] (= res (core/-eval (c/compile {} (elm/equivalent [x y])) {} nil nil)) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" false + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" false - {:type "Null"} #elm/boolean"true" false - #elm/boolean"true" {:type "Null"} false)) + {:type "Null"} #elm/boolean "true" false + #elm/boolean "true" {:type "Null"} false)) (testing "Integer" (are [x y res] (= res (core/-eval (c/compile {} (elm/equivalent [x y])) {} nil nil)) - #elm/integer"1" #elm/integer"1" true - #elm/integer"1" #elm/integer"2" false + #elm/integer "1" #elm/integer "1" true + #elm/integer "1" #elm/integer "2" false - {:type "Null"} #elm/integer"1" false - #elm/integer"1" {:type "Null"} false)) + {:type "Null"} #elm/integer "1" false + #elm/integer "1" {:type "Null"} false)) (testing "Decimal" (are [x y res] (= res (core/-eval (c/compile {} (elm/equivalent [x y])) {} nil nil)) - #elm/decimal"1.1" #elm/decimal"1.1" true - #elm/decimal"1.1" #elm/decimal"2.1" false + #elm/decimal "1.1" #elm/decimal "1.1" true + #elm/decimal "1.1" #elm/decimal "2.1" false - {:type "Null"} #elm/decimal"1.1" false - #elm/decimal"1.1" {:type "Null"} false)) + {:type "Null"} #elm/decimal "1.1" false + #elm/decimal "1.1" {:type "Null"} false)) (testing "Mixed Integer Decimal" (are [x y res] (= res (core/-eval (c/compile {} (elm/equivalent [x y])) {} nil nil)) - #elm/integer"1" #elm/decimal"1" true - #elm/decimal"1" #elm/integer"1" true)) + #elm/integer "1" #elm/decimal "1" true + #elm/decimal "1" #elm/integer "1" true)) (testing "Quantity" (are [x y res] (= res (core/-eval (c/compile {} (elm/equivalent [x y])) {} nil nil)) - #elm/quantity[1] #elm/quantity[1] true - #elm/quantity[1] #elm/quantity[2] false + #elm/quantity [1] #elm/quantity [1] true + #elm/quantity [1] #elm/quantity [2] false - #elm/quantity[1 "s"] #elm/quantity[1 "s"] true - #elm/quantity[1 "m"] #elm/quantity[1 "m"] true - #elm/quantity[100 "cm"] #elm/quantity[1 "m"] true - #elm/quantity[1 "s"] #elm/quantity[2 "s"] false - #elm/quantity[1 "s"] #elm/quantity[1 "m"] false + #elm/quantity [1 "s"] #elm/quantity [1 "s"] true + #elm/quantity [1 "m"] #elm/quantity [1 "m"] true + #elm/quantity [100 "cm"] #elm/quantity [1 "m"] true + #elm/quantity [1 "s"] #elm/quantity [2 "s"] false + #elm/quantity [1 "s"] #elm/quantity [1 "m"] false - {:type "Null"} #elm/quantity[1] false - #elm/quantity[1] {:type "Null"} false + {:type "Null"} #elm/quantity [1] false + #elm/quantity [1] {:type "Null"} false - {:type "Null"} #elm/quantity[1 "s"] false - #elm/quantity[1 "s"] {:type "Null"} false)) + {:type "Null"} #elm/quantity [1 "s"] false + #elm/quantity [1 "s"] {:type "Null"} false)) (testing "List" (are [x y res] (= res (core/-eval (c/compile {} (elm/equivalent [x y])) {} nil nil)) - #elm/list [#elm/integer"1"] #elm/list [#elm/integer"1"] true + #elm/list [#elm/integer "1"] #elm/list [#elm/integer "1"] true #elm/list [] #elm/list [] true - #elm/list [#elm/integer"1"] #elm/list [] false - #elm/list [#elm/integer"1"] #elm/list [#elm/integer"2"] false - #elm/list [#elm/integer"1" #elm/integer"1"] - #elm/list [#elm/integer"1" #elm/integer"2"] false + #elm/list [#elm/integer "1"] #elm/list [] false + #elm/list [#elm/integer "1"] #elm/list [#elm/integer "2"] false + #elm/list [#elm/integer "1" #elm/integer "1"] + #elm/list [#elm/integer "1" #elm/integer "2"] false - #elm/list [#elm/integer"1" {:type "Null"}] - #elm/list [#elm/integer"1" {:type "Null"}] true + #elm/list [#elm/integer "1" {:type "Null"}] + #elm/list [#elm/integer "1" {:type "Null"}] true #elm/list [{:type "Null"}] #elm/list [{:type "Null"}] true - #elm/list [#elm/date"2019"] #elm/list [#elm/date"2019-01"] false + #elm/list [#elm/date "2019"] #elm/list [#elm/date "2019-01"] false {:type "Null"} #elm/list [] false #elm/list [] {:type "Null"} false)) @@ -371,7 +373,9 @@ (tu/code "a" "2020" "0") (tu/code "a" "2010" "0") true {:type "Null"} (tu/code "a" "0") false - (tu/code "a" "0") {:type "Null"} false))) + (tu/code "a" "0") {:type "Null"} false)) + + (tu/testing-binary-form elm/equivalent)) ;; 12.3. Greater @@ -405,14 +409,14 @@ "2" "1" true "1" "1" false) - (tu/testing-binary-null elm/greater #elm/integer"1")) + (tu/testing-binary-null elm/greater #elm/integer "1")) (testing "Decimal" (are [x y res] (= res (tu/compile-binop elm/greater elm/decimal x y)) "2.1" "1.1" true "1.1" "1.1" false) - (tu/testing-binary-null elm/greater #elm/decimal"1.1")) + (tu/testing-binary-null elm/greater #elm/decimal "1.1")) (testing "String" (are [x y res] (= res (tu/compile-binop elm/greater elm/string x y)) @@ -433,35 +437,35 @@ [1 "m"] [1 "m"] false [100 "cm"] [1 "m"] false) - (tu/testing-binary-null elm/greater #elm/quantity[1])) + (tu/testing-binary-null elm/greater #elm/quantity [1])) (testing "Date with year precision" (are [x y res] (= res (tu/compile-binop elm/greater elm/date x y)) "2014" "2013" true "2013" "2013" false) - (tu/testing-binary-null elm/greater #elm/date"2013")) + (tu/testing-binary-null elm/greater #elm/date "2013")) (testing "DateTime with year precision" (are [x y res] (= res (tu/compile-binop elm/greater elm/date-time x y)) "2014" "2013" true "2013" "2013" false) - (tu/testing-binary-null elm/greater #elm/date-time"2013")) + (tu/testing-binary-null elm/greater #elm/date-time "2013")) (testing "DateTime with year-month precision" (are [x y res] (= res (tu/compile-binop elm/greater elm/date-time x y)) "2013-07" "2013-06" true "2013-06" "2013-06" false) - (tu/testing-binary-null elm/greater #elm/date-time"2013-06")) + (tu/testing-binary-null elm/greater #elm/date-time "2013-06")) (testing "DateTime with date precision" (are [x y res] (= res (tu/compile-binop elm/greater elm/date-time x y)) "2013-06-16" "2013-06-15" true "2013-06-15" "2013-06-15" false) - (tu/testing-binary-null elm/greater #elm/date-time"2013-06-15")) + (tu/testing-binary-null elm/greater #elm/date-time "2013-06-15")) (testing "Comparing dates with mixed precisions (year and year-month) results in null." (are [x y res] (= res (tu/compile-binop elm/greater elm/date x y)) @@ -473,7 +477,9 @@ "00:00:01" "00:00:00" true "00:00:00" "00:00:00" false) - (tu/testing-binary-null elm/greater #elm/time"00:00:00"))) + (tu/testing-binary-null elm/greater #elm/time "00:00:00")) + + (tu/testing-binary-form elm/greater)) ;; 12.4. GreaterOrEqual @@ -508,7 +514,7 @@ "2" "1" true "1" "2" false) - (tu/testing-binary-null elm/greater-or-equal #elm/integer"1")) + (tu/testing-binary-null elm/greater-or-equal #elm/integer "1")) (testing "Decimal" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/decimal x y)) @@ -516,7 +522,7 @@ "2.1" "1.1" true "1.1" "2.1" false) - (tu/testing-binary-null elm/greater-or-equal #elm/decimal"1.1")) + (tu/testing-binary-null elm/greater-or-equal #elm/decimal "1.1")) (testing "String" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/string x y)) @@ -532,7 +538,7 @@ "2013-06-15" "2013-06-15" true "2013-06-14" "2013-06-15" false) - (tu/testing-binary-null elm/greater-or-equal #elm/date"2013-06-15")) + (tu/testing-binary-null elm/greater-or-equal #elm/date "2013-06-15")) (testing "DateTime with year precision" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/date-time x y)) @@ -540,7 +546,7 @@ "2013" "2013" true "2012" "2013" false) - (tu/testing-binary-null elm/greater-or-equal #elm/date"2013")) + (tu/testing-binary-null elm/greater-or-equal #elm/date "2013")) (testing "DateTime with year-month precision" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/date-time x y)) @@ -548,7 +554,7 @@ "2013-06" "2013-06" true "2013-05" "2013-06" false) - (tu/testing-binary-null elm/greater-or-equal #elm/date"2013-06")) + (tu/testing-binary-null elm/greater-or-equal #elm/date "2013-06")) (testing "DateTime with date precision" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/date-time x y)) @@ -556,7 +562,7 @@ "2013-06-15" "2013-06-15" true "2013-06-14" "2013-06-15" false) - (tu/testing-binary-null elm/greater-or-equal #elm/date"2013-06-15")) + (tu/testing-binary-null elm/greater-or-equal #elm/date "2013-06-15")) (testing "Time" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/time x y)) @@ -564,7 +570,7 @@ "00:00:01" "00:00:00" true "00:00:00" "00:00:01" false) - (tu/testing-binary-null elm/greater-or-equal #elm/time"00:00:00")) + (tu/testing-binary-null elm/greater-or-equal #elm/time "00:00:00")) (testing "Quantity" (are [x y res] (= res (tu/compile-binop elm/greater-or-equal elm/quantity x y)) @@ -580,7 +586,9 @@ [100 "cm"] [1 "m"] true [1 "m"] [101 "cm"] false) - (tu/testing-binary-null elm/greater-or-equal #elm/quantity[1]))) + (tu/testing-binary-null elm/greater-or-equal #elm/quantity [1])) + + (tu/testing-binary-form elm/greater-or-equal)) ;; 12.5. Less @@ -612,14 +620,14 @@ "1" "2" true "1" "1" false) - (tu/testing-binary-null elm/less #elm/integer"1")) + (tu/testing-binary-null elm/less #elm/integer "1")) (testing "Decimal" (are [x y res] (= res (tu/compile-binop elm/less elm/decimal x y)) "1.1" "2.1" true "1.1" "1.1" false) - (tu/testing-binary-null elm/less #elm/decimal"1.1")) + (tu/testing-binary-null elm/less #elm/decimal "1.1")) (testing "String" (are [x y res] (= res (tu/compile-binop elm/less elm/string x y)) @@ -633,7 +641,7 @@ "2012" "2013" true "2013" "2013" false) - (tu/testing-binary-null elm/less #elm/date"2013")) + (tu/testing-binary-null elm/less #elm/date "2013")) (testing "Comparing dates with mixed precisions (year and year-month) results in null." (are [x y res] (= res (tu/compile-binop elm/less elm/date x y)) @@ -645,7 +653,7 @@ "2013-06-14" "2013-06-15" true "2013-06-15" "2013-06-15" false) - (tu/testing-binary-null elm/less #elm/date"2013-06-15")) + (tu/testing-binary-null elm/less #elm/date "2013-06-15")) (testing "Comparing dates with mixed precisions (year-month and full) results in null." (are [x y res] (= res (tu/compile-binop elm/less elm/date x y)) @@ -657,35 +665,35 @@ "2012" "2013" true "2013" "2013" false) - (tu/testing-binary-null elm/less #elm/date-time"2013")) + (tu/testing-binary-null elm/less #elm/date-time "2013")) (testing "DateTime with year-month precision" (are [x y res] (= res (tu/compile-binop elm/less elm/date-time x y)) "2013-05" "2013-06" true "2013-06" "2013-06" false) - (tu/testing-binary-null elm/less #elm/date-time"2013-06")) + (tu/testing-binary-null elm/less #elm/date-time "2013-06")) (testing "DateTime with date precision" (are [x y res] (= res (tu/compile-binop elm/less elm/date-time x y)) "2013-06-14" "2013-06-15" true "2013-06-15" "2013-06-15" false) - (tu/testing-binary-null elm/less #elm/date-time"2013-06-15")) + (tu/testing-binary-null elm/less #elm/date-time "2013-06-15")) (testing "DateTime with full precision (there is only one precision)" (are [x y res] (= res (tu/compile-binop elm/less elm/date-time x y)) "2013-06-15T11" "2013-06-15T12" true "2013-06-15T12" "2013-06-15T12" false) - (tu/testing-binary-null elm/less #elm/date-time"2013-06-15T12")) + (tu/testing-binary-null elm/less #elm/date-time "2013-06-15T12")) (testing "Time with full precision (there is only one precision)" (are [x y res] (= res (tu/compile-binop elm/less elm/time x y)) "12:30:14" "12:30:15" true "12:30:15" "12:30:15" false) - (tu/testing-binary-null elm/less #elm/time"12:30:15")) + (tu/testing-binary-null elm/less #elm/time "12:30:15")) (testing "Quantity" (are [x y res] (= res (tu/compile-binop elm/less elm/quantity x y)) @@ -698,7 +706,9 @@ [1 "m"] [101 "cm"] true [1 "m"] [100 "cm"] false) - (tu/testing-binary-null elm/less #elm/quantity[1]))) + (tu/testing-binary-null elm/less #elm/quantity [1])) + + (tu/testing-binary-form elm/less)) ;; 12.6. LessOrEqual @@ -733,7 +743,7 @@ "1" "2" true "2" "1" false) - (tu/testing-binary-null elm/less-or-equal #elm/integer"1")) + (tu/testing-binary-null elm/less-or-equal #elm/integer "1")) (testing "Decimal" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/decimal x y)) @@ -741,7 +751,7 @@ "1.1" "2.1" true "2.1" "1.1" false) - (tu/testing-binary-null elm/less-or-equal #elm/decimal"1.1")) + (tu/testing-binary-null elm/less-or-equal #elm/decimal "1.1")) (testing "Date with full precision" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/date x y)) @@ -749,12 +759,12 @@ "2013-06-15" "2013-06-15" true "2013-06-16" "2013-06-15" false) - (tu/testing-binary-null elm/less-or-equal #elm/date"2013-06-15")) + (tu/testing-binary-null elm/less-or-equal #elm/date "2013-06-15")) (testing "Mixed Date and DateTime" (are [x y res] (= res (c/compile {} (elm/less-or-equal [x y]))) - #elm/date"2013-06-15" #elm/date-time"2013-06-15T00" nil - #elm/date-time"2013-06-15T00" #elm/date"2013-06-15" nil)) + #elm/date "2013-06-15" #elm/date-time "2013-06-15T00" nil + #elm/date-time "2013-06-15T00" #elm/date "2013-06-15" nil)) (testing "DateTime with year precision" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/date-time x y)) @@ -762,7 +772,7 @@ "2013" "2013" true "2014" "2013" false) - (tu/testing-binary-null elm/less-or-equal #elm/date"2013")) + (tu/testing-binary-null elm/less-or-equal #elm/date "2013")) (testing "DateTime with year-month precision" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/date-time x y)) @@ -770,7 +780,7 @@ "2013-06" "2013-06" true "2013-07" "2013-06" false) - (tu/testing-binary-null elm/less-or-equal #elm/date"2013-06")) + (tu/testing-binary-null elm/less-or-equal #elm/date "2013-06")) (testing "DateTime with date precision" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/date-time x y)) @@ -778,7 +788,7 @@ "2013-06-15" "2013-06-15" true "2013-06-16" "2013-06-15" false) - (tu/testing-binary-null elm/less-or-equal #elm/date"2013-06-15")) + (tu/testing-binary-null elm/less-or-equal #elm/date "2013-06-15")) (testing "Time" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/time x y)) @@ -786,7 +796,7 @@ "00:00:00" "00:00:01" true "00:00:01" "00:00:00" false) - (tu/testing-binary-null elm/less-or-equal #elm/time"00:00:00")) + (tu/testing-binary-null elm/less-or-equal #elm/time "00:00:00")) (testing "Quantity" (are [x y res] (= res (tu/compile-binop elm/less-or-equal elm/quantity x y)) @@ -802,7 +812,9 @@ [1 "m"] [100 "cm"] true [101 "cm"] [1 "m"] false) - (tu/testing-binary-null elm/less-or-equal #elm/quantity[1]))) + (tu/testing-binary-null elm/less-or-equal #elm/quantity [1])) + + (tu/testing-binary-form elm/less-or-equal)) ;; 12.7. NotEqual @@ -810,183 +822,3 @@ ;; Normalized to Not Equal (deftest compile-not-equal-test (tu/unsupported-binary-operand "NotEqual")) - - - -;; 13. Logical Operators - -;; 13.1. And -;; -;; The And operator returns the logical conjunction of its arguments. Note that -;; this operator is defined using 3-valued logic semantics. This means that if -;; either argument is false, the result is false; if both arguments are true, -;; the result is true; otherwise, the result is null. Note also that ELM does -;; not prescribe short-circuit evaluation. -(deftest compile-and-test - (testing "Static" - (are [x y res] (= res (c/compile {} (elm/and [x y]))) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" false - #elm/boolean"true" {:type "Null"} nil - - #elm/boolean"false" #elm/boolean"true" false - #elm/boolean"false" #elm/boolean"false" false - #elm/boolean"false" {:type "Null"} false - - {:type "Null"} #elm/boolean"true" nil - {:type "Null"} #elm/boolean"false" false - {:type "Null"} {:type "Null"} nil)) - - (testing "Dynamic" - (are [x y res] (= res (tu/dynamic-compile-eval (elm/and [x y]))) - #elm/boolean"true" #elm/parameter-ref"true" true - #elm/parameter-ref"true" #elm/boolean"true" true - #elm/parameter-ref"true" #elm/parameter-ref"true" true - #elm/parameter-ref"true" {:type "Null"} nil - {:type "Null"} #elm/parameter-ref"true" nil - - #elm/boolean"true" #elm/parameter-ref"false" false - #elm/parameter-ref"false" #elm/boolean"true" false - #elm/parameter-ref"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" {:type "Null"} false - {:type "Null"} #elm/parameter-ref"false" false - - #elm/boolean"false" #elm/parameter-ref"nil" false - #elm/parameter-ref"nil" #elm/boolean"false" false - #elm/boolean"true" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"true" nil - #elm/parameter-ref"nil" #elm/parameter-ref"nil" nil))) - - -;; 13.2. Implies -;; -;; The Implies operator returns the logical implication of its arguments. Note -;; that this operator is defined using 3-valued logic semantics. This means that -;; if the left operand evaluates to true, this operator returns the boolean -;; evaluation of the right operand. If the left operand evaluates to false, this -;; operator returns true. Otherwise, this operator returns true if the right -;; operand evaluates to true, and null otherwise. -;; -;; Note that implies may use short-circuit evaluation in the case that the first -;; operand evaluates to false. -(deftest compile-implies-test - (are [x y res] (= res (core/-eval (c/compile {} {:type "Or" :operand [{:type "Not" :operand x} y]}) {} nil nil)) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" false - #elm/boolean"true" {:type "Null"} nil - - #elm/boolean"false" #elm/boolean"true" true - #elm/boolean"false" #elm/boolean"false" true - #elm/boolean"false" {:type "Null"} true - - {:type "Null"} #elm/boolean"true" true - {:type "Null"} #elm/boolean"false" nil - {:type "Null"} {:type "Null"} nil)) - - -;; 13.3. Not -;; -;; The Not operator returns the logical negation of its argument. If the -;; argument is true, the result is false; if the argument is false, the result -;; is true; otherwise, the result is null. -(deftest compile-not-test - (testing "Static" - (are [x res] (= res (c/compile {} (elm/not x))) - #elm/boolean"true" false - #elm/boolean"false" true - {:type "Null"} nil)) - - (testing "Dynamic" - (are [x res] (= res (tu/dynamic-compile-eval (elm/not x))) - #elm/parameter-ref"true" false - #elm/parameter-ref"false" true - #elm/parameter-ref"nil" nil))) - - -;; 13.4. Or -;; -;; The Or operator returns the logical disjunction of its arguments. Note that -;; this operator is defined using 3-valued logic semantics. This means that if -;; either argument is true, the result is true; if both arguments are false, the -;; result is false; otherwise, the result is null. Note also that ELM does not -;; prescribe short-circuit evaluation. -(deftest compile-or-test - (testing "Static" - (are [x y res] (= res (c/compile {} (elm/or [x y]))) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" true - #elm/boolean"true" {:type "Null"} true - - #elm/boolean"false" #elm/boolean"true" true - #elm/boolean"false" #elm/boolean"false" false - #elm/boolean"false" {:type "Null"} nil - - {:type "Null"} #elm/boolean"true" true - {:type "Null"} #elm/boolean"false" nil - {:type "Null"} {:type "Null"} nil)) - - (testing "Dynamic" - (are [x y res] (= res (tu/dynamic-compile-eval (elm/or [x y]))) - #elm/boolean"false" #elm/parameter-ref"true" true - #elm/parameter-ref"true" #elm/boolean"false" true - #elm/parameter-ref"true" #elm/parameter-ref"true" true - #elm/parameter-ref"true" {:type "Null"} true - {:type "Null"} #elm/parameter-ref"true" true - - #elm/boolean"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" #elm/boolean"false" false - #elm/parameter-ref"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" {:type "Null"} nil - {:type "Null"} #elm/parameter-ref"false" nil - - #elm/boolean"true" #elm/parameter-ref"nil" true - #elm/parameter-ref"nil" #elm/boolean"true" true - #elm/boolean"false" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"false" nil - #elm/parameter-ref"nil" #elm/parameter-ref"nil" nil))) - - -;; 13.5. Xor -;; -;; The Xor operator returns the exclusive or of its arguments. Note that this -;; operator is defined using 3-valued logic semantics. This means that the -;; result is true if and only if one argument is true and the other is false, -;; and that the result is false if and only if both arguments are true or both -;; arguments are false. If either or both arguments are null, the result is -;; null. -(deftest compile-xor-test - (testing "Static" - (are [x y res] (= res (c/compile {} (elm/xor [x y]))) - #elm/boolean"true" #elm/boolean"true" false - #elm/boolean"true" #elm/boolean"false" true - #elm/boolean"true" {:type "Null"} nil - - #elm/boolean"false" #elm/boolean"true" true - #elm/boolean"false" #elm/boolean"false" false - #elm/boolean"false" {:type "Null"} nil - - {:type "Null"} #elm/boolean"true" nil - {:type "Null"} #elm/boolean"false" nil - {:type "Null"} {:type "Null"} nil)) - - (testing "Dynamic" - (are [x y res] (= res (tu/dynamic-compile-eval (elm/xor [x y]))) - #elm/boolean"true" #elm/parameter-ref"true" false - #elm/parameter-ref"true" #elm/boolean"true" false - #elm/boolean"false" #elm/parameter-ref"true" true - #elm/parameter-ref"true" #elm/boolean"false" true - #elm/parameter-ref"true" #elm/parameter-ref"true" false - - #elm/boolean"true" #elm/parameter-ref"false" true - #elm/parameter-ref"false" #elm/boolean"true" true - #elm/boolean"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" #elm/boolean"false" false - #elm/parameter-ref"false" #elm/parameter-ref"false" false - - #elm/boolean"true" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"true" nil - #elm/boolean"false" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"false" nil - {:type "Null"} #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" {:type "Null"} nil - #elm/parameter-ref"nil" #elm/parameter-ref"nil" nil))) diff --git a/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj b/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj index 166957031..ba936a8cb 100644 --- a/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj @@ -35,12 +35,12 @@ (deftest compile-if-test (testing "Static" (are [elm res] (= res (c/compile {} elm)) - #elm/if[#elm/boolean "true" #elm/integer"1" #elm/integer"2"] 1 - #elm/if[#elm/boolean "false" #elm/integer"1" #elm/integer"2"] 2 - #elm/if[{:type "Null"} #elm/integer"1" #elm/integer"2"] 2)) + #elm/if [#elm/boolean "true" #elm/integer "1" #elm/integer "2"] 1 + #elm/if [#elm/boolean "false" #elm/integer "1" #elm/integer "2"] 2 + #elm/if [{:type "Null"} #elm/integer "1" #elm/integer "2"] 2)) (testing "Dynamic" (are [elm res] (= res (tu/dynamic-compile-eval elm)) - #elm/if[#elm/parameter-ref"true" #elm/integer"1" #elm/integer"2"] 1 - #elm/if[#elm/parameter-ref"false" #elm/integer"1" #elm/integer"2"] 2 - #elm/if[#elm/parameter-ref"nil" #elm/integer"1" #elm/integer"2"] 2))) + #elm/if [#elm/parameter-ref "true" #elm/integer "1" #elm/integer "2"] 1 + #elm/if [#elm/parameter-ref "false" #elm/integer "1" #elm/integer "2"] 2 + #elm/if [#elm/parameter-ref "nil" #elm/integer "1" #elm/integer "2"] 2))) diff --git a/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj b/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj index b097837e2..7171bc51e 100644 --- a/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj @@ -73,55 +73,55 @@ ;; null, but if it is, day must be null as well. (deftest compile-date-test (testing "Static Null year" - (is (nil? (c/compile {} #elm/date[{:type "null"}])))) + (is (nil? (c/compile {} #elm/date [{:type "null"}])))) (testing "Static year" - (is (= (system/date 2019) (c/compile {} #elm/date"2019")))) + (is (= (system/date 2019) (c/compile {} #elm/date "2019")))) (testing "Static year over 10.000" - (given (ba/try-anomaly (c/compile {} #elm/date"10001")) + (given (ba/try-anomaly (c/compile {} #elm/date "10001")) ::anom/category := ::anom/incorrect ::anom/message := "Year `10001` out of range.")) (testing "Dynamic year has type :system/date" (let [compile-ctx {:library {:parameters {:def [{:name "year"}]}}} - elm #elm/date[#elm/parameter-ref"year"]] + elm #elm/date [#elm/parameter-ref "year"]] (is (= :system/date (system/type (c/compile compile-ctx elm)))))) (testing "Dynamic Null year" (let [compile-ctx {:library {:parameters {:def [{:name "year"}]}}} - elm #elm/date[#elm/parameter-ref"year"] + elm #elm/date [#elm/parameter-ref "year"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"year" nil}}] (is (nil? (core/-eval expr eval-ctx nil nil))))) (testing "Dynamic year" (let [compile-ctx {:library {:parameters {:def [{:name "year"}]}}} - elm #elm/date[#elm/parameter-ref"year"] + elm #elm/date [#elm/parameter-ref "year"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"year" 2019}}] (is (= (system/date 2019) (core/-eval expr eval-ctx nil nil))))) (testing "Dynamic Null month" (let [compile-ctx {:library {:parameters {:def [{:name "month"}]}}} - elm #elm/date[#elm/integer"2018" #elm/parameter-ref"month"] + elm #elm/date [#elm/integer "2018" #elm/parameter-ref "month"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"month" nil}}] (is (= (system/date 2018) (core/-eval expr eval-ctx nil nil))))) (testing "Static year-month" (are [elm res] (= res (c/compile {} elm)) - #elm/date"2019-03" + #elm/date "2019-03" (system/date 2019 3))) (testing "Dynamic year-month has type :system/date" (let [compile-ctx {:library {:parameters {:def [{:name "month"}]}}} - elm #elm/date[#elm/integer"2019" #elm/parameter-ref"month"]] + elm #elm/date [#elm/integer "2019" #elm/parameter-ref "month"]] (is (= :system/date (system/type (c/compile compile-ctx elm)))))) (testing "Dynamic year-month" (let [compile-ctx {:library {:parameters {:def [{:name "month"}]}}} - elm #elm/date[#elm/integer"2019" #elm/parameter-ref"month"] + elm #elm/date [#elm/integer "2019" #elm/parameter-ref "month"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"month" 3}}] (is (= (system/date 2019 3) (core/-eval expr eval-ctx nil nil))))) @@ -129,39 +129,39 @@ (testing "Dynamic Null month and day" (let [compile-ctx {:library {:parameters {:def [{:name "month"} {:name "day"}]}}} - elm #elm/date[#elm/integer"2020" - #elm/parameter-ref"month" - #elm/parameter-ref"day"] + elm #elm/date [#elm/integer "2020" + #elm/parameter-ref "month" + #elm/parameter-ref "day"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"month" nil "day" nil}}] (is (= (system/date 2020) (core/-eval expr eval-ctx nil nil))))) (testing "Dynamic date has type :system/date" (let [compile-ctx {:library {:parameters {:def [{:name "day"}]}}} - elm #elm/date[#elm/integer"2018" - #elm/integer"5" - #elm/parameter-ref"day"]] + elm #elm/date [#elm/integer "2018" + #elm/integer "5" + #elm/parameter-ref "day"]] (is (= :system/date (system/type (c/compile compile-ctx elm)))))) (testing "Dynamic Null day" (let [compile-ctx {:library {:parameters {:def [{:name "day"}]}}} - elm #elm/date[#elm/integer"2018" - #elm/integer"5" - #elm/parameter-ref"day"] + elm #elm/date [#elm/integer "2018" + #elm/integer "5" + #elm/parameter-ref "day"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"day" nil}}] (is (= (system/date 2018 5) (core/-eval expr eval-ctx nil nil))))) (testing "Static date" (are [elm res] (= res (c/compile {} elm)) - #elm/date"2019-03-23" + #elm/date "2019-03-23" (system/date 2019 3 23))) (testing "Dynamic date" (let [compile-ctx {:library {:parameters {:def [{:name "day"}]}}} - elm #elm/date[#elm/integer"2019" - #elm/integer"3" - #elm/parameter-ref"day"] + elm #elm/date [#elm/integer "2019" + #elm/integer "3" + #elm/parameter-ref "day"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"day" 23}}] (is (= (system/date 2019 3 23) (core/-eval expr eval-ctx nil nil))))) @@ -189,11 +189,13 @@ ;; ;; If the argument is null, the result is null. (deftest compile-date-from-test - (are [x res] (= res (core/-eval (c/compile {} (elm/date-from x)) {:now tu/now} nil nil)) - #elm/date"2019-04-17" (system/date 2019 4 17) - #elm/date-time"2019-04-17T12:48" (system/date 2019 4 17)) + (are [x res] (= res (c/compile {} (elm/date-from x))) + #elm/date "2019-04-17" (system/date 2019 4 17) + #elm/date-time "2019-04-17T12:48" (system/date 2019 4 17)) - (tu/testing-unary-null elm/date-from)) + (tu/testing-unary-null elm/date-from) + + (tu/testing-unary-form elm/date-from)) ;; 18.8. DateTime @@ -212,37 +214,37 @@ (is (nil? (c/compile {} #elm/date-time[{:type "null"}])))) (testing "Static year" - (is (= (system/date-time 2019) (c/compile {} #elm/date-time"2019")))) + (is (= (system/date-time 2019) (c/compile {} #elm/date-time "2019")))) (testing "Dynamic Null year" (let [compile-ctx {:library {:parameters {:def [{:name "year"}]}}} - elm #elm/date-time[#elm/parameter-ref"year"] + elm #elm/date-time[#elm/parameter-ref "year"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"year" nil}}] (is (nil? (core/-eval expr eval-ctx nil nil))))) (testing "Dynamic year" (let [compile-ctx {:library {:parameters {:def [{:name "year"}]}}} - elm #elm/date-time[#elm/parameter-ref"year"] + elm #elm/date-time[#elm/parameter-ref "year"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"year" 2019}}] (is (= (system/date-time 2019) (core/-eval expr eval-ctx nil nil))))) (testing "Dynamic Null month" (let [compile-ctx {:library {:parameters {:def [{:name "month"}]}}} - elm #elm/date-time[#elm/integer"2018" #elm/parameter-ref"month"] + elm #elm/date-time[#elm/integer "2018" #elm/parameter-ref "month"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"month" nil}}] (is (= (system/date-time 2018) (core/-eval expr eval-ctx nil nil))))) (testing "Static year-month" (are [elm res] (= res (c/compile {} elm)) - #elm/date-time"2019-03" + #elm/date-time "2019-03" (system/date-time 2019 3))) (testing "Dynamic year-month" (let [compile-ctx {:library {:parameters {:def [{:name "month"}]}}} - elm #elm/date-time[#elm/integer"2019" #elm/parameter-ref"month"] + elm #elm/date-time[#elm/integer "2019" #elm/parameter-ref "month"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"month" 3}}] (is (= (system/date-time 2019 3) (core/-eval expr eval-ctx nil nil))))) @@ -250,47 +252,47 @@ (testing "Dynamic Null month and day" (let [compile-ctx {:library {:parameters {:def [{:name "month"} {:name "day"}]}}} - elm #elm/date-time[#elm/integer"2020" - #elm/parameter-ref"month" - #elm/parameter-ref"day"] + elm #elm/date-time[#elm/integer "2020" + #elm/parameter-ref "month" + #elm/parameter-ref "day"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"month" nil "day" nil}}] (is (= (system/date-time 2020) (core/-eval expr eval-ctx nil nil))))) (testing "Dynamic Null day" (let [compile-ctx {:library {:parameters {:def [{:name "day"}]}}} - elm #elm/date-time[#elm/integer"2018" - #elm/integer"5" - #elm/parameter-ref"day"] + elm #elm/date-time[#elm/integer "2018" + #elm/integer "5" + #elm/parameter-ref "day"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"day" nil}}] (is (= (system/date-time 2018 5) (core/-eval expr eval-ctx nil nil))))) (testing "Static date" (are [elm res] (= res (c/compile {} elm)) - #elm/date-time"2019-03-23" + #elm/date-time "2019-03-23" (system/date-time 2019 3 23))) (testing "Dynamic date" (let [compile-ctx {:library {:parameters {:def [{:name "day"}]}}} - elm #elm/date-time[#elm/integer"2019" - #elm/integer"3" - #elm/parameter-ref"day"] + elm #elm/date-time[#elm/integer "2019" + #elm/integer "3" + #elm/parameter-ref "day"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"day" 23}}] (is (= (system/date-time 2019 3 23) (core/-eval expr eval-ctx nil nil))))) (testing "Static hour" (are [elm res] (= res (c/compile {} elm)) - #elm/date-time"2019-03-23T12" + #elm/date-time "2019-03-23T12" (system/date-time 2019 3 23 12 0 0))) (testing "Dynamic hour" (let [compile-ctx {:library {:parameters {:def [{:name "hour"}]}}} - elm #elm/date-time[#elm/integer"2019" - #elm/integer"3" - #elm/integer"23" - #elm/parameter-ref"hour"] + elm #elm/date-time[#elm/integer "2019" + #elm/integer "3" + #elm/integer "23" + #elm/parameter-ref "hour"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"hour" 12}}] (is (= (system/date-time 2019 3 23 12 0 0) @@ -298,60 +300,60 @@ (testing "minute" (are [elm res] (= res (c/compile {} elm)) - #elm/date-time"2019-03-23T12:13" + #elm/date-time "2019-03-23T12:13" (system/date-time 2019 3 23 12 13 0))) (testing "second" (are [elm res] (= res (c/compile {} elm)) - #elm/date-time"2019-03-23T12:13:14" + #elm/date-time "2019-03-23T12:13:14" (system/date-time 2019 3 23 12 13 14))) (testing "millisecond" (are [elm res] (= res (c/compile {} elm)) - #elm/date-time"2019-03-23T12:13:14.1" + #elm/date-time "2019-03-23T12:13:14.1" (system/date-time 2019 3 23 12 13 14 1))) (testing "Invalid DateTime above max value" (are [elm] (thrown? Exception (c/compile {} elm)) - #elm/date-time"10000-12-31T23:59:59.999")) + #elm/date-time "10000-12-31T23:59:59.999")) (testing "with offset" (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) - #elm/date-time[#elm/integer"2019" #elm/integer"3" #elm/integer"23" - #elm/integer"12" #elm/integer"13" #elm/integer"14" #elm/integer"0" - #elm/decimal"-2"] + #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" + #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" + #elm/decimal "-2"] (system/date-time 2019 3 23 14 13 14) - #elm/date-time[#elm/integer"2019" #elm/integer"3" #elm/integer"23" - #elm/integer"12" #elm/integer"13" #elm/integer"14" #elm/integer"0" - #elm/decimal"-1"] + #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" + #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" + #elm/decimal "-1"] (system/date-time 2019 3 23 13 13 14) - #elm/date-time[#elm/integer"2019" #elm/integer"3" #elm/integer"23" - #elm/integer"12" #elm/integer"13" #elm/integer"14" #elm/integer"0" - #elm/decimal"0"] + #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" + #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" + #elm/decimal "0"] (system/date-time 2019 3 23 12 13 14) - #elm/date-time[#elm/integer"2019" #elm/integer"3" #elm/integer"23" - #elm/integer"12" #elm/integer"13" #elm/integer"14" #elm/integer"0" - #elm/decimal"1"] + #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" + #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" + #elm/decimal "1"] (system/date-time 2019 3 23 11 13 14) - #elm/date-time[#elm/integer"2019" #elm/integer"3" #elm/integer"23" - #elm/integer"12" #elm/integer"13" #elm/integer"14" #elm/integer"0" - #elm/decimal"2"] + #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" + #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" + #elm/decimal "2"] (system/date-time 2019 3 23 10 13 14) - #elm/date-time[#elm/integer"2012" #elm/integer"3" #elm/integer"10" - #elm/integer"10" #elm/integer"20" #elm/integer"0" #elm/integer"999" - #elm/decimal"7"] + #elm/date-time[#elm/integer "2012" #elm/integer "3" #elm/integer "10" + #elm/integer "10" #elm/integer "20" #elm/integer "0" #elm/integer "999" + #elm/decimal "7"] (system/date-time 2012 3 10 3 20 0 999))) (testing "with decimal offset" (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) - #elm/date-time[#elm/integer"2019" #elm/integer"3" #elm/integer"23" - #elm/integer"12" #elm/integer"13" #elm/integer"14" #elm/integer"0" - #elm/decimal"1.5"] + #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" + #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" + #elm/decimal "1.5"] (system/date-time 2019 3 23 10 43 14))) (testing "an ELM date-time (only literals) always evaluates to something implementing Temporal" @@ -387,7 +389,10 @@ "2019-04-17" "Day" 17)) (are [x precision res] (= res (eval (compile elm/date-time x precision))) - "2019-04-17T12:48" "Hour" 12))) + "2019-04-17T12:48" "Hour" 12)) + + (tu/testing-unary-precision-form elm/date-time-component-from "Year" "Month" + "Day" "Hour" "Minute" "Second" "Millisecond")) ;; 18.10. DifferenceBetween @@ -454,7 +459,9 @@ "2018" "2018" "Month" "2018-01" "2018-01" "Day" - "2018-01-01" "2018-01-01" "Hour"))))) + "2018-01-01" "2018-01-01" "Hour")))) + + (tu/testing-binary-precision-form elm/difference-between "Year" "Month" "Day")) ;; 18.11. DurationBetween @@ -520,7 +527,9 @@ "2018" "2018" "Month" "2018-01" "2018-01" "Day" - "2018-01-01" "2018-01-01" "Hour"))))) + "2018-01-01" "2018-01-01" "Hour")))) + + (tu/testing-binary-precision-form elm/duration-between "Year" "Month" "Day")) ;; 18.12. Not Equal @@ -528,6 +537,24 @@ ;; See 12.7. NotEqual +;; 18.13. Now +;; +;; The Now operator returns the date and time of the start timestamp associated +;; with the evaluation request. Now is defined in this way for two reasons: +;; +;; 1) The operation will always return the same value within any given +;; evaluation, ensuring that the result of an expression containing Now will +;; always return the same result. +;; +;; 2) The operation will return the timestamp associated with the evaluation +;; request, allowing the evaluation to be performed with the same timezone +;; offset information as the data delivered with the evaluation request. +(deftest compile-now-test + (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) + {:type "Now"} + tu/now)) + + ;; 18.14. SameAs ;; ;; The SameAs operator is defined for Date, DateTime, and Time values, as well @@ -574,9 +601,9 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-18" false) - (tu/testing-binary-null elm/same-as #elm/date"2019") - (tu/testing-binary-null elm/same-as #elm/date"2019-04") - (tu/testing-binary-null elm/same-as #elm/date"2019-04-17") + (tu/testing-binary-null elm/same-as #elm/date "2019") + (tu/testing-binary-null elm/same-as #elm/date "2019-04") + (tu/testing-binary-null elm/same-as #elm/date "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/same-as elm/date x y "year")) @@ -596,9 +623,9 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-18" false) - (tu/testing-binary-null elm/same-as #elm/date-time"2019") - (tu/testing-binary-null elm/same-as #elm/date-time"2019-04") - (tu/testing-binary-null elm/same-as #elm/date-time"2019-04-17") + (tu/testing-binary-null elm/same-as #elm/date-time "2019") + (tu/testing-binary-null elm/same-as #elm/date-time "2019-04") + (tu/testing-binary-null elm/same-as #elm/date-time "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/same-as elm/date-time x y "year")) @@ -607,25 +634,9 @@ "2019-04" "2019-04" true "2019-04" "2019-05" true "2019-04-17" "2019-04-17" true - "2019-04-17" "2019-04-18" true)))) - + "2019-04-17" "2019-04-18" true))) -;; 18.13. Now -;; -;; The Now operator returns the date and time of the start timestamp associated -;; with the evaluation request. Now is defined in this way for two reasons: -;; -;; 1) The operation will always return the same value within any given -;; evaluation, ensuring that the result of an expression containing Now will -;; always return the same result. -;; -;; 2) The operation will return the timestamp associated with the evaluation -;; request, allowing the evaluation to be performed with the same timezone -;; offset information as the data delivered with the evaluation request. -(deftest compile-now-test - (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) - {:type "Now"} - tu/now)) + (tu/testing-binary-precision-form elm/same-as)) ;; 18.15. SameOrBefore @@ -674,8 +685,8 @@ (deftest compile-same-or-before-test (testing "Interval" (are [x y res] (= res (tu/compile-binop elm/same-or-before elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] - [#elm/integer"2" #elm/integer"3"] true)) + [#elm/integer "1" #elm/integer "2"] + [#elm/integer "2" #elm/integer "3"] true)) (testing "Date" (are [x y res] (= res (tu/compile-binop elm/same-or-before elm/date x y)) @@ -689,9 +700,9 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-16" false) - (tu/testing-binary-null elm/same-or-before #elm/date"2019") - (tu/testing-binary-null elm/same-or-before #elm/date"2019-04") - (tu/testing-binary-null elm/same-or-before #elm/date"2019-04-17") + (tu/testing-binary-null elm/same-or-before #elm/date "2019") + (tu/testing-binary-null elm/same-or-before #elm/date "2019-04") + (tu/testing-binary-null elm/same-or-before #elm/date "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/same-or-before elm/date x y "year")) @@ -714,9 +725,9 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-16" false) - (tu/testing-binary-null elm/same-or-before #elm/date-time"2019") - (tu/testing-binary-null elm/same-or-before #elm/date-time"2019-04") - (tu/testing-binary-null elm/same-or-before #elm/date-time"2019-04-17") + (tu/testing-binary-null elm/same-or-before #elm/date-time "2019") + (tu/testing-binary-null elm/same-or-before #elm/date-time "2019-04") + (tu/testing-binary-null elm/same-or-before #elm/date-time "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/same-or-before elm/date-time x y "year")) @@ -725,7 +736,9 @@ "2019" "2018" false "2019-04" "2019-05" true "2019-04" "2019-04" true - "2019-04" "2019-03" true)))) + "2019-04" "2019-03" true))) + + (tu/testing-binary-precision-form elm/same-or-before)) ;; 18.15. SameOrAfter @@ -774,8 +787,8 @@ (deftest compile-same-or-after-test (testing "Interval" (are [x y res] (= res (tu/compile-binop elm/same-or-after elm/interval x y)) - [#elm/integer"2" #elm/integer"3"] - [#elm/integer"1" #elm/integer"2"] true)) + [#elm/integer "2" #elm/integer "3"] + [#elm/integer "1" #elm/integer "2"] true)) (testing "Date" (are [x y res] (= res (tu/compile-binop elm/same-or-after elm/date x y)) @@ -789,9 +802,9 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-18" false) - (tu/testing-binary-null elm/same-or-after #elm/date"2019") - (tu/testing-binary-null elm/same-or-after #elm/date"2019-04") - (tu/testing-binary-null elm/same-or-after #elm/date"2019-04-17") + (tu/testing-binary-null elm/same-or-after #elm/date "2019") + (tu/testing-binary-null elm/same-or-after #elm/date "2019-04") + (tu/testing-binary-null elm/same-or-after #elm/date "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/same-or-after elm/date x y "year")) @@ -814,9 +827,9 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-18" false) - (tu/testing-binary-null elm/same-or-after #elm/date-time"2019") - (tu/testing-binary-null elm/same-or-after #elm/date-time"2019-04") - (tu/testing-binary-null elm/same-or-after #elm/date-time"2019-04-17") + (tu/testing-binary-null elm/same-or-after #elm/date-time "2019") + (tu/testing-binary-null elm/same-or-after #elm/date-time "2019-04") + (tu/testing-binary-null elm/same-or-after #elm/date-time "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/same-or-after elm/date-time x y "year")) @@ -825,7 +838,9 @@ "2019" "2020" false "2019-04" "2019-03" true "2019-04" "2019-04" true - "2019-04" "2019-05" true)))) + "2019-04" "2019-05" true))) + + (tu/testing-binary-precision-form elm/same-or-after)) ;; 18.18. Time @@ -842,54 +857,54 @@ (deftest compile-time-test (testing "Static hour" (are [elm res] (= res (c/compile {} elm)) - #elm/time [#elm/integer"12"] + #elm/time [#elm/integer "12"] (date-time/local-time 12))) (testing "Dynamic hour" (let [compile-ctx {:library {:parameters {:def [{:name "hour"}]}}} - elm #elm/time [#elm/parameter-ref"hour"] + elm #elm/time [#elm/parameter-ref "hour"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"hour" 12}}] (is (= (date-time/local-time 12) (core/-eval expr eval-ctx nil nil))))) (testing "Static hour-minute" (are [elm res] (= res (c/compile {} elm)) - #elm/time [#elm/integer"12" #elm/integer"13"] + #elm/time [#elm/integer "12" #elm/integer "13"] (date-time/local-time 12 13))) (testing "Dynamic hour-minute" (let [compile-ctx {:library {:parameters {:def [{:name "minute"}]}}} - elm #elm/time [#elm/integer"12" #elm/parameter-ref"minute"] + elm #elm/time [#elm/integer "12" #elm/parameter-ref "minute"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"minute" 13}}] (is (= (date-time/local-time 12 13) (core/-eval expr eval-ctx nil nil))))) (testing "Static hour-minute-second" (are [elm res] (= res (c/compile {} elm)) - #elm/time [#elm/integer"12" #elm/integer"13" #elm/integer"14"] + #elm/time [#elm/integer "12" #elm/integer "13" #elm/integer "14"] (date-time/local-time 12 13 14))) (testing "Dynamic hour-minute-second" (let [compile-ctx {:library {:parameters {:def [{:name "second"}]}}} - elm #elm/time [#elm/integer"12" - #elm/integer"13" - #elm/parameter-ref"second"] + elm #elm/time [#elm/integer "12" + #elm/integer "13" + #elm/parameter-ref "second"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"second" 14}}] (is (= (date-time/local-time 12 13 14) (core/-eval expr eval-ctx nil nil))))) (testing "Static hour-minute-second-millisecond" (are [elm res] (= res (c/compile {} elm)) - #elm/time [#elm/integer"12" #elm/integer"13" #elm/integer"14" - #elm/integer"15"] + #elm/time [#elm/integer "12" #elm/integer "13" #elm/integer "14" + #elm/integer "15"] (date-time/local-time 12 13 14 15))) (testing "Dynamic hour-minute-second-millisecond" (let [compile-ctx {:library {:parameters {:def [{:name "millisecond"}]}}} - elm #elm/time [#elm/integer"12" - #elm/integer"13" - #elm/integer"14" - #elm/parameter-ref"millisecond"] + elm #elm/time [#elm/integer "12" + #elm/integer "13" + #elm/integer "14" + #elm/parameter-ref "millisecond"] expr (c/compile compile-ctx elm) eval-ctx {:parameters {"millisecond" 15}}] (is (= (date-time/local-time 12 13 14 15) (core/-eval expr eval-ctx nil nil))))) diff --git a/modules/cql/test/blaze/elm/compiler/external_data_test.clj b/modules/cql/test/blaze/elm/compiler/external_data_test.clj index 04709d2bc..d6d38bed8 100644 --- a/modules/cql/test/blaze/elm/compiler/external_data_test.clj +++ b/modules/cql/test/blaze/elm/compiler/external_data_test.clj @@ -11,12 +11,11 @@ [blaze.elm.compiler.core :as core] [blaze.elm.compiler.external-data] [blaze.elm.compiler.test-util :as tu] - [blaze.elm.literal :as elm] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type] [blaze.test-util :refer [with-system]] [clojure.spec.test.alpha :as st] - [clojure.test :as test :refer [deftest testing]] + [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] [juxt.iota :refer [given]]) (:import @@ -91,7 +90,7 @@ {:node node :eval-context "Patient" :library {}} - expr (c/compile context (elm/retrieve {:type "Observation"})) + expr (c/compile context #elm/retrieve{:type "Observation"}) db (d/db node) patient (d/resource-handle db "Patient" "0")] @@ -123,18 +122,23 @@ {:def [{:name "sys-def-131750" :id "system-192253"}]}}} - elm (elm/retrieve - {:type "Observation" - :codes #elm/list[#elm/code["sys-def-131750" - "code-192300"]]}) + elm #elm/retrieve + {:type "Observation" + :codes #elm/list [#elm/code ["sys-def-131750" + "code-192300"]]} expr (c/compile context elm) db (d/db node) patient (d/resource-handle db "Patient" "0")] - (given (core/-eval expr {:db db} patient nil) - count := 1 - [0 fhir-spec/fhir-type] := :fhir/Observation - [0 :id] := "1")))) + (testing "eval" + (given (core/-eval expr {:db db} patient nil) + count := 1 + [0 fhir-spec/fhir-type] := :fhir/Observation + [0 :id] := "1")) + + (testing "form" + (is (= '(compartment-query-retrieve "Observation" [["code" "system-192253|code-192300"]]) + (core/-form expr))))))) (testing "with two codes" (with-system-data [{:blaze.db/keys [node]} mem-node-system] @@ -169,11 +173,11 @@ {:def [{:name "sys-def-131750" :id "system-192253"}]}}} - elm (elm/retrieve - {:type "Observation" - :codes - #elm/list[#elm/code["sys-def-131750" "code-192300"] - #elm/code["sys-def-131750" "code-140541"]]}) + elm #elm/retrieve + {:type "Observation" + :codes + #elm/list [#elm/code ["sys-def-131750" "code-192300"] + #elm/code ["sys-def-131750" "code-140541"]]} expr (c/compile context elm) db (d/db node) patient (d/resource-handle db "Patient" "0")] @@ -226,7 +230,7 @@ :id "system-225806"}]}}} elm #elm/retrieve {:type "Medication" - :codes #elm/list[#elm/code["sys-def-225944" + :codes #elm/list [#elm/code ["sys-def-225944" "code-225809"]]} expr (c/compile context elm) db (d/db node)] @@ -248,7 +252,7 @@ :id "system-225806"}]}}} elm #elm/retrieve {:type "Medication" - :codes #elm/list[#elm/code["sys-def-225944" + :codes #elm/list [#elm/code ["sys-def-225944" "code-225809"]] :code-property "foo"}] @@ -268,7 +272,7 @@ elm #elm/retrieve {:type "Observation" :context #elm/expression-ref "name-174207" - :codes #elm/list[#elm/code["sys-def-174848" + :codes #elm/list [#elm/code ["sys-def-174848" "code-174911"]]} expr (c/compile {:node node :library library} elm)] (given expr @@ -285,7 +289,7 @@ elm #elm/retrieve {:type "Observation" :context #elm/expression-ref "name-174207" - :codes #elm/list[#elm/code["sys-def-174848" + :codes #elm/list [#elm/code ["sys-def-174848" "code-174911"]] :code-property "foo"}] (given (ba/try-anomaly (c/compile {:node node :library library} elm)) diff --git a/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj b/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj index c64c20475..1bf13c797 100644 --- a/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj @@ -31,7 +31,7 @@ (test/use-fixtures :each fixture) -(def interval-zero #elm/interval [#elm/integer"0" #elm/integer"0"]) +(def interval-zero #elm/interval [#elm/integer "0" #elm/integer "0"]) ;; 19.1. Interval ;; @@ -90,30 +90,30 @@ (are [elm res] (= res (c/compile {} elm)) #elm/interval [:< #elm/as ["{urn:hl7-org:elm-types:r1}Integer" {:type "Null"}] - #elm/integer"1"] + #elm/integer "1"] (interval nil 1) - #elm/interval [#elm/integer"1" + #elm/interval [#elm/integer "1" #elm/as ["{urn:hl7-org:elm-types:r1}Integer" {:type "Null"}] :>] (interval 1 nil) - #elm/interval [:< #elm/integer"1" #elm/integer"2"] (interval 2 2) - #elm/interval [#elm/integer"1" #elm/integer"2" :>] (interval 1 1) - #elm/interval [:< #elm/integer"1" #elm/integer"3" :>] (interval 2 2))) + #elm/interval [:< #elm/integer "1" #elm/integer "2"] (interval 2 2) + #elm/interval [#elm/integer "1" #elm/integer "2" :>] (interval 1 1) + #elm/interval [:< #elm/integer "1" #elm/integer "3" :>] (interval 2 2))) (testing "Dynamic" (are [elm res] (= res (tu/dynamic-compile-eval elm)) - (elm/interval [:< (elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/parameter-ref"nil"]) - #elm/integer"1"]) + (elm/interval [:< (elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/parameter-ref "nil"]) + #elm/integer "1"]) (interval nil 1) - (elm/interval [#elm/integer"1" - (elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/parameter-ref"nil"]) :>]) + (elm/interval [#elm/integer "1" + (elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/parameter-ref "nil"]) :>]) (interval 1 nil))) (testing "Invalid interval" (are [elm] (thrown? Exception (core/-eval (c/compile {} elm) {} nil nil)) - #elm/interval [#elm/integer"5" #elm/integer"3"]))) + #elm/interval [#elm/integer "5" #elm/integer "3"]))) ;; 19.2. After @@ -160,36 +160,36 @@ (testing "Interval" (testing "if both intervals are closed, the start of the first (3) has to be greater then the end of the second (2)" (are [x y res] (= res (tu/compile-binop elm/after elm/interval x y)) - [#elm/integer"3" #elm/integer"4"] - [#elm/integer"1" #elm/integer"2"] true - [#elm/integer"2" #elm/integer"3"] - [#elm/integer"1" #elm/integer"2"] false)) + [#elm/integer "3" #elm/integer "4"] + [#elm/integer "1" #elm/integer "2"] true + [#elm/integer "2" #elm/integer "3"] + [#elm/integer "1" #elm/integer "2"] false)) (testing "if one of the intervals is open, start and end can be the same (2)" (are [x y res] (= res (tu/compile-binop elm/after elm/interval x y)) - [#elm/integer"2" #elm/integer"3"] - [#elm/integer"1" #elm/integer"2" :>] true - [:< #elm/integer"2" #elm/integer"3"] - [#elm/integer"1" #elm/integer"2"] true - [:< #elm/integer"2" #elm/integer"3"] - [#elm/integer"1" #elm/integer"2" :>] true)) + [#elm/integer "2" #elm/integer "3"] + [#elm/integer "1" #elm/integer "2" :>] true + [:< #elm/integer "2" #elm/integer "3"] + [#elm/integer "1" #elm/integer "2"] true + [:< #elm/integer "2" #elm/integer "3"] + [#elm/integer "1" #elm/integer "2" :>] true)) (testing "if both intervals are open, start and end can overlap slightly" (are [x y res] (= res (tu/compile-binop elm/after elm/interval x y)) - [:< #elm/integer"2" #elm/integer"4"] - [#elm/integer"1" #elm/integer"3" :>] true)) + [:< #elm/integer "2" #elm/integer "4"] + [#elm/integer "1" #elm/integer "3" :>] true)) (testing "if one of the relevant bounds is infinity, the result is false" (are [x y res] (= res (tu/compile-binop elm/after elm/interval x y)) - [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer"3"] - [#elm/integer"1" #elm/integer"2"] false - [#elm/integer"2" #elm/integer"3"] - [#elm/integer"1" {:type "Null"}] false)) + [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer "3"] + [#elm/integer "1" #elm/integer "2"] false + [#elm/integer "2" #elm/integer "3"] + [#elm/integer "1" {:type "Null"}] false)) (testing "if the second interval has an unknown high bound, the result is null" (are [x y res] (= res (tu/compile-binop elm/after elm/interval x y)) - [#elm/integer"2" #elm/integer"3"] - [#elm/integer"1" {:type "Null"} :>] nil)) + [#elm/integer "2" #elm/integer "3"] + [#elm/integer "1" {:type "Null"} :>] nil)) (tu/testing-binary-null elm/after interval-zero)) @@ -205,9 +205,9 @@ "2019-04-17" "2019-04-17" false "2019-04-17" "2019-04-18" false) - (tu/testing-binary-null elm/after #elm/date"2019") - (tu/testing-binary-null elm/after #elm/date"2019-04") - (tu/testing-binary-null elm/after #elm/date"2019-04-17") + (tu/testing-binary-null elm/after #elm/date "2019") + (tu/testing-binary-null elm/after #elm/date "2019-04") + (tu/testing-binary-null elm/after #elm/date "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/after elm/date x y "year")) @@ -233,9 +233,9 @@ "2019-04-17" "2019-04-17" false "2019-04-17" "2019-04-18" false) - (tu/testing-binary-null elm/after #elm/date-time"2019") - (tu/testing-binary-null elm/after #elm/date-time"2019-04") - (tu/testing-binary-null elm/after #elm/date-time"2019-04-17") + (tu/testing-binary-null elm/after #elm/date-time "2019") + (tu/testing-binary-null elm/after #elm/date-time "2019-04") + (tu/testing-binary-null elm/after #elm/date-time "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/after elm/date-time @@ -248,7 +248,9 @@ "2019-04" "2019-05" false "2019-04-17" "2019-04-16" false "2019-04-17" "2019-04-17" false - "2019-04-17" "2019-04-18" false)))) + "2019-04-17" "2019-04-18" false))) + + (tu/testing-binary-precision-form elm/after)) ;; 19.3. Before @@ -294,36 +296,36 @@ (testing "Interval" (testing "if both intervals are closed, the end of the first (2) has to be less then the start of the second (3)" (are [x y res] (= res (tu/compile-binop elm/before elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] - [#elm/integer"3" #elm/integer"4"] true - [#elm/integer"1" #elm/integer"2"] - [#elm/integer"2" #elm/integer"3"] false)) + [#elm/integer "1" #elm/integer "2"] + [#elm/integer "3" #elm/integer "4"] true + [#elm/integer "1" #elm/integer "2"] + [#elm/integer "2" #elm/integer "3"] false)) (testing "if one of the intervals is open, start and end can be the same (2)" (are [x y res] (= res (tu/compile-binop elm/before elm/interval x y)) - [#elm/integer"1" #elm/integer"2" :>] - [#elm/integer"2" #elm/integer"3"] true - [#elm/integer"1" #elm/integer"2"] - [:< #elm/integer"2" #elm/integer"3"] true - [#elm/integer"1" #elm/integer"2" :>] - [:< #elm/integer"2" #elm/integer"3"] true)) + [#elm/integer "1" #elm/integer "2" :>] + [#elm/integer "2" #elm/integer "3"] true + [#elm/integer "1" #elm/integer "2"] + [:< #elm/integer "2" #elm/integer "3"] true + [#elm/integer "1" #elm/integer "2" :>] + [:< #elm/integer "2" #elm/integer "3"] true)) (testing "if both intervals are open, start and end can overlap slightly" (are [x y res] (= res (tu/compile-binop elm/before elm/interval x y)) - [#elm/integer"1" #elm/integer"3" :>] - [:< #elm/integer"2" #elm/integer"4"] true)) + [#elm/integer "1" #elm/integer "3" :>] + [:< #elm/integer "2" #elm/integer "4"] true)) (testing "if one of the relevant bounds is infinity, the result is false" (are [x y res] (= res (tu/compile-binop elm/before elm/interval x y)) - [#elm/integer"1" {:type "Null"}] - [#elm/integer"2" #elm/integer"3"] false - [#elm/integer"1" #elm/integer"2"] - [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer"3"] false)) + [#elm/integer "1" {:type "Null"}] + [#elm/integer "2" #elm/integer "3"] false + [#elm/integer "1" #elm/integer "2"] + [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer "3"] false)) (testing "if the second interval has an unknown low bound, the result is null" (are [x y res] (= res (tu/compile-binop elm/before elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] - [:< {:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer"3"] nil)) + [#elm/integer "1" #elm/integer "2"] + [:< {:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer "3"] nil)) (tu/testing-binary-null elm/before interval-zero)) @@ -339,9 +341,9 @@ "2019-04-17" "2019-04-17" false "2019-04-17" "2019-04-16" false) - (tu/testing-binary-null elm/before #elm/date"2019") - (tu/testing-binary-null elm/before #elm/date"2019-04") - (tu/testing-binary-null elm/before #elm/date"2019-04-17") + (tu/testing-binary-null elm/before #elm/date "2019") + (tu/testing-binary-null elm/before #elm/date "2019-04") + (tu/testing-binary-null elm/before #elm/date "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/before elm/date x y @@ -368,9 +370,9 @@ "2019-04-17" "2019-04-17" false "2019-04-17" "2019-04-16" false) - (tu/testing-binary-null elm/before #elm/date-time"2019") - (tu/testing-binary-null elm/before #elm/date-time"2019-04") - (tu/testing-binary-null elm/before #elm/date-time"2019-04-17") + (tu/testing-binary-null elm/before #elm/date-time "2019") + (tu/testing-binary-null elm/before #elm/date-time "2019-04") + (tu/testing-binary-null elm/before #elm/date-time "2019-04-17") (testing "with year precision" (are [x y res] (= res (tu/compile-binop-precision elm/before elm/date-time @@ -383,7 +385,9 @@ "2019-04" "2019-03" false "2019-04-17" "2019-04-18" false "2019-04-17" "2019-04-17" false - "2019-04-17" "2019-04-16" false)))) + "2019-04-17" "2019-04-16" false))) + + (tu/testing-binary-precision-form elm/before)) ;; 19.4. Collapse @@ -419,27 +423,29 @@ (deftest compile-collapse-test (testing "Integer" (are [source per res] (= res (core/-eval (c/compile {} (elm/collapse [source per])) {} nil nil)) - #elm/list [#elm/interval [#elm/integer"1" #elm/integer"2"]] + #elm/list [#elm/interval [#elm/integer "1" #elm/integer "2"]] {:type "Null"} [(interval 1 2)] - #elm/list [#elm/interval [#elm/integer"1" #elm/integer"2"] - #elm/interval [#elm/integer"2" #elm/integer"3"]] + #elm/list [#elm/interval [#elm/integer "1" #elm/integer "2"] + #elm/interval [#elm/integer "2" #elm/integer "3"]] {:type "Null"} [(interval 1 3)] #elm/list [{:type "Null"}] {:type "Null"} [] #elm/list [{:type "Null"} {:type "Null"}] {:type "Null"} [] - #elm/list[] {:type "Null"} [] + #elm/list [] {:type "Null"} [] {:type "Null"} {:type "Null"} nil)) (testing "DateTime" (are [source per res] (= res (core/-eval (c/compile {} (elm/collapse [source per])) {} nil nil)) - #elm/list [#elm/interval [#elm/date-time"2012-01-01" #elm/date-time"2012-01-15"] - #elm/interval [#elm/date-time"2012-01-16" #elm/date-time"2012-05-25"]] + #elm/list [#elm/interval [#elm/date-time "2012-01-01" #elm/date-time "2012-01-15"] + #elm/interval [#elm/date-time "2012-01-16" #elm/date-time "2012-05-25"]] {:type "Null"} - [(interval (system/date-time 2012 1 1) (system/date-time 2012 5 25))]))) + [(interval (system/date-time 2012 1 1) (system/date-time 2012 5 25))])) + + (tu/testing-binary-form elm/collapse)) ;; 19.5. Contains @@ -466,32 +472,26 @@ (deftest compile-contains-test (testing "Interval" (testing "Integer" - (are [interval x res] (= res (core/-eval (c/compile {} (elm/contains [interval x])) {} nil nil)) - #elm/interval [#elm/integer"1" #elm/integer"1"] #elm/integer"1" true - #elm/interval [#elm/integer"1" #elm/integer"1"] #elm/integer"2" false)) - - (testing "Null" - (are [interval x] (nil? (c/compile {} (elm/contains [interval x]))) - interval-zero {:type "Null"} + (are [interval x res] (= res (c/compile {} (elm/contains [interval x]))) + #elm/interval [#elm/integer "1" #elm/integer "1"] #elm/integer "1" true + #elm/interval [#elm/integer "1" #elm/integer "1"] #elm/integer "2" false) - {:type "Null"} {:type "Null"}))) + (tu/testing-binary-null elm/contains interval-zero #elm/integer "1"))) (testing "List" (are [list x res] (= res (core/-eval (c/compile {} (elm/contains [list x])) {} nil nil)) - #elm/list[] #elm/integer"1" false + #elm/list [] #elm/integer "1" false - #elm/list [#elm/integer"1"] #elm/integer"1" true - #elm/list [#elm/integer"1"] #elm/integer"2" false + #elm/list [#elm/integer "1"] #elm/integer "1" true + #elm/list [#elm/integer "1"] #elm/integer "2" false - #elm/list [#elm/quantity[1 "m"]] #elm/quantity[100 "cm"] true + #elm/list [#elm/quantity [1 "m"]] #elm/quantity [100 "cm"] true - #elm/list [#elm/date"2019"] #elm/date"2019-01" false) + #elm/list [#elm/date "2019"] #elm/date "2019-01" false) - (testing "Null" - (are [list x] (nil? (c/compile {} (elm/contains [list x]))) - #elm/list[] {:type "Null"} + (tu/testing-binary-null elm/contains #elm/list [] #elm/integer "1")) - {:type "Null"} {:type "Null"})))) + (tu/testing-binary-precision-form elm/contains)) ;; 19.6. End @@ -510,17 +510,19 @@ (deftest compile-end-test (testing "Integer" (are [x res] (= res (tu/compile-unop elm/end elm/interval x)) - [#elm/integer"1" #elm/integer"2"] 2 - [#elm/integer"1" #elm/integer"2" :>] 1 - [#elm/integer"1" {:type "Null"}] Integer/MAX_VALUE)) + [#elm/integer "1" #elm/integer "2"] 2 + [#elm/integer "1" #elm/integer "2" :>] 1 + [#elm/integer "1" {:type "Null"}] Integer/MAX_VALUE)) (testing "Decimal" (are [x res] (= res (tu/compile-unop elm/end elm/interval x)) - [#elm/decimal"1" #elm/decimal"2.1"] 2.1M - [#elm/decimal"1" #elm/decimal"2.1" :>] 2.09999999M - [#elm/decimal"1" {:type "Null"}] decimal/max)) + [#elm/decimal "1" #elm/decimal "2.1"] 2.1M + [#elm/decimal "1" #elm/decimal "2.1" :>] 2.09999999M + [#elm/decimal "1" {:type "Null"}] decimal/max)) - (tu/testing-unary-null elm/end)) + (tu/testing-unary-null elm/end) + + (tu/testing-unary-form elm/end)) ;; 19.7. Ends @@ -541,11 +543,13 @@ (deftest compile-ends-test (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/ends elm/interval x y)) - [#elm/integer"1" #elm/integer"3"] [#elm/integer"1" #elm/integer"3"] true - [#elm/integer"2" #elm/integer"3"] [#elm/integer"1" #elm/integer"3"] true - [#elm/integer"1" #elm/integer"3"] [#elm/integer"2" #elm/integer"3"] false)) + [#elm/integer "1" #elm/integer "3"] [#elm/integer "1" #elm/integer "3"] true + [#elm/integer "2" #elm/integer "3"] [#elm/integer "1" #elm/integer "3"] true + [#elm/integer "1" #elm/integer "3"] [#elm/integer "2" #elm/integer "3"] false)) + + (tu/testing-binary-null elm/ends interval-zero) - (tu/testing-binary-null elm/ends interval-zero)) + (tu/testing-binary-precision-form elm/ends)) ;; 19.8. Equal @@ -580,22 +584,24 @@ (testing "List" (are [x y res] (= res (tu/compile-binop elm/except elm/list x y)) [] [] [] - [] [#elm/integer"1"] [] - [#elm/integer"1"] [#elm/integer"1"] [] - [#elm/integer"1"] [] [1] - [#elm/integer"1"] [#elm/integer"2"] [1] - [#elm/integer"1" #elm/integer"2"] [#elm/integer"2"] [1] - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1"] [2]) + [] [#elm/integer "1"] [] + [#elm/integer "1"] [#elm/integer "1"] [] + [#elm/integer "1"] [] [1] + [#elm/integer "1"] [#elm/integer "2"] [1] + [#elm/integer "1" #elm/integer "2"] [#elm/integer "2"] [1] + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1"] [2]) - (tu/testing-binary-null elm/except #elm/list[])) + (tu/testing-binary-null elm/except #elm/list [])) (testing "Interval" (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/except elm/interval x y)) - [#elm/integer"1" #elm/integer"3"] [#elm/integer"3" #elm/integer"4"] (interval 1 2) - [#elm/integer"3" #elm/integer"5"] [#elm/integer"1" #elm/integer"3"] (interval 4 5))) + [#elm/integer "1" #elm/integer "3"] [#elm/integer "3" #elm/integer "4"] (interval 1 2) + [#elm/integer "3" #elm/integer "5"] [#elm/integer "1" #elm/integer "3"] (interval 4 5))) + + (tu/testing-binary-null elm/except interval-zero)) - (tu/testing-binary-null elm/except interval-zero))) + (tu/testing-binary-form elm/except)) ;; 19.11. Expand @@ -673,21 +679,23 @@ (testing "List" (are [x y res] (= res (tu/compile-binop elm/includes elm/list x y)) [] [] true - [#elm/integer"1"] [#elm/integer"1"] true - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1"] true + [#elm/integer "1"] [#elm/integer "1"] true + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1"] true [{:type "Null"}] [{:type "Null"}] false) - (tu/testing-binary-null elm/includes #elm/list[])) + (tu/testing-binary-null elm/includes #elm/list [])) (testing "Interval" (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/includes elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1" #elm/integer"2"] true - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1" #elm/integer"3"] false)) + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1" #elm/integer "2"] true + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1" #elm/integer "3"] false)) - (tu/testing-binary-null elm/includes interval-zero))) + (tu/testing-binary-null elm/includes interval-zero)) + + (tu/testing-binary-precision-form elm/includes)) ;; 19.14. IncludedIn @@ -719,38 +727,40 @@ (deftest compile-intersect-test (testing "List" (are [x y res] (= res (tu/compile-binop elm/intersect elm/list x y)) - [#elm/integer"1"] [#elm/integer"1"] [1] - [#elm/integer"1"] [#elm/integer"2"] [] + [#elm/integer "1"] [#elm/integer "1"] [1] + [#elm/integer "1"] [#elm/integer "2"] [] - [#elm/integer"1"] [#elm/integer"1" #elm/integer"2"] [1] + [#elm/integer "1"] [#elm/integer "1" #elm/integer "2"] [1] - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1"] [1]) + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1"] [1]) - (tu/testing-binary-null elm/intersect #elm/list[])) + (tu/testing-binary-null elm/intersect #elm/list [])) (testing "Interval" (are [x y res] (= res (tu/compile-binop elm/intersect elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] - [#elm/integer"2" #elm/integer"3"] + [#elm/integer "1" #elm/integer "2"] + [#elm/integer "2" #elm/integer "3"] (interval 2 2) - [#elm/integer"2" #elm/integer"3"] - [#elm/integer"1" #elm/integer"2"] + [#elm/integer "2" #elm/integer "3"] + [#elm/integer "1" #elm/integer "2"] (interval 2 2) - [#elm/integer"1" #elm/integer"10"] - [#elm/integer"5" #elm/integer"8"] + [#elm/integer "1" #elm/integer "10"] + [#elm/integer "5" #elm/integer "8"] (interval 5 8) - [#elm/integer"1" #elm/integer"10"] - [#elm/integer"5" {:type "Null"} :>] + [#elm/integer "1" #elm/integer "10"] + [#elm/integer "5" {:type "Null"} :>] nil - [#elm/integer"1" #elm/integer"2"] - [#elm/integer"3" #elm/integer"4"] + [#elm/integer "1" #elm/integer "2"] + [#elm/integer "3" #elm/integer "4"] nil) - (tu/testing-binary-null elm/intersect interval-zero))) + (tu/testing-binary-null elm/intersect interval-zero)) + + (tu/testing-binary-form elm/intersect)) ;; 19.16. Meets @@ -778,10 +788,12 @@ (deftest compile-meets-before-test (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/meets-before elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] [#elm/integer"3" #elm/integer"4"] true - [#elm/integer"1" #elm/integer"2"] [#elm/integer"4" #elm/integer"5"] false)) + [#elm/integer "1" #elm/integer "2"] [#elm/integer "3" #elm/integer "4"] true + [#elm/integer "1" #elm/integer "2"] [#elm/integer "4" #elm/integer "5"] false)) - (tu/testing-binary-null elm/meets-before interval-zero)) + (tu/testing-binary-null elm/meets-before interval-zero) + + (tu/testing-binary-precision-form elm/meets-before)) ;; 19.18. MeetsAfter @@ -801,10 +813,12 @@ (deftest compile-meets-after-test (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/meets-after elm/interval x y)) - [#elm/integer"3" #elm/integer"4"] [#elm/integer"1" #elm/integer"2"] true - [#elm/integer"4" #elm/integer"5"] [#elm/integer"1" #elm/integer"2"] false)) + [#elm/integer "3" #elm/integer "4"] [#elm/integer "1" #elm/integer "2"] true + [#elm/integer "4" #elm/integer "5"] [#elm/integer "1" #elm/integer "2"] false)) + + (tu/testing-binary-null elm/meets-after interval-zero) - (tu/testing-binary-null elm/meets-after interval-zero)) + (tu/testing-binary-precision-form elm/meets-after)) ;; 19.20. Overlaps @@ -827,37 +841,39 @@ (deftest compile-overlaps-test (testing "Static" (are [x y res] (= res (tu/compile-binop elm/overlaps elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] [#elm/integer"3" #elm/integer"4"] false - [#elm/integer"3" #elm/integer"4"] [#elm/integer"1" #elm/integer"2"] false + [#elm/integer "1" #elm/integer "2"] [#elm/integer "3" #elm/integer "4"] false + [#elm/integer "3" #elm/integer "4"] [#elm/integer "1" #elm/integer "2"] false - [#elm/integer"1" #elm/integer"2"] [#elm/integer"2" #elm/integer"4"] true - [#elm/integer"2" #elm/integer"4"] [#elm/integer"1" #elm/integer"2"] true + [#elm/integer "1" #elm/integer "2"] [#elm/integer "2" #elm/integer "4"] true + [#elm/integer "2" #elm/integer "4"] [#elm/integer "1" #elm/integer "2"] true - [#elm/integer"1" #elm/integer"3"] [#elm/integer"2" #elm/integer"4"] true - [#elm/integer"2" #elm/integer"4"] [#elm/integer"1" #elm/integer"3"] true + [#elm/integer "1" #elm/integer "3"] [#elm/integer "2" #elm/integer "4"] true + [#elm/integer "2" #elm/integer "4"] [#elm/integer "1" #elm/integer "3"] true - [#elm/integer"2" #elm/integer"3"] [#elm/integer"1" #elm/integer"4"] true - [#elm/integer"1" #elm/integer"4"] [#elm/integer"2" #elm/integer"3"] true + [#elm/integer "2" #elm/integer "3"] [#elm/integer "1" #elm/integer "4"] true + [#elm/integer "1" #elm/integer "4"] [#elm/integer "2" #elm/integer "3"] true - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1" #elm/integer"2"] true)) + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1" #elm/integer "2"] true)) (testing "Dynamic" (are [x y res] (= res (tu/dynamic-compile-eval (elm/overlaps [(elm/interval x) (elm/interval y)]))) - [#elm/integer"1" #elm/parameter-ref"2"] [#elm/integer"3" #elm/parameter-ref"4"] false - [#elm/integer"3" #elm/parameter-ref"4"] [#elm/integer"1" #elm/parameter-ref"2"] false + [#elm/integer "1" #elm/parameter-ref "2"] [#elm/integer "3" #elm/parameter-ref "4"] false + [#elm/integer "3" #elm/parameter-ref "4"] [#elm/integer "1" #elm/parameter-ref "2"] false + + [#elm/integer "1" #elm/parameter-ref "2"] [#elm/integer "2" #elm/parameter-ref "4"] true + [#elm/integer "2" #elm/parameter-ref "4"] [#elm/integer "1" #elm/parameter-ref "2"] true - [#elm/integer"1" #elm/parameter-ref"2"] [#elm/integer"2" #elm/parameter-ref"4"] true - [#elm/integer"2" #elm/parameter-ref"4"] [#elm/integer"1" #elm/parameter-ref"2"] true + [#elm/integer "1" #elm/parameter-ref "3"] [#elm/integer "2" #elm/parameter-ref "4"] true + [#elm/integer "2" #elm/parameter-ref "4"] [#elm/integer "1" #elm/parameter-ref "3"] true - [#elm/integer"1" #elm/parameter-ref"3"] [#elm/integer"2" #elm/parameter-ref"4"] true - [#elm/integer"2" #elm/parameter-ref"4"] [#elm/integer"1" #elm/parameter-ref"3"] true + [#elm/integer "2" #elm/parameter-ref "3"] [#elm/integer "1" #elm/parameter-ref "4"] true + [#elm/integer "1" #elm/parameter-ref "4"] [#elm/integer "2" #elm/parameter-ref "3"] true - [#elm/integer"2" #elm/parameter-ref"3"] [#elm/integer"1" #elm/parameter-ref"4"] true - [#elm/integer"1" #elm/parameter-ref"4"] [#elm/integer"2" #elm/parameter-ref"3"] true + [#elm/integer "1" #elm/parameter-ref "2"] [#elm/integer "1" #elm/parameter-ref "2"] true)) - [#elm/integer"1" #elm/parameter-ref"2"] [#elm/integer"1" #elm/parameter-ref"2"] true)) + (tu/testing-binary-null elm/overlaps interval-zero) - (tu/testing-binary-null elm/overlaps interval-zero)) + (tu/testing-binary-precision-form elm/overlaps)) ;; 19.21. OverlapsBefore @@ -884,10 +900,12 @@ (deftest compile-point-from-test (testing "Integer" (are [x res] (= res (tu/compile-unop elm/point-from elm/interval x)) - [#elm/integer"1" #elm/integer"1"] 1 - [#elm/integer"2" #elm/integer"2"] 2)) + [#elm/integer "1" #elm/integer "1"] 1 + [#elm/integer "2" #elm/integer "2"] 2)) - (tu/testing-unary-null elm/point-from)) + (tu/testing-unary-null elm/point-from) + + (tu/testing-unary-form elm/point-from)) ;; 19.24. ProperContains @@ -914,11 +932,13 @@ (testing "Interval" (testing "Integer" (are [interval x res] (= res (c/compile {} (elm/proper-contains [interval x]))) - #elm/interval [#elm/integer"1" #elm/integer"3"] #elm/integer"2" true - #elm/interval [#elm/integer"1" #elm/integer"1"] #elm/integer"1" false - #elm/interval [#elm/integer"1" #elm/integer"1"] #elm/integer"2" false)) + #elm/interval [#elm/integer "1" #elm/integer "3"] #elm/integer "2" true + #elm/interval [#elm/integer "1" #elm/integer "1"] #elm/integer "1" false + #elm/interval [#elm/integer "1" #elm/integer "1"] #elm/integer "2" false)) + + (tu/testing-binary-null elm/proper-contains interval-zero)) - (tu/testing-binary-null elm/proper-contains interval-zero))) + (tu/testing-binary-precision-form elm/proper-contains)) ;; 19.25. ProperIn @@ -954,10 +974,12 @@ (testing "Interval" (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/proper-includes elm/interval x y)) - [#elm/integer"1" #elm/integer"3"] [#elm/integer"1" #elm/integer"2"] true - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1" #elm/integer"2"] false)) + [#elm/integer "1" #elm/integer "3"] [#elm/integer "1" #elm/integer "2"] true + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1" #elm/integer "2"] false)) - (tu/testing-binary-null elm/proper-includes interval-zero))) + (tu/testing-binary-null elm/proper-includes interval-zero)) + + (tu/testing-binary-precision-form elm/proper-includes)) ;; 19.27. ProperIncludedIn @@ -999,17 +1021,19 @@ (deftest compile-start-test (testing "Integer" (are [x res] (= res (tu/compile-unop elm/start elm/interval x)) - [#elm/integer"1" #elm/integer"2"] 1 - [:< #elm/integer"1" #elm/integer"2"] 2 - [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer"2"] Integer/MIN_VALUE)) + [#elm/integer "1" #elm/integer "2"] 1 + [:< #elm/integer "1" #elm/integer "2"] 2 + [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Integer"} #elm/integer "2"] Integer/MIN_VALUE)) (testing "Decimal" (are [x res] (= res (tu/compile-unop elm/start elm/interval x)) - [#elm/decimal"1.1" #elm/decimal"2"] 1.1M - [:< #elm/decimal"1.1" #elm/decimal"2"] 1.10000001M - [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Decimal"} #elm/decimal"2"] decimal/min)) + [#elm/decimal "1.1" #elm/decimal "2"] 1.1M + [:< #elm/decimal "1.1" #elm/decimal "2"] 1.10000001M + [{:type "Null" :resultTypeName "{urn:hl7-org:elm-types:r1}Decimal"} #elm/decimal "2"] decimal/min)) + + (tu/testing-unary-null elm/start) - (tu/testing-unary-null elm/start)) + (tu/testing-unary-form elm/start)) ;; 19.30. Starts @@ -1030,11 +1054,13 @@ (deftest compile-starts-test (testing "Integer" (are [x y res] (= res (tu/compile-binop elm/starts elm/interval x y)) - [#elm/integer"1" #elm/integer"3"] [#elm/integer"1" #elm/integer"3"] true - [#elm/integer"1" #elm/integer"2"] [#elm/integer"1" #elm/integer"3"] true - [#elm/integer"2" #elm/integer"3"] [#elm/integer"1" #elm/integer"3"] false)) + [#elm/integer "1" #elm/integer "3"] [#elm/integer "1" #elm/integer "3"] true + [#elm/integer "1" #elm/integer "2"] [#elm/integer "1" #elm/integer "3"] true + [#elm/integer "2" #elm/integer "3"] [#elm/integer "1" #elm/integer "3"] false)) + + (tu/testing-binary-null elm/starts interval-zero) - (tu/testing-binary-null elm/starts interval-zero)) + (tu/testing-binary-precision-form elm/starts)) ;; 19.31. Union @@ -1058,17 +1084,19 @@ (testing "List" (are [x y res] (= res (tu/compile-binop elm/union elm/list x y)) [{:type "Null"}] [{:type "Null"}] [nil nil] - [#elm/integer"1"] [#elm/integer"1"] [1] - [#elm/integer"1"] [#elm/integer"2"] [1 2] - [#elm/integer"1"] [#elm/integer"1" #elm/integer"2"] [1 2]) + [#elm/integer "1"] [#elm/integer "1"] [1] + [#elm/integer "1"] [#elm/integer "2"] [1 2] + [#elm/integer "1"] [#elm/integer "1" #elm/integer "2"] [1 2]) - (tu/testing-binary-null elm/union #elm/list[])) + (tu/testing-binary-null elm/union #elm/list [])) (testing "Interval" (are [x y res] (= res (tu/compile-binop elm/union elm/interval x y)) - [#elm/integer"1" #elm/integer"2"] [#elm/integer"3" #elm/integer"4"] (interval 1 4)) + [#elm/integer "1" #elm/integer "2"] [#elm/integer "3" #elm/integer "4"] (interval 1 4)) - (tu/testing-binary-null elm/union interval-zero))) + (tu/testing-binary-null elm/union interval-zero)) + + (tu/testing-binary-form elm/union)) ;; 19.32. Width @@ -1083,6 +1111,8 @@ (deftest compile-width-test (testing "Integer" (are [x res] (= res (tu/compile-unop elm/width elm/interval x)) - [#elm/integer"1" #elm/integer"2"] 1)) + [#elm/integer "1" #elm/integer "2"] 1)) + + (tu/testing-unary-null elm/width) - (tu/testing-unary-null elm/width)) + (tu/testing-unary-form elm/width)) diff --git a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj index 29fc02a3b..17fb8db9f 100644 --- a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj @@ -51,13 +51,13 @@ #elm/list [{:type "Null"}] [nil] - #elm/list [#elm/integer"1"] + #elm/list [#elm/integer "1"] [1] - #elm/list [#elm/integer"1" {:type "Null"}] + #elm/list [#elm/integer "1" {:type "Null"}] [1 nil] - #elm/list [#elm/integer"1" #elm/integer"2"] + #elm/list [#elm/integer "1" #elm/integer "2"] [1 2])) @@ -77,15 +77,15 @@ (deftest compile-current-test (testing "default scope" (satisfies-prop 100 - (prop/for-all [x (s/gen int?)] - (= x (core/-eval (c/compile {} {:type "Current"}) {} nil x))))) + (prop/for-all [x (s/gen int?)] + (= x (core/-eval (c/compile {} {:type "Current"}) {} nil x))))) (testing "named scope" (satisfies-prop 100 - (prop/for-all [scope (s/gen string?) - x (s/gen int?)] - (let [expr (c/compile {} {:type "Current" :scope scope})] - (= x (core/-eval expr {} nil {scope x}))))))) + (prop/for-all [scope (s/gen string?) + x (s/gen int?)] + (let [expr (c/compile {} {:type "Current" :scope scope})] + (= x (core/-eval expr {} nil {scope x}))))))) ;; 20.4. Distinct @@ -101,17 +101,19 @@ ;; ;; If the source argument is null, the result is null. (deftest compile-distinct-test - (are [list res] (= res (core/-eval (c/compile {} (elm/distinct list)) {} nil nil)) - #elm/list [#elm/integer"1"] [1] - #elm/list [#elm/integer"1" #elm/integer"1"] [1] - #elm/list [#elm/integer"1" #elm/integer"1" #elm/integer"2"] [1 2] + (are [list res] (= res (c/compile {} (elm/distinct list))) + #elm/list [#elm/integer "1"] [1] + #elm/list [#elm/integer "1" #elm/integer "1"] [1] + #elm/list [#elm/integer "1" #elm/integer "1" #elm/integer "2"] [1 2] #elm/list [{:type "Null"}] [nil] #elm/list [{:type "Null"} {:type "Null"}] [nil nil] #elm/list [{:type "Null"} {:type "Null"} {:type "Null"}] [nil nil nil] - #elm/list [#elm/quantity[100 "cm"] #elm/quantity[1 "m"]] [(quantity/quantity 100 "cm")] - #elm/list [#elm/quantity[1 "m"] #elm/quantity[100 "cm"]] [(quantity/quantity 1 "m")] + #elm/list [#elm/quantity [100 "cm"] #elm/quantity [1 "m"]] [(quantity/quantity 100 "cm")] + #elm/list [#elm/quantity [1 "m"] #elm/quantity [100 "cm"]] [(quantity/quantity 1 "m")]) - {:type "Null"} nil)) + (tu/testing-unary-null elm/distinct) + + (tu/testing-unary-form elm/distinct)) ;; 20.5. Equal @@ -135,12 +137,14 @@ ;; ;; If the argument is null, the result is false. (deftest compile-exists-test - (are [list res] (= res (core/-eval (c/compile {} (elm/exists list)) {} nil nil)) - #elm/list [#elm/integer"1"] true - #elm/list [#elm/integer"1" #elm/integer"1"] true + (are [list res] (= res (c/compile {} (elm/exists list))) + #elm/list [#elm/integer "1"] true + #elm/list [#elm/integer "1" #elm/integer "1"] true #elm/list [] false - {:type "Null"} false)) + {:type "Null"} false) + + (tu/testing-unary-form elm/exists)) ;; 20.9. Filter @@ -151,10 +155,10 @@ ;; If the source argument is null, the result is null. (deftest compile-filter-test (are [source condition res] (= res (core/-eval (c/compile {} {:type "Filter" :source source :condition condition :scope "A"}) {} nil nil)) - #elm/list [#elm/integer"1"] #elm/boolean"false" [] - #elm/list [#elm/integer"1"] #elm/equal [#elm/current "A" #elm/integer"1"] [1] + #elm/list [#elm/integer "1"] #elm/boolean "false" [] + #elm/list [#elm/integer "1"] #elm/equal [#elm/current "A" #elm/integer "1"] [1] - {:type "Null"} #elm/boolean"true" nil)) + {:type "Null"} #elm/boolean "true" nil)) ;; 20.10. First @@ -166,8 +170,8 @@ ;; If the argument is null, the result is null. (deftest compile-first-test (are [source res] (= res (core/-eval (c/compile {} (elm/first source)) {} nil nil)) - #elm/list [#elm/integer"1"] 1 - #elm/list [#elm/integer"1" #elm/integer"2"] 1 + #elm/list [#elm/integer "1"] 1 + #elm/list [#elm/integer "1" #elm/integer "2"] 1 {:type "Null"} nil)) @@ -178,15 +182,17 @@ ;; ;; If the argument is null, the result is null. (deftest compile-flatten-test - (are [list res] (= res (core/-eval (c/compile {} (elm/flatten list)) {} nil nil)) + (are [list res] (= res (c/compile {} (elm/flatten list))) #elm/list [] [] - #elm/list [#elm/integer"1"] [1] - #elm/list [#elm/integer"1" #elm/list [#elm/integer"2"]] [1 2] - #elm/list [#elm/integer"1" #elm/list [#elm/integer"2"] #elm/integer"3"] [1 2 3] - #elm/list [#elm/integer"1" #elm/list [#elm/integer"2" #elm/list [#elm/integer"3"]]] [1 2 3] - #elm/list [#elm/list [#elm/integer"1" #elm/list [#elm/integer"2"]] #elm/integer"3"] [1 2 3] + #elm/list [#elm/integer "1"] [1] + #elm/list [#elm/integer "1" #elm/list [#elm/integer "2"]] [1 2] + #elm/list [#elm/integer "1" #elm/list [#elm/integer "2"] #elm/integer "3"] [1 2 3] + #elm/list [#elm/integer "1" #elm/list [#elm/integer "2" #elm/list [#elm/integer "3"]]] [1 2 3] + #elm/list [#elm/list [#elm/integer "1" #elm/list [#elm/integer "2"]] #elm/integer "3"] [1 2 3]) - {:type "Null"} nil)) + (tu/testing-unary-null elm/flatten) + + (tu/testing-unary-form elm/flatten)) ;; 20.12. ForEach @@ -203,14 +209,14 @@ (deftest compile-for-each-test (testing "Without scope" (are [source element res] (= res (core/-eval (c/compile {} {:type "ForEach" :source source :element element}) {} nil nil)) - #elm/list [#elm/integer"1"] {:type "Null"} [nil] + #elm/list [#elm/integer "1"] {:type "Null"} [nil] {:type "Null"} {:type "Null"} nil)) (testing "With scope" (are [source element res] (= res (core/-eval (c/compile {} {:type "ForEach" :source source :element element :scope "A"}) {} nil nil)) - #elm/list [#elm/integer"1"] #elm/current "A" [1] - #elm/list [#elm/integer"1" #elm/integer"2"] #elm/add [#elm/current "A" #elm/integer"1"] [2 3] + #elm/list [#elm/integer "1"] #elm/current "A" [1] + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/add [#elm/current "A" #elm/integer "1"] [2 3] {:type "Null"} {:type "Null"} nil))) @@ -244,13 +250,13 @@ ;; If either argument is null, the result is null. (deftest compile-index-of-test (are [source element res] (= res (core/-eval (c/compile {} {:type "IndexOf" :source source :element element}) {} nil nil)) - #elm/list [] #elm/integer"1" -1 - #elm/list [#elm/integer"1"] #elm/integer"1" 0 - #elm/list [#elm/integer"1" #elm/integer"1"] #elm/integer"1" 0 - #elm/list [#elm/integer"1" #elm/integer"2"] #elm/integer"2" 1 + #elm/list [] #elm/integer "1" -1 + #elm/list [#elm/integer "1"] #elm/integer "1" 0 + #elm/list [#elm/integer "1" #elm/integer "1"] #elm/integer "1" 0 + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/integer "2" 1 #elm/list [] {:type "Null"} nil - {:type "Null"} #elm/integer"1" nil + {:type "Null"} #elm/integer "1" nil {:type "Null"} {:type "Null"} nil)) @@ -268,8 +274,8 @@ ;; If the argument is null, the result is null. (deftest compile-last-test (are [source res] (= res (core/-eval (c/compile {} {:type "Last" :source source}) {} nil nil)) - #elm/list [#elm/integer"1"] 1 - #elm/list [#elm/integer"1" #elm/integer"2"] 2 + #elm/list [#elm/integer "1"] 1 + #elm/list [#elm/integer "1" #elm/integer "2"] 2 {:type "Null"} nil)) @@ -325,11 +331,13 @@ (deftest compile-singleton-from-test (are [list res] (= res (core/-eval (c/compile {} (elm/singleton-from list)) {} nil nil)) #elm/list [] nil - #elm/list [#elm/integer"1"] 1 + #elm/list [#elm/integer "1"] 1 {:type "Null"} nil) (are [list] (thrown? Exception (core/-eval (c/compile {} (elm/singleton-from list)) {} nil nil)) - #elm/list [#elm/integer"1" #elm/integer"1"])) + #elm/list [#elm/integer "1" #elm/integer "1"]) + + (tu/testing-unary-null elm/singleton-from)) ;; 20.26. Slice @@ -347,17 +355,17 @@ ;; the startIndex, the result is an empty list. (deftest compile-slice-test (are [source start end res] (= res (core/-eval (c/compile {} {:type "Slice" :source source :startIndex start :endIndex end}) {} nil nil)) - #elm/list [#elm/integer"1"] #elm/integer"0" #elm/integer"1" [1] - #elm/list [#elm/integer"1" #elm/integer"2"] #elm/integer"0" #elm/integer"1" [1] - #elm/list [#elm/integer"1" #elm/integer"2"] #elm/integer"1" #elm/integer"2" [2] - #elm/list [#elm/integer"1" #elm/integer"2" #elm/integer"3"] #elm/integer"1" #elm/integer"3" [2 3] - #elm/list [#elm/integer"1" #elm/integer"2"] {:type "Null"} {:type "Null"} [1 2] + #elm/list [#elm/integer "1"] #elm/integer "0" #elm/integer "1" [1] + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/integer "0" #elm/integer "1" [1] + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/integer "1" #elm/integer "2" [2] + #elm/list [#elm/integer "1" #elm/integer "2" #elm/integer "3"] #elm/integer "1" #elm/integer "3" [2 3] + #elm/list [#elm/integer "1" #elm/integer "2"] {:type "Null"} {:type "Null"} [1 2] - #elm/list [#elm/integer"1"] #elm/integer"-1" #elm/integer"0" [] - #elm/list [#elm/integer"1"] #elm/integer"1" #elm/integer"0" [] + #elm/list [#elm/integer "1"] #elm/integer "-1" #elm/integer "0" [] + #elm/list [#elm/integer "1"] #elm/integer "1" #elm/integer "0" [] - {:type "Null"} #elm/integer"0" #elm/integer"0" nil + {:type "Null"} #elm/integer "0" #elm/integer "0" nil {:type "Null"} {:type "Null"} {:type "Null"} nil)) @@ -373,10 +381,10 @@ ;; If the argument is null, the result is null. (deftest compile-sort-test (are [source by res] (= res (core/-eval (c/compile {} {:type "Sort" :source source :by [by]}) {} nil nil)) - #elm/list [#elm/integer"2" #elm/integer"1"] + #elm/list [#elm/integer "2" #elm/integer "1"] {:type "ByDirection" :direction "asc"} [1 2] - #elm/list [#elm/integer"1" #elm/integer"2"] + #elm/list [#elm/integer "1" #elm/integer "2"] {:type "ByDirection" :direction "desc"} [2 1] {:type "Null"} {:type "ByDirection" :direction "asc"} nil)) diff --git a/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj b/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj index 406bb29d6..edfd657f6 100644 --- a/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj @@ -39,37 +39,60 @@ (deftest compile-and-test (testing "Static" (are [x y res] (= res (c/compile {} (elm/and [x y]))) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" false - #elm/boolean"true" {:type "Null"} nil + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" false + #elm/boolean "true" {:type "Null"} nil - #elm/boolean"false" #elm/boolean"true" false - #elm/boolean"false" #elm/boolean"false" false - #elm/boolean"false" {:type "Null"} false + #elm/boolean "false" #elm/boolean "true" false + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} false - {:type "Null"} #elm/boolean"true" nil - {:type "Null"} #elm/boolean"false" false + {:type "Null"} #elm/boolean "true" nil + {:type "Null"} #elm/boolean "false" false {:type "Null"} {:type "Null"} nil)) (testing "Dynamic" (are [x y res] (= res (tu/dynamic-compile-eval (elm/and [x y]))) - #elm/boolean"true" #elm/parameter-ref"true" true - #elm/parameter-ref"true" #elm/boolean"true" true - #elm/parameter-ref"true" #elm/parameter-ref"true" true - #elm/parameter-ref"true" {:type "Null"} nil - {:type "Null"} #elm/parameter-ref"true" nil - - #elm/boolean"true" #elm/parameter-ref"false" false - #elm/parameter-ref"false" #elm/boolean"true" false - #elm/parameter-ref"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" {:type "Null"} false - {:type "Null"} #elm/parameter-ref"false" false - - #elm/boolean"false" #elm/parameter-ref"nil" false - #elm/parameter-ref"nil" #elm/boolean"false" false - #elm/boolean"true" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"true" nil - #elm/parameter-ref"nil" #elm/parameter-ref"nil" nil))) + #elm/boolean "true" #elm/parameter-ref "true" true + #elm/parameter-ref "true" #elm/boolean "true" true + #elm/parameter-ref "true" #elm/parameter-ref "true" true + #elm/parameter-ref "true" {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "true" nil + + #elm/boolean "true" #elm/parameter-ref "false" false + #elm/parameter-ref "false" #elm/boolean "true" false + #elm/parameter-ref "false" #elm/parameter-ref "false" false + #elm/parameter-ref "false" {:type "Null"} false + {:type "Null"} #elm/parameter-ref "false" false + + #elm/boolean "false" #elm/parameter-ref "nil" false + #elm/parameter-ref "nil" #elm/boolean "false" false + #elm/boolean "true" #elm/parameter-ref "nil" nil + #elm/parameter-ref "nil" #elm/boolean "true" nil + #elm/parameter-ref "nil" #elm/parameter-ref "nil" nil)) + + (testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "a"} {:name "b"}]}}}] + (are [x y form] (= form (c/form (c/compile compile-ctx# (elm/and [x y])))) + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" false + #elm/boolean "true" {:type "Null"} nil + #elm/boolean "true" #elm/parameter-ref "b" '(param-ref "b") + + #elm/boolean "false" #elm/boolean "true" false + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} false + #elm/boolean "false" #elm/parameter-ref "b" false + + {:type "Null"} #elm/boolean "true" nil + {:type "Null"} #elm/boolean "false" false + {:type "Null"} {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "b" '(and nil (param-ref "b")) + + #elm/parameter-ref "a" #elm/boolean "true" '(param-ref "a") + #elm/parameter-ref "a" #elm/boolean "false" false + #elm/parameter-ref "a" {:type "Null"} '(and nil (param-ref "a")) + #elm/parameter-ref "a" #elm/parameter-ref "b" '(and (param-ref "a") (param-ref "b")))))) ;; 13.2. Implies @@ -86,16 +109,16 @@ (deftest compile-implies-test (testing "Static" (are [x y res] (= res (c/compile {} (elm/or [(elm/not x) y]))) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" false - #elm/boolean"true" {:type "Null"} nil + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" false + #elm/boolean "true" {:type "Null"} nil - #elm/boolean"false" #elm/boolean"true" true - #elm/boolean"false" #elm/boolean"false" true - #elm/boolean"false" {:type "Null"} true + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" true + #elm/boolean "false" {:type "Null"} true - {:type "Null"} #elm/boolean"true" true - {:type "Null"} #elm/boolean"false" nil + {:type "Null"} #elm/boolean "true" true + {:type "Null"} #elm/boolean "false" nil {:type "Null"} {:type "Null"} nil))) @@ -107,15 +130,17 @@ (deftest compile-not-test (testing "Static" (are [x res] (= res (c/compile {} (elm/not x))) - #elm/boolean"true" false - #elm/boolean"false" true + #elm/boolean "true" false + #elm/boolean "false" true {:type "Null"} nil)) (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/not x))) - #elm/parameter-ref"true" false - #elm/parameter-ref"false" true - #elm/parameter-ref"nil" nil))) + #elm/parameter-ref "true" false + #elm/parameter-ref "false" true + #elm/parameter-ref "nil" nil)) + + (tu/testing-unary-form elm/not)) ;; 13.4. Or @@ -128,37 +153,60 @@ (deftest compile-or-test (testing "Static" (are [x y res] (= res (c/compile {} (elm/or [x y]))) - #elm/boolean"true" #elm/boolean"true" true - #elm/boolean"true" #elm/boolean"false" true - #elm/boolean"true" {:type "Null"} true + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} true - #elm/boolean"false" #elm/boolean"true" true - #elm/boolean"false" #elm/boolean"false" false - #elm/boolean"false" {:type "Null"} nil + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} nil - {:type "Null"} #elm/boolean"true" true - {:type "Null"} #elm/boolean"false" nil + {:type "Null"} #elm/boolean "true" true + {:type "Null"} #elm/boolean "false" nil {:type "Null"} {:type "Null"} nil)) (testing "Dynamic" (are [x y res] (= res (tu/dynamic-compile-eval (elm/or [x y]))) - #elm/boolean"false" #elm/parameter-ref"true" true - #elm/parameter-ref"true" #elm/boolean"false" true - #elm/parameter-ref"true" #elm/parameter-ref"true" true - #elm/parameter-ref"true" {:type "Null"} true - {:type "Null"} #elm/parameter-ref"true" true - - #elm/boolean"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" #elm/boolean"false" false - #elm/parameter-ref"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" {:type "Null"} nil - {:type "Null"} #elm/parameter-ref"false" nil - - #elm/boolean"true" #elm/parameter-ref"nil" true - #elm/parameter-ref"nil" #elm/boolean"true" true - #elm/boolean"false" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"false" nil - #elm/parameter-ref"nil" #elm/parameter-ref"nil" nil))) + #elm/boolean "false" #elm/parameter-ref "true" true + #elm/parameter-ref "true" #elm/boolean "false" true + #elm/parameter-ref "true" #elm/parameter-ref "true" true + #elm/parameter-ref "true" {:type "Null"} true + {:type "Null"} #elm/parameter-ref "true" true + + #elm/boolean "false" #elm/parameter-ref "false" false + #elm/parameter-ref "false" #elm/boolean "false" false + #elm/parameter-ref "false" #elm/parameter-ref "false" false + #elm/parameter-ref "false" {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "false" nil + + #elm/boolean "true" #elm/parameter-ref "nil" true + #elm/parameter-ref "nil" #elm/boolean "true" true + #elm/boolean "false" #elm/parameter-ref "nil" nil + #elm/parameter-ref "nil" #elm/boolean "false" nil + #elm/parameter-ref "nil" #elm/parameter-ref "nil" nil)) + + (testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "a"} {:name "b"}]}}}] + (are [x y form] (= form (c/form (c/compile compile-ctx# (elm/or [x y])))) + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} true + #elm/boolean "true" #elm/parameter-ref "b" true + + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} nil + #elm/boolean "false" #elm/parameter-ref "b" '(param-ref "b") + + {:type "Null"} #elm/boolean "true" true + {:type "Null"} #elm/boolean "false" nil + {:type "Null"} {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "b" '(or nil (param-ref "b")) + + #elm/parameter-ref "a" #elm/boolean "true" true + #elm/parameter-ref "a" #elm/boolean "false" '(param-ref "a") + #elm/parameter-ref "a" {:type "Null"} '(or nil (param-ref "a")) + #elm/parameter-ref "a" #elm/parameter-ref "b" '(or (param-ref "a") (param-ref "b")))))) ;; 13.5. Xor @@ -172,36 +220,59 @@ (deftest compile-xor-test (testing "Static" (are [x y res] (= res (c/compile {} (elm/xor [x y]))) - #elm/boolean"true" #elm/boolean"true" false - #elm/boolean"true" #elm/boolean"false" true - #elm/boolean"true" {:type "Null"} nil + #elm/boolean "true" #elm/boolean "true" false + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} nil - #elm/boolean"false" #elm/boolean"true" true - #elm/boolean"false" #elm/boolean"false" false - #elm/boolean"false" {:type "Null"} nil + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} nil - {:type "Null"} #elm/boolean"true" nil - {:type "Null"} #elm/boolean"false" nil + {:type "Null"} #elm/boolean "true" nil + {:type "Null"} #elm/boolean "false" nil {:type "Null"} {:type "Null"} nil)) (testing "Dynamic" (are [x y res] (= res (tu/dynamic-compile-eval (elm/xor [x y]))) - #elm/boolean"true" #elm/parameter-ref"true" false - #elm/parameter-ref"true" #elm/boolean"true" false - #elm/boolean"false" #elm/parameter-ref"true" true - #elm/parameter-ref"true" #elm/boolean"false" true - #elm/parameter-ref"true" #elm/parameter-ref"true" false - - #elm/boolean"true" #elm/parameter-ref"false" true - #elm/parameter-ref"false" #elm/boolean"true" true - #elm/boolean"false" #elm/parameter-ref"false" false - #elm/parameter-ref"false" #elm/boolean"false" false - #elm/parameter-ref"false" #elm/parameter-ref"false" false - - #elm/boolean"true" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"true" nil - #elm/boolean"false" #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" #elm/boolean"false" nil - {:type "Null"} #elm/parameter-ref"nil" nil - #elm/parameter-ref"nil" {:type "Null"} nil - #elm/parameter-ref"nil" #elm/parameter-ref"nil" nil))) + #elm/boolean "true" #elm/parameter-ref "true" false + #elm/parameter-ref "true" #elm/boolean "true" false + #elm/boolean "false" #elm/parameter-ref "true" true + #elm/parameter-ref "true" #elm/boolean "false" true + #elm/parameter-ref "true" #elm/parameter-ref "true" false + + #elm/boolean "true" #elm/parameter-ref "false" true + #elm/parameter-ref "false" #elm/boolean "true" true + #elm/boolean "false" #elm/parameter-ref "false" false + #elm/parameter-ref "false" #elm/boolean "false" false + #elm/parameter-ref "false" #elm/parameter-ref "false" false + + #elm/boolean "true" #elm/parameter-ref "nil" nil + #elm/parameter-ref "nil" #elm/boolean "true" nil + #elm/boolean "false" #elm/parameter-ref "nil" nil + #elm/parameter-ref "nil" #elm/boolean "false" nil + {:type "Null"} #elm/parameter-ref "nil" nil + #elm/parameter-ref "nil" {:type "Null"} nil + #elm/parameter-ref "nil" #elm/parameter-ref "nil" nil)) + + (testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "a"} {:name "b"}]}}}] + (are [x y form] (= form (c/form (c/compile compile-ctx# (elm/xor [x y])))) + #elm/boolean "true" #elm/boolean "true" false + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} nil + #elm/boolean "true" #elm/parameter-ref "b" '(not (param-ref "b")) + + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} nil + #elm/boolean "false" #elm/parameter-ref "b" '(param-ref "b") + + {:type "Null"} #elm/boolean "true" nil + {:type "Null"} #elm/boolean "false" nil + {:type "Null"} {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "b" nil + + #elm/parameter-ref "a" #elm/boolean "true" '(not (param-ref "a")) + #elm/parameter-ref "a" #elm/boolean "false" '(param-ref "a") + #elm/parameter-ref "a" {:type "Null"} nil + #elm/parameter-ref "a" #elm/parameter-ref "b" '(xor (param-ref "a") (param-ref "b")))))) diff --git a/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj b/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj index 853ac31cb..7a73dc6c8 100644 --- a/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj @@ -45,9 +45,9 @@ (are [elm res] (= res (core/-eval (c/compile {} (elm/coalesce elm)) {} nil nil)) [] nil [{:type "Null"}] nil - [#elm/boolean"false" #elm/boolean"true"] false - [{:type "Null"} #elm/integer"1" #elm/integer"2"] 1 - [#elm/integer"2"] 2 + [#elm/boolean "false" #elm/boolean "true"] false + [{:type "Null"} #elm/integer "1" #elm/integer "2"] 1 + [#elm/integer "2"] 2 [#elm/list []] nil [{:type "Null"} #elm/list [#elm/string "a"]] ["a"] [#elm/list [{:type "Null"} #elm/string "a"]] "a")) @@ -61,15 +61,17 @@ (deftest compile-is-false-test (testing "Static" (are [x res] (= res (c/compile {} (elm/is-false x))) - #elm/boolean"true" false - #elm/boolean"false" true + #elm/boolean "true" false + #elm/boolean "false" true {:type "Null"} false)) (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/is-false x))) - #elm/parameter-ref"true" false - #elm/parameter-ref"false" true - #elm/parameter-ref"nil" false))) + #elm/parameter-ref "true" false + #elm/parameter-ref "false" true + #elm/parameter-ref "nil" false)) + + (tu/testing-unary-form elm/is-false)) ;; 14.4. IsNull @@ -80,15 +82,17 @@ (deftest compile-is-null-test (testing "Static" (are [x res] (= res (c/compile {} (elm/is-null x))) - #elm/boolean"true" false - #elm/boolean"false" false + #elm/boolean "true" false + #elm/boolean "false" false {:type "Null"} true)) (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/is-null x))) - #elm/parameter-ref"true" false - #elm/parameter-ref"false" false - #elm/parameter-ref"nil" true))) + #elm/parameter-ref "true" false + #elm/parameter-ref "false" false + #elm/parameter-ref "nil" true)) + + (tu/testing-unary-form elm/is-null)) ;; 14.5. IsTrue @@ -99,12 +103,14 @@ (deftest compile-is-true-test (testing "Static" (are [x res] (= res (c/compile {} (elm/is-true x))) - #elm/boolean"true" true - #elm/boolean"false" false + #elm/boolean "true" true + #elm/boolean "false" false {:type "Null"} false)) (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/is-true x))) - #elm/parameter-ref"true" true - #elm/parameter-ref"false" false - #elm/parameter-ref"nil" false))) + #elm/parameter-ref "true" true + #elm/parameter-ref "false" false + #elm/parameter-ref "nil" false)) + + (tu/testing-unary-form elm/is-true)) diff --git a/modules/cql/test/blaze/elm/compiler/parameters_test.clj b/modules/cql/test/blaze/elm/compiler/parameters_test.clj index c63ac3353..bcef1b140 100644 --- a/modules/cql/test/blaze/elm/compiler/parameters_test.clj +++ b/modules/cql/test/blaze/elm/compiler/parameters_test.clj @@ -42,13 +42,16 @@ {:library {:parameters {:def - [{:name "parameter-def-101820"}]}}}] - (is (= (->ParameterRef "parameter-def-101820") - (c/compile context #elm/parameter-ref"parameter-def-101820"))))) + [{:name "parameter-def-101820"}]}}} + expr (c/compile context #elm/parameter-ref "parameter-def-101820")] + (is (= (->ParameterRef "parameter-def-101820") expr)) + + (testing "form" + (is (= '(param-ref "parameter-def-101820") (core/-form expr)))))) (testing "definition not found" (let [context {:library {}}] - (given (ba/try-anomaly (c/compile context #elm/parameter-ref"parameter-def-103701")) + (given (ba/try-anomaly (c/compile context #elm/parameter-ref "parameter-def-103701")) ::anom/category := ::anom/incorrect ::anom/message := "Parameter definition `parameter-def-103701` not found." :context := context))) @@ -59,7 +62,7 @@ {:parameters {:def [{:name "parameter-def-111045"}]}}} - expr (c/compile context #elm/parameter-ref"parameter-def-111045")] + expr (c/compile context #elm/parameter-ref "parameter-def-111045")] (given (ba/try-anomaly (core/-eval expr {} nil nil)) ::anom/category := ::anom/incorrect ::anom/message := "Value of parameter `parameter-def-111045` not found." diff --git a/modules/cql/test/blaze/elm/compiler/queries_test.clj b/modules/cql/test/blaze/elm/compiler/queries_test.clj index 41adf5ce2..4cbba0382 100644 --- a/modules/cql/test/blaze/elm/compiler/queries_test.clj +++ b/modules/cql/test/blaze/elm/compiler/queries_test.clj @@ -21,9 +21,7 @@ [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] [cognitect.anomalies :as anom] - [juxt.iota :refer [given]]) - (:import - [clojure.lang IPersistentCollection])) + [juxt.iota :refer [given]])) (st/instrument) @@ -64,9 +62,9 @@ [{:alias "S" :expression #elm/list - [#elm/quantity[2 "m"] - #elm/quantity[1 "m"] - #elm/quantity[1 "m"]]}] + [#elm/quantity [2 "m"] + #elm/quantity [1 "m"] + #elm/quantity [1 "m"]]}] :sort {:by [{:type "ByExpression" @@ -85,12 +83,12 @@ [{:alias "S" :expression #elm/list - [#elm/instance["{urn:hl7-org:elm-types:r1}Code" - {"system" #elm/string"foo" - "code" #elm/string"c"}] - #elm/instance["{urn:hl7-org:elm-types:r1}Code" - {"system" #elm/string"bar" - "code" #elm/string"c"}]]}] + [#elm/instance ["{urn:hl7-org:elm-types:r1}Code" + {"system" #elm/string "foo" + "code" #elm/string "c"}] + #elm/instance ["{urn:hl7-org:elm-types:r1}Code" + {"system" #elm/string "bar" + "code" #elm/string "c"}]]}] :sort {:by [{:type "ByExpression" @@ -110,13 +108,18 @@ :return {:distinct false :expression {:type "AliasRef" :name "S"}}} [1 1])) - (testing "returns only the first item on optimize first" - (let [query {:type "Query" - :source - [{:alias "S" - :expression #elm/list [#elm/integer "1" #elm/integer "1"]}]} - res (core/-eval (c/compile {:optimizations #{:first}} query) {} nil nil)] - (is (not (instance? IPersistentCollection res)))))) + (testing "with query hint optimize first" + (let [elm {:type "Query" + :source + [{:alias "S" + :expression #elm/list [#elm/integer "1" #elm/integer "1"]}]} + expr (c/compile {:optimizations #{:first}} elm)] + + (testing "eval" + (is (= [1] (into [] (core/-eval expr {} nil nil))))) + + (testing "form" + (is (= '(eduction-query distinct [1 1]) (core/-form expr))))))) (testing "Retrieve queries" (with-system-data [{:blaze.db/keys [node]} mem-node-system] @@ -138,70 +141,85 @@ :resultTypeName "{http://hl7.org/fhir}string" :life/source-type "{http://hl7.org/fhir}Patient"}] - (let [query {:type "Query" - :source - [{:alias "P" - :expression retrieve}]}] - (given (core/-eval (c/compile {:node node :eval-context "Unfiltered"} query) {:db db} nil nil) - [0 fhir-spec/fhir-type] := :fhir/Patient - [0 :id] := "0")) - - (let [query {:type "Query" - :source - [{:alias "P" - :expression retrieve}] - :where where}] - (is (empty? (core/-eval (c/compile {:node node :eval-context "Unfiltered"} query) {:db db} nil nil)))) - - (let [query {:type "Query" - :source - [{:alias "P" - :expression retrieve}] - :return {:expression return}}] - (is (nil? (first (core/-eval (c/compile {:node node :eval-context "Unfiltered"} query) {:db db} nil nil))))) - - (let [query {:type "Query" - :source - [{:alias "P" - :expression retrieve}] - :where where - :return {:expression return}}] - (is (empty? (core/-eval (c/compile {:node node :eval-context "Unfiltered"} query) {:db db} nil nil))))))) + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}]} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + (testing "eval" + (given (core/-eval expr {:db db} nil nil) + [0 fhir-spec/fhir-type] := :fhir/Patient + [0 :id] := "0")) + + (testing "form" + (is (= '(vector-query distinct (retrieve "Patient")) (core/-form expr))))) + + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}] + :where where} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + (testing "eval" + (is (empty? (core/-eval expr {:db db} nil nil)))) + + (testing "form" + (is (= '(vector-query + (comp (where (equal (:gender default) 2)) distinct) + (retrieve "Patient")) + (core/-form expr))))) + + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}] + :return {:expression return}} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + (is (nil? (first (core/-eval expr {:db db} nil nil))))) + + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}] + :where where + :return {:expression return}} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + (is (empty? (core/-eval expr {:db db} nil nil))))))) (testing "Unsupported With clause" (let [elm {:type "Query" - :source - [{:expression - {:type "Retrieve" - :dataType "{http://hl7.org/fhir}Condition"} - :alias "C"}] - :relationship - [{:type "With" - :alias "P" - :expression - {:type "Retrieve" :dataType "{http://hl7.org/fhir}Procedure"} - :suchThat - {:type "Equal" - :operand [#elm/integer "1" #elm/integer "1"]}}]}] + :source + [{:expression + {:type "Retrieve" + :dataType "{http://hl7.org/fhir}Condition"} + :alias "C"}] + :relationship + [{:type "With" + :alias "P" + :expression + {:type "Retrieve" :dataType "{http://hl7.org/fhir}Procedure"} + :suchThat + {:type "Equal" + :operand [#elm/integer "1" #elm/integer "1"]}}]}] (given (ba/try-anomaly (c/compile {} elm)) ::anom/category := ::anom/unsupported ::anom/message := "Unsupported With clause in query expression."))) (testing "Unsupported Without clause" (let [elm {:type "Query" - :source - [{:expression - {:type "Retrieve" - :dataType "{http://hl7.org/fhir}Condition"} - :alias "C"}] - :relationship - [{:type "Without" - :alias "P" - :expression - {:type "Retrieve" :dataType "{http://hl7.org/fhir}Procedure"} - :suchThat - {:type "Equal" - :operand [#elm/integer "1" #elm/integer "1"]}}]}] + :source + [{:expression + {:type "Retrieve" + :dataType "{http://hl7.org/fhir}Condition"} + :alias "C"}] + :relationship + [{:type "Without" + :alias "P" + :expression + {:type "Retrieve" :dataType "{http://hl7.org/fhir}Procedure"} + :suchThat + {:type "Equal" + :operand [#elm/integer "1" #elm/integer "1"]}}]}] (given (ba/try-anomaly (c/compile {} elm)) ::anom/category := ::anom/unsupported ::anom/message := "Unsupported Without clause in query expression.")))) diff --git a/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj b/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj index 5288c58ba..e715f2551 100644 --- a/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj +++ b/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj @@ -9,6 +9,7 @@ [blaze.elm.compiler.core :as core] [blaze.elm.compiler.test-util :as tu] [blaze.elm.interval :as interval] + [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [blaze.elm.quantity :as quantity] [blaze.fhir.spec.type.system :as system] @@ -52,55 +53,86 @@ (testing "Eval" (let [library {:statements {:def [{:name "name-170312"}]}} expr (c/compile {:library library} #elm/expression-ref "name-170312")] - (is (= ::result (core/-eval expr {:library-context {"name-170312" ::result}} nil nil)))))) + (is (= ::result (core/-eval expr {:library-context {"name-170312" ::result}} nil nil))))) + + (testing "form" + (let [library {:statements {:def [{:name "name-170312"}]}} + expr (c/compile {:library library} #elm/expression-ref "name-170312")] + (is (= '(expr-ref "name-170312") (core/-form expr)))))) ;; 9.4. FunctionRef +;; +;; The FunctionRef type defines an expression that invokes a previously defined +;; function. The result of evaluating each operand is passed to the function. (deftest compile-function-ref-test + (testing "ToQuantity" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm (elm/function-ref "ToQuantity" #elm/parameter-ref "x") + expr (c/compile compile-ctx elm)] + (testing "eval" + (are [x res] (= res (core/-eval expr {:parameters {"x" x}} nil nil)) + {:value 23M :code "kg"} (quantity/quantity 23M "kg") + {:value 42M} (quantity/quantity 42M "1") + {} nil)) + + (testing "form" + (is (= '(call "ToQuantity" (param-ref "x")) (core/-form expr)))))) + + (testing "ToDateTime" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm (elm/function-ref "ToDateTime" #elm/parameter-ref "x") + expr (c/compile compile-ctx elm) + eval-ctx (fn [x] {:now tu/now :parameters {"x" x}})] + (testing "eval" + (are [x res] (= res (core/-eval expr (eval-ctx x) nil nil)) + #fhir/dateTime"2022-02-22" + (system/date-time 2022 2 22) + #fhir/instant"2021-02-23T15:12:45Z" + (system/date-time 2021 2 23 15 12 45) + #fhir/instant"2021-02-23T15:12:45+01:00" + (system/date-time 2021 2 23 14 12 45))) + + (testing "form" + (is (= '(call "ToDateTime" (param-ref "x")) (core/-form expr)))))) + (testing "ToString" - (are [elm res] - (= res (core/-eval (c/compile {} elm) {} nil nil)) - {:type "FunctionRef" - :libraryName "FHIRHelpers" - :name "ToString" - :operand [#elm/string "foo"]} - "foo")) + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm (elm/function-ref "ToString" #elm/parameter-ref "x") + expr (c/compile compile-ctx elm)] + (testing "eval" + (are [x res] (= res (core/-eval expr {:parameters {"x" x}} nil nil)) + "string-195733" "string-195733" + #fhir/uri"uri-195924" "uri-195924")) - (testing "ToQuantity" - (let [context {:library {:parameters {:def [{:name "x"}]}}} - elm {:type "FunctionRef" - :libraryName "FHIRHelpers" - :name "ToQuantity" - :operand [#elm/parameter-ref"x"]} - expr (c/compile context elm)] - (are [x res] (= res (core/-eval expr {:parameters {"x" x}} nil nil)) - {:value 23M :code "kg"} (quantity/quantity 23M "kg") - {:value 42M} (quantity/quantity 42M "1") - {} nil))) + (testing "form" + (is (= '(call "ToString" (param-ref "x")) (core/-form expr)))))) (testing "ToInterval" - (let [context {:library {:parameters {:def [{:name "x"}]}}} - elm {:type "FunctionRef" - :libraryName "FHIRHelpers" - :name "ToInterval" - :operand [#elm/parameter-ref"x"]} - expr (c/compile context elm)] - (are [x res] (= res (core/-eval expr {:now tu/now :parameters {"x" x}} nil nil)) - #fhir/Period - {:start #fhir/dateTime"2021-02-23T15:12:45+01:00" - :end #fhir/dateTime"2021-02-23T16:00:00+01:00"} - (interval/interval - (system/date-time 2021 2 23 14 12 45) - (system/date-time 2021 2 23 15 0 0)) - #fhir/Period - {:start nil - :end #fhir/dateTime"2021-02-23T16:00:00+01:00"} - (interval/interval - nil - (system/date-time 2021 2 23 15 0 0)) - #fhir/Period - {:start #fhir/dateTime"2021-02-23T15:12:45+01:00" - :end nil} - (interval/interval - (system/date-time 2021 2 23 14 12 45) - nil))))) + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm (elm/function-ref "ToInterval" #elm/parameter-ref "x") + expr (c/compile compile-ctx elm) + eval-ctx (fn [x] {:now tu/now :parameters {"x" x}})] + (testing "eval" + (are [x res] (= res (core/-eval expr (eval-ctx x) nil nil)) + #fhir/Period + {:start #fhir/dateTime"2021-02-23T15:12:45+01:00" + :end #fhir/dateTime"2021-02-23T16:00:00+01:00"} + (interval/interval + (system/date-time 2021 2 23 14 12 45) + (system/date-time 2021 2 23 15 0 0)) + #fhir/Period + {:start nil + :end #fhir/dateTime"2021-02-23T16:00:00+01:00"} + (interval/interval + nil + (system/date-time 2021 2 23 15 0 0)) + #fhir/Period + {:start #fhir/dateTime"2021-02-23T15:12:45+01:00" + :end nil} + (interval/interval + (system/date-time 2021 2 23 14 12 45) + nil))) + + (testing "form" + (is (= '(call "ToInterval" (param-ref "x")) (core/-form expr))))))) diff --git a/modules/cql/test/blaze/elm/compiler/simple_values_test.clj b/modules/cql/test/blaze/elm/compiler/simple_values_test.clj index 1b015ee82..05e8496f4 100644 --- a/modules/cql/test/blaze/elm/compiler/simple_values_test.clj +++ b/modules/cql/test/blaze/elm/compiler/simple_values_test.clj @@ -34,49 +34,49 @@ (deftest compile-literal-test (testing "Boolean Literal" (are [elm res] (= res (c/compile {} elm)) - #elm/boolean"true" true - #elm/boolean"false" false)) + #elm/boolean "true" true + #elm/boolean "false" false)) (testing "Decimal Literal" (are [elm res] (= res (c/compile {} elm)) - #elm/decimal"-1" -1M - #elm/decimal"0" 0M - #elm/decimal"1" 1M + #elm/decimal "-1" -1M + #elm/decimal "0" 0M + #elm/decimal "1" 1M - #elm/decimal"-0.1" -0.1M - #elm/decimal"0.0" 0M - #elm/decimal"0.1" 0.1M + #elm/decimal "-0.1" -0.1M + #elm/decimal "0.0" 0M + #elm/decimal "0.1" 0.1M - #elm/decimal"0.000000001" 0M - #elm/decimal"0.000000005" 1E-8M + #elm/decimal "0.000000001" 0M + #elm/decimal "0.000000005" 1E-8M - #elm/decimal"-99999999999999999999.99999999" -99999999999999999999.99999999M - #elm/decimal"99999999999999999999.99999999" 99999999999999999999.99999999M) + #elm/decimal "-99999999999999999999.99999999" -99999999999999999999.99999999M + #elm/decimal "99999999999999999999.99999999" 99999999999999999999.99999999M) (testing "failure" - (given (ba/try-anomaly (c/compile {} #elm/decimal"x")) + (given (ba/try-anomaly (c/compile {} #elm/decimal "x")) ::anom/category := ::anom/incorrect ::anom/message := "Incorrect decimal literal `x`."))) (testing "Long Literal" (are [elm res] (= res (c/compile {} elm)) - #elm/long"-1" -1 - #elm/long"0" 0 - #elm/long"1" 1) + #elm/long "-1" -1 + #elm/long "0" 0 + #elm/long "1" 1) (testing "failure" - (given (ba/try-anomaly (c/compile {} #elm/long"x")) + (given (ba/try-anomaly (c/compile {} #elm/long "x")) ::anom/category := ::anom/incorrect ::anom/message := "Incorrect long literal `x`."))) (testing "Integer Literal" (are [elm res] (= res (c/compile {} elm)) - #elm/integer"-1" -1 - #elm/integer"0" 0 - #elm/integer"1" 1) + #elm/integer "-1" -1 + #elm/integer "0" 0 + #elm/integer "1" 1) (testing "failure" - (given (ba/try-anomaly (c/compile {} #elm/integer"x")) + (given (ba/try-anomaly (c/compile {} #elm/integer "x")) ::anom/category := ::anom/incorrect ::anom/message := "Incorrect integer literal `x`."))) diff --git a/modules/cql/test/blaze/elm/compiler/string_operators_test.clj b/modules/cql/test/blaze/elm/compiler/string_operators_test.clj index 707a568c9..5b896b757 100644 --- a/modules/cql/test/blaze/elm/compiler/string_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/string_operators_test.clj @@ -7,6 +7,7 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.test-util :as tu] + [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest testing]])) @@ -80,16 +81,25 @@ ;; ;; If either argument is null, the result is null. (deftest compile-ends-with-test - (are [s suffix res] (= res (core/-eval (c/compile {} {:type "EndsWith" :operand [s suffix]}) {} nil nil)) - #elm/string "a" #elm/string "a" true - #elm/string "ab" #elm/string "b" true + (testing "static" + (are [s suffix res] (= res (c/compile {} (elm/ends-with [s suffix]))) + #elm/string "a" #elm/string "a" true + #elm/string "ab" #elm/string "b" true - #elm/string "a" #elm/string "b" false - #elm/string "ba" #elm/string "b" false + #elm/string "a" #elm/string "b" false + #elm/string "ba" #elm/string "b" false)) - {:type "Null"} #elm/string "a" nil - #elm/string "a" {:type "Null"} nil - {:type "Null"} {:type "Null"} nil)) + (testing "dynamic" + (are [s suffix res] (= res (tu/dynamic-compile-eval (elm/ends-with [s suffix]))) + #elm/parameter-ref "a" #elm/string "a" true + #elm/parameter-ref "ab" #elm/string "b" true + + #elm/parameter-ref "a" #elm/string "b" false + #elm/parameter-ref "ba" #elm/string "b" false)) + + (tu/testing-binary-null elm/ends-with #elm/string "a") + + (tu/testing-binary-form elm/ends-with)) ;; 17.4. Equal @@ -114,28 +124,26 @@ ;; If either argument is null, the result is null. (deftest compile-indexer-test (testing "String" - (are [x i res] (= res (core/-eval (c/compile {} {:type "Indexer" :operand [x i]}) {} nil nil)) - #elm/string "a" #elm/integer"0" "a" - #elm/string "ab" #elm/integer"1" "b" + (are [x i res] (= res (c/compile {} (elm/indexer [x i]))) + #elm/string "a" #elm/integer "0" "a" + #elm/string "ab" #elm/integer "1" "b" - #elm/string "" #elm/integer"-1" nil - #elm/string "" #elm/integer"0" nil - #elm/string "a" #elm/integer"1" nil + #elm/string "" #elm/integer "-1" nil + #elm/string "a" #elm/integer "1" nil) - #elm/string "" {:type "Null"} nil - {:type "Null"} #elm/integer"0" nil)) + (tu/testing-binary-null elm/indexer #elm/string "a" #elm/integer "0")) (testing "List" - (are [x i res] (= res (core/-eval (c/compile {} {:type "Indexer" :operand [x i]}) {} nil nil)) - #elm/list [#elm/integer"1"] #elm/integer"0" 1 - #elm/list [#elm/integer"1" #elm/integer"2"] #elm/integer"1" 2 + (are [x i res] (= res (c/compile {} (elm/indexer [x i]))) + #elm/list [#elm/integer "1"] #elm/integer "0" 1 + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/integer "1" 2 - #elm/list [] #elm/integer"-1" nil - #elm/list [] #elm/integer"0" nil - #elm/list [#elm/integer"1"] #elm/integer"1" nil + #elm/list [] #elm/integer "-1" nil + #elm/list [#elm/integer "1"] #elm/integer "1" nil) - #elm/list [] {:type "Null"} nil - {:type "Null"} #elm/integer"0" nil))) + (tu/testing-binary-null elm/indexer #elm/list [] #elm/integer "0")) + + (tu/testing-binary-form elm/indexer)) ;; 17.7. LastPositionOf @@ -168,13 +176,22 @@ ;; ;; If the argument is null, the result is 0. (deftest compile-length-test - (are [x res] (= res (core/-eval (c/compile {} {:type "Length" :operand x}) {} nil nil)) - #elm/string "" 0 - #elm/string "a" 1 - #elm/list [] 0 - #elm/list [#elm/integer"1"] 1 + (testing "static" + (are [x res] (= res (c/compile {} (elm/length x))) + #elm/string "" 0 + #elm/string "a" 1 + #elm/list [] 0 + #elm/list [#elm/integer "1"] 1 + + {:type "Null"} 0)) + + (testing "dynamic" + (are [x res] (= res (tu/dynamic-compile-eval (elm/length x))) + #elm/parameter-ref "empty-string" 0 + #elm/parameter-ref "a" 1 + #elm/parameter-ref "nil" 0)) - {:type "Null"} 0)) + (tu/testing-unary-form elm/length)) ;; 17.9. Lower @@ -189,11 +206,19 @@ ;; ;; If the argument is null, the result is null. (deftest compile-lower-test - (are [s res] (= res (core/-eval (c/compile {} {:type "Lower" :operand s}) {} nil nil)) - #elm/string "" "" - #elm/string "A" "a" + (testing "static" + (are [s res] (= res (c/compile {} (elm/lower s))) + #elm/string "" "" + #elm/string "A" "a")) - {:type "Null"} nil)) + (testing "dynamic" + (are [s res] (= res (tu/dynamic-compile-eval (elm/lower s))) + #elm/parameter-ref "empty-string" "" + #elm/parameter-ref "A" "a")) + + (tu/testing-unary-null elm/lower) + + (tu/testing-unary-form elm/lower)) ;; 17.10. Matches @@ -210,14 +235,14 @@ ;; such, CQL does not prescribe a particular dialect, but recommends the use of ;; the PCRE dialect. (deftest compile-matches-test - (are [s pattern res] (= res (core/-eval (c/compile {} {:type "Matches" :operand [s pattern]}) {} nil nil)) + (are [s pattern res] (= res (c/compile {} (elm/matches [s pattern]))) #elm/string "a" #elm/string "a" true - #elm/string "a" #elm/string "\\d" false + #elm/string "a" #elm/string "\\d" false) - {:type "Null"} #elm/string "a" nil - #elm/string "a" {:type "Null"} nil - {:type "Null"} {:type "Null"} nil)) + (tu/testing-binary-null elm/matches #elm/string "a") + + (tu/testing-binary-form elm/matches)) ;; 17.11. NotEqual @@ -321,16 +346,25 @@ ;; ;; If either argument is null, the result is null. (deftest compile-starts-with-test - (are [s prefix res] (= res (core/-eval (c/compile {} {:type "StartsWith" :operand [s prefix]}) {} nil nil)) - #elm/string "a" #elm/string "a" true - #elm/string "ba" #elm/string "b" true + (testing "static" + (are [s prefix res] (= res (c/compile {} (elm/starts-with [s prefix]))) + #elm/string "a" #elm/string "a" true + #elm/string "ba" #elm/string "b" true - #elm/string "a" #elm/string "b" false - #elm/string "ab" #elm/string "b" false + #elm/string "a" #elm/string "b" false + #elm/string "ab" #elm/string "b" false)) - {:type "Null"} #elm/string "a" nil - #elm/string "a" {:type "Null"} nil - {:type "Null"} {:type "Null"} nil)) + (testing "dynamic" + (are [s prefix res] (= res (tu/dynamic-compile-eval (elm/starts-with [s prefix]))) + #elm/parameter-ref "a" #elm/string "a" true + #elm/parameter-ref "ba" #elm/string "b" true + + #elm/parameter-ref "a" #elm/string "b" false + #elm/parameter-ref "ab" #elm/string "b" false)) + + (tu/testing-binary-null elm/starts-with #elm/string "a") + + (tu/testing-binary-form elm/starts-with)) ;; 17.17. Substring @@ -348,25 +382,25 @@ (deftest compile-substring-test (testing "Without length" (are [s start-index res] (= res (core/-eval (c/compile {} {:type "Substring" :stringToSub s :startIndex start-index}) {} nil nil)) - #elm/string "ab" #elm/integer"1" "b" + #elm/string "ab" #elm/integer "1" "b" - #elm/string "a" #elm/integer"-1" nil - #elm/string "a" #elm/integer"1" nil - {:type "Null"} #elm/integer"0" nil + #elm/string "a" #elm/integer "-1" nil + #elm/string "a" #elm/integer "1" nil + {:type "Null"} #elm/integer "0" nil #elm/string "a" {:type "Null"} nil {:type "Null"} {:type "Null"} nil)) (testing "With length" (are [s start-index length res] (= res (core/-eval (c/compile {} {:type "Substring" :stringToSub s :startIndex start-index :length length}) {} nil nil)) - #elm/string "a" #elm/integer"0" #elm/integer"1" "a" - #elm/string "a" #elm/integer"0" #elm/integer"2" "a" - #elm/string "abc" #elm/integer"1" #elm/integer"1" "b" + #elm/string "a" #elm/integer "0" #elm/integer "1" "a" + #elm/string "a" #elm/integer "0" #elm/integer "2" "a" + #elm/string "abc" #elm/integer "1" #elm/integer "1" "b" - #elm/string "a" #elm/integer"-1" #elm/integer"0" nil - #elm/string "a" #elm/integer"2" #elm/integer"0" nil - {:type "Null"} #elm/integer"0" #elm/integer"0" nil - #elm/string "a" {:type "Null"} #elm/integer"0" nil - {:type "Null"} {:type "Null"} #elm/integer"0" nil))) + #elm/string "a" #elm/integer "-1" #elm/integer "0" nil + #elm/string "a" #elm/integer "2" #elm/integer "0" nil + {:type "Null"} #elm/integer "0" #elm/integer "0" nil + #elm/string "a" {:type "Null"} #elm/integer "0" nil + {:type "Null"} {:type "Null"} #elm/integer "0" nil))) ;; 17.18. Upper @@ -381,8 +415,16 @@ ;; ;; If the argument is null, the result is null. (deftest compile-upper-test - (are [s res] (= res (core/-eval (c/compile {} {:type "Upper" :operand s}) {} nil nil)) - #elm/string "" "" - #elm/string "a" "A" + (testing "static" + (are [s res] (= res (c/compile {} (elm/upper s))) + #elm/string "" "" + #elm/string "a" "A")) + + (testing "dynamic" + (are [s res] (= res (tu/dynamic-compile-eval (elm/upper s))) + #elm/parameter-ref "empty-string" "" + #elm/parameter-ref "a" "A")) + + (tu/testing-unary-null elm/upper) - {:type "Null"} nil)) + (tu/testing-unary-form elm/upper)) diff --git a/modules/cql/test/blaze/elm/compiler/structured_values_test.clj b/modules/cql/test/blaze/elm/compiler/structured_values_test.clj index 34fe83084..1210ffa78 100644 --- a/modules/cql/test/blaze/elm/compiler/structured_values_test.clj +++ b/modules/cql/test/blaze/elm/compiler/structured_values_test.clj @@ -42,10 +42,10 @@ ;; expression, including another Tuple. (deftest compile-tuple-test (are [elm res] (= res (core/-eval (c/compile {} elm) {} nil nil)) - #elm/tuple{"id" #elm/integer"1"} + #elm/tuple{"id" #elm/integer "1"} {:id 1} - #elm/tuple{"id" #elm/integer"1" "name" #elm/string "john"} + #elm/tuple{"id" #elm/integer "1" "name" #elm/string "john"} {:id 1 :name "john"})) @@ -108,7 +108,10 @@ {:eval-context "Patient"} elm) result (coll/first (core/-eval expr nil nil {"R" entity}))] - (is (= identifier result)))) + (is (= identifier result)) + + (testing "form" + (is (= '(:identifier R) (core/-form expr)))))) (testing "without source-type" (let [elm @@ -230,7 +233,10 @@ :life/single-query-scope "R"} elm) result (coll/first (core/-eval expr nil nil entity))] - (is (= identifier result)))) + (is (= identifier result)) + + (testing "form" + (is (= '(:identifier default) (core/-form expr)))))) (testing "without source-type" (let [elm @@ -333,7 +339,10 @@ :identifier [identifier]} expr (c/compile {:library library :eval-context "Patient"} elm) result (coll/first (core/-eval expr {:library-context {"Patient" source}} nil nil))] - (is (= identifier result)))) + (is (= identifier result)) + + (testing "form" + (is (= '(:identifier (expr-ref "Patient")) (core/-form expr)))))) (testing "without source-type" (let [library {:statements {:def [{:name "Patient"}]}} @@ -424,7 +433,7 @@ {:name "name" :type {:name "{urn:hl7-org:elm-types:r1}String" :type "NamedTypeSpecifier"}}]} :element - [{:name "id" :value #elm/integer"1"}]}} + [{:name "id" :value #elm/integer "1"}]}} 1)) (testing "Quantity" @@ -434,7 +443,7 @@ {:resultTypeName "{urn:hl7-org:elm-types:r1}Decimal" :path "value" :type "Property" - :source #elm/quantity[42 "m"]} + :source #elm/quantity [42 "m"]} 42M)) (testing "unit" @@ -443,7 +452,7 @@ {:resultTypeName "{urn:hl7-org:elm-types:r1}String" :path "unit" :type "Property" - :source #elm/quantity[42 "m"]} + :source #elm/quantity [42 "m"]} "m"))) (testing "nil" diff --git a/modules/cql/test/blaze/elm/compiler/test_util.clj b/modules/cql/test/blaze/elm/compiler/test_util.clj index 3fa54fe00..924fcc5cb 100644 --- a/modules/cql/test/blaze/elm/compiler/test_util.clj +++ b/modules/cql/test/blaze/elm/compiler/test_util.clj @@ -51,11 +51,19 @@ {:name "1"} {:name "2"} {:name "3"} - {:name "4"}]}}}) + {:name "4"} + {:name "empty-string"} + {:name "a"} + {:name "ab"} + {:name "b"} + {:name "ba"} + {:name "A"}]}}}) (def dynamic-eval-ctx - {:parameters {"true" true "false" false "nil" nil "1" 1 "2" 2 "3" 3 "4" 4}}) + {:parameters + {"true" true "false" false "nil" nil "1" 1 "2" 2 "3" 3 "4" 4 + "empty-string" "" "a" "a" "ab" "ab" "b" "b" "ba" "ba" "A" "A"}}) (defn dynamic-compile-eval [elm] @@ -85,7 +93,7 @@ (defmacro testing-unary-dynamic-null [elm-constructor] `(testing "Dynamic Null" - (let [elm# (~elm-constructor #elm/parameter-ref"nil")] + (let [elm# (~elm-constructor #elm/parameter-ref "nil")] (is (nil? (dynamic-compile-eval elm#)))))) @@ -105,15 +113,15 @@ (defmacro testing-binary-dynamic-null [elm-constructor non-null-op-1 non-null-op-2] `(testing "Dynamic Null" (let [elm# (~elm-constructor - [#elm/parameter-ref"nil" - #elm/parameter-ref"nil"])] + [#elm/parameter-ref "nil" + #elm/parameter-ref "nil"])] (is (nil? (dynamic-compile-eval elm#)))) (let [elm# (~elm-constructor [~non-null-op-1 - #elm/parameter-ref"nil"])] + #elm/parameter-ref "nil"])] (is (nil? (dynamic-compile-eval elm#)))) (let [elm# (~elm-constructor - [#elm/parameter-ref"nil" + [#elm/parameter-ref "nil" ~non-null-op-2])] (is (nil? (dynamic-compile-eval elm#)))))) @@ -144,3 +152,52 @@ (defn compile-binop-precision [constructor op-constructor op-1 op-2 precision] (c/compile {} (constructor [(op-constructor op-1) (op-constructor op-2) precision]))) + + +(defmacro testing-unary-form [elm-constructor] + (let [form-name (symbol (name elm-constructor))] + `(testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "x"}]}}} + elm# (~elm-constructor (elm/parameter-ref "x")) + expr# (c/compile compile-ctx# elm#)] + (is (= (quote (~form-name (~'param-ref "x"))) (core/-form expr#))))))) + + +(defmacro testing-unary-precision-form + ([elm-constructor] + `(testing-unary-precision-form ~elm-constructor "year" "month")) + ([elm-constructor & precisions] + (let [form-name (symbol (name elm-constructor))] + `(testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "x"}]}}}] + (doseq [precision# ~(vec precisions)] + (let [elm# (~elm-constructor [(elm/parameter-ref "x") precision#]) + expr# (c/compile compile-ctx# elm#)] + (is (= (list '~form-name '(~'param-ref "x") precision#) + (core/-form expr#)))))))))) + + +(defmacro testing-binary-form [elm-constructor] + (let [form-name (symbol (name elm-constructor))] + `(testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "x"} {:name "y"}]}}} + elm# (~elm-constructor [(elm/parameter-ref "x") + (elm/parameter-ref "y")]) + expr# (c/compile compile-ctx# elm#)] + (is (= (quote (~form-name (~'param-ref "x") (~'param-ref "y"))) + (core/-form expr#))))))) + + +(defmacro testing-binary-precision-form + ([elm-constructor] + `(testing-binary-precision-form ~elm-constructor "year" "month")) + ([elm-constructor & precisions] + (let [form-name (symbol (name elm-constructor))] + `(testing "form" + (let [compile-ctx# {:library {:parameters {:def [{:name "x"} {:name "y"}]}}}] + (doseq [precision# ~(vec precisions)] + (let [elm# (~elm-constructor [(elm/parameter-ref "x") + (elm/parameter-ref "y") precision#]) + expr# (c/compile compile-ctx# elm#)] + (is (= (list '~form-name '(~'param-ref "x") '(~'param-ref "y") + precision#) (core/-form expr#)))))))))) diff --git a/modules/cql/test/blaze/elm/compiler/type_operators_test.clj b/modules/cql/test/blaze/elm/compiler/type_operators_test.clj index fea9474fb..f972b4974 100644 --- a/modules/cql/test/blaze/elm/compiler/type_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/type_operators_test.clj @@ -44,7 +44,7 @@ (deftest compile-as-test (testing "FHIR types" (are [elm resource res] (= res (core/-eval (c/compile {} elm) {} nil {"R" resource})) - #elm/as["{http://hl7.org/fhir}boolean" + #elm/as ["{http://hl7.org/fhir}boolean" {:path "deceased" :scope "R" :type "Property"}] @@ -52,67 +52,93 @@ true #elm/as ["{http://hl7.org/fhir}integer" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Observation :value (int 1)} (int 1) #elm/as ["{http://hl7.org/fhir}string" - {:path "name" - :scope "R" - :type "Property"}] + {:path "name" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Account :name "a"} "a" #elm/as ["{http://hl7.org/fhir}decimal" - {:path "duration" - :scope "R" - :type "Property"}] + {:path "duration" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Media :duration 1.1M} 1.1M #elm/as ["{http://hl7.org/fhir}uri" - {:path "url" - :scope "R" - :type "Property"}] + {:path "url" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Measure :url #fhir/uri"a"} #fhir/uri"a" #elm/as ["{http://hl7.org/fhir}url" - {:path "address" - :scope "R" - :type "Property"}] + {:path "address" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Endpoint :address #fhir/url"a"} #fhir/url"a" #elm/as ["{http://hl7.org/fhir}dateTime" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Observation :value #fhir/dateTime"2019-09-04"} #fhir/dateTime"2019-09-04" #elm/as ["{http://hl7.org/fhir}Quantity" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Observation :value #fhir/dateTime"2019-09-04"} nil)) (testing "ELM types" (are [elm res] (= res (core/-eval (c/compile {} elm) {} nil nil)) - #elm/as ["{urn:hl7-org:elm-types:r1}Boolean" #elm/boolean"true"] + #elm/as ["{urn:hl7-org:elm-types:r1}Boolean" #elm/boolean "true"] true - #elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/integer"1"] + #elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/integer "1"] 1 #elm/as ["{urn:hl7-org:elm-types:r1}Integer" {:type "Null"}] nil - #elm/as ["{urn:hl7-org:elm-types:r1}DateTime" #elm/date-time"2019-09-04"] - (system/date-time 2019 9 4)))) + #elm/as ["{urn:hl7-org:elm-types:r1}DateTime" #elm/date-time "2019-09-04"] + (system/date-time 2019 9 4))) + + (testing "form" + (are [elm form] (= form (core/-form (c/compile {} elm))) + #elm/as ["{urn:hl7-org:elm-types:r1}Integer" {:type "Null"}] + nil + + #elm/as ["{urn:hl7-org:elm-types:r1}Integer" #elm/integer "1"] + '(as elm/integer 1) + + #elm/as ["{http://hl7.org/fhir}dateTime" + {:path "value" + :scope "R" + :type "Property"}] + '(as fhir/dateTime (:value R)) + + {:type "As" + :asTypeSpecifier + {:type "ListTypeSpecifier" + :elementType + {:type "NamedTypeSpecifier" + :name "{http://hl7.org/fhir}Quantity"}} + :operand + {:path "value" + :scope "R" + :type "Property"}} + '(as (list fhir/Quantity) (:value R))))) ;; TODO 22.2. CanConvert @@ -130,13 +156,24 @@ ;; ;; If either argument is null, the result is null. (deftest compile-can-convert-quantity-test - (are [argument unit] (true? (core/-eval (c/compile {} #elm/can-convert-quantity [argument unit]) {} nil nil)) - #elm/quantity[5 "mg"] #elm/string "g") + (let [compile-op (partial tu/compile-binop elm/can-convert-quantity + elm/quantity elm/string)] + (testing "true" + (are [argument unit] (true? (compile-op argument unit)) + [5 "mg"] "g")) + + (testing "false" + (are [argument unit] (false? (compile-op argument unit)) + [5 "mg"] "m"))) - (are [argument unit] (false? (core/-eval (c/compile {} #elm/can-convert-quantity [argument unit]) {} nil nil)) - #elm/quantity[5 "mg"] #elm/string "m") + (tu/testing-binary-null elm/can-convert-quantity #elm/quantity [1 "m"] + #elm/string "m") - (tu/testing-binary-null elm/can-convert-quantity #elm/quantity[1 "m"] #elm/string "m")) + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "q"}]}}} + elm #elm/can-convert-quantity[#elm/parameter-ref "q" #elm/string "g"] + expr (c/compile compile-ctx elm)] + (is (= '(can-convert-quantity (param-ref "q") "g") (core/-form expr)))))) ;; 22.4. Children @@ -180,12 +217,18 @@ ;; If either argument is null, the result is null. (deftest compile-convert-quantity-test (are [argument unit res] (p/equal res (core/-eval (c/compile {} (elm/convert-quantity [argument unit])) {} nil nil)) - #elm/quantity[5 "mg"] #elm/string "g" (quantity/quantity 0.005 "g")) + #elm/quantity [5 "mg"] #elm/string "g" (quantity/quantity 0.005 "g")) (are [argument unit] (nil? (core/-eval (c/compile {} (elm/convert-quantity [argument unit])) {} nil nil)) - #elm/quantity[5 "mg"] #elm/string "m") + #elm/quantity [5 "mg"] #elm/string "m") - (tu/testing-binary-null elm/convert-quantity #elm/quantity[5 "mg"] #elm/string "m")) + (tu/testing-binary-null elm/convert-quantity #elm/quantity [5 "mg"] #elm/string "m") + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "q"}]}}} + elm #elm/convert-quantity[#elm/parameter-ref "q" #elm/string "g"] + expr (c/compile compile-ctx elm)] + (is (= '(convert-quantity (param-ref "q") "g") (core/-form expr)))))) ;; TODO 22.7. ConvertsToBoolean @@ -378,8 +421,7 @@ ;; If the argument is null, the result is null. (deftest compile-to-decimal-test (testing "String" - (are [x res] (= res (core/-eval (tu/compile-unop elm/to-decimal elm/string x) - {} nil nil)) + (are [x res] (= res (tu/compile-unop elm/to-decimal elm/string x)) (str decimal/min) decimal/min "-1.1" -1.1M "-1" -1M @@ -391,7 +433,13 @@ (str (+ decimal/max 1e-8M)) nil "a" nil)) - (tu/testing-unary-null elm/to-decimal)) + (tu/testing-unary-null elm/to-decimal) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/to-decimal #elm/parameter-ref "x" + expr (c/compile compile-ctx elm)] + (is (= '(to-decimal (param-ref "x")) (core/-form expr)))))) ;; 22.25. ToInteger @@ -431,7 +479,13 @@ "true" 1 "false" 0)) - (tu/testing-unary-null elm/to-integer)) + (tu/testing-unary-null elm/to-integer) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/to-integer #elm/parameter-ref "x" + expr (c/compile compile-ctx elm)] + (is (= '(to-integer (param-ref "x")) (core/-form expr)))))) ;; 22.26. ToList @@ -458,7 +512,13 @@ "1" [1])) (testing "Null" - (is (= [] (core/-eval (c/compile {} #elm/to-list{:type "Null"}) {} nil nil))))) + (is (= [] (core/-eval (c/compile {} #elm/to-list{:type "Null"}) {} nil nil)))) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/to-list #elm/parameter-ref "x" + expr (c/compile compile-ctx elm)] + (is (= '(to-list (param-ref "x")) (core/-form expr)))))) ;; 22.27. ToLong @@ -502,7 +562,13 @@ "true" 1 "false" 0)) - (tu/testing-unary-null elm/to-long)) + (tu/testing-unary-null elm/to-long) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/to-long #elm/parameter-ref "x" + expr (c/compile compile-ctx elm)] + (is (= '(to-long (param-ref "x")) (core/-form expr)))))) ;; 22.28. ToQuantity @@ -569,7 +635,13 @@ ;; TODO: Ratio - (tu/testing-unary-null elm/to-quantity)) + (tu/testing-unary-null elm/to-quantity) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/to-quantity #elm/parameter-ref "x" + expr (c/compile compile-ctx elm)] + (is (= '(to-quantity (param-ref "x")) (core/-form expr)))))) ;; TODO 22.29. ToRatio @@ -651,7 +723,13 @@ ;; TODO: Ratio - (tu/testing-unary-null elm/to-string)) + (tu/testing-unary-null elm/to-string) + + (testing "form" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/to-string #elm/parameter-ref "x" + expr (c/compile compile-ctx elm)] + (is (= '(to-string (param-ref "x")) (core/-form expr)))))) ;; TODO 22.31. ToTime diff --git a/modules/cql/test/blaze/elm/literal.clj b/modules/cql/test/blaze/elm/literal.clj index 83a3a3639..8edaf0f4e 100644 --- a/modules/cql/test/blaze/elm/literal.clj +++ b/modules/cql/test/blaze/elm/literal.clj @@ -106,6 +106,13 @@ :name name}) +;; 9.4. FunctionRef +(defn function-ref [name & ops] + {:type "FunctionRef" + :name name + :operand ops}) + + ;; 11. External Data @@ -318,11 +325,13 @@ (assoc :precision precision))) +;; 16.20. Subtract (defn subtract [ops] {:type "Subtract" :operand ops}) +;; 16.21. Successor (defn successor [op] {:type "Successor" :operand op}) @@ -334,11 +343,60 @@ :operand op}) +;; 16.23. TruncatedDivide (defn truncated-divide [ops] {:type "TruncatedDivide" :operand ops}) + +;; 17. String Operators + +;; 17.3. EndsWith +(defn ends-with [ops] + {:type "EndsWith" + :operand ops}) + + +;; 17.6. Indexer +(defn indexer [ops] + {:type "Indexer" + :operand ops}) + + +;; 17.8. Length +(defn length [x] + {:type "Length" + :operand x}) + + +;; 17.9. Lower +(defn lower [x] + {:type "Lower" + :operand x}) + + +;; 17.10. Matches +(defn matches [ops] + {:type "Matches" + :operand ops}) + + +;; 17.16. StartsWith +(defn starts-with [ops] + {:type "StartsWith" + :operand ops}) + + +;; 17.18. Upper +(defn upper [x] + {:type "Upper" + :operand x}) + + + +;; 18. Date and Time Operators + ;; 18.14. SameAs (defn same-as [[x y precision]] (cond-> @@ -495,8 +553,12 @@ ;; 19.5. Contains -(defn contains [ops] - {:type "Contains" :operand ops}) +(defn contains [[list x precision]] + (cond-> + {:type "Contains" + :operand [list x]} + precision + (assoc :precision precision))) ;; 19.6. End @@ -505,8 +567,12 @@ ;; 19.7. Ends -(defn ends [ops] - {:type "Ends" :operand ops}) +(defn ends [[x y precision]] + (cond-> + {:type "Ends" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.10. Except @@ -515,8 +581,12 @@ ;; 19.13. Includes -(defn includes [ops] - {:type "Includes" :operand ops}) +(defn includes [[x y precision]] + (cond-> + {:type "Includes" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.15. Intersect @@ -525,18 +595,30 @@ ;; 19.17. MeetsBefore -(defn meets-before [ops] - {:type "MeetsBefore" :operand ops}) +(defn meets-before [[x y precision]] + (cond-> + {:type "MeetsBefore" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.18. MeetsAfter -(defn meets-after [ops] - {:type "MeetsAfter" :operand ops}) +(defn meets-after [[x y precision]] + (cond-> + {:type "MeetsAfter" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.20. Overlaps -(defn overlaps [ops] - {:type "Overlaps" :operand ops}) +(defn overlaps [[x y precision]] + (cond-> + {:type "Overlaps" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.23. PointFrom @@ -545,13 +627,21 @@ ;; 19.24. ProperContains -(defn proper-contains [ops] - {:type "ProperContains" :operand ops}) +(defn proper-contains [[x y precision]] + (cond-> + {:type "ProperContains" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.26. ProperIncludes -(defn proper-includes [ops] - {:type "ProperIncludes" :operand ops}) +(defn proper-includes [[x y precision]] + (cond-> + {:type "ProperIncludes" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.29. Start @@ -560,8 +650,12 @@ ;; 19.30. Starts -(defn starts [ops] - {:type "Starts" :operand ops}) +(defn starts [[x y precision]] + (cond-> + {:type "Starts" + :operand [x y]} + precision + (assoc :precision precision))) ;; 19.31. Union diff --git a/modules/cql/test/blaze/elm/literal_spec.clj b/modules/cql/test/blaze/elm/literal_spec.clj index 20708cbdd..e9b87effb 100644 --- a/modules/cql/test/blaze/elm/literal_spec.clj +++ b/modules/cql/test/blaze/elm/literal_spec.clj @@ -1,6 +1,6 @@ (ns blaze.elm.literal-spec (:require - [blaze.elm.literal :as literal] + [blaze.elm.literal :as elm] [blaze.elm.spec] [clojure.spec.alpha :as s])) @@ -9,22 +9,22 @@ ;; 1. Simple Values ;; 1.1. Literal -(s/fdef literal/boolean +(s/fdef elm/boolean :args (s/cat :s string?) :ret :elm/expression) -(s/fdef literal/decimal +(s/fdef elm/decimal :args (s/cat :s string?) :ret :elm/expression) -(s/fdef literal/integer +(s/fdef elm/integer :args (s/cat :s string?) :ret :elm/expression) -(s/fdef literal/string +(s/fdef elm/string :args (s/cat :s string?) :ret :elm/expression) @@ -33,13 +33,13 @@ ;; 2. Structured Values ;; 2.1. Tuple -(s/fdef literal/tuple +(s/fdef elm/tuple :args (s/cat :arg (s/map-of string? :elm/expression)) :ret :elm/expression) ;; 2.1. Instance -(s/fdef literal/instance +(s/fdef elm/instance :args (s/cat :arg (s/tuple string? (s/map-of string? :elm/expression))) :ret :elm/expression) @@ -48,7 +48,7 @@ ;; 3. Clinical Values ;; 3.1 Code -(s/fdef literal/code +(s/fdef elm/code :args (s/cat :args @@ -57,13 +57,13 @@ ;; 3.3. CodeRef -(s/fdef literal/code-ref +(s/fdef elm/code-ref :args (s/cat :name string?) :ret :elm/expression) ;; 3.9. Quantity -(s/fdef literal/quantity +(s/fdef elm/quantity :args (s/cat :args (s/spec (s/cat :value number? :unit (s/? string?)))) :ret :elm/expression) @@ -72,192 +72,193 @@ ;; 9. Reusing Logic ;; 9.2. ExpressionRef -(s/fdef literal/expression-ref +(s/fdef elm/expression-ref :args (s/cat :name string?) :ret :elm/expression) -(s/fdef literal/equal +(s/fdef elm/equal :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/equivalent +(s/fdef elm/equivalent :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/greater +(s/fdef elm/greater :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/greater-or-equal +(s/fdef elm/greater-or-equal :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/less +(s/fdef elm/less :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/less-or-equal +(s/fdef elm/less-or-equal :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/and +(s/fdef elm/and :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/not +(s/fdef elm/not :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/or +(s/fdef elm/or :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/xor +(s/fdef elm/xor :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/is-false +(s/fdef elm/is-false :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/is-null +(s/fdef elm/is-null :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/is-true +(s/fdef elm/is-true :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/list +(s/fdef elm/list :args (s/cat :elements (s/coll-of :elm/expression)) :ret :elm/expression) -(s/fdef literal/if-expr +(s/fdef elm/if-expr :args (s/cat :ops (s/tuple :elm/expression :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/abs +(s/fdef elm/abs :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/add +(s/fdef elm/add :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/ceiling +(s/fdef elm/ceiling :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/divide +(s/fdef elm/divide :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/exp +(s/fdef elm/exp :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/floor +(s/fdef elm/floor :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/log +(s/fdef elm/log :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/ln +(s/fdef elm/ln :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/modulo +(s/fdef elm/modulo :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/multiply +(s/fdef elm/multiply :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/negate +(s/fdef elm/negate :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/power +(s/fdef elm/power :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/predecessor +(s/fdef elm/predecessor :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/round - :args (s/cat :arg (s/coll-of :elm/expression)) +(s/fdef elm/round + :args (s/cat :ops (s/spec (s/cat :x :elm/expression + :precision (s/? :elm/expression)))) :ret :elm/expression) -(s/fdef literal/subtract +(s/fdef elm/subtract :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/successor +(s/fdef elm/successor :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/truncate +(s/fdef elm/truncate :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/truncated-divide +(s/fdef elm/truncated-divide :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) -(s/fdef literal/date +(s/fdef elm/date :args (s/cat :arg (s/alt :str string? :exprs (s/coll-of :elm/expression))) :ret :elm/expression) -(s/fdef literal/date-from +(s/fdef elm/date-from :args (s/cat :op :elm/expression) :ret :elm/expression) -(s/fdef literal/date-time +(s/fdef elm/date-time :args (s/cat :arg (s/alt :str string? :exprs (s/coll-of :elm/expression))) :ret :elm/expression) -(s/fdef literal/time +(s/fdef elm/time :args (s/cat :arg (s/alt :str string? :exprs (s/coll-of :elm/expression))) :ret :elm/expression) @@ -269,123 +270,156 @@ :high :elm/expression :high-open (s/? #{:>}))) -(s/fdef literal/interval +(s/fdef elm/interval :args (s/cat :arg (s/spec ::interval-arg)) :ret :elm/expression) ;; 19.2. After -(s/fdef literal/after +(s/fdef elm/after :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression :precision (s/? string?)))) :ret :elm/expression) ;; 19.3. Before -(s/fdef literal/before +(s/fdef elm/before :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression :precision (s/? string?)))) :ret :elm/expression) ;; 19.4. Collapse -(s/fdef literal/collapse +(s/fdef elm/collapse :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) ;; 19.5. Contains -(s/fdef literal/contains - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) +(s/fdef elm/contains + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) + :ret :elm/expression) + + +;; 19.6. End +(s/fdef elm/end + :args (s/cat :interval :elm/expression) + :ret :elm/expression) + + +;; 19.7. Ends +(s/fdef elm/ends + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) ;; 19.13. Except -(s/fdef literal/except +(s/fdef elm/except :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) ;; 19.13. Includes -(s/fdef literal/includes - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) +(s/fdef elm/includes + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) ;; 19.15. Intersect -(s/fdef literal/intersect +(s/fdef elm/intersect :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) ;; 19.17. MeetsBefore -(s/fdef literal/meets-before - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) +(s/fdef elm/meets-before + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) ;; 19.18. MeetsAfter -(s/fdef literal/meets-after - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) +(s/fdef elm/meets-after + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) + :ret :elm/expression) + + +;; 19.20. Overlaps +(s/fdef elm/overlaps + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) ;; 19.24. ProperContains -(s/fdef literal/proper-contains - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) +(s/fdef elm/proper-contains + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) ;; 19.26. ProperIncludes -(s/fdef literal/proper-includes - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) +(s/fdef elm/proper-includes + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) + :ret :elm/expression) + + +;; 19.30. ProperIncludes +(s/fdef elm/starts + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) ;; 19.31. Union -(s/fdef literal/union +(s/fdef elm/union :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) ;; 20.3. Current -(s/fdef literal/current +(s/fdef elm/current :args (s/cat :scope string?) :ret :elm/expression) ;; 20.4. Distinct -(s/fdef literal/distinct +(s/fdef elm/distinct :args (s/cat :list :elm/expression) :ret :elm/expression) ;; 20.8. Exists -(s/fdef literal/exists +(s/fdef elm/exists :args (s/cat :list :elm/expression) :ret :elm/expression) ;; 20.10. First -(s/fdef literal/first +(s/fdef elm/first :args (s/cat :source :elm/expression) :ret :elm/expression) ;; 20.11. Flatten -(s/fdef literal/flatten +(s/fdef elm/flatten :args (s/cat :list :elm/expression) :ret :elm/expression) ;; 20.25. SingletonFrom -(s/fdef literal/singleton-from +(s/fdef elm/singleton-from :args (s/cat :list :elm/expression) :ret :elm/expression) ;; 20.28. Times -(s/fdef literal/times +(s/fdef elm/times :args (s/cat :lists (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) @@ -394,61 +428,67 @@ ;; 22. Type Operators ;; 22.1. As -(s/fdef literal/as +(s/fdef elm/as :args (s/cat :arg (s/tuple string? :elm/expression)) :ret :elm/expression) ;; 22.6. ConvertQuantity -(s/fdef literal/convert-quantity +(s/fdef elm/convert-quantity :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) ;; 22.17. Descendents -(s/fdef literal/descendents +(s/fdef elm/descendents :args (s/cat :source :elm/expression) :ret :elm/expression) ;; 22.22. ToDate -(s/fdef literal/to-date +(s/fdef elm/to-date :args (s/cat :operand :elm/expression) :ret :elm/expression) ;; 22.23. ToDateTime -(s/fdef literal/to-date-time +(s/fdef elm/to-date-time :args (s/cat :operand :elm/expression) :ret :elm/expression) ;; 22.24. ToDecimal -(s/fdef literal/to-decimal +(s/fdef elm/to-decimal :args (s/cat :operand :elm/expression) :ret :elm/expression) ;; 22.25. ToInteger -(s/fdef literal/to-integer +(s/fdef elm/to-integer :args (s/cat :operand :elm/expression) :ret :elm/expression) ;; 22.26. ToList -(s/fdef literal/to-list +(s/fdef elm/to-list + :args (s/cat :operand :elm/expression) + :ret :elm/expression) + + +;; 22.27. ToLong +(s/fdef elm/to-long :args (s/cat :operand :elm/expression) :ret :elm/expression) ;; 22.28. ToQuantity -(s/fdef literal/to-quantity +(s/fdef elm/to-quantity :args (s/cat :operand :elm/expression) :ret :elm/expression) ;; 22.30. ToString -(s/fdef literal/to-string +(s/fdef elm/to-string :args (s/cat :operand :elm/expression) :ret :elm/expression) @@ -457,6 +497,6 @@ ;; 23. Clinical Operators ;; 23.4. CalculateAgeAt -(s/fdef literal/calculate-age-at +(s/fdef elm/calculate-age-at :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) :ret :elm/expression) diff --git a/modules/cql/test/blaze/elm/normalizer_test.clj b/modules/cql/test/blaze/elm/normalizer_test.clj index b768545d8..1b838c166 100644 --- a/modules/cql/test/blaze/elm/normalizer_test.clj +++ b/modules/cql/test/blaze/elm/normalizer_test.clj @@ -3,6 +3,7 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.elm.literal :as elm] + [blaze.elm.literal-spec] [blaze.elm.normalizer :refer [normalize]] [blaze.elm.normalizer-spec] [clojure.spec.test.alpha :as st] diff --git a/modules/cql/test/blaze/elm/spec_test.clj b/modules/cql/test/blaze/elm/spec_test.clj index 700921c99..2d1331e4c 100644 --- a/modules/cql/test/blaze/elm/spec_test.clj +++ b/modules/cql/test/blaze/elm/spec_test.clj @@ -24,7 +24,7 @@ (deftest literal-test (testing "valid" (are [x] (s/valid? :elm/expression x) - #elm/boolean"true")) + #elm/boolean "true")) (testing "invalid" (given (s/explain-data :elm/expression {:type "Literal"}) @@ -34,7 +34,7 @@ (deftest literal-integer-test (testing "valid" (are [x] (s/valid? :elm/integer x) - #elm/integer"0")) + #elm/integer "0")) (testing "invalid" (given (s/explain-data :elm/integer nil) @@ -43,14 +43,14 @@ (given (s/explain-data :elm/integer {:type "Literal"}) [::s/problems 0 :pred] := `(fn [~'%] (contains? ~'% :valueType))) - (given (s/explain-data :elm/integer #elm/boolean"true") + (given (s/explain-data :elm/integer #elm/boolean "true") [::s/problems 0 :path 0] := :valueType))) (deftest literal-decimal-test (testing "valid" (are [x] (s/valid? :elm/decimal x) - #elm/decimal"0")) + #elm/decimal "0")) (testing "invalid" (given (s/explain-data :elm/decimal nil) @@ -59,7 +59,7 @@ (given (s/explain-data :elm/decimal {:type "Literal"}) [::s/problems 0 :pred] := `(fn [~'%] (contains? ~'% :valueType))) - (given (s/explain-data :elm/decimal #elm/boolean"true") + (given (s/explain-data :elm/decimal #elm/boolean "true") [::s/problems 0 :path 0] := :valueType))) @@ -67,7 +67,7 @@ (testing "valid" (are [x] (s/valid? :elm/expression x) #elm/tuple{} - #elm/tuple{"id" #elm/integer"0"})) + #elm/tuple{"id" #elm/integer "0"})) (testing "invalid" (given (s/explain-data :elm/expression {:type "Tuple" :element "foo"}) @@ -86,8 +86,8 @@ (deftest instance-test (testing "valid" (are [x] (s/valid? :elm/expression x) - #elm/instance["{urn:hl7-org:elm-types:r1}Code" - {"system" #elm/string"foo" "code" #elm/string"bar"}])) + #elm/instance ["{urn:hl7-org:elm-types:r1}Code" + {"system" #elm/string "foo" "code" #elm/string "bar"}])) (testing "invalid" (given (s/explain-data :elm/expression {:type "Instance"}) @@ -114,7 +114,7 @@ (testing "valid" (are [x] (s/valid? :elm/expression x) {:type "Query" - :source [{:alias "foo" :expression #elm/integer"0"}]})) + :source [{:alias "foo" :expression #elm/integer "0"}]})) (testing "invalid" (given (s/explain-data :elm/expression {:type "Query"}) @@ -131,54 +131,54 @@ (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0"}]}) + [{:expression #elm/integer "0"}]}) [::s/problems 0 :pred] := `(fn [~'%] (contains? ~'% :alias))) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort "foo"}) [::s/problems 0 :pred] := `map?) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {}}) [::s/problems 0 :pred] := `(fn [~'%] (contains? ~'% :by))) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {:by "foo"}}) [::s/problems 0 :pred] := `coll?) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {:by ["foo"]}}) [::s/problems 0 :pred] := `blaze.elm.spec/sort-by-item) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {:by [{:type "ByDirection"}]}}) [::s/problems 0 :pred] := `(fn [~'%] (contains? ~'% :direction))) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {:by [{:type "ByColumn"}]}}) [::s/problems 0 :pred] := `(fn [~'%] (contains? ~'% :direction))) (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {:by @@ -189,7 +189,7 @@ (given (s/explain-data :elm/expression {:type "Query" :source - [{:expression #elm/integer"0" + [{:expression #elm/integer "0" :alias "foo"}] :sort {:by diff --git a/modules/cql/test/data_readers.clj b/modules/cql/test/data_readers.clj index 21ec385c7..c13cf38fe 100644 --- a/modules/cql/test/data_readers.clj +++ b/modules/cql/test/data_readers.clj @@ -27,6 +27,13 @@ elm/list blaze.elm.literal/list elm/if blaze.elm.literal/if-expr elm/abs blaze.elm.literal/abs + elm/ends-with blaze.elm.literal/ends-with + elm/indexer blaze.elm.literal/indexer + elm/length blaze.elm.literal/length + elm/lower blaze.elm.literal/lower + elm/matches blaze.elm.literal/matches + elm/starts-with blaze.elm.literal/starts-with + elm/upper blaze.elm.literal/upper elm/add blaze.elm.literal/add elm/ceiling blaze.elm.literal/ceiling elm/divide blaze.elm.literal/divide @@ -48,8 +55,12 @@ elm/date blaze.elm.literal/date elm/date-from blaze.elm.literal/date-from elm/date-time blaze.elm.literal/date-time + elm/date-time-component-from blaze.elm.literal/date-time-component-from + elm/difference-between blaze.elm.literal/difference-between + elm/duration-between blaze.elm.literal/duration-between elm/time blaze.elm.literal/time elm/interval blaze.elm.literal/interval + elm/contains blaze.elm.literal/contains elm/intersect blaze.elm.literal/intersect elm/current blaze.elm.literal/current elm/distinct blaze.elm.literal/distinct @@ -66,6 +77,7 @@ elm/to-decimal blaze.elm.literal/to-decimal elm/to-integer blaze.elm.literal/to-integer elm/to-list blaze.elm.literal/to-list + elm/to-long blaze.elm.literal/to-long elm/to-quantity blaze.elm.literal/to-quantity elm/to-string blaze.elm.literal/to-string elm/calculate-age-at blaze.elm.literal/calculate-age-at} diff --git a/modules/db/test/blaze/db/impl/search_param/date_test.clj b/modules/db/test/blaze/db/impl/search_param/date_test.clj index f77e5d25b..42d689939 100644 --- a/modules/db/test/blaze/db/impl/search_param/date_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/date_test.clj @@ -13,7 +13,6 @@ [blaze.fhir-path :as fhir-path] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] - [blaze.fhir.spec.type :as type] [blaze.fhir.structure-definition-repo] [blaze.test-util :refer [with-system]] [clojure.spec.test.alpha :as st] @@ -208,7 +207,7 @@ (testing "issued" (let [patient {:fhir/type :fhir/DiagnosticReport :id "id-155607" - :issued (type/->Instant "2019-11-17T00:14:29.917+01:00")} + :issued #fhir/instant"2019-11-17T00:14:29.917+01:00"} hash (hash/generate patient) [[_ k0]] (search-param/index-entries From a6b3ce91caecfa9f0926c16274cbd920aa5721bb Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Sat, 26 Feb 2022 14:52:49 +0100 Subject: [PATCH 06/14] Update Dev Dependencies --- .github/workflows/build.yml | 12 ++++++------ deps.edn | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 08da2488d..c1b5f22a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,7 +76,7 @@ jobs: steps: - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: ${{ matrix.java-version }} @@ -107,7 +107,7 @@ jobs: steps: - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' @@ -149,7 +149,7 @@ jobs: steps: - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: ${{ matrix.java-version }} @@ -177,7 +177,7 @@ jobs: steps: - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' @@ -544,7 +544,7 @@ jobs: steps: - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' @@ -846,7 +846,7 @@ jobs: steps: - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' diff --git a/deps.edn b/deps.edn index d3a24ac08..55f9263ea 100644 --- a/deps.edn +++ b/deps.edn @@ -78,7 +78,7 @@ :outdated {:replace-deps {com.github.liquidz/antq - {:mvn/version "1.5.0"} + {:mvn/version "1.5.1"} org.slf4j/slf4j-nop {:mvn/version "1.7.36"}} From 7727f6e2dd3ab64c7d305d42a2d53b8c6fb1aac6 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Sat, 26 Feb 2022 16:37:17 +0100 Subject: [PATCH 07/14] Resolve Issues with Large Methods I saw this problem by starting Blaze with the YourKit profiler. The problem was always Clojure case expressions resulting in large Java switch statements. --- .../blaze/elm/compiler/logical_operators.clj | 22 ++++++----- modules/cql/src/blaze/elm/compiler/macros.clj | 20 ++++++---- modules/db/deps.edn | 3 -- modules/fhir-path/src/blaze/fhir_path.clj | 38 +++++++++---------- 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/modules/cql/src/blaze/elm/compiler/logical_operators.clj b/modules/cql/src/blaze/elm/compiler/logical_operators.clj index a7dc5ff92..b19361ee6 100644 --- a/modules/cql/src/blaze/elm/compiler/logical_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/logical_operators.clj @@ -21,9 +21,10 @@ (defn- nil-and "Creates an and-expression where one operand is known to be nil." [x] - (case x - (true nil) nil + (condp identical? x + true nil false false + nil nil (nil-and-expr x))) @@ -31,7 +32,7 @@ "Creates an and-expression where `a` is known to be dynamic and `b` could be static or dynamic." [a b] - (case b + (condp identical? b true a false false nil (nil-and-expr a) @@ -51,7 +52,7 @@ (defmethod core/compile* :elm.compiler.type/and [context {[a b] :operand}] (let [a (core/compile* context a)] - (case a + (condp identical? a true (core/compile* context b) false false nil (nil-and (core/compile* context b)) @@ -83,9 +84,10 @@ (defn- nil-or "Creates an or-expression where one operand is known to be nil." [x] - (case x + (condp identical? x true true - (false nil) nil + false nil + nil nil (nil-or-expr x))) @@ -93,7 +95,7 @@ "Creates an or-expression where `a` is known to be dynamic and `b` could be static or dynamic." [a b] - (case b + (condp identical? b true true false a nil (nil-or-expr a) @@ -113,7 +115,7 @@ (defmethod core/compile* :elm.compiler.type/or [context {[a b] :operand}] (let [a (core/compile* context a)] - (case a + (condp identical? a true true false (core/compile* context b) nil (nil-or (core/compile* context b)) @@ -125,7 +127,7 @@ "Creates an xor-expression where `a` is known to be dynamic and `b` could be static or dynamic." [a b] - (case b + (condp identical? b true (reify core/Expression (-eval [_ context resource scope] @@ -148,7 +150,7 @@ (defmethod core/compile* :elm.compiler.type/xor [context {[a b] :operand}] (let [a (core/compile* context a)] - (case a + (condp identical? a true (core/compile* context {:type "Not" :operand b}) false (core/compile* context b) nil nil diff --git a/modules/cql/src/blaze/elm/compiler/macros.clj b/modules/cql/src/blaze/elm/compiler/macros.clj index b20cce95d..f0d62d2e9 100644 --- a/modules/cql/src/blaze/elm/compiler/macros.clj +++ b/modules/cql/src/blaze/elm/compiler/macros.clj @@ -3,6 +3,10 @@ [blaze.elm.compiler.core :as core])) +(defn- compile-kw [name] + (keyword "elm.compiler.type" (clojure.core/name name))) + + (defmacro defunop {:arglists '([name attr-map? bindings & body])} [name & more] @@ -10,7 +14,7 @@ more (if (map? (first more)) (next more) more) [[operand-binding expr-binding] & body] more] (if expr-binding - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# expr#] (let [operand# (core/compile* (merge context# ~attr-map) (:operand expr#))] (if (core/static? operand#) @@ -24,7 +28,7 @@ ~@body)) (-form [~'_] (list (quote ~name) (core/-form operand#))))))) - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# expr#] (let [operand# (core/compile* (merge context# ~attr-map) (:operand expr#))] (if (core/static? operand#) @@ -44,7 +48,7 @@ (let [attr-map (when (map? (first more)) (first more)) more (if (map? (first more)) (next more) more) [[op-1-binding op-2-binding] & body] more] - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# {[operand-1# operand-2#] :operand}] (let [context# (merge context# ~attr-map) operand-1# (core/compile* context# operand-1#) @@ -65,7 +69,7 @@ (defmacro defternop {:arglists '([name bindings & body])} [name [op-1-binding op-2-binding op-3-binding] & body] - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# {[operand-1# operand-2# operand-3#] :operand}] (let [operand-1# (core/compile* context# operand-1#) operand-2# (core/compile* context# operand-2#) @@ -81,7 +85,7 @@ (defmacro defnaryop {:arglists '([name bindings & body])} [name [operands-binding] & body] - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# {operands# :operand}] (let [operands# (mapv #(core/compile* context# %) operands#)] (reify core/Expression @@ -93,7 +97,7 @@ (defmacro defaggop {:arglists '([name bindings & body])} [name [source-binding] & body] - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# {source# :source}] (let [source# (core/compile* context# source#)] (reify core/Expression @@ -105,7 +109,7 @@ (defmacro defunopp {:arglists '([name bindings & body])} [name [operand-binding precision-binding expr-binding] & body] - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# {operand# :operand precision# :precision :as expr#}] (let [operand# (core/compile* context# operand#) ~precision-binding (some-> precision# core/to-chrono-unit) @@ -124,7 +128,7 @@ (let [attr-map (when (map? (first more)) (first more)) more (if (map? (first more)) (next more) more) [[op-1-binding op-2-binding precision-binding] & body] more] - `(defmethod core/compile* ~(keyword "elm.compiler.type" (clojure.core/name name)) + `(defmethod core/compile* ~(compile-kw name) [context# {[operand-1# operand-2#] :operand precision# :precision}] (let [context# (merge context# ~attr-map) operand-1# (core/compile* context# operand-1#) diff --git a/modules/db/deps.edn b/modules/db/deps.edn index 54cf6e776..9dc0450b7 100644 --- a/modules/db/deps.edn +++ b/modules/db/deps.edn @@ -45,9 +45,6 @@ {blaze/test-util {:local/root "../test-util"} - com.clojure-goes-fast/clj-java-decompiler - {:mvn/version "0.3.1"} - lambdaisland/kaocha {:mvn/version "1.63.998"}} diff --git a/modules/fhir-path/src/blaze/fhir_path.clj b/modules/fhir-path/src/blaze/fhir_path.clj index cf253d423..1e89c065d 100644 --- a/modules/fhir-path/src/blaze/fhir_path.clj +++ b/modules/fhir-path/src/blaze/fhir_path.clj @@ -113,13 +113,13 @@ (throw-anom (ba/incorrect (singleton-evaluation-msg coll))))) -(defrecord StartExpression [] +(deftype StartExpression [] Expression (-eval [_ _ coll] coll)) -(defrecord TypedStartExpression [rf] +(deftype TypedStartExpression [rf] Expression (-eval [_ _ coll] (.reduce ^IReduceInit coll rf []))) @@ -131,7 +131,7 @@ (->TypedStartExpression ((filter pred) conj)))) -(defrecord GetChildrenExpression [f] +(deftype GetChildrenExpression [f] Expression (-eval [_ _ coll] (.reduce ^IReduceInit coll f []))) @@ -147,13 +147,13 @@ :else res))))) -(defrecord InvocationExpression [expression invocation] +(deftype InvocationExpression [expression invocation] Expression (-eval [_ context coll] (-eval invocation context (-eval expression context coll)))) -(defrecord IndexerExpression [expression index] +(deftype IndexerExpression [expression index] Expression (-eval [_ context coll] (let [coll (-eval expression context coll) @@ -161,7 +161,7 @@ [(nth coll idx [])]))) -(defrecord PlusExpression [left-expr right-expr] +(deftype PlusExpression [left-expr right-expr] Expression (-eval [_ context coll] (let [left (singleton :fhir/string (-eval left-expr context coll)) @@ -177,7 +177,7 @@ (pr-str coll))) -(defrecord IsTypeExpression [expression type-specifier] +(deftype IsTypeExpression [expression type-specifier] Expression (-eval [_ context coll] (let [coll (-eval expression context coll)] @@ -194,7 +194,7 @@ (pr-str coll))) -(defrecord AsTypeExpression [expression type-specifier] +(deftype AsTypeExpression [expression type-specifier] Expression (-eval [_ context coll] (let [coll (-eval expression context coll)] @@ -208,7 +208,7 @@ (throw-anom (ba/incorrect (as-type-specifier-msg coll))))))) -(defrecord UnionExpression [e1 e2] +(deftype UnionExpression [e1 e2] Expression (-eval [_ context coll] (let [^Counted c1 (-eval e1 context coll) @@ -224,7 +224,7 @@ (vec (reduce conj (set c1) c2)))))) -(defrecord EqualExpression [left-expr right-expr] +(deftype EqualExpression [left-expr right-expr] Expression (-eval [_ context coll] (let [left (-eval left-expr context coll) @@ -241,7 +241,7 @@ [false])))))) -(defrecord NotEqualExpression [left-expr right-expr] +(deftype NotEqualExpression [left-expr right-expr] Expression (-eval [_ context coll] (let [left (-eval left-expr context coll) @@ -259,7 +259,7 @@ ;; See: http://hl7.org/fhirpath/index.html#and -(defrecord AndExpression [expr-a expr-b] +(deftype AndExpression [expr-a expr-b] Expression (-eval [_ context coll] (let [a (singleton :fhir/boolean (-eval expr-a context coll))] @@ -273,7 +273,7 @@ :else [])))))) -(defrecord AsFunctionExpression [type-specifier] +(deftype AsFunctionExpression [type-specifier] Expression (-eval [_ _ coll] (case (.count ^Counted coll) @@ -286,19 +286,19 @@ (throw-anom (ba/incorrect (as-type-specifier-msg coll)))))) -(defrecord OfTypeFunctionExpression [type-specifier] +(deftype OfTypeFunctionExpression [type-specifier] Expression (-eval [_ _ coll] (filterv #(identical? type-specifier (fhir-spec/fhir-type %)) coll))) -(defrecord ExistsFunctionExpression [] +(deftype ExistsFunctionExpression [] Expression (-eval [_ _ coll] [(if (empty? coll) false true)])) -(defrecord ExistsWithCriteriaFunctionExpression [criteria] +(deftype ExistsWithCriteriaFunctionExpression [criteria] Expression (-eval [_ _ _] (throw-anom (ba/unsupported "unsupported `exists` function")))) @@ -327,7 +327,7 @@ []) -(defrecord ResolveFunctionExpression [] +(deftype ResolveFunctionExpression [] Expression (-eval [_ context coll] (.reduce ^IReduceInit coll #(.reduce (resolve context %2) conj %1) []))) @@ -364,7 +364,7 @@ (pr-str x))) -(defrecord WhereFunctionExpression [where-rf] +(deftype WhereFunctionExpression [where-rf] Expression (-eval [_ context coll] (.reduce ^IReduceInit coll (where-rf context) []))) @@ -412,7 +412,7 @@ ;; Additional functions (https://www.hl7.org/fhir/fhirpath.html#functions) -(defrecord ExtensionFunctionExpression [rf] +(deftype ExtensionFunctionExpression [rf] Expression (-eval [_ _ coll] (.reduce ^IReduceInit coll rf []))) From ac4edd127349685c22e3837187139459f1bfd809 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Sun, 27 Feb 2022 22:02:54 +0100 Subject: [PATCH 08/14] Intern Uri, Canonical, Code, Coding and CodeableConcept In FHIR, some values repeat in many resources. First uri's are used as system's in Codings and Identifiers. Second canonical values are used to refer to other resources. Third codes are often the same for a large number of resources. Last, Coding and CodeableConcept contain system and code values and are also often the same in it's entirety. By interning instances of those values, only one instance will resist in memory as opposed to many. Because all values are immutable, there is no risk in sharing instances. The memory savings are about 50 % for Synthea BMI Observations. --- modules/db/test/blaze/db/api_test.clj | 12 ++-- .../fhir-structure/resources/data_readers.clj | 8 +-- .../src/blaze/fhir/spec/impl.clj | 40 +++++++------ .../src/blaze/fhir/spec/impl/intern.clj | 40 +++++++++++++ .../src/blaze/fhir/spec/type.clj | 30 ++++++++-- .../test/blaze/fhir/spec/impl/intern_test.clj | 54 ++++++++++++++++++ .../test/blaze/fhir/spec/impl_test.clj | 12 ++-- .../blaze/interaction/history/instance.clj | 2 +- .../src/blaze/interaction/history/system.clj | 2 +- .../src/blaze/interaction/history/type.clj | 2 +- .../src/blaze/interaction/history/util.clj | 4 +- .../src/blaze/interaction/search/util.clj | 2 +- .../blaze/interaction/search_compartment.clj | 4 +- .../src/blaze/interaction/search_system.clj | 4 +- .../src/blaze/interaction/search_type.clj | 4 +- .../src/blaze/interaction/transaction.clj | 6 +- .../blaze/interaction/transaction_test.clj | 56 +++++++++---------- .../operation/evaluate_measure/measure.clj | 2 +- .../evaluate_measure/measure/stratifier.clj | 2 +- .../evaluate_measure/middleware/params.clj | 2 +- .../evaluate_measure/measure_test.clj | 6 +- .../fhir/operation/evaluate_measure_test.clj | 12 ++-- .../src/blaze/rest_api/capabilities.clj | 10 ++-- .../blaze/rest_api/middleware/auth_guard.clj | 2 +- modules/rest-util/src/blaze/handler/util.clj | 8 +-- 25 files changed, 223 insertions(+), 103 deletions(-) create mode 100644 modules/fhir-structure/src/blaze/fhir/spec/impl/intern.clj create mode 100644 modules/fhir-structure/test/blaze/fhir/spec/impl/intern_test.clj diff --git a/modules/db/test/blaze/db/api_test.clj b/modules/db/test/blaze/db/api_test.clj index 0f2e27307..2d3029714 100644 --- a/modules/db/test/blaze/db/api_test.clj +++ b/modules/db/test/blaze/db/api_test.clj @@ -3007,9 +3007,9 @@ {:fhir/type :fhir/Observation :id id :subject #fhir/Reference{:reference "Patient/0"} :code - (type/map->CodeableConcept + (type/codeable-concept {:coding - [(type/map->Coding + [(type/coding {:system #fhir/uri"system" :code code})]})})] (with-system [{:blaze.db/keys [node]} system] @@ -3033,9 +3033,9 @@ {:fhir/type :fhir/Observation :id id :subject #fhir/Reference{:reference "Patient/0"} :code - (type/map->CodeableConcept + (type/codeable-concept {:coding - [(type/map->Coding + [(type/coding {:system #fhir/uri"system" :code code})]})})] (with-system [{:blaze.db/keys [node]} system] @@ -3088,9 +3088,9 @@ {:fhir/type :fhir/Observation :id id :subject #fhir/Reference{:reference "Patient/0"} :code - (type/map->CodeableConcept + (type/codeable-concept {:coding - [(type/map->Coding + [(type/coding {:system #fhir/uri"system" :code code})]})})] (with-system [{:blaze.db/keys [node]} system] diff --git a/modules/fhir-structure/resources/data_readers.clj b/modules/fhir-structure/resources/data_readers.clj index 75f2aed21..ccd22eef1 100644 --- a/modules/fhir-structure/resources/data_readers.clj +++ b/modules/fhir-structure/resources/data_readers.clj @@ -1,8 +1,8 @@ {fhir/integer clojure.core/int fhir/long clojure.core/long - fhir/uri blaze.fhir.spec.type/->Uri + fhir/uri blaze.fhir.spec.type/uri fhir/url blaze.fhir.spec.type/->Url - fhir/canonical blaze.fhir.spec.type/->Canonical + fhir/canonical blaze.fhir.spec.type/canonical fhir/base64Binary blaze.fhir.spec.type/->Base64Binary fhir/instant blaze.fhir.spec.type/->Instant fhir/date blaze.fhir.spec.type/->Date @@ -18,8 +18,8 @@ fhir/xhtml blaze.fhir.spec.type/->Xhtml fhir/Attachment blaze.fhir.spec.type/map->Attachment fhir/Extension blaze.fhir.spec.type/map->Extension - fhir/Coding blaze.fhir.spec.type/map->Coding - fhir/CodeableConcept blaze.fhir.spec.type/map->CodeableConcept + fhir/Coding blaze.fhir.spec.type/coding + fhir/CodeableConcept blaze.fhir.spec.type/codeable-concept fhir/Quantity blaze.fhir.spec.type/map->Quantity fhir/Period blaze.fhir.spec.type/map->Period fhir/Identifier blaze.fhir.spec.type/map->Identifier diff --git a/modules/fhir-structure/src/blaze/fhir/spec/impl.clj b/modules/fhir-structure/src/blaze/fhir/spec/impl.clj index ad671a572..8f606e823 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/impl.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/impl.clj @@ -425,9 +425,9 @@ (group-by :choice-group child-spec-defs))) -(defn- json-object-spec-form [class-name child-spec-defs] +(defn- json-object-spec-form [create-fn child-spec-defs] `(specs/json-object - ~(symbol "blaze.fhir.spec.type" (str "map->" class-name)) + ~(symbol "blaze.fhir.spec.type" create-fn) ~(into {} (comp @@ -448,18 +448,20 @@ :modifier :json :spec-form (case key + :fhir.json/Coding + (json-object-spec-form "coding" child-spec-defs) + :fhir.json/CodeableConcept + (json-object-spec-form "codeable-concept" child-spec-defs) (:fhir.json/Attachment :fhir.json/Extension - :fhir.json/Coding - :fhir.json/CodeableConcept :fhir.json/Quantity :fhir.json/Period :fhir.json/Identifier :fhir.json/Reference :fhir.json/Meta) - (json-object-spec-form path-part child-spec-defs) + (json-object-spec-form (str "map->" path-part) child-spec-defs) :fhir.json.Bundle.entry/search - (json-object-spec-form "BundleEntrySearch" child-spec-defs) + (json-object-spec-form "map->BundleEntrySearch" child-spec-defs) (conj (seq (remap-choice-conformer-forms child-spec-defs)) (json-type-conformer-form kind parent-path-parts path-part) (schema-spec-form :json child-spec-defs) @@ -596,9 +598,9 @@ child-spec-defs))})) -(defn- cbor-object-spec-form [class-name child-spec-defs] +(defn- cbor-object-spec-form [create-fn child-spec-defs] `(specs/json-object - ~(symbol "blaze.fhir.spec.type" (str "map->" class-name)) + ~(symbol "blaze.fhir.spec.type" create-fn) ~(into {} (comp @@ -620,18 +622,20 @@ :modifier :cbor :spec-form (case key + :fhir.cbor/Coding + (cbor-object-spec-form "coding" child-spec-defs) + :fhir.cbor/CodeableConcept + (cbor-object-spec-form "codeable-concept" child-spec-defs) (:fhir.cbor/Attachment :fhir.cbor/Extension - :fhir.cbor/Coding - :fhir.cbor/CodeableConcept :fhir.cbor/Quantity :fhir.cbor/Period :fhir.cbor/Identifier :fhir.cbor/Reference :fhir.cbor/Meta) - (cbor-object-spec-form path-part child-spec-defs) + (cbor-object-spec-form (str "map->" path-part) child-spec-defs) :fhir.cbor.Bundle.entry/search - (cbor-object-spec-form "BundleEntrySearch" child-spec-defs) + (cbor-object-spec-form "map->BundleEntrySearch" child-spec-defs) (conj (seq (remap-choice-conformer-forms child-spec-defs)) (json-type-conformer-form kind parent-path-parts path-part) (schema-spec-form :cbor child-spec-defs) @@ -722,15 +726,15 @@ "integer" `(s/and int? (s/conformer int identity)) "string" `(specs/regex ~pattern identity) "decimal" `(s/conformer conform-decimal-json identity) - "uri" `(specs/regex ~pattern type/->Uri) + "uri" `(specs/regex ~pattern type/uri) "url" `(specs/regex ~pattern type/->Url) - "canonical" `(specs/regex ~pattern type/->Canonical) + "canonical" `(specs/regex ~pattern type/canonical) "base64Binary" `(specs/regex ~pattern type/->Base64Binary) "instant" `(specs/regex ~pattern type/->Instant) "date" `(specs/regex ~pattern type/->Date) "dateTime" `(specs/regex ~pattern type/->DateTime) "time" `(specs/regex ~pattern type/->Time) - "code" `(specs/regex ~pattern type/->Code) + "code" `(specs/regex ~pattern type/code) "oid" `(specs/regex ~pattern type/->Oid) "id" `(specs/regex ~pattern type/->Id) "markdown" `(specs/regex ~pattern type/->Markdown) @@ -774,15 +778,15 @@ "integer" `(s/conformer int identity) "string" `any? "decimal" `any? - "uri" `(s/conformer type/->Uri identity) + "uri" `(s/conformer type/uri identity) "url" `(s/conformer type/->Url identity) - "canonical" `(s/conformer type/->Canonical identity) + "canonical" `(s/conformer type/canonical identity) "base64Binary" `(s/conformer type/->Base64Binary identity) "instant" `(s/conformer type/->Instant identity) "date" `(s/conformer type/->Date identity) "dateTime" `(s/conformer type/->DateTime identity) "time" `(s/conformer type/->Time identity) - "code" `(s/conformer type/->Code identity) + "code" `(s/conformer type/code identity) "oid" `(s/conformer type/->Oid identity) "id" `(s/conformer type/->Id identity) "markdown" `(s/conformer type/->Markdown identity) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/impl/intern.clj b/modules/fhir-structure/src/blaze/fhir/spec/impl/intern.clj new file mode 100644 index 000000000..af982b136 --- /dev/null +++ b/modules/fhir-structure/src/blaze/fhir/spec/impl/intern.clj @@ -0,0 +1,40 @@ +(ns blaze.fhir.spec.impl.intern + (:import + [clojure.lang Util] + [java.lang.ref ReferenceQueue WeakReference] + [java.util.concurrent ConcurrentHashMap])) + + +(set! *warn-on-reflection* true) + + +(defn intern-value + "Returns a function of arity 1 that creates a value using `create-fn` only if + no value exists already in an internal cache using the argument as key. + + Should be used the following way: + + (def intern-foo + \"Creates interned instances of foo.\" + (intern-value foo)) + + Holds weak references to values so that they can be collected under high + pressure. The algorithm was taken from Clojure 1.10.3 keyword interning." + [create-fn] + (let [cache (ConcurrentHashMap.) + rq (ReferenceQueue.)] + (fn [key] + (loop [ref (.get cache key)] + (if ref + (if-let [existing-value (.get ^WeakReference ref)] + existing-value + (do (.remove cache key ref) + (recur (.get cache key)))) + (let [new-value (create-fn key)] + (Util/clearCache rq cache) + (if-let [ref (.putIfAbsent cache key (WeakReference. new-value rq))] + (if-let [existing-value (.get ^WeakReference ref)] + existing-value + (do (.remove cache key ref) + (recur (.get cache key)))) + new-value))))))) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type.clj b/modules/fhir-structure/src/blaze/fhir/spec/type.clj index b18d2619c..53400fa7e 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type.clj @@ -1,6 +1,7 @@ (ns blaze.fhir.spec.type (:refer-clojure :exclude [decimal? string? type uri? uuid?]) (:require + [blaze.fhir.spec.impl.intern :as intern] [blaze.fhir.spec.type.macros :as macros :refer [defcomplextype]] [blaze.fhir.spec.type.protocols :as p] [blaze.fhir.spec.type.system :as system] @@ -201,6 +202,7 @@ ;; ---- uri ------------------------------------------------------------------- + (deftype Uri [value] p/FhirType (-type [_] :fhir/uri) @@ -233,10 +235,14 @@ (.write w "\"")) +(def uri + (intern/intern-value ->Uri)) + + (defn xml->Uri {:arglists '([element])} [{{:keys [_id _extension value]} :attrs}] - (->Uri value)) + (uri value)) (defn uri? [x] @@ -323,10 +329,14 @@ (.write w "\"")) +(def canonical + (intern/intern-value ->Canonical)) + + (defn xml->Canonical {:arglists '([element])} [{{:keys [_id value]} :attrs _extensions :content}] - (->Canonical value)) + (canonical value)) (defn canonical? [x] @@ -746,8 +756,12 @@ (.writeString gen ^String (.value extended-code))))) +(def code + (intern/intern-value ->Code)) + + (defn tagged-literal->Code [x] - (if (string? x) (->Code x) (map->ExtendedCode x))) + (if (string? x) (code x) (map->ExtendedCode x))) (defn xml->Code @@ -756,7 +770,7 @@ [{{:keys [id value]} :attrs extensions :content}] (if (or id (seq extensions)) (->ExtendedCode id extensions value) - (->Code value))) + (code value))) (defn code? [x] @@ -1183,6 +1197,10 @@ display :string}) +(def coding + (intern/intern-value map->Coding)) + + (declare coding-serializer) @@ -1195,6 +1213,10 @@ text :string}) +(def codeable-concept + (intern/intern-value map->CodeableConcept)) + + (declare codeable-concept-serializer) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/impl/intern_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/impl/intern_test.clj new file mode 100644 index 000000000..80aef82fc --- /dev/null +++ b/modules/fhir-structure/test/blaze/fhir/spec/impl/intern_test.clj @@ -0,0 +1,54 @@ +(ns blaze.fhir.spec.impl.intern-test + (:require + [blaze.executors :as ex] + [blaze.fhir.spec.impl.intern :as intern] + [clojure.spec.test.alpha :as st] + [clojure.test :as test :refer [deftest is testing]]) + (:import + [java.util.concurrent TimeUnit CountDownLatch])) + + +(set! *warn-on-reflection* true) +(st/instrument) + + +(defn- fixture [f] + (st/instrument) + (f) + (st/unstrument)) + + +(test/use-fixtures :each fixture) + + +(defrecord TestType [x]) + + +(def identity-intern + (intern/intern-value ->TestType)) + + +(deftest intern-test + (testing "both constructions lead to the same instance" + (is (identical? (identity-intern "a") (identity-intern "a")))) + + (testing "parallel construction" + (dotimes [x 100] + (let [n 100 + pool (ex/io-pool n "constructor-%d") + atoms (repeatedly n #(atom nil)) + latch (CountDownLatch. 1) + ready (CountDownLatch. n)] + (doseq [atom atoms] + (ex/execute! + pool + #(do (.countDown ready) + (.await latch) + (reset! atom (identity-intern x))))) + ;; wait for threads to be created + (.await ready) + (.countDown latch) + (ex/shutdown! pool) + (ex/await-termination pool 10 TimeUnit/SECONDS) + (let [value (identity-intern x)] + (is (every? #(identical? value (deref %)) atoms))))))) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj index d0d962c18..1adbc3555 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj @@ -135,7 +135,7 @@ [{:key :fhir/uri :spec-form `type/uri?} {:key :fhir.json/uri - :spec-form `(specs/regex "\\S*" type/->Uri)} + :spec-form `(specs/regex "\\S*" type/uri)} {:key :fhir.xml/uri :spec-form `(s2/and @@ -145,7 +145,7 @@ (s2/schema {:content (s2/coll-of :fhir.xml/Extension)}) (s2/conformer type/xml->Uri type/to-xml))} {:key :fhir.cbor/uri - :spec-form `(s2/conformer type/->Uri identity)}]))) + :spec-form `(s2/conformer type/uri identity)}]))) (testing "canonical" (is (= (-> (impl/primitive-type->spec-defs (primitive-type structure-definition-repo "canonical")) @@ -153,7 +153,7 @@ [{:key :fhir/canonical :spec-form `type/canonical?} {:key :fhir.json/canonical - :spec-form `(specs/regex "\\S*" type/->Canonical)} + :spec-form `(specs/regex "\\S*" type/canonical)} {:key :fhir.xml/canonical :spec-form `(s2/and @@ -163,7 +163,7 @@ (s2/schema {:content (s2/coll-of :fhir.xml/Extension)}) (s2/conformer type/xml->Canonical type/to-xml))} {:key :fhir.cbor/canonical - :spec-form `(s2/conformer type/->Canonical identity)}]))) + :spec-form `(s2/conformer type/canonical identity)}]))) (testing "base64Binary" (is (= (-> (impl/primitive-type->spec-defs (primitive-type structure-definition-repo "base64Binary")) @@ -189,7 +189,7 @@ [{:key :fhir/code :spec-form `type/code?} {:key :fhir.json/code - :spec-form `(specs/regex "[^\\s]+(\\s[^\\s]+)*" type/->Code)} + :spec-form `(specs/regex "[^\\s]+(\\s[^\\s]+)*" type/code)} {:key :fhir.xml/code :spec-form `(s2/and @@ -199,7 +199,7 @@ (s2/schema {:content (s2/coll-of :fhir.xml/Extension)}) (s2/conformer type/xml->Code type/to-xml))} {:key :fhir.cbor/code - :spec-form `(s2/conformer type/->Code identity)}]))) + :spec-form `(s2/conformer type/code identity)}]))) (testing "unsignedInt" (is (= (-> (impl/primitive-type->spec-defs (primitive-type structure-definition-repo "unsignedInt")) diff --git a/modules/interaction/src/blaze/interaction/history/instance.clj b/modules/interaction/src/blaze/interaction/history/instance.clj index 3c332dbdf..3c22dd6f8 100644 --- a/modules/interaction/src/blaze/interaction/history/instance.clj +++ b/modules/interaction/src/blaze/interaction/history/instance.clj @@ -23,7 +23,7 @@ (defn- link [context query-params relation resource-handle] {:fhir/type :fhir.Bundle/link :relation relation - :url (type/->Uri (history-util/nav-url context query-params + :url (type/uri (history-util/nav-url context query-params (:t resource-handle)))}) diff --git a/modules/interaction/src/blaze/interaction/history/system.clj b/modules/interaction/src/blaze/interaction/history/system.clj index 6d4de3778..bc469f96f 100644 --- a/modules/interaction/src/blaze/interaction/history/system.clj +++ b/modules/interaction/src/blaze/interaction/history/system.clj @@ -28,7 +28,7 @@ (:t resource-handle) (-> resource-handle fhir-spec/fhir-type name) (:id resource-handle)) - type/->Uri)}) + type/uri)}) (defn- build-response diff --git a/modules/interaction/src/blaze/interaction/history/type.clj b/modules/interaction/src/blaze/interaction/history/type.clj index a4d3e3cc8..45611dd07 100644 --- a/modules/interaction/src/blaze/interaction/history/type.clj +++ b/modules/interaction/src/blaze/interaction/history/type.clj @@ -22,7 +22,7 @@ (defn- link [context query-params relation resource-handle] {:fhir/type :fhir.Bundle/link :relation relation - :url (type/->Uri (history-util/nav-url context query-params + :url (type/uri (history-util/nav-url context query-params (:t resource-handle) (:id resource-handle)))}) diff --git a/modules/interaction/src/blaze/interaction/history/util.clj b/modules/interaction/src/blaze/interaction/history/util.clj index 0d1923d7e..1fab0a099 100644 --- a/modules/interaction/src/blaze/interaction/history/util.clj +++ b/modules/interaction/src/blaze/interaction/history/util.clj @@ -80,11 +80,11 @@ (defn build-entry [context {:fhir/keys [type] :keys [id] :as resource}] (cond-> - {:fullUrl (type/->Uri (fhir-util/instance-url context (name type) id)) + {:fullUrl (type/uri (fhir-util/instance-url context (name type) id)) :request {:fhir/type :fhir.Bundle.entry/request :method (method resource) - :url (type/->Uri (url (assoc context :blaze/base-url "") (name type) id + :url (type/uri (url (assoc context :blaze/base-url "") (name type) id resource))} :response {:fhir/type :fhir.Bundle.entry/response diff --git a/modules/interaction/src/blaze/interaction/search/util.clj b/modules/interaction/src/blaze/interaction/search/util.clj index b665bffd9..130708652 100644 --- a/modules/interaction/src/blaze/interaction/search/util.clj +++ b/modules/interaction/src/blaze/interaction/search/util.clj @@ -17,6 +17,6 @@ (entry context resource match)) ([context {:fhir/keys [type] :keys [id] :as resource} mode] {:fhir/type :fhir.Bundle/entry - :fullUrl (type/->Uri (fhir-util/instance-url context (name type) id)) + :fullUrl (type/uri (fhir-util/instance-url context (name type) id)) :resource resource :search mode})) diff --git a/modules/interaction/src/blaze/interaction/search_compartment.clj b/modules/interaction/src/blaze/interaction/search_compartment.clj index 1e14c8448..fd46227f3 100644 --- a/modules/interaction/src/blaze/interaction/search_compartment.clj +++ b/modules/interaction/src/blaze/interaction/search_compartment.clj @@ -54,7 +54,7 @@ {:keys [page-offset] :as params} :params} clauses] {:fhir/type :fhir.Bundle/link :relation "self" - :url (type/->Uri (nav/url base-url match params clauses (iu/t db) + :url (type/uri (nav/url base-url match params clauses (iu/t db) {"__page-offset" page-offset}))}) @@ -68,7 +68,7 @@ (iu/t db) (next-link-offset params entries))] {:fhir/type :fhir.Bundle/link :relation "next" - :url (type/->Uri url)})) + :url (type/uri url)})) (defn- bundle* [context handles clauses] diff --git a/modules/interaction/src/blaze/interaction/search_system.clj b/modules/interaction/src/blaze/interaction/search_system.clj index ed31f65f3..b4c888027 100644 --- a/modules/interaction/src/blaze/interaction/search_system.clj +++ b/modules/interaction/src/blaze/interaction/search_system.clj @@ -44,7 +44,7 @@ (defn- self-link [{:keys [match params] :blaze/keys [base-url db]} entries] {:fhir/type :fhir.Bundle/link :relation "self" - :url (type/->Uri (nav/url base-url match params [] (iu/t db) + :url (type/uri (nav/url base-url match params [] (iu/t db) (self-link-offset entries)))}) @@ -59,7 +59,7 @@ (iu/t db) (next-link-offset entries))] {:fhir/type :fhir.Bundle/link :relation "next" - :url (type/->Uri url)})) + :url (type/uri url)})) (defn- normal-bundle diff --git a/modules/interaction/src/blaze/interaction/search_type.clj b/modules/interaction/src/blaze/interaction/search_type.clj index 33ff3936d..9aa82970f 100644 --- a/modules/interaction/src/blaze/interaction/search_type.clj +++ b/modules/interaction/src/blaze/interaction/search_type.clj @@ -122,7 +122,7 @@ (let [url (self-link-url-fn clauses (self-link-offset first-entry))] {:fhir/type :fhir.Bundle/link :relation "self" - :url (type/->Uri url)})) + :url (type/uri url)})) (defn- next-link-offset [next-handle] @@ -134,7 +134,7 @@ (do-sync [url (next-link-url-fn clauses (next-link-offset next-handle))] {:fhir/type :fhir.Bundle/link :relation "next" - :url (type/->Uri url)})) + :url (type/uri url)})) (defn- total diff --git a/modules/interaction/src/blaze/interaction/transaction.clj b/modules/interaction/src/blaze/interaction/transaction.clj index 36e3ad9a0..4027ea96b 100644 --- a/modules/interaction/src/blaze/interaction/transaction.clj +++ b/modules/interaction/src/blaze/interaction/transaction.clj @@ -247,7 +247,7 @@ (defn- location [context type id vid] - (type/->Uri (fhir-util/versioned-instance-url context type id vid))) + (type/uri (fhir-util/versioned-instance-url context type id vid))) (defn- created-entry @@ -367,7 +367,7 @@ :status (str status)} location - (assoc :location (type/->Uri location)) + (assoc :location (type/uri location)) etag (assoc :etag etag) @@ -503,7 +503,7 @@ (defn- response-bundle [context type entries] {:fhir/type :fhir/Bundle :id (iu/luid context) - :type (type/->Code (str (type/value type) "-response")) + :type (type/code (str (type/value type) "-response")) :entry entries}) diff --git a/modules/interaction/test/blaze/interaction/transaction_test.clj b/modules/interaction/test/blaze/interaction/transaction_test.clj index fba2519db..0c00a3f49 100644 --- a/modules/interaction/test/blaze/interaction/transaction_test.clj +++ b/modules/interaction/test/blaze/interaction/transaction_test.clj @@ -239,7 +239,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type)}})] + :type (type/code type)}})] (testing "response status" (is (= 200 status))) @@ -248,7 +248,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")) + :type := (type/code (str type "-response")) :entry :? empty?))))) (testing "and update interaction" @@ -271,7 +271,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -281,7 +281,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (is (nil? resource))) @@ -302,7 +302,7 @@ {:headers {"prefer" "return=representation"} :body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -312,7 +312,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (given resource @@ -349,7 +349,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -359,7 +359,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (is (nil? resource))) @@ -381,7 +381,7 @@ {:headers {"prefer" "return=representation"} :body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -391,7 +391,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (given resource @@ -425,7 +425,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -435,7 +435,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (is (nil? resource))) @@ -456,7 +456,7 @@ {:headers {"prefer" "return=representation"} :body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -466,7 +466,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (given resource @@ -495,7 +495,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry [{:fhir/type :fhir.Bundle/entry :resource @@ -514,7 +514,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (is (nil? resource))) @@ -538,7 +538,7 @@ {:headers {"prefer" "return=representation"} :body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry [{:fhir/type :fhir.Bundle/entry :resource @@ -557,7 +557,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (given resource @@ -585,7 +585,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry [{:fhir/type :fhir.Bundle/entry :resource @@ -604,7 +604,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (is (nil? resource))) @@ -628,7 +628,7 @@ {:headers {"prefer" "return=representation"} :body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry [{:fhir/type :fhir.Bundle/entry :resource @@ -647,7 +647,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (given resource @@ -679,7 +679,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry entries}})] (testing "response status" @@ -689,7 +689,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (is (nil? resource))) @@ -709,7 +709,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry [{:fhir/type :fhir.Bundle/entry :request @@ -724,7 +724,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "returns error" (testing "with status" @@ -747,7 +747,7 @@ @(handler {:body {:fhir/type :fhir/Bundle - :type (type/->Code type) + :type (type/code type) :entry [{:fhir/type :fhir.Bundle/entry :request @@ -762,7 +762,7 @@ (given body :fhir/type := :fhir/Bundle :id := "AAAAAAAAAAAAAAAA" - :type := (type/->Code (str type "-response")))) + :type := (type/code (str type "-response")))) (testing "entry resource" (given resource diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj index 8df4ffd3d..8b3a763d3 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj @@ -267,7 +267,7 @@ "population" #fhir/code"summary" "subject-list" #fhir/code"subject-list" "subject" #fhir/code"individual") - :measure (type/->Canonical measure-ref) + :measure (type/canonical measure-ref) :date now :period (type/map->Period diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj index 3490676a7..be6d8515f 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/stratifier.clj @@ -7,7 +7,7 @@ (defn- value-concept [value] - (type/map->CodeableConcept {:text (str (if (nil? value) "null" value))})) + (type/codeable-concept {:text (str (if (nil? value) "null" value))})) (defn- stratum* [population value] diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj index db481b77d..8d40f9120 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/middleware/params.clj @@ -56,7 +56,7 @@ (defn- coerce-report-type [_ value] (if-not (s/valid? :blaze.fhir.operation.evaluate-measure/report-type value) (ba/incorrect (invalid-report-type-param-msg value) :fhir/issue "value") - (type/->Code value))) + (type/code value))) (defn- invalid-subject-param-msg [subject] diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj index dee36eb1d..ac495be1c 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj @@ -123,11 +123,11 @@ (defn- population-concept [code] - (type/map->CodeableConcept + (type/codeable-concept {:coding - [(type/map->Coding + [(type/coding {:system #fhir/uri"http://terminology.hl7.org/CodeSystem/measure-population" - :code (type/->Code code)})]})) + :code (type/code code)})]})) (defn- cql-expression [expr] diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj index edb6fc84e..e14c733ea 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj @@ -44,19 +44,19 @@ (defn- scoring-concept [code] - (type/map->CodeableConcept + (type/codeable-concept {:coding - [(type/map->Coding + [(type/coding {:system #fhir/uri"http://terminology.hl7.org/CodeSystem/measure-scoring" - :code (type/->Code code)})]})) + :code (type/code code)})]})) (defn- population-concept [code] - (type/map->CodeableConcept + (type/codeable-concept {:coding - [(type/map->Coding + [(type/coding {:system #fhir/uri"http://terminology.hl7.org/CodeSystem/measure-population" - :code (type/->Code code)})]})) + :code (type/code code)})]})) (defn- cql-expression [expr] diff --git a/modules/rest-api/src/blaze/rest_api/capabilities.clj b/modules/rest-api/src/blaze/rest_api/capabilities.clj index 7723a3a20..e00386c61 100644 --- a/modules/rest-api/src/blaze/rest_api/capabilities.clj +++ b/modules/rest-api/src/blaze/rest_api/capabilities.clj @@ -30,7 +30,7 @@ #(some #{name} (:blaze.rest-api.operation/resource-types %)) operations)] (cond-> - {:type (type/->Code name) + {:type (type/code name) :interaction (reduce (fn [res code] @@ -39,7 +39,7 @@ (conj res (cond-> - {:code (type/->Code (clojure.core/name code))} + {:code (type/code (clojure.core/name code))} doc (assoc :documentation (type/->Markdown doc)))) res)) @@ -69,9 +69,9 @@ (transduce (map (fn [{:keys [name url type]}] - (cond-> {:name name :type (type/->Code type)} + (cond-> {:name name :type (type/code type)} url - (assoc :definition (type/->Canonical url)) + (assoc :definition (type/canonical url)) (= "quantity" type) (assoc :documentation quantity-documentation)))) conj @@ -88,7 +88,7 @@ [code def-uri type-handler instance-handler]}] (when (or type-handler instance-handler) {:name code - :definition (type/->Canonical def-uri)}))) + :definition (type/canonical def-uri)}))) operations)))))) diff --git a/modules/rest-api/src/blaze/rest_api/middleware/auth_guard.clj b/modules/rest-api/src/blaze/rest_api/middleware/auth_guard.clj index 135a8bb39..c50651575 100644 --- a/modules/rest-api/src/blaze/rest_api/middleware/auth_guard.clj +++ b/modules/rest-api/src/blaze/rest_api/middleware/auth_guard.clj @@ -26,6 +26,6 @@ :severity #fhir/code"error" :code #fhir/code"login" :details - (type/map->CodeableConcept + (type/codeable-concept {:coding [msg-auth-required]})}]}) (ring/status 401)))))) diff --git a/modules/rest-util/src/blaze/handler/util.clj b/modules/rest-util/src/blaze/handler/util.clj index ae4bb1deb..caf04c818 100644 --- a/modules/rest-util/src/blaze/handler/util.clj +++ b/modules/rest-util/src/blaze/handler/util.clj @@ -38,9 +38,9 @@ (cond-> {:fhir/type :fhir.OperationOutcome/issue :severity #fhir/code"error" - :code (or (some-> code type/->Code) (issue-code category))} + :code (or (some-> code type/code) (issue-code category))} severity - (assoc :severity (type/->Code severity)) + (assoc :severity (type/code severity)) diagnostics (assoc :diagnostics diagnostics) (coll? expression) @@ -59,13 +59,13 @@ (cond-> {:fhir/type :fhir.OperationOutcome/issue :severity #fhir/code"error" - :code (or (some-> issue type/->Code) (issue-code category))} + :code (or (some-> issue type/code) (issue-code category))} operation-outcome (assoc :details {:coding [{:system #fhir/uri"http://terminology.hl7.org/CodeSystem/operation-outcome" - :code (type/->Code operation-outcome)}]}) + :code (type/code operation-outcome)}]}) message (assoc :diagnostics message) stacktrace From 8c18c09c678b9c79b3c1803cf8e2e547365b602b Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Mon, 28 Feb 2022 20:23:40 +0100 Subject: [PATCH 09/14] Add Real Use Case CQL Query to Tests --- .../blaze/elm/compiler/clinical_operators.clj | 23 +- .../cql/src/blaze/elm/compiler/queries.clj | 4 +- .../src/blaze/elm/compiler/type_operators.clj | 4 +- .../elm/compiler/clinical_operators_test.clj | 13 +- .../elm/compiler/type_operators_test.clj | 4 +- modules/cql/test/blaze/elm/literal.clj | 8 +- modules/cql/test/blaze/elm/literal_spec.clj | 3 +- .../evaluate_measure/measure_test.clj | 5 +- .../evaluate_measure/q38-di-surv-data.json | 240 ++++++++++++++++++ .../evaluate_measure/q38-di-surv-query.cql | 25 ++ 10 files changed, 301 insertions(+), 28 deletions(-) create mode 100644 modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-data.json create mode 100644 modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-query.cql diff --git a/modules/cql/src/blaze/elm/compiler/clinical_operators.clj b/modules/cql/src/blaze/elm/compiler/clinical_operators.clj index 50b3ee3b7..a24043f69 100644 --- a/modules/cql/src/blaze/elm/compiler/clinical_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/clinical_operators.clj @@ -14,20 +14,17 @@ ;; 23.4. CalculateAgeAt -(defrecord CalculateAgeAtExpression [birth-date date precision] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (p/duration-between - (p/to-date (core/-eval birth-date context resource scope) now) - (core/-eval date context resource scope) - precision))) - - (defmethod core/compile* :elm.compiler.type/calculate-age-at [context {[birth-date date] :operand precision :precision}] (when-let [birth-date (core/compile* context birth-date)] (when-let [date (core/compile* context date)] - (->CalculateAgeAtExpression - birth-date - date - (some-> precision core/to-chrono-unit))))) + (let [chrono-precision (some-> precision core/to-chrono-unit)] + (reify core/Expression + (-eval [_ {:keys [now] :as context} resource scope] + (p/duration-between + (p/to-date (core/-eval birth-date context resource scope) now) + (core/-eval date context resource scope) + chrono-precision)) + (-form [_] + (list 'calculate-age-at (core/-form birth-date) (core/-form date) + precision))))))) diff --git a/modules/cql/src/blaze/elm/compiler/queries.clj b/modules/cql/src/blaze/elm/compiler/queries.clj index fcf465382..bb4e07510 100644 --- a/modules/cql/src/blaze/elm/compiler/queries.clj +++ b/modules/cql/src/blaze/elm/compiler/queries.clj @@ -45,7 +45,9 @@ (filter (fn eval-with-clause [lhs-entity] (some->> (core/-eval lhs-operand context resource lhs-entity) - (contains? index))))))))) + (contains? index)))))))) + (-form [_] + (list 'with (core/-form rhs)))) #_(defn- with-xform-factory [create-with-clause] diff --git a/modules/cql/src/blaze/elm/compiler/type_operators.clj b/modules/cql/src/blaze/elm/compiler/type_operators.clj index 1aad04a51..37f122acb 100644 --- a/modules/cql/src/blaze/elm/compiler/type_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/type_operators.clj @@ -179,7 +179,9 @@ (defrecord ToDateTimeOperatorExpression [operand] core/Expression (-eval [_ {:keys [now] :as context} resource scope] - (p/to-date-time (core/-eval operand context resource scope) now))) + (p/to-date-time (core/-eval operand context resource scope) now)) + (-form [_] + (list 'to-date-time (core/-form operand)))) (defmethod core/compile* :elm.compiler.type/to-date-time diff --git a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj index 997a14cdc..202ff38b0 100644 --- a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj @@ -58,18 +58,17 @@ (deftest compile-calculate-age-at-test (testing "Year" (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) - {:type "CalculateAgeAt" :operand [#elm/date "2018" #elm/date "2019"] - :precision "Year"} + #elm/calculate-age-at [#elm/date "2018" #elm/date "2019" "year"] 1 - {:type "CalculateAgeAt" :operand [#elm/date "2018" #elm/date "2018"] - :precision "Year"} + #elm/calculate-age-at [#elm/date "2018" #elm/date "2018" "year"] 0 - {:type "CalculateAgeAt" :operand [#elm/date "2018" #elm/date "2018"] - :precision "Month"} + #elm/calculate-age-at [#elm/date "2018" #elm/date "2018" "month"] nil)) - (tu/testing-binary-null elm/calculate-age-at #elm/date "2018")) + (tu/testing-binary-null elm/calculate-age-at #elm/date "2018") + + (tu/testing-binary-precision-form elm/calculate-age-at "year" "month" "day")) ;; 23.5. Equal diff --git a/modules/cql/test/blaze/elm/compiler/type_operators_test.clj b/modules/cql/test/blaze/elm/compiler/type_operators_test.clj index f972b4974..7c0d3e3a3 100644 --- a/modules/cql/test/blaze/elm/compiler/type_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/type_operators_test.clj @@ -396,7 +396,9 @@ "2020-03-08" (system/date-time 2020 3 8) "2020-03-08T12:13" (system/date-time 2020 3 8 12 13)))) - (tu/testing-unary-null elm/to-date-time)) + (tu/testing-unary-null elm/to-date-time) + + (tu/testing-unary-form elm/to-date-time)) ;; 22.24. ToDecimal diff --git a/modules/cql/test/blaze/elm/literal.clj b/modules/cql/test/blaze/elm/literal.clj index 8edaf0f4e..278c7d37e 100644 --- a/modules/cql/test/blaze/elm/literal.clj +++ b/modules/cql/test/blaze/elm/literal.clj @@ -847,5 +847,9 @@ ;; 23. Clinical Operators ;; 23.4. CalculateAgeAt -(defn calculate-age-at [ops] - {:type "CalculateAgeAt" :operand ops}) +(defn calculate-age-at [[x y precision]] + (cond-> + {:type "CalculateAgeAt" + :operand [x y]} + precision + (assoc :precision precision))) diff --git a/modules/cql/test/blaze/elm/literal_spec.clj b/modules/cql/test/blaze/elm/literal_spec.clj index e9b87effb..c7c294143 100644 --- a/modules/cql/test/blaze/elm/literal_spec.clj +++ b/modules/cql/test/blaze/elm/literal_spec.clj @@ -498,5 +498,6 @@ ;; 23.4. CalculateAgeAt (s/fdef elm/calculate-age-at - :args (s/cat :ops (s/tuple :elm/expression :elm/expression)) + :args (s/cat :ops (s/spec (s/cat :x :elm/expression :y :elm/expression + :precision (s/? string?)))) :ret :elm/expression) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj index ac495be1c..672976676 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure_test.clj @@ -342,7 +342,8 @@ "q34-medication" 1 "q35-literal-library-ref" 1 "q36-parameter" 1 - "q37-overlaps" 3) + "q37-overlaps" 3 + "q38-di-surv" 2) (let [result (evaluate "q1" "subject-list")] (testing "MeasureReport is valid" @@ -495,6 +496,6 @@ (comment (log/set-level! :debug) - (evaluate "q37-overlaps") + (evaluate "q38-di-surv") ) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-data.json b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-data.json new file mode 100644 index 000000000..967c33ab1 --- /dev/null +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-data.json @@ -0,0 +1,240 @@ +{ + "resourceType": "Bundle", + "type": "transaction", + "entry": [ + { + "resource": { + "resourceType": "Patient", + "id": "0", + "gender": "male", + "birthDate": "2020" + }, + "request": { + "method": "PUT", + "url": "Patient/0" + } + }, + { + "resource": { + "resourceType": "Patient", + "id": "1" + }, + "request": { + "method": "PUT", + "url": "Patient/1", + "gender": "female", + "birthDate": "2019" + } + }, + { + "resource": { + "resourceType": "Patient", + "id": "2", + "gender": "male", + "birthDate": "2019" + }, + "request": { + "method": "PUT", + "url": "Patient/2" + } + }, + { + "resource": { + "resourceType": "Patient", + "id": "3", + "gender": "female", + "birthDate": "2018" + }, + "request": { + "method": "PUT", + "url": "Patient/3" + } + }, + { + "resource": { + "resourceType": "Patient", + "id": "4", + "gender": "male", + "birthDate": "2000" + }, + "request": { + "method": "PUT", + "url": "Patient/4" + } + }, + { + "resource": { + "resourceType": "Condition", + "id": "0", + "code": { + "coding": [ + { + "system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm", + "code": "E10.0-" + } + ] + }, + "subject": { + "reference": "Patient/0" + }, + "encounter": { + "reference": "Encounter/0" + } + }, + "request": { + "method": "PUT", + "url": "Condition/0" + } + }, + { + "resource": { + "resourceType": "Condition", + "id": "3", + "code": { + "coding": [ + { + "system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm", + "code": "E10.11" + } + ] + }, + "subject": { + "reference": "Patient/3" + }, + "encounter": { + "reference": "Encounter/3" + } + }, + "request": { + "method": "PUT", + "url": "Condition/3" + } + }, + { + "resource": { + "resourceType": "Encounter", + "id": "0", + "type": { + "coding": [ + { + "system": "http://fhir.de/CodeSystem/kontaktart-de", + "code": "normalstationaer" + } + ] + }, + "subject": { + "reference": "Patient/0" + }, + "period": { + "start": "2021-04-01", + "end": "2021-04-11" + } + }, + "request": { + "method": "PUT", + "url": "Encounter/0" + } + }, + { + "resource": { + "resourceType": "Encounter", + "id": "1", + "type": { + "coding": [ + { + "system": "http://fhir.de/CodeSystem/kontaktart-de", + "code": "normalstationaer" + } + ] + }, + "subject": { + "reference": "Patient/1" + }, + "period": { + "start": "2022-04-01", + "end": "2022-04-11" + } + }, + "request": { + "method": "PUT", + "url": "Encounter/1" + } + }, + { + "resource": { + "resourceType": "Encounter", + "id": "3", + "type": { + "coding": [ + { + "system": "http://fhir.de/CodeSystem/kontaktart-de", + "code": "normalstationaer" + } + ] + }, + "subject": { + "reference": "Patient/3" + }, + "period": { + "start": "2021-07-21", + "end": "2021-08-10" + } + }, + "request": { + "method": "PUT", + "url": "Encounter/3" + } + }, + { + "resource": { + "resourceType": "Measure", + "id": "0", + "url": "0", + "status": "active", + "subjectCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/resource-types", + "code": "Patient" + } + ] + }, + "library": [ + "0" + ], + "scoring": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/measure-scoring", + "code": "cohort" + } + ] + }, + "group": [ + { + "population": [ + { + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/measure-population", + "code": "initial-population" + } + ] + }, + "criteria": { + "language": "text/cql", + "expression": "InInitialPopulation" + } + } + ] + } + ] + }, + "request": { + "method": "PUT", + "url": "Measure/0" + } + } + ] +} diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-query.cql b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-query.cql new file mode 100644 index 000000000..dd307b5e5 --- /dev/null +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/q38-di-surv-query.cql @@ -0,0 +1,25 @@ +library DiSurv +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +codesystem snomed: 'http://snomed.info/sct' +codesystem icd_10_gm: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm' +codesystem kontaktart: 'http://fhir.de/CodeSystem/kontaktart-de' + +context Patient + +define "Diabetes mellitus, Typ 1 Diagnose": + [Condition: Code 'E10.0-' from icd_10_gm] union + [Condition: Code 'E10.01' from icd_10_gm] union + [Condition: Code 'E10.1-' from icd_10_gm] union + [Condition: Code 'E10.11' from icd_10_gm] + +define "Stationäre Aufnahme": + [Encounter: Code 'normalstationaer' from kontaktart] + +define InInitialPopulation: + exists "Stationäre Aufnahme" E + with "Diabetes mellitus, Typ 1 Diagnose" C + such that C.encounter.reference = 'Encounter/' + E.id + where E.period included in Interval[@2021-01-01T, @2021-12-31T] + and AgeInYearsAt(E.period.start) < 5 From 19ca6ff602624a30d6451f0e34b641ad305bee39 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Wed, 2 Mar 2022 14:06:17 +0100 Subject: [PATCH 10/14] Measure Resource Handle Size --- modules/db/deps.edn | 5 +- .../db/impl/index/resource_handle_test.clj | 50 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 modules/db/test-perf/blaze/db/impl/index/resource_handle_test.clj diff --git a/modules/db/deps.edn b/modules/db/deps.edn index 9dc0450b7..c0e030754 100644 --- a/modules/db/deps.edn +++ b/modules/db/deps.edn @@ -58,7 +58,10 @@ {:local/root "../test-util"} criterium/criterium - {:mvn/version "0.4.6"}}} + {:mvn/version "0.4.6"} + + org.openjdk.jol/jol-core + {:mvn/version "0.16"}}} :test-coverage {:extra-paths ["test"] diff --git a/modules/db/test-perf/blaze/db/impl/index/resource_handle_test.clj b/modules/db/test-perf/blaze/db/impl/index/resource_handle_test.clj new file mode 100644 index 000000000..ce1d790bc --- /dev/null +++ b/modules/db/test-perf/blaze/db/impl/index/resource_handle_test.clj @@ -0,0 +1,50 @@ +(ns blaze.db.impl.index.resource-handle-test + (:require + [blaze.db.impl.byte-buffer :as bb] + [blaze.db.impl.index.resource-handle :as rh] + [clojure.spec.test.alpha :as st] + [clojure.test :as test :refer [are deftest testing]] + [cuerdas.core :as str]) + (:import + [org.openjdk.jol.info GraphLayout])) + + +(st/instrument) + + +(defn- fixture [f] + (st/instrument) + (f) + (st/unstrument)) + + +(test/use-fixtures :each fixture) + + +(defn- total-size [& xs] + (.totalSize (GraphLayout/parseInstance (object-array xs)))) + + +(defn- resource-handle [id-size] + (rh/resource-handle 0 (str/repeat "0" id-size) 0 (bb/allocate 40))) + + +(deftest resource-handle-test + (testing "instance size" + (are [id-size size] (= size (total-size (resource-handle id-size))) + 1 288 + 8 288 + 9 296 + 16 296 + 17 304 + 24 304 + 25 312 + 32 312 + 33 320 + 40 320 + 41 328 + 48 328 + 49 336 + 56 336 + 57 344 + 64 344))) From 124976eb9a9226f3bfbfcc89b843740a05a7a35c Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Thu, 3 Mar 2022 19:25:10 +0100 Subject: [PATCH 11/14] Use Records For HumanName and Address, Intern Meta --- docs/implementation/fhir-data-model.md | 46 +- modules/db/test/blaze/db/api_test.clj | 549 +++++++++--------- .../db/impl/search_param/string_test.clj | 11 +- .../fhir-path/test/blaze/fhir_path_test.clj | 30 +- modules/fhir-structure/deps.edn | 13 + .../fhir-structure/resources/data_readers.clj | 4 +- .../src/blaze/fhir/spec/impl.clj | 38 +- .../src/blaze/fhir/spec/impl/specs.clj | 17 +- .../src/blaze/fhir/spec/type.clj | 50 ++ .../src/blaze/fhir/spec/type/macros.clj | 19 +- .../test-perf/blaze/fhir/spec_test_perf.clj | 25 + .../test/blaze/fhir/spec/impl_test.clj | 18 +- .../test/blaze/fhir/spec/memory.clj | 25 + .../test/blaze/fhir/spec/type_test.clj | 255 +++++--- .../test/blaze/fhir/spec_test.clj | 459 +++++++++++++-- 15 files changed, 1080 insertions(+), 479 deletions(-) create mode 100644 modules/fhir-structure/test-perf/blaze/fhir/spec_test_perf.clj create mode 100644 modules/fhir-structure/test/blaze/fhir/spec/memory.clj diff --git a/docs/implementation/fhir-data-model.md b/docs/implementation/fhir-data-model.md index 5c5cb360c..3117a20ee 100644 --- a/docs/implementation/fhir-data-model.md +++ b/docs/implementation/fhir-data-model.md @@ -72,9 +72,7 @@ The internal representation of the example above looks like this: ```clojure {:fhir/type :fhir/Patient :id "0" - :name - [{:fhir/type :fhir/HumanName - :text "John Doe"}] + :name [#fhir/HumanName{:text "John Doe"}] :birthDate #fhir/date"2020" :deceased false} ``` @@ -98,27 +96,27 @@ First, the `-type` method will return the FHIR type of a value and second the `- The following table shows the mapping from primitive FHIR types to Java types: -FHIR Type | FHIRPath Type | Java Type | Heap Size ------------|----------------|-----------|----------- -boolean | System.Boolean | Boolean | interned -integer | System.Integer | Integer | 16 bytes -string | System.String | String | 40 bytes + content in 8 bytes increments -decimal | System.Decimal | BigDecimal | 40 bytes for practical small decimals -uri | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -url | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -canonical | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -base64Binary | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -instant | System.DateTime | Instant or class with embedded OffsetDateTime | 24 bytes or 112 bytes -date | System.Date | Year, YearMonth, LocalDate | 16 bytes, 24 bytes, 24 bytes -dateTime | System.DateTime | Class with embedded Year, Class with embedded YearMonth, Class with embedded LocalDate, LocalDateTime, OffsetDateTime | 32 bytes, 40 bytes, 40 bytes, 72 bytes, 96 bytes (zone offsets are cached) -time | System.Time | LocalTime | 24 bytes -code | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -oid | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -id | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -markdown | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments -unsignedInt | System.Integer | Class with embedded int | 16 bytes -positiveInt | System.Integer | Class with embedded int | 16 bytes -uuid | System.String | java.util.UUID | 32 bytes +| FHIR Type | FHIRPath Type | Java Type | Heap Size | +|--------------|-----------------|-----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------| +| boolean | System.Boolean | Boolean | interned | +| integer | System.Integer | Integer | 16 bytes | +| string | System.String | String | 40 bytes + content in 8 bytes increments | +| decimal | System.Decimal | BigDecimal | 40 bytes for practical small decimals | +| uri | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| url | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| canonical | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| base64Binary | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| instant | System.DateTime | Instant or class with embedded OffsetDateTime | 24 bytes or 112 bytes | +| date | System.Date | Year, YearMonth, LocalDate | 16 bytes, 24 bytes, 24 bytes | +| dateTime | System.DateTime | Class with embedded Year, Class with embedded YearMonth, Class with embedded LocalDate, LocalDateTime, OffsetDateTime | 32 bytes, 40 bytes, 40 bytes, 72 bytes, 96 bytes (zone offsets are cached) | +| time | System.Time | LocalTime | 24 bytes | +| code | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| oid | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| id | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| markdown | System.String | Class with embedded String | 56 bytes + content in 8 bytes increments | +| unsignedInt | System.Integer | Class with embedded int | 16 bytes | +| positiveInt | System.Integer | Class with embedded int | 16 bytes | +| uuid | System.String | java.util.UUID | 32 bytes | For `boolean`, `integer` `string` and `decimal`, the obvious Java types are used. `BigDecimal` is used instead of `double` because FHIR recommends a decimal of basis 10. diff --git a/modules/db/test/blaze/db/api_test.clj b/modules/db/test/blaze/db/api_test.clj index 2d3029714..81553957d 100644 --- a/modules/db/test/blaze/db/api_test.clj +++ b/modules/db/test/blaze/db/api_test.clj @@ -847,11 +847,11 @@ [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Patient/0"}} + {:reference "Patient/0"}} {:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Observation/0"}}]}]]] + {:reference "Observation/0"}}]}]]] (testing "returns only the patient referenced in the list" (given (pull-type-query node "Patient" [["_list" "0"]]) @@ -876,15 +876,15 @@ [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Patient/0"}} + {:reference "Patient/0"}} {:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Patient/2"}} + {:reference "Patient/2"}} {:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Patient/3"}}]}]]] + {:reference "Patient/3"}}]}]]] (testing "it is possible to start with the second patient" (given (pull-type-query node "Patient" [["_list" "0"]] "2") @@ -901,48 +901,48 @@ [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"} + {:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]} :value #fhir/Quantity - {:value 130M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 130M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "O1" :subject #fhir/Reference - {:reference "Patient/0"} + {:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]} :value #fhir/Quantity - {:value 150M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 150M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "O2" :subject #fhir/Reference - {:reference "Patient/1"} + {:reference "Patient/1"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]} :value #fhir/Quantity - {:value 100M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}]]] + {:value 100M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}]]] (testing "select the Patient with >= 130 mm[Hg]" (let [clauses [["_has:Observation:patient:code-value-quantity" "8480-6$ge130"]]] @@ -1002,20 +1002,16 @@ :birthDate #fhir/date"2020-02-08" :deceased true :address - [{:fhir/type :fhir/Address - :line ["Philipp-Rosenthal-Straße 27"] - :city "Leipzig"}] - :name - [{:fhir/type :fhir/HumanName - :family "Müller"}]}] + [#fhir/Address{:line ["Philipp-Rosenthal-Straße 27"] + :city "Leipzig"}] + :name [#fhir/HumanName{:family "Müller"}]}] [:put {:fhir/type :fhir/Patient :id "id-1" :active true :gender #fhir/code"female" :birthDate #fhir/date"2020-02" :address - [{:fhir/type :fhir/Address - :city "Berlin"}] + [#fhir/Address{:city "Berlin"}] :telecom [{:fhir/type :fhir/ContactPoint :system #fhir/code"email" @@ -1030,12 +1026,9 @@ :birthDate #fhir/date"2020" :deceased #fhir/dateTime"2020-03" :address - [{:fhir/type :fhir/Address - :line ["Liebigstraße 20a"] - :city "Leipzig"}] - :name - [{:fhir/type :fhir/HumanName - :family "Schmidt"}]}] + [#fhir/Address{:line ["Liebigstraße 20a"] + :city "Leipzig"}] + :name [#fhir/HumanName{:family "Schmidt"}]}] [:put {:fhir/type :fhir/Patient :id "id-3" :birthDate #fhir/date"2019"}] @@ -1505,9 +1498,9 @@ [[[:put {:fhir/type :fhir/Practitioner :id "id-0" :name - [{:fhir/type :fhir/HumanName - :family "Müller" - :given ["Hans" "Martin"]}]}]]] + [#fhir/HumanName + {:family "Müller" + :given ["Hans" "Martin"]}]}]]] (testing "name" (testing "using family" @@ -1531,18 +1524,18 @@ :id "id-0" :type #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"https://fhir.bbmri.de/CodeSystem/SampleMaterialType" - :code #fhir/code"dna"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"https://fhir.bbmri.de/CodeSystem/SampleMaterialType" + :code #fhir/code"dna"}]} :collection {:fhir/type :fhir.Specimen/collection :bodySite #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"urn:oid:2.16.840.1.113883.6.43.1" - :code #fhir/code"C77.4"}]}}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"urn:oid:2.16.840.1.113883.6.43.1" + :code #fhir/code"C77.4"}]}}}]]] (testing "bodysite" (testing "using system|code" @@ -1647,13 +1640,13 @@ :id "id-0" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://fhir.de/CodeSystem/dimdi/icd-10-gm" - :code #fhir/code"C71.4"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://fhir.de/CodeSystem/dimdi/icd-10-gm" + :code #fhir/code"C71.4"}]} :subject #fhir/Reference - {:reference "Patient/id-0"} + {:reference "Patient/id-0"} :onset {:fhir/type :fhir/Age :value 63M}}] @@ -1685,33 +1678,33 @@ [[[:put {:fhir/type :fhir/Condition :id "0" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:code #fhir/code"0"}]}}] + {:coding + [#fhir/Coding + {:code #fhir/code"0"}]}}] [:put {:fhir/type :fhir/Condition :id "3" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:code #fhir/code"0"}]}}] + {:coding + [#fhir/Coding + {:code #fhir/code"0"}]}}] [:put {:fhir/type :fhir/Condition :id "4" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:code #fhir/code"0"}]}}] + {:coding + [#fhir/Coding + {:code #fhir/code"0"}]}}] [:put {:fhir/type :fhir/Condition :id "1" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:code #fhir/code"1"}]}}] + {:coding + [#fhir/Coding + {:code #fhir/code"1"}]}}] [:put {:fhir/type :fhir/Condition :id "2" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:code #fhir/code"1"}]}}]]] + {:coding + [#fhir/Coding + {:code #fhir/code"1"}]}}]]] (testing "code" (testing "starting with ID `1` does not return Conditions with ID `3` @@ -1736,42 +1729,42 @@ :status #fhir/code"final" :effective #fhir/Period - {:start #fhir/dateTime"2021-02-23T15:12:45+01:00" - :end #fhir/dateTime"2021-02-23T16:00:00+01:00"} + {:start #fhir/dateTime"2021-02-23T15:12:45+01:00" + :end #fhir/dateTime"2021-02-23T16:00:00+01:00"} :value #fhir/Quantity - {:value 0M - :unit "kg/m²" - :code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 0M + :unit "kg/m²" + :code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-1" :status #fhir/code"final" :effective #fhir/dateTime"2021-02-25" :value #fhir/Quantity - {:value 1M - :unit "kg/m²" - :code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 1M + :unit "kg/m²" + :code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-2" :status #fhir/code"final" :value #fhir/Quantity - {:value 2.11M - :unit "kg/m²" - :code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 2.11M + :unit "kg/m²" + :code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-3" :status #fhir/code"final" :value #fhir/Quantity - {:value 3M - :unit "kg/m²" - :code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org"}}]]] + {:value 3M + :unit "kg/m²" + :code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org"}}]]] (testing "date" (testing "with year precision" @@ -2107,19 +2100,19 @@ :status #fhir/code"final" :value #fhir/Quantity - {:value 23.42M - :unit "kg/m²" - :code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 23.42M + :unit "kg/m²" + :code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-1" :status #fhir/code"final" :value #fhir/Quantity - {:value 23.42M - :unit "kg/m²" - :code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org"}}]]] + {:value 23.42M + :unit "kg/m²" + :code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org"}}]]] (testing "full result" (let [clauses [["value-quantity" "23.42"]]] @@ -2140,20 +2133,20 @@ :id "id-0" :value #fhir/Quantity - {:value 0M - :unit "m" - :code #fhir/code"m" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 0M + :unit "m" + :code #fhir/code"m" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/TestScript :id "id-0" :useContext [{:fhir/type :fhir/UsageContext :value #fhir/Quantity - {:value 0M - :unit "m" - :code #fhir/code"m" - :system #fhir/uri"http://unitsofmeasure.org"}}]}]]] + {:value 0M + :unit "m" + :code #fhir/code"m" + :system #fhir/uri"http://unitsofmeasure.org"}}]}]]] (testing "ResourceSearchParamValue index looks like it should" (is (= (r-sp-v-tu/decode-index-entries @@ -2206,57 +2199,57 @@ :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]} :value #fhir/Quantity - {:value 130M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 130M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-1" :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]} :value #fhir/Quantity - {:value 150M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 150M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-2" :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8462-4"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8462-4"}]} :value #fhir/Quantity - {:value 90M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}] + {:value 90M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}] [:put {:fhir/type :fhir/Observation :id "id-3" :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8462-4"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8462-4"}]} :value #fhir/Quantity - {:value 70M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}}]]] + {:value 70M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}}]]] (testing "as first clause" (let [clauses [["code-value-quantity" "8480-6$ge140"]]] @@ -2396,52 +2389,52 @@ :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"94564-2" - :display "SARS-CoV-2 (COVID-19) IgM Ab [Presence]"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"94564-2" + :display "SARS-CoV-2 (COVID-19) IgM Ab [Presence]"}]} :value #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://snomed.info/sct" - :code #fhir/code"260373001" - :display "Detected (qualifier value)"}]}}] + {:coding + [#fhir/Coding + {:system #fhir/uri"http://snomed.info/sct" + :code #fhir/code"260373001" + :display "Detected (qualifier value)"}]}}] [:put {:fhir/type :fhir/Observation :id "id-1" :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"94564-2" - :display "SARS-CoV-2 (COVID-19) IgM Ab [Presence]"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"94564-2" + :display "SARS-CoV-2 (COVID-19) IgM Ab [Presence]"}]} :value #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://snomed.info/sct" - :code #fhir/code"260415000" - :display "Not detected (qualifier value)"}]}}] + {:coding + [#fhir/Coding + {:system #fhir/uri"http://snomed.info/sct" + :code #fhir/code"260415000" + :display "Not detected (qualifier value)"}]}}] [:put {:fhir/type :fhir/Observation :id "id-2" :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"94564-2" - :display "SARS-CoV-2 (COVID-19) IgM Ab [Presence]"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"94564-2" + :display "SARS-CoV-2 (COVID-19) IgM Ab [Presence]"}]} :value #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://snomed.info/sct" - :code #fhir/code"260373001" - :display "Detected (qualifier value)"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"http://snomed.info/sct" + :code #fhir/code"260373001" + :display "Detected (qualifier value)"}]}}]]] (testing "as first clause" (testing "code as system|code" @@ -2551,14 +2544,14 @@ [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Patient/0"}}]}] + {:reference "Patient/0"}}]}] [:put {:fhir/type :fhir/List :id "id-143814" :entry [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:reference "Patient/1"}}]}]]] + {:reference "Patient/1"}}]}]]] (let [clauses [["item" "Patient/1"]]] (given (pull-type-query node "List" clauses) @@ -2573,20 +2566,20 @@ [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:identifier - #fhir/Identifier - {:system #fhir/uri"system-122917" - :value "value-122931"}}}]}] + {:identifier + #fhir/Identifier + {:system #fhir/uri"system-122917" + :value "value-122931"}}}]}] [:put {:fhir/type :fhir/List :id "id-143814" :entry [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:identifier - #fhir/Identifier - {:system #fhir/uri"system-122917" - :value "value-143818"}}}]}]]] + {:identifier + #fhir/Identifier + {:system #fhir/uri"system-122917" + :value "value-143818"}}}]}]]] (let [clauses [["item:identifier" "system-122917|value-122931"]]] (given (pull-type-query node "List" clauses) @@ -2600,34 +2593,34 @@ :id "id-123058" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-152812" - :code #fhir/code"code-152819"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system-152812" + :code #fhir/code"code-152819"}]} :entry [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:identifier - #fhir/Identifier - {:system #fhir/uri"system-122917" - :value "value-122931"}}}]}] + {:identifier + #fhir/Identifier + {:system #fhir/uri"system-122917" + :value "value-122931"}}}]}] [:put {:fhir/type :fhir/List :id "id-143814" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-152812" - :code #fhir/code"code-152819"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system-152812" + :code #fhir/code"code-152819"}]} :entry [{:fhir/type :fhir.List/entry :item #fhir/Reference - {:identifier - #fhir/Identifier - {:system #fhir/uri"system-122917" - :value "value-143818"}}}]}]]] + {:identifier + #fhir/Identifier + {:system #fhir/uri"system-122917" + :value "value-143818"}}}]}]]] (let [clauses [["code" "system-152812|code-152819"] ["item:identifier" "system-122917|value-143818"]]] @@ -2672,10 +2665,10 @@ :id "id-0" :method #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-164844" - :code #fhir/code"code-164847"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system-164844" + :code #fhir/code"code-164847"}]} :prediction [{:fhir/type :fhir.RiskAssessment/prediction :probability 0.9M}]}] @@ -2689,10 +2682,10 @@ :id "id-2" :method #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-164844" - :code #fhir/code"code-164847"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system-164844" + :code #fhir/code"code-164847"}]} :prediction [{:fhir/type :fhir.RiskAssessment/prediction :probability 0.5M}]}]]] @@ -2898,7 +2891,7 @@ [[:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"}}]]] + {:reference "Patient/0"}}]]] (given @(pull-compartment-resources node "Patient" "0" "Observation") count := 1 @@ -2912,11 +2905,11 @@ [[:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"}}]] + {:reference "Patient/0"}}]] [[:put {:fhir/type :fhir/Observation :id "1" :subject #fhir/Reference - {:reference "Patient/0"}}]]] + {:reference "Patient/0"}}]]] (given @(pull-compartment-resources node "Patient" "0" "Observation") count := 2 @@ -2933,7 +2926,7 @@ [[:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"}}]] + {:reference "Patient/0"}}]] [[:delete "Observation" "0"]]] (is (coll/empty? (d/list-compartment-resource-handles @@ -2945,15 +2938,15 @@ [[:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"}}]] + {:reference "Patient/0"}}]] [[:put {:fhir/type :fhir/Observation :id "1" :subject #fhir/Reference - {:reference "Patient/0"}}]] + {:reference "Patient/0"}}]] [[:put {:fhir/type :fhir/Observation :id "2" :subject #fhir/Reference - {:reference "Patient/0"}}]]] + {:reference "Patient/0"}}]]] (given @(pull-compartment-resources node "Patient" "0" "Observation" "1") [0 :fhir/type] := :fhir/Observation @@ -2989,10 +2982,10 @@ :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]}}]]] (given @(pull-compartment-query node "Patient" "0" "Observation" @@ -3072,10 +3065,10 @@ :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system" - :code #fhir/code"code"}]}}]] + {:coding + [#fhir/Coding + {:system #fhir/uri"system" + :code #fhir/code"code"}]}}]] [[:delete "Observation" "0"]]] (is (coll/empty? (d/compartment-query @@ -3117,10 +3110,10 @@ :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]}}]]] (given @(pull-compartment-query node "Patient" "0" "Observation" @@ -3136,16 +3129,16 @@ :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]} :value #fhir/Quantity - {:code #fhir/code"kg/m2" - :unit "kg/m²" - :system #fhir/uri"http://unitsofmeasure.org" - :value 42M}}]]] + {:code #fhir/code"kg/m2" + :unit "kg/m²" + :system #fhir/uri"http://unitsofmeasure.org" + :value 42M}}]]] (testing "matches second criteria" (given @(pull-compartment-query @@ -3189,45 +3182,45 @@ [:put {:fhir/type :fhir/Condition :id "1" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system" - :code #fhir/code"code-a"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system" + :code #fhir/code"code-a"}]} :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Condition :id "2" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system" - :code #fhir/code"code-b"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system" + :code #fhir/code"code-b"}]} :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "3" :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system" - :code #fhir/code"code-a"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system" + :code #fhir/code"code-a"}]} :value #fhir/Quantity - {:code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org" - :value 42M}}] + {:code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org" + :value 42M}}] [:put {:fhir/type :fhir/Observation :id "4" :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system" - :code #fhir/code"code-b"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system" + :code #fhir/code"code-b"}]} :value #fhir/Quantity - {:code #fhir/code"kg/m2" - :system #fhir/uri"http://unitsofmeasure.org" - :value 23M}}]]] + {:code #fhir/code"kg/m2" + :system #fhir/uri"http://unitsofmeasure.org" + :value 23M}}]]] (testing "token search parameter" (testing "as first clause" @@ -3294,10 +3287,10 @@ :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]}}]]] (given @(let [query (d/compile-compartment-query node "Patient" "Observation" @@ -3671,7 +3664,7 @@ [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"}}]]] + {:reference "Patient/0"}}]]] (let [db (d/db node) observation (d/resource-handle db "Observation" "0")] @@ -3695,10 +3688,10 @@ [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"} + {:reference "Patient/0"} :encounter #fhir/Reference - {:reference "Encounter/0"}}]]] + {:reference "Encounter/0"}}]]] (let [db (d/db node) observation (d/resource-handle db "Observation" "0")] @@ -3713,7 +3706,7 @@ [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Group/0"}}]]] + {:reference "Group/0"}}]]] (let [db (d/db node) observation (d/resource-handle db "Observation" "0")] @@ -3742,10 +3735,10 @@ [[[:put {:fhir/type :fhir/Observation :id "0" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]}}]]] (let [db (d/db node) observation (d/resource-handle db "Observation" "0")] @@ -3755,9 +3748,7 @@ (testing "non-reference search parameter family" (with-system-data [{:blaze.db/keys [node]} system] [[[:put {:fhir/type :fhir/Patient :id "0" - :name - [{:fhir/type :fhir/HumanName - :family "Müller"}]}]]] + :name [#fhir/HumanName{:family "Müller"}]}]]] (let [db (d/db node) patient (d/resource-handle db "Patient" "0")] @@ -3773,11 +3764,11 @@ [:put {:fhir/type :fhir/Observation :id "1" :subject #fhir/Reference - {:reference "Patient/0"}}] + {:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "2" :subject #fhir/Reference - {:reference "Patient/0"}}]]] + {:reference "Patient/0"}}]]] (let [db (d/db node) patients (d/resource-handle db "Patient" "0")] @@ -3795,10 +3786,10 @@ [:put {:fhir/type :fhir/Observation :id "0" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]}}]]] (let [db (d/db node) patients (d/resource-handle db "Patient" "0")] @@ -3851,13 +3842,13 @@ [:put {:fhir/type :fhir/Observation :id "0" :subject #fhir/Reference - {:reference "Patient/0"} + {:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]}}]]] (with-open [batch-db (d/new-batch-db (d/db node))] (given @(let [query (d/compile-compartment-query @@ -3875,10 +3866,10 @@ :subject #fhir/Reference{:reference "Patient/0"} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]}}]]] + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]}}]]] (with-open [batch-db (d/new-batch-db (d/db node))] (given @(let [query (d/compile-compartment-query-lenient diff --git a/modules/db/test/blaze/db/impl/search_param/string_test.clj b/modules/db/test/blaze/db/impl/search_param/string_test.clj index 2dbe916c1..337e01bc0 100644 --- a/modules/db/test/blaze/db/impl/search_param/string_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/string_test.clj @@ -61,7 +61,7 @@ (testing "missing family is not a problem" (let [patient {:fhir/type :fhir/Patient :id "id-164114" - :name [{:fhir/type :fhir/HumanName}]} + :name [#fhir/HumanName{}]} hash (hash/generate patient)] (is (empty? (search-param/index-entries @@ -70,9 +70,7 @@ (let [patient {:fhir/type :fhir/Patient :id "id-122929" - :name - [{:fhir/type :fhir/HumanName - :family "family-102508"}]} + :name [#fhir/HumanName{:family "family-102508"}]} hash (hash/generate patient) [[_ k0] [_ k1]] (search-param/index-entries @@ -98,9 +96,8 @@ (let [patient {:fhir/type :fhir/Patient :id "id-122929" :address - [{:fhir/type :fhir/Address - :line ["line-120252"] - :city "city-105431"}]} + [#fhir/Address{:line ["line-120252"] + :city "city-105431"}]} hash (hash/generate patient) [[_ k0] [_ k1] [_ k2] [_ k3]] (search-param/index-entries diff --git a/modules/fhir-path/test/blaze/fhir_path_test.clj b/modules/fhir-path/test/blaze/fhir_path_test.clj index 3926b1d23..eb6186f4b 100644 --- a/modules/fhir-path/test/blaze/fhir_path_test.clj +++ b/modules/fhir-path/test/blaze/fhir_path_test.clj @@ -134,9 +134,7 @@ (eval "Patient.name.family + ', ' + Patient.name.given" {:fhir/type :fhir/Patient :id "foo" - :name - [{:fhir/type :fhir/HumanName - :family "Doe"}]}) + :name [#fhir/HumanName{:family "Doe"}]}) identity := ["Doe, "])) (testing "with one given name" @@ -144,20 +142,14 @@ (eval "Patient.name.family + ', ' + Patient.name.given" {:fhir/type :fhir/Patient :id "foo" - :name - [{:fhir/type :fhir/HumanName - :family "Doe" - :given ["John"]}]}) + :name [#fhir/HumanName{:family "Doe" :given ["John"]}]}) identity := ["Doe, John"])) (testing "with two given names" (given (eval "Patient.name.family + ', ' + Patient.name.given" {:fhir/type :fhir/Patient :id "foo" - :name - [{:fhir/type :fhir/HumanName - :family "Doe" - :given ["John" "Foo"]}]}) + :name [#fhir/HumanName{:family "Doe" :given ["John" "Foo"]}]}) ::anom/category := ::anom/incorrect ::anom/message := "unable to evaluate `[\"John\" \"Foo\"]` as singleton")) @@ -165,11 +157,9 @@ (given (eval "Patient.name.family + ', ' + Patient.name" {:fhir/type :fhir/Patient :id "foo" - :name - [{:fhir/type :fhir/HumanName - :family "Doe"}]}) + :name [#fhir/HumanName{:family "Doe"}]}) ::anom/category := ::anom/incorrect - ::anom/message := "unable to evaluate `[{:fhir/type :fhir/HumanName, :family \"Doe\"}]` as singleton"))) + ::anom/message := "unable to evaluate `[#fhir/HumanName{:family \"Doe\"}]` as singleton"))) (testing "and expression" (testing "with one telecom" @@ -347,9 +337,7 @@ "Patient.address.where(line)" {:fhir/type :fhir/Patient :id "id-162953" - :address - [{:fhir/type :fhir/Address - :line ["a" "b"]}]}) + :address [#fhir/Address{:line ["a" "b"]}]}) ::anom/category := ::anom/incorrect ::anom/message := "multiple result items `[\"a\" \"b\"]` while evaluating where function criteria")) @@ -409,10 +397,8 @@ (let [patient {:fhir/type :fhir/Patient :id "foo" :name - [{:fhir/type :fhir/HumanName - :family "Doe"} - {:fhir/type :fhir/HumanName - :family "Bolton"}]}] + [#fhir/HumanName{:family "Doe"} + #fhir/HumanName{:family "Bolton"}]}] (are [expr res] (= res (eval expr patient)) "{} | {}" [] "1 | {}" [1] diff --git a/modules/fhir-structure/deps.edn b/modules/fhir-structure/deps.edn index d79593415..f5cf15789 100644 --- a/modules/fhir-structure/deps.edn +++ b/modules/fhir-structure/deps.edn @@ -55,6 +55,19 @@ :main-opts ["-m" "kaocha.runner"]} + :test-perf + {:extra-paths ["test-perf"] + + :extra-deps + {blaze/test-util + {:local/root "../test-util"} + + criterium/criterium + {:mvn/version "0.4.6"} + + org.openjdk.jol/jol-core + {:mvn/version "0.16"}}} + :test-coverage {:extra-paths ["test"] diff --git a/modules/fhir-structure/resources/data_readers.clj b/modules/fhir-structure/resources/data_readers.clj index ccd22eef1..9b1d32faa 100644 --- a/modules/fhir-structure/resources/data_readers.clj +++ b/modules/fhir-structure/resources/data_readers.clj @@ -23,8 +23,10 @@ fhir/Quantity blaze.fhir.spec.type/map->Quantity fhir/Period blaze.fhir.spec.type/map->Period fhir/Identifier blaze.fhir.spec.type/map->Identifier + fhir/HumanName blaze.fhir.spec.type/map->HumanName + fhir/Address blaze.fhir.spec.type/map->Address fhir/Reference blaze.fhir.spec.type/map->Reference - fhir/Meta blaze.fhir.spec.type/map->Meta + fhir/Meta blaze.fhir.spec.type/mk-meta fhir/BundleEntrySearch blaze.fhir.spec.type/map->BundleEntrySearch system/date blaze.fhir.spec.type.system/parse-date system/date-time blaze.fhir.spec.type.system/parse-date-time} diff --git a/modules/fhir-structure/src/blaze/fhir/spec/impl.clj b/modules/fhir-structure/src/blaze/fhir/spec/impl.clj index 8f606e823..bd994749a 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/impl.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/impl.clj @@ -1,6 +1,7 @@ (ns blaze.fhir.spec.impl (:require [blaze.anomaly :as ba :refer [throw-anom]] + [blaze.fhir.spec.impl.intern :as intern] [blaze.fhir.spec.impl.specs :as specs] [blaze.fhir.spec.type :as type] [clojure.alpha.spec :as s] @@ -51,8 +52,13 @@ `(fn [~'s] (re-matches #"[A-Za-z0-9\-\.]{1,64}" ~'s))) +(def ^{:arglists '([s])} intern-string + "Returns an interned String without using String/intern." + (intern/intern-value identity)) + + (def uri-matcher-form - `(fn [~'s] (re-matches #"\S*" ~'s))) + `(specs/regex #"\S*" intern-string)) (defn element? [x] @@ -82,7 +88,7 @@ (:json nil) `(s/and string? ~uri-matcher-form) :xml `(s/and element? (s/conformer conform-xml-value unform-xml-value) ~uri-matcher-form) :xmlAttr `(s/and string? ~uri-matcher-form) - :cbor `any?)) + :cbor `(s/conformer intern-string))) (defn- string-spec [modifier type] @@ -192,7 +198,10 @@ :modifier :json :min min :max max - :spec-form (keyword "fhir.json" (:code type))} + :spec-form + (if (= "Quantity.unit" path) + `(specs/regex #"[ \r\n\t\S]+" intern-string) + (keyword "fhir.json" (:code type)))} (cond-> {:key (path-parts->key' "fhir.xml" (split-path path)) :modifier :xml @@ -207,7 +216,10 @@ :modifier :cbor :min min :max max - :spec-form (keyword "fhir.cbor" (:code type))}])) + :spec-form + (if (= "Quantity.unit" path) + `(s/conformer intern-string) + (keyword "fhir.cbor" (:code type)))}])) (defn elem-def->spec-def @@ -334,6 +346,8 @@ :fhir/Quantity :fhir/Period :fhir/Identifier + :fhir/HumanName + :fhir/Address :fhir/Reference :fhir/Meta) (record-spec-form path-part child-spec-defs) @@ -452,13 +466,16 @@ (json-object-spec-form "coding" child-spec-defs) :fhir.json/CodeableConcept (json-object-spec-form "codeable-concept" child-spec-defs) + :fhir.json/Meta + (json-object-spec-form "mk-meta" child-spec-defs) (:fhir.json/Attachment :fhir.json/Extension :fhir.json/Quantity :fhir.json/Period :fhir.json/Identifier - :fhir.json/Reference - :fhir.json/Meta) + :fhir.json/HumanName + :fhir.json/Address + :fhir.json/Reference) (json-object-spec-form (str "map->" path-part) child-spec-defs) :fhir.json.Bundle.entry/search (json-object-spec-form "map->BundleEntrySearch" child-spec-defs) @@ -589,6 +606,8 @@ :fhir.xml/Quantity :fhir.xml/Period :fhir.xml/Identifier + :fhir.xml/HumanName + :fhir.xml/Address :fhir.xml/Reference :fhir.xml/Meta) (special-xml-schema-spec-form kind (name key) child-spec-defs) @@ -626,13 +645,16 @@ (cbor-object-spec-form "coding" child-spec-defs) :fhir.cbor/CodeableConcept (cbor-object-spec-form "codeable-concept" child-spec-defs) + :fhir.cbor/Meta + (cbor-object-spec-form "mk-meta" child-spec-defs) (:fhir.cbor/Attachment :fhir.cbor/Extension :fhir.cbor/Quantity :fhir.cbor/Period :fhir.cbor/Identifier - :fhir.cbor/Reference - :fhir.cbor/Meta) + :fhir.cbor/HumanName + :fhir.cbor/Address + :fhir.cbor/Reference) (cbor-object-spec-form (str "map->" path-part) child-spec-defs) :fhir.cbor.Bundle.entry/search (cbor-object-spec-form "map->BundleEntrySearch" child-spec-defs) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/impl/specs.clj b/modules/fhir-structure/src/blaze/fhir/spec/impl/specs.clj index 81aceaa3a..88aa84f98 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/impl/specs.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/impl/specs.clj @@ -9,6 +9,9 @@ (set! *warn-on-reflection* true) +(declare regex) + + (defn- regex-impl [pattern f-form] (let [f (s/resolve-fn f-form)] @@ -28,20 +31,23 @@ (defmethod s/expand-spec `regex - [[_ pattern f]] + [[_ pattern f-form]] {:clojure.spec/op `regex :pattern pattern - :f f}) + :f-form f-form}) (defmethod s/create-spec `regex - [{:keys [pattern f]}] - (regex-impl pattern f)) + [{:keys [pattern f-form]}] + (regex-impl pattern f-form)) ;; ---- Record Spec ----------------------------------------------------------- +(declare record) + + (defn- record-impl [class-sym spec-forms] (let [class (resolve class-sym) specs (delay (into {} (map #(vector (key %) (s/resolve-spec (val %)))) spec-forms)) @@ -98,6 +104,9 @@ [{:path path :pred form :val v :via via :in in}]))) +(declare json-object) + + (defn- json-object-impl [constructor-sym spec-forms key-map] (let [constructor (resolve constructor-sym) specs (delay (into {} (map #(vector (key %) (s/resolve-spec (val %)))) spec-forms)) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type.clj b/modules/fhir-structure/src/blaze/fhir/spec/type.clj index 53400fa7e..9db1f5b96 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type.clj @@ -1277,6 +1277,43 @@ [ref]))) +(defcomplextype HumanName [id extension use text family given prefix suffix period] + :hash-num 46 + :field-serializers + {id :string + extension ^{:cardinality :many} extension-serializer + use code-serializer + text :string + family :string + given :strings + prefix :strings + suffix :strings + period period-serializer}) + + +(declare human-name-serializer) + + +(defcomplextype Address [id extension use type text line city district state postalCode country period] + :hash-num 47 + :field-serializers + {id :string + extension ^{:cardinality :many} extension-serializer + use code-serializer + type code-serializer + text :string + line :strings + city :string + district :string + state :string + postalCode :string + country :string + period period-serializer}) + + +(declare address-serializer) + + (defcomplextype Reference [id extension reference type identifier display] :hash-num 43 :references @@ -1309,6 +1346,10 @@ tag ^{:cardinality :many} coding-serializer}) +(def mk-meta + (intern/intern-value map->Meta)) + + (declare meta-serializer) @@ -1353,8 +1394,17 @@ (.addSerializer Coding coding-serializer) (.addSerializer CodeableConcept codeable-concept-serializer) (.addSerializer Quantity quantity-serializer) + ;; Range + ;; Ratio (.addSerializer Period period-serializer) + ;; SampledData (.addSerializer Identifier identifier-serializer) + (.addSerializer HumanName human-name-serializer) + (.addSerializer Address address-serializer) + ;; ContactPoint + ;; Timing + ;; Signature + ;; Annotation (.addSerializer Reference reference-serializer) (.addSerializer Meta meta-serializer) (.addSerializer BundleEntrySearch bundle-entry-search-serializer))) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj b/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj index 53a853bcb..cc74d055b 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj @@ -30,6 +30,16 @@ (reduce conj! to from)) +(defn- write-string [gen s] + `(.writeString ~(with-meta gen {:tag `JsonGenerator}) ~(with-meta s {:tag `String}))) + + +(defn- serialize [serializer x gen provider] + `(.serialize ~(with-meta serializer {:tag `JsonSerializer}) ~x ~gen ~provider)) + + +(comment (serialize 's 1 'g 'p)) + (defmacro defcomplextype [name [& fields] & {:keys [fhir-type hash-num references field-serializers]}] (let [sink-sym (gensym "sink") @@ -76,6 +86,11 @@ (case serializer :string `[(.writeStringField ~'gen ~(str field) ~field)] + :strings + `[(.writeArrayFieldStart ~'gen ~(str field)) + (dotimes [~'i (count ~field)] + ~(write-string 'gen `(nth ~field ~'i))) + (.writeEndArray ~'gen)] :decimal `[(.writeNumberField ~'gen ~(str field) ~(with-meta field {:tag `BigDecimal}))] :dynamic @@ -86,8 +101,8 @@ (dyn-serialize ~'gen ~'provider ~field)] (if (= :many (:cardinality (meta serializer))) `[(.writeArrayFieldStart ~'gen ~(str field)) - (dotimes [i# (count ~field)] - (.serialize ~(with-meta serializer {:tag `JsonSerializer}) (nth ~field i#) ~'gen ~'provider)) + (dotimes [~'i (count ~field)] + ~(serialize serializer `(nth ~field ~'i) 'gen 'provider)) (.writeEndArray ~'gen)] `[(.writeFieldName ~'gen ~(str field)) (.serialize ~(with-meta serializer {:tag `JsonSerializer}) ~field ~'gen ~'provider)]))))) diff --git a/modules/fhir-structure/test-perf/blaze/fhir/spec_test_perf.clj b/modules/fhir-structure/test-perf/blaze/fhir/spec_test_perf.clj new file mode 100644 index 000000000..8ba634ac8 --- /dev/null +++ b/modules/fhir-structure/test-perf/blaze/fhir/spec_test_perf.clj @@ -0,0 +1,25 @@ +(ns blaze.fhir.spec-test-perf + (:require + [blaze.fhir.spec :as fhir-spec] + [blaze.test-util :as tu] + [clojure.test :refer [are deftest testing]] + [criterium.core :as criterium])) + + +(tu/init-fhir-specs) + + +(deftest unform-json-test + (are [x mean] (< (:mean (criterium/quick-benchmark (fhir-spec/unform-json x) {}) mean)) + #fhir/HumanName{:family "Doe" :given ["John"]} 0.3 + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"17861-6"}]} 0.4)) + + +(comment + (criterium/quick-bench (fhir-spec/unform-json #fhir/HumanName{:family "Doe" :given ["John"]})) + (criterium/quick-bench (fhir-spec/unform-json #fhir/CodeableConcept{:coding [#fhir/Coding{:system #fhir/uri"http://loinc.org" :code #fhir/code"17861-6"}]})) + ) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj index 1adbc3555..87be13fef 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj @@ -436,11 +436,11 @@ (testing "XML representation of Extension" (given (group-by :key (impl/struct-def->spec-def (complex-type structure-definition-repo "Extension"))) [:fhir.Extension/url 0 :spec-form regexes->str] - := `(s2/and string? (fn [~'s] (re-matches "\\S*" ~'s))) + := `(s2/and string? (specs/regex "\\S*" impl/intern-string)) [:fhir.json.Extension/url 0 :spec-form regexes->str] - := `(s2/and string? (fn [~'s] (re-matches "\\S*" ~'s))) + := `(s2/and string? (specs/regex "\\S*" impl/intern-string)) [:fhir.xml.Extension/url 0 :spec-form regexes->str] - := `(s2/and string? (fn [~'s] (re-matches "\\S*" ~'s))) + := `(s2/and string? (specs/regex "\\S*" impl/intern-string)) [:fhir.xml.Extension/url 0 :representation] := :xmlAttr)) (testing "XML representation of Coding" @@ -472,7 +472,17 @@ [:fhir.xml.Questionnaire/item 0 :spec-form 2 1 :item] := `(s2/and (s2/conformer impl/ensure-coll clojure.core/identity) - (s2/coll-of :fhir.xml.Questionnaire.item/item)))))) + (s2/coll-of :fhir.xml.Questionnaire.item/item)))) + + (testing "JSON representation of Quantity.unit" + (given (group-by :key (impl/struct-def->spec-def (complex-type structure-definition-repo "Quantity"))) + [:fhir.json.Quantity/unit 0 :spec-form regexes->str] + := `(specs/regex "[ \\r\\n\\t\\S]+" impl/intern-string))) + + (testing "CBOR representation of Quantity.unit" + (given (group-by :key (impl/struct-def->spec-def (complex-type structure-definition-repo "Quantity"))) + [:fhir.cbor.Quantity/unit 0 :spec-form regexes->str] + := `(s2/conformer impl/intern-string))))) (def sexp prxml/sexp-as-element) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/memory.clj b/modules/fhir-structure/test/blaze/fhir/spec/memory.clj new file mode 100644 index 000000000..372b00b06 --- /dev/null +++ b/modules/fhir-structure/test/blaze/fhir/spec/memory.clj @@ -0,0 +1,25 @@ +(ns blaze.fhir.spec.memory + (:import + [clojure.lang PersistentVector] + [org.openjdk.jol.info GraphLayout])) + + +(defn graph-layout ^GraphLayout [& roots] + (GraphLayout/parseInstance (object-array roots))) + + +(defn total-size [& roots] + (-> (apply graph-layout roots) + (.subtract (graph-layout (PersistentVector/EMPTY_NODE))) + (.totalSize))) + + +(defn print-layout [& roots] + (-> (apply graph-layout roots) + (.subtract (graph-layout (PersistentVector/EMPTY_NODE))) + (.toPrintable))) + + +(defn print-total-layout [& roots] + (-> (apply graph-layout roots) + (.toPrintable))) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj index 8e9608e65..a8271bd85 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj @@ -1,5 +1,6 @@ (ns blaze.fhir.spec.type-test (:require + [blaze.fhir.spec.memory :as mem] [blaze.fhir.spec.type :as type] [blaze.fhir.spec.type.system :as system] [clojure.data.xml.name :as xml-name] @@ -12,7 +13,6 @@ (:import [java.time Instant LocalDate LocalTime OffsetDateTime Year YearMonth ZoneOffset] - [org.openjdk.jol.info ClassLayout GraphLayout] [com.google.common.hash Hashing])) @@ -31,22 +31,6 @@ (test/use-fixtures :each fixture) -(defn class-layout [c] - (.toPrintable (ClassLayout/parseClass c))) - - -(defn instance-size [c] - (.instanceSize (ClassLayout/parseClass c))) - - -(defn graph-layout [& xs] - (.toPrintable (GraphLayout/parseInstance (object-array xs)))) - - -(defn total-size [& xs] - (.totalSize (GraphLayout/parseInstance (object-array xs)))) - - (defn murmur3 [x] (let [hasher (.newHasher (Hashing/murmur3_32_fixed))] (type/hash-into x hasher) @@ -145,7 +129,7 @@ nil)) (testing "instance size" - (is (= 16 (total-size #fhir/integer 1))))) + (is (= 16 (mem/total-size #fhir/integer 1))))) (deftest long-test @@ -175,7 +159,7 @@ nil)) (testing "instance size" - (is (= 24 (total-size #fhir/long 1))))) + (is (= 24 (mem/total-size #fhir/long 1))))) (deftest string-test @@ -208,7 +192,7 @@ nil)) (testing "instance size" - (are [s size] (= size (total-size s)) + (are [s size] (= size (mem/total-size s)) "" 40 "a" 48 (str/repeat "a" 8) 48 @@ -247,7 +231,7 @@ nil)) (testing "instance size" - (is (= 40 (total-size 1.1M))))) + (is (= 40 (mem/total-size 1.1M))))) (deftest uri-test @@ -288,8 +272,8 @@ (is (= "#fhir/uri\"142600\"" (pr-str #fhir/uri"142600")))) (testing "instance size" - (is (= 56 (total-size #fhir/uri""))) - (is (= 64 (total-size #fhir/uri"a"))))) + (is (= 56 (mem/total-size #fhir/uri""))) + (is (= 64 (mem/total-size #fhir/uri"a"))))) (deftest url-test @@ -330,8 +314,8 @@ (is (= "#fhir/url\"142600\"" (pr-str #fhir/url"142600")))) (testing "instance size" - (is (= 56 (total-size #fhir/url""))) - (is (= 64 (total-size #fhir/url"a"))))) + (is (= 56 (mem/total-size #fhir/url""))) + (is (= 64 (mem/total-size #fhir/url"a"))))) (deftest canonical-test @@ -372,8 +356,8 @@ (is (= "#fhir/canonical\"142600\"" (pr-str #fhir/canonical"142600")))) (testing "instance size" - (is (= 56 (total-size #fhir/canonical""))) - (is (= 64 (total-size #fhir/canonical"a"))))) + (is (= 56 (mem/total-size #fhir/canonical""))) + (is (= 64 (mem/total-size #fhir/canonical"a"))))) (deftest base64Binary-test @@ -416,9 +400,9 @@ (is (= "#fhir/base64Binary\"YQo=\"" (pr-str #fhir/base64Binary"YQo=")))) (testing "instance size" - (is (= 56 (total-size #fhir/base64Binary""))) - (is (= 64 (total-size #fhir/base64Binary"YQo="))) - (is (= 72 (total-size #fhir/base64Binary"MTA1NjE0Cg=="))))) + (is (= 56 (mem/total-size #fhir/base64Binary""))) + (is (= 64 (mem/total-size #fhir/base64Binary"YQo="))) + (is (= 72 (mem/total-size #fhir/base64Binary"MTA1NjE0Cg=="))))) (deftest instant-test @@ -456,10 +440,10 @@ (is (= Instant/EPOCH #fhir/instant"1970-01-01T00:00:00+00:00"))) (testing "instance size" (testing "backed by OffsetDateTime, taking into account shared offsets" - (is (= 112 (- (total-size #fhir/instant"2020-01-01T00:00:00+02:00") - (total-size ZoneOffset/UTC))))) + (is (= 112 (- (mem/total-size #fhir/instant"2020-01-01T00:00:00+02:00") + (mem/total-size ZoneOffset/UTC))))) (testing "backed by java.time.Instant" - (is (= 24 (total-size Instant/EPOCH))))) + (is (= 24 (mem/total-size Instant/EPOCH))))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/instant"2020-01-01T00:00:00+00:00" "d81f6bc2" @@ -498,7 +482,7 @@ (is (not= #fhir/date"2020" #fhir/date"2021")) (is (not= #fhir/date"2020" "2020"))) (testing "instance size" - (is (= 16 (total-size #fhir/date"2020")))) + (is (= 16 (mem/total-size #fhir/date"2020")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/date"2020" "c92be432")) @@ -526,7 +510,7 @@ (is (not= #fhir/date"2020-01" #fhir/date"2020-02")) (is (not= #fhir/date"2020-01" "2020-01"))) (testing "instance size" - (is (= 24 (total-size #fhir/date"2020-01")))) + (is (= 24 (mem/total-size #fhir/date"2020-01")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/date"2020-01" "fbcdf97f")) @@ -555,7 +539,7 @@ (is (not= #fhir/date"2020-01-01" #fhir/date"2020-01-02")) (is (not= #fhir/date"2020-01-01" "2020-01-01"))) (testing "instance size" - (is (= 24 (total-size #fhir/date"2020-01-01")))) + (is (= 24 (mem/total-size #fhir/date"2020-01-01")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/date"2020-01-01" "cd20e081")) @@ -585,7 +569,7 @@ (is (not= #fhir/dateTime"2020" #fhir/dateTime"2021")) (is (not= #fhir/dateTime"2020" "2020"))) (testing "instance size" - (is (= 32 (total-size #fhir/dateTime"2020")))) + (is (= 32 (mem/total-size #fhir/dateTime"2020")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/dateTime"2020" "41e906ff")) @@ -617,7 +601,7 @@ (is (not= #fhir/dateTime"2020-01" #fhir/dateTime"2020-02")) (is (not= #fhir/dateTime"2020-01" "2020-01"))) (testing "instance size" - (is (= 40 (total-size #fhir/dateTime"2020-01")))) + (is (= 40 (mem/total-size #fhir/dateTime"2020-01")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/dateTime"2020-01" "9d6c5bd3")) @@ -645,7 +629,7 @@ (testing "equals" (is (= #fhir/dateTime"2020-01-01" #fhir/dateTime"2020-01-01"))) (testing "instance size" - (is (= 40 (total-size #fhir/dateTime"2020-01-01")))) + (is (= 40 (mem/total-size #fhir/dateTime"2020-01-01")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/dateTime"2020-01-01" "39fe9bdb")) @@ -674,7 +658,7 @@ (is (= #fhir/dateTime"2020-01-01T00:00:00" #fhir/dateTime"2020-01-01T00:00:00"))) (testing "instance size" - (is (= 72 (total-size #fhir/dateTime"2020-01-01T00:00:00")))) + (is (= 72 (mem/total-size #fhir/dateTime"2020-01-01T00:00:00")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/dateTime"2020-01-01T00:00:00" "da537591")) @@ -701,7 +685,7 @@ (is (= #fhir/dateTime"2020-01-01T00:00:00.000" #fhir/dateTime"2020-01-01T00:00:00.000"))) (testing "instance size" - (is (= 72 (total-size #fhir/dateTime"2020-01-01T00:00:00.000")))) + (is (= 72 (mem/total-size #fhir/dateTime"2020-01-01T00:00:00.000")))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/dateTime"2020-01-01T00:00:00.000" "da537591")) @@ -728,8 +712,8 @@ (is (= #fhir/dateTime"2020-01-01T00:00:00Z" #fhir/dateTime"2020-01-01T00:00:00Z"))) (testing "instance size taking into account shared offsets" - (is (= 96 (- (total-size #fhir/dateTime"2020-01-01T00:00:00Z") - (total-size ZoneOffset/UTC))))) + (is (= 96 (- (mem/total-size #fhir/dateTime"2020-01-01T00:00:00Z") + (mem/total-size ZoneOffset/UTC))))) (testing "hash-into" (are [x hex] (= hex (murmur3 x)) #fhir/dateTime"2020-01-01T00:00:00Z" "d541a45")) @@ -880,7 +864,7 @@ nil)) (testing "instance size" - (is (= 24 (total-size #fhir/time"13:53:21"))))) + (is (= 24 (mem/total-size #fhir/time"13:53:21"))))) (def gender-extension @@ -956,8 +940,8 @@ (is (= "#fhir/code\"175718\"" (pr-str #fhir/code"175718")))) (testing "instance size" - (is (= 56 (total-size #fhir/code""))) - (is (= 64 (total-size #fhir/code"175718"))))) + (is (= 56 (mem/total-size #fhir/code""))) + (is (= 64 (mem/total-size #fhir/code"175718"))))) (deftest oid-test @@ -1000,8 +984,8 @@ (testing "instance size" (testing "instance size" - (is (= 56 (total-size #fhir/oid""))) - (is (= 64 (total-size #fhir/oid"175718")))))) + (is (= 56 (mem/total-size #fhir/oid""))) + (is (= 64 (mem/total-size #fhir/oid"175718")))))) (deftest id-test @@ -1043,8 +1027,8 @@ (is (= "#fhir/id\"175718\"" (pr-str #fhir/id"175718")))) (testing "instance size" - (is (= 56 (total-size #fhir/id""))) - (is (= 64 (total-size #fhir/id"175718"))))) + (is (= 56 (mem/total-size #fhir/id""))) + (is (= 64 (mem/total-size #fhir/id"175718"))))) (deftest markdown-test @@ -1087,8 +1071,8 @@ (is (= "#fhir/markdown\"175718\"" (pr-str #fhir/markdown"175718")))) (testing "instance size" - (is (= 56 (total-size #fhir/markdown""))) - (is (= 64 (total-size #fhir/markdown"175718"))))) + (is (= 56 (mem/total-size #fhir/markdown""))) + (is (= 64 (mem/total-size #fhir/markdown"175718"))))) (deftest unsignedInt-test @@ -1131,8 +1115,8 @@ (is (= "#fhir/unsignedInt 160845" (pr-str #fhir/unsignedInt 160845)))) (testing "instance size" - (is (= 16 (total-size #fhir/unsignedInt 0))) - (is (= 16 (total-size #fhir/unsignedInt 175718))))) + (is (= 16 (mem/total-size #fhir/unsignedInt 0))) + (is (= 16 (mem/total-size #fhir/unsignedInt 175718))))) (deftest positiveInt-test @@ -1175,8 +1159,8 @@ (is (= "#fhir/positiveInt 160845" (pr-str #fhir/positiveInt 160845)))) (testing "instance size" - (is (= 16 (total-size #fhir/positiveInt 0))) - (is (= 16 (total-size #fhir/positiveInt 175718))))) + (is (= 16 (mem/total-size #fhir/positiveInt 0))) + (is (= 16 (mem/total-size #fhir/positiveInt 175718))))) (deftest uuid-test @@ -1220,7 +1204,7 @@ nil)) (testing "instance size" - (is (= 32 (total-size #fhir/uuid"urn:uuid:6d270b7d-bf7d-4c95-8e30-4d87360d47a3"))))) + (is (= 32 (mem/total-size #fhir/uuid"urn:uuid:6d270b7d-bf7d-4c95-8e30-4d87360d47a3"))))) (def xhtml-element @@ -1267,8 +1251,8 @@ (is (= "#fhir/xhtml\"175718\"" (pr-str #fhir/xhtml"175718")))) (testing "instance size" - (is (= 56 (total-size #fhir/xhtml""))) - (is (= 64 (total-size #fhir/xhtml"175718"))))) + (is (= 56 (mem/total-size #fhir/xhtml""))) + (is (= 64 (mem/total-size #fhir/xhtml"175718"))))) (deftest attachment-test @@ -1316,7 +1300,7 @@ [])) (testing "instance size" - (is (= 72 (total-size #fhir/Attachment{})))) + (is (= 72 (mem/total-size #fhir/Attachment{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1359,7 +1343,7 @@ [])) (testing "instance size" - (is (= 48 (total-size #fhir/Extension{})))) + (is (= 48 (mem/total-size #fhir/Extension{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1400,7 +1384,7 @@ [])) (testing "instance size" - (is (= 56 (total-size #fhir/Coding{})))) + (is (= 56 (mem/total-size #fhir/Coding{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1435,7 +1419,7 @@ [])) (testing "instance size" - (is (= 48 (total-size #fhir/CodeableConcept{})))) + (is (= 48 (mem/total-size #fhir/CodeableConcept{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1479,7 +1463,7 @@ [])) (testing "instance size" - (is (= 56 (total-size #fhir/Quantity{})))) + (is (= 56 (mem/total-size #fhir/Quantity{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1514,7 +1498,7 @@ [])) (testing "instance size" - (is (= 48 (total-size #fhir/Period{})))) + (is (= 48 (mem/total-size #fhir/Period{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1561,7 +1545,7 @@ [])) (testing "instance size" - (is (= 64 (total-size #fhir/Identifier{})))) + (is (= 64 (mem/total-size #fhir/Identifier{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1569,6 +1553,130 @@ #fhir/Identifier{:id "212329"} "#fhir/Identifier{:id \"212329\"}"))) +(deftest human-name-test + (testing "type" + (is (= :fhir/HumanName (type/type #fhir/HumanName{})))) + + (testing "hash-into" + (are [x hex] (= hex (murmur3 x)) + #fhir/HumanName{} + "af56fc23" + + #fhir/HumanName{:id "id-130739"} + "ebba60f8" + + #fhir/HumanName{:extension [#fhir/Extension{}]} + "4947bc16" + + #fhir/HumanName{:use #fhir/code"use-155144"} + "60b2b58c" + + #fhir/HumanName{:text "text-212402"} + "b9ab5f61" + + #fhir/HumanName{:family "family-212422"} + "915831d8" + + #fhir/HumanName{:given ["given-212441"]} + "e26a58ee" + + #fhir/HumanName{:given ["given-212448" "given-212454"]} + "b46d5198" + + #fhir/HumanName{:prefix ["prefix-212514"]} + "1a411067" + + #fhir/HumanName{:prefix ["prefix-212523" "prefix-212525"]} + "32529f07" + + #fhir/HumanName{:suffix ["suffix-212542"]} + "3181f719" + + #fhir/HumanName{:suffix ["suffix-212547" "suffix-212554"]} + "69ca06e0" + + #fhir/HumanName{:period #fhir/Period{}} + "18b2a823")) + + (testing "references" + (are [x refs] (= refs (type/references x)) + #fhir/HumanName{} + [])) + + (testing "instance size" + (is (= 64 (mem/total-size #fhir/HumanName{})))) + + (testing "print" + (are [v s] (= s (pr-str v)) + #fhir/HumanName{} "#fhir/HumanName{}" + #fhir/HumanName{:id "212625"} "#fhir/HumanName{:id \"212625\"}"))) + + +(deftest address-test + (testing "type" + (is (= :fhir/Address (type/type #fhir/Address{})))) + + (testing "hash-into" + (are [x hex] (= hex (murmur3 x)) + #fhir/Address{} + "4a6b5e4f" + + #fhir/Address{:id "id-130739"} + "bd6a5731" + + #fhir/Address{:extension [#fhir/Extension{}]} + "2a3786e7" + + #fhir/Address{:use #fhir/code"use-155144"} + "b6cf1d48" + + #fhir/Address{:type #fhir/code"type-084442"} + "54c286c3" + + #fhir/Address{:text "text-212402"} + "15baed84" + + #fhir/Address{:line ["line-212441"]} + "eafac0f1" + + #fhir/Address{:line ["line-212448" "line-212454"]} + "62f4cf8f" + + #fhir/Address{:city "city-084705"} + "9765a1e9" + + #fhir/Address{:district "district-084717"} + "9e6dc6b8" + + #fhir/Address{:state "state-084729"} + "17a7640f" + + #fhir/Address{:postalCode "postalCode-084832"} + "8880561c" + + #fhir/Address{:country "country-084845"} + "57c51a7d" + + #fhir/Address{:period #fhir/Period{}} + "fb17905a")) + + (testing "references" + (are [x refs] (= refs (type/references x)) + #fhir/Address{} + [])) + + (testing "instance size" + (are [x size] (= size (mem/total-size x)) + #fhir/Address{} 80 + #fhir/Address{:text "text-212402"} 136 + #fhir/Address{:line ["line-212441"]} 200)) + + (testing "print" + (are [v s] (= s (pr-str v)) + #fhir/Address{} "#fhir/Address{}" + #fhir/Address{:id "084856"} "#fhir/Address{:id \"084856\"}"))) + + (deftest reference-test (testing "type" (is (= :fhir/Reference (type/type #fhir/Reference{})))) @@ -1625,7 +1733,7 @@ [["Patient" "0"] ["Patient" "1"]])) (testing "instance size" - (is (= 56 (total-size #fhir/Reference{})))) + (is (= 56 (mem/total-size #fhir/Reference{})))) (testing "print" (are [v s] (= s (pr-str v)) @@ -1651,7 +1759,7 @@ #fhir/Meta{:versionId #fhir/id"versionId-161415"} "9edaa9b" - (type/map->Meta {:lastUpdated Instant/EPOCH}) + (type/mk-meta {:lastUpdated Instant/EPOCH}) "38b8dfe3" #fhir/Meta{:source #fhir/uri"source-161629"} @@ -1680,7 +1788,14 @@ [["Patient" "2"]])) (testing "instance size" - (is (= 64 (total-size #fhir/Meta{})))) + (are [x size] (= size (mem/total-size x)) + #fhir/Meta{} 64 + #fhir/Meta{:profile [#fhir/canonical"foo"]} 192) + + (testing "two interned instances take the same memory as one" + (is (= 192 (mem/total-size #fhir/Meta{:profile [#fhir/canonical"foo"]} + #fhir/Meta{:profile [#fhir/canonical"foo"]}))))) + (testing "print" (are [v s] (= s (pr-str v)) @@ -1715,7 +1830,7 @@ [])) (testing "instance size" - (is (= 48 (total-size #fhir/BundleEntrySearch{})))) + (is (= 48 (mem/total-size #fhir/BundleEntrySearch{})))) (testing "print" (are [v s] (= s (pr-str v)) diff --git a/modules/fhir-structure/test/blaze/fhir/spec_test.clj b/modules/fhir-structure/test/blaze/fhir/spec_test.clj index 14a1a79d9..0d6ab8cd3 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec_test.clj @@ -3,6 +3,7 @@ [blaze.anomaly :as ba] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec-spec] + [blaze.fhir.spec.memory :as mem] [blaze.fhir.spec.type :as type] [blaze.test-util :as tu] [clojure.alpha.spec :as s2] @@ -61,14 +62,14 @@ {:fhir/type :fhir/Condition :id "id-204446" :meta #fhir/Meta - {:versionId #fhir/id"1" - :profile [#fhir/canonical"url-164445"]} + {:versionId #fhir/id"1" + :profile [#fhir/canonical"url-164445"]} :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-204435" - :code #fhir/code"code-204441"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"system-204435" + :code #fhir/code"code-204441"}]} :subject #fhir/Reference{:reference "Patient/id-145552"} :onset #fhir/dateTime"2020-01-30"}))) @@ -177,10 +178,10 @@ (is (= {:fhir/type :fhir/Observation :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"39156-5"}]}} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"39156-5"}]}} (fhir-spec/conform-json {:resourceType "Observation" :code {:coding [{:system "http://loinc.org" :code "39156-5"}]}})))) @@ -240,10 +241,10 @@ (is (= {:fhir/type :fhir/Observation :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"39156-5"}]}} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"39156-5"}]}} (conform-xml [::f/Observation [::f/code @@ -255,15 +256,15 @@ (is (= {:fhir/type :fhir/Patient :gender #fhir/code - {:extension - [#fhir/Extension - {:url "http://fhir.de/StructureDefinition/gender-amtlich-de" - :value - #fhir/Coding - {:system #fhir/uri"http://fhir.de/CodeSystem/gender-amtlich-de" - :code #fhir/code"D" - :display "divers"}}] - :value "other"}} + {:extension + [#fhir/Extension + {:url "http://fhir.de/StructureDefinition/gender-amtlich-de" + :value + #fhir/Coding + {:system #fhir/uri"http://fhir.de/CodeSystem/gender-amtlich-de" + :code #fhir/code"D" + :display "divers"}}] + :value "other"}} (conform-xml [:Patient [:gender @@ -338,10 +339,10 @@ {:fhir/type :fhir/Observation :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"39156-5"}]}} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"39156-5"}]}} "{\"code\":{\"coding\":[{\"system\":\"http://loinc.org\",\"code\":\"39156-5\"}]},\"resourceType\":\"Observation\"}")) (testing "Observation with valueQuantity" @@ -349,10 +350,10 @@ {:fhir/type :fhir/Observation :value #fhir/Quantity - {:value 36.6M - :unit "kg/m^2" - :system #fhir/uri"http://unitsofmeasure.org" - :code #fhir/code"kg/m2"}} + {:value 36.6M + :unit "kg/m^2" + :system #fhir/uri"http://unitsofmeasure.org" + :code #fhir/code"kg/m2"}} "{\"valueQuantity\":{\"value\":36.6,\"unit\":\"kg/m^2\",\"system\":\"http://unitsofmeasure.org\",\"code\":\"kg/m2\"},\"resourceType\":\"Observation\"}"))) @@ -367,7 +368,12 @@ (given (fhir-spec/conform-cbor {}) ::anom/category := ::anom/incorrect ::anom/message := "Invalid intermediate representation of a resource." - :x := {}))) + :x := {})) + + (testing "Patient" + (let [patient {:resourceType "Patient" + :name [{:given ["given-212441"]}]}] + (mem/print-total-layout (fhir-spec/conform-cbor patient))))) (defn- conform-unform-cbor [resource] @@ -405,20 +411,20 @@ {:fhir/type :fhir/Observation :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"39156-5"}]}})) + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"39156-5"}]}})) (testing "Observation with valueQuantity" (are [resource] (= resource (conform-unform-cbor resource)) {:fhir/type :fhir/Observation :value #fhir/Quantity - {:value 36.6M - :unit "kg/m^2" - :system #fhir/uri"http://unitsofmeasure.org" - :code #fhir/code"kg/m2"}}))) + {:value 36.6M + :unit "kg/m^2" + :system #fhir/uri"http://unitsofmeasure.org" + :code #fhir/code"kg/m2"}}))) (deftest unform-primitives-test @@ -477,15 +483,15 @@ {:fhir/type :fhir/Patient :gender #fhir/code - {:extension - [#fhir/Extension - {:url "http://fhir.de/StructureDefinition/gender-amtlich-de" - :value - #fhir/Coding - {:system #fhir/uri"http://fhir.de/CodeSystem/gender-amtlich-de" - :code #fhir/code"D" - :display "divers"}}] - :value "other"}})))) + {:extension + [#fhir/Extension + {:url "http://fhir.de/StructureDefinition/gender-amtlich-de" + :value + #fhir/Coding + {:system #fhir/uri"http://fhir.de/CodeSystem/gender-amtlich-de" + :code #fhir/code"D" + :display "divers"}}] + :value "other"}})))) (testing "Patient with Narrative" (let [xml (sexp [::f/Patient {:xmlns "http://hl7.org/fhir"} @@ -1143,6 +1149,35 @@ (sexp [nil {} [::f/creation {:value "2021"}]]))))) +(deftest extension-url-test + (testing "conforming" + (testing "JSON" + (testing "valid" + (are [json fhir] (= fhir (s2/conform :fhir.json.Extension/url json)) + "" "" + "url-103640" "url-103640")) + + (testing "invalid" + (are [json] (not (s2/valid? :fhir.json.Extension/url json)) + " " + 1)))) + + (testing "conformed instance size" + (testing "JSON" + (testing "two interned instances take the same memory as one" + (is (= (mem/total-size "foo") + (mem/total-size + (s2/conform :fhir.json.Extension/url (String. "foo")) + (s2/conform :fhir.json.Extension/url (String. "foo"))))))) + + (testing "CBOR" + (testing "two interned instances take the same memory as one" + (is (= (mem/total-size "foo") + (mem/total-size + (s2/conform :fhir.cbor.Extension/url (String. "foo")) + (s2/conform :fhir.cbor.Extension/url (String. "foo"))))))))) + + (deftest extension-test (testing "FHIR spec" (testing "valid" @@ -1178,6 +1213,23 @@ {:url "foo" :valueCodeableConcept {}} #fhir/Extension{:url "foo" :value #fhir/CodeableConcept{}}))) + (testing "conformed instance size" + (testing "JSON" + (are [json size] (= size (mem/total-size (s2/conform :fhir.json/Extension json))) + {} 48 + {:url "foo" :valueCode "bar"} 160) + + (testing "two instances have only the 48 byte instance overhead" + (is (= (+ (mem/total-size + (s2/conform :fhir.json/Extension + {:url "foo" :valueCode "bar"})) + 48) + (mem/total-size + (s2/conform :fhir.json/Extension + {:url (String. "foo") :valueCode "bar"}) + (s2/conform :fhir.json/Extension + {:url (String. "foo") :valueCode "bar"}))))))) + (testing "unforming" (testing "JSON" (are [fhir json] (= json (fhir-spec/parse-json (fhir-spec/unform-json fhir))) @@ -1206,10 +1258,10 @@ {:valueCodeableConcept {:text "text-104840"}} #fhir/Extension - {:value - #fhir/CodeableConcept - {:coding - [#fhir/Coding{:system #fhir/uri"system-105127"}]}} + {:value + #fhir/CodeableConcept + {:coding + [#fhir/Coding{:system #fhir/uri"system-105127"}]}} {:valueCodeableConcept {:coding [{:system "system-105127"}]}} #fhir/Extension{:value {:fhir/type :fhir/Annotation :text "text-105422"}} @@ -1238,10 +1290,10 @@ #fhir/Extension{:value #fhir/CodeableConcept{}} {:valueCodeableConcept {}} - #fhir/Extension{:value {:fhir/type :fhir/Address}} + #fhir/Extension{:value #fhir/Address{}} {:valueAddress {}} - #fhir/Extension{:value {:fhir/type :fhir/Address :city "foo"}} + #fhir/Extension{:value #fhir/Address{:city "foo"}} {:valueAddress {:city "foo"}})))) @@ -1262,6 +1314,16 @@ {:system "foo" :code "bar"} #fhir/Coding{:system #fhir/uri"foo" :code #fhir/code"bar"}))) + (testing "conformed instance size" + (testing "JSON" + (are [json size] (= size (mem/total-size (s2/conform :fhir.json/Coding json))) + {} 56 + {:system "foo" :code "bar"} 184) + + (testing "two interned instances take the same memory as one" + (is (= 184 (mem/total-size (s2/conform :fhir.json/Coding {:system "foo" :code "bar"}) + (s2/conform :fhir.json/Coding {:system "foo" :code "bar"}))))))) + (testing "unforming" (testing "JSON" (are [fhir json] (= json (fhir-spec/parse-json (fhir-spec/unform-json fhir))) @@ -1361,6 +1423,35 @@ {:text "text-223528"})))) +(deftest quantity-unit-test + (testing "conforming" + (testing "JSON" + (testing "valid" + (are [json fhir] (= fhir (s2/conform :fhir.json.Quantity/unit json)) + " " " " + "unit-103640" "unit-103640")) + + (testing "invalid" + (are [json] (not (s2/valid? :fhir.json.Quantity/unit json)) + "" + 1)))) + + (testing "conformed instance size" + (testing "JSON" + (testing "two interned instances take the same memory as one" + (is (= (mem/total-size "foo") + (mem/total-size + (s2/conform :fhir.json.Quantity/unit (String. "foo")) + (s2/conform :fhir.json.Quantity/unit (String. "foo"))))))) + + (testing "CBOR" + (testing "two interned instances take the same memory as one" + (is (= (mem/total-size "foo") + (mem/total-size + (s2/conform :fhir.cbor.Quantity/unit (String. "foo")) + (s2/conform :fhir.cbor.Quantity/unit (String. "foo"))))))))) + + (deftest quantity-test (testing "FHIR spec" (testing "valid" @@ -1554,6 +1645,248 @@ (sexp [nil {} [::f/assigner]]))))) +(deftest human-name-test + (testing "FHIR spec" + (testing "valid" + (are [x] (s2/valid? :fhir/HumanName x) + #fhir/HumanName{} + #fhir/HumanName{:use #fhir/code"usual"})) + + (testing "invalid" + (are [x] (not (s2/valid? :fhir/HumanName x)) + #fhir/HumanName{:use "usual"}))) + + (testing "conforming" + (testing "JSON" + (are [json fhir] (= fhir (s2/conform :fhir.json/HumanName json)) + {} + #fhir/HumanName{} + + {:use "usual"} + #fhir/HumanName{:use #fhir/code"usual"} + + {:given ["given-212441"]} + #fhir/HumanName{:given ["given-212441"]} + + {:use 1} + ::s2/invalid)) + + (testing "CBOR" + (are [cbor fhir] (= fhir (s2/conform :fhir.cbor/HumanName cbor)) + {} + #fhir/HumanName{} + + {:use "usual"} + #fhir/HumanName{:use #fhir/code"usual"} + + {:given ["given-212441"]} + #fhir/HumanName{:given ["given-212441"]}))) + + (testing "conformed instance size" + (testing "JSON" + (are [json size] (= size (mem/total-size (s2/conform :fhir.json/HumanName json))) + {} 64 + {:use "usual"} 128 + {:given ["given-212441"]} 184)) + + (testing "CBOR" + (are [cbor size] (= size (mem/total-size (s2/conform :fhir.cbor/HumanName cbor))) + {} 64 + {:use "usual"} 128 + {:given ["given-212441"]} 184))) + + (testing "unforming" + (testing "JSON" + (are [fhir json] (= json (fhir-spec/parse-json (fhir-spec/unform-json fhir))) + #fhir/HumanName{} + {} + + #fhir/HumanName{:id "id-155426"} + {:id "id-155426"} + + #fhir/HumanName{:extension [#fhir/Extension{}]} + {:extension [{}]} + + #fhir/HumanName{:extension [#fhir/Extension{} #fhir/Extension{}]} + {:extension [{} {}]} + + #fhir/HumanName{:use #fhir/code"use-155449"} + {:use "use-155449"} + + #fhir/HumanName{:text "text-141140"} + {:text "text-141140"} + + #fhir/HumanName{:family "family-141158"} + {:family "family-141158"} + + #fhir/HumanName{:given ["given-212441"]} + {:given ["given-212441"]} + + #fhir/HumanName{:given ["given-212448" "given-212454"]} + {:given ["given-212448" "given-212454"]} + + #fhir/HumanName{:period #fhir/Period{}} + {:period {}})) + + (testing "XML" + (are [fhir xml] (= xml (fhir-spec/unform-xml fhir)) + #fhir/HumanName{} + (sexp []) + + #fhir/HumanName{:id "id-155426"} + (sexp [nil {:id "id-155426"}]) + + #fhir/HumanName{:extension [#fhir/Extension{}]} + (sexp [nil {} [::f/extension]]) + + #fhir/HumanName{:extension [#fhir/Extension{} #fhir/Extension{}]} + (sexp [nil {} [::f/extension] [::f/extension]]) + + #fhir/HumanName{:use #fhir/code"use-155449"} + (sexp [nil {} [::f/use {:value "use-155449"}]]) + + #fhir/HumanName{:text "text-141140"} + (sexp [nil {} [::f/text {:value "text-141140"}]]) + + #fhir/HumanName{:family "family-141158"} + (sexp [nil {} [::f/family {:value "family-141158"}]]) + + #fhir/HumanName{:given ["given-212441"]} + (sexp [nil {} [::f/given {:value "given-212441"}]]) + + #fhir/HumanName{:given ["given-212441" "given-170006"]} + (sexp [nil {} + [::f/given {:value "given-212441"}] + [::f/given {:value "given-170006"}]]) + + #fhir/HumanName{:period #fhir/Period{}} + (sexp [nil {} [::f/period]]))))) + + +(deftest address-test + (testing "FHIR spec" + (testing "valid" + (are [x] (s2/valid? :fhir/Address x) + #fhir/Address{} + #fhir/Address{:use #fhir/code"usual"})) + + (testing "invalid" + (are [x] (not (s2/valid? :fhir/Address x)) + #fhir/Address{:use "usual"}))) + + (testing "conforming" + (testing "JSON" + (are [json fhir] (= fhir (s2/conform :fhir.json/Address json)) + {} + #fhir/Address{} + + {:use "usual"} + #fhir/Address{:use #fhir/code"usual"} + + {:use 1} + ::s2/invalid))) + + (testing "conformed instance size" + (are [json size] (= size (mem/total-size (s2/conform :fhir.json/Address json))) + {} 80 + {:extension [{:url "foo1foo1" :valueCode "bar"}]} 304 + {:extension [{:url (String. "foo") :valueCode (String. "bar")} + {:url (String. "foo") :valueCode (String. "bar")}]} 352 + {:text "text-212402"} 136 + {:line ["line-212441"]} 200)) + + (testing "unforming" + (testing "JSON" + (are [fhir json] (= json (fhir-spec/parse-json (fhir-spec/unform-json fhir))) + #fhir/Address{} + {} + + #fhir/Address{:id "id-155426"} + {:id "id-155426"} + + #fhir/Address{:extension [#fhir/Extension{}]} + {:extension [{}]} + + #fhir/Address{:extension [#fhir/Extension{} #fhir/Extension{}]} + {:extension [{} {}]} + + #fhir/Address{:use #fhir/code"use-155449"} + {:use "use-155449"} + + #fhir/Address{:text "text-170345"} + {:text "text-170345"} + + #fhir/Address{:line ["line-171433"]} + {:line ["line-171433"]} + + #fhir/Address{:line ["line-171433" "line-171857"]} + {:line ["line-171433" "line-171857"]} + + #fhir/Address{:city "city-171937"} + {:city "city-171937"} + + #fhir/Address{:district "district-171937"} + {:district "district-171937"} + + #fhir/Address{:state "state-171937"} + {:state "state-171937"} + + #fhir/Address{:postalCode "postalCode-171937"} + {:postalCode "postalCode-171937"} + + #fhir/Address{:country "country-171937"} + {:country "country-171937"} + + #fhir/Address{:period #fhir/Period{}} + {:period {}})) + + (testing "XML" + (are [fhir xml] (= xml (fhir-spec/unform-xml fhir)) + #fhir/Address{} + (sexp []) + + #fhir/Address{:id "id-155426"} + (sexp [nil {:id "id-155426"}]) + + #fhir/Address{:extension [#fhir/Extension{}]} + (sexp [nil {} [::f/extension]]) + + #fhir/Address{:extension [#fhir/Extension{} #fhir/Extension{}]} + (sexp [nil {} [::f/extension] [::f/extension]]) + + #fhir/Address{:use #fhir/code"use-155449"} + (sexp [nil {} [::f/use {:value "use-155449"}]]) + + #fhir/Address{:text "text-170345"} + (sexp [nil {} [::f/text {:value "text-170345"}]]) + + #fhir/Address{:line ["line-171433"]} + (sexp [nil {} [::f/line {:value "line-171433"}]]) + + #fhir/Address{:line ["line-171433" "line-171857"]} + (sexp [nil {} + [::f/line {:value "line-171433"}] + [::f/line {:value "line-171857"}]]) + + #fhir/Address{:city "city-171937"} + (sexp [nil {} [::f/city {:value "city-171937"}]]) + + #fhir/Address{:district "district-171937"} + (sexp [nil {} [::f/district {:value "district-171937"}]]) + + #fhir/Address{:state "state-171937"} + (sexp [nil {} [::f/state {:value "state-171937"}]]) + + #fhir/Address{:postalCode "postalCode-171937"} + (sexp [nil {} [::f/postalCode {:value "postalCode-171937"}]]) + + #fhir/Address{:country "country-171937"} + (sexp [nil {} [::f/country {:value "country-171937"}]]) + + #fhir/Address{:period #fhir/Period{}} + (sexp [nil {} [::f/period]]))))) + + (deftest reference-test (testing "FHIR spec" (testing "valid" @@ -1614,7 +1947,7 @@ (are [x] (s2/valid? :fhir/Meta x) #fhir/Meta{} #fhir/Meta{:versionId #fhir/id"1"} - (type/map->Meta {:lastUpdated Instant/EPOCH}))) + (type/mk-meta {:lastUpdated Instant/EPOCH}))) (testing "invalid" (are [x] (not (s2/valid? :fhir/Meta x)) @@ -1633,7 +1966,17 @@ ::s2/invalid {:lastUpdated "1970-01-01T00:00:00Z"} - (type/map->Meta {:lastUpdated Instant/EPOCH})))) + (type/mk-meta {:lastUpdated Instant/EPOCH})))) + + (testing "conformed instance size" + (are [json size] (= size (mem/total-size (s2/conform :fhir.json/Meta json))) + {} 64 + {:versionId "1"} 128 + {:profile ["foo"]} 192) + + (testing "two interned instances take the same memory as one" + (is (= 192 (mem/total-size (s2/conform :fhir.json/Meta {:profile ["foo"]}) + (s2/conform :fhir.json/Meta {:profile ["foo"]})))))) (testing "unforming" (testing "JSON" @@ -1656,7 +1999,7 @@ #fhir/Meta{:versionId #fhir/id"versionId-161812"} {:versionId "versionId-161812"} - (type/map->Meta {:lastUpdated Instant/EPOCH}) + (type/mk-meta {:lastUpdated Instant/EPOCH}) {:lastUpdated "1970-01-01T00:00:00Z"} #fhir/Meta{:source #fhir/uri"source-162704"} From 2f85de14eb5aea6e028b2049a9242d2c748ddb1a Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Mon, 7 Mar 2022 14:41:18 +0100 Subject: [PATCH 12/14] Update Dependencies --- .github/workflows/build.yml | 38 +++++++++---------- deps.edn | 2 +- modules/byte-string/deps.edn | 4 +- modules/cql/.clj-kondo/config.edn | 1 - modules/cql/deps.edn | 2 +- modules/db-tx-log-kafka/.clj-kondo/config.edn | 1 - modules/db/.clj-kondo/config.edn | 1 - modules/fhir-structure/deps.edn | 4 +- modules/kv/deps.edn | 2 +- modules/luid/deps.edn | 2 +- modules/page-store/deps.edn | 2 +- 11 files changed, 28 insertions(+), 31 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c1b5f22a2..82a01f7c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,10 +22,10 @@ jobs: - name: Setup clj-kondo uses: DeLaGuardo/setup-clj-kondo@master with: - version: '2022.02.09' + version: '2022.03.04' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Lint run: make lint @@ -84,10 +84,10 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - tools-deps: '1.10.3.1082' + tools-deps: '1.10.3.1087' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Local Maven Repo uses: actions/cache@v2 @@ -115,10 +115,10 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - tools-deps: '1.10.3.1082' + tools-deps: '1.10.3.1087' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Local Maven Repo uses: actions/cache@v2 @@ -157,10 +157,10 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - tools-deps: '1.10.3.1082' + tools-deps: '1.10.3.1087' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Local Maven Repo uses: actions/cache@v2 @@ -185,10 +185,10 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - tools-deps: '1.10.3.1082' + tools-deps: '1.10.3.1087' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Local Maven Repo uses: actions/cache@v2 @@ -267,7 +267,7 @@ jobs: steps: - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Blazectl run: .github/scripts/install-blazectl.sh @@ -456,7 +456,7 @@ jobs: steps: - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Blazectl run: .github/scripts/install-blazectl.sh @@ -502,7 +502,7 @@ jobs: steps: - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Blazectl run: .github/scripts/install-blazectl.sh @@ -552,10 +552,10 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - tools-deps: '1.10.3.1082' + tools-deps: '1.10.3.1087' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Local Maven Repo uses: actions/cache@v2 @@ -600,7 +600,7 @@ jobs: steps: - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v1 @@ -633,7 +633,7 @@ jobs: steps: - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Blazectl run: .github/scripts/install-blazectl.sh @@ -854,10 +854,10 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - tools-deps: '1.10.3.1082' + tools-deps: '1.10.3.1087' - name: Check out Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache Local Maven Repo uses: actions/cache@v2 diff --git a/deps.edn b/deps.edn index 55f9263ea..403e48352 100644 --- a/deps.edn +++ b/deps.edn @@ -78,7 +78,7 @@ :outdated {:replace-deps {com.github.liquidz/antq - {:mvn/version "1.5.1"} + {:mvn/version "1.6.0"} org.slf4j/slf4j-nop {:mvn/version "1.7.36"}} diff --git a/modules/byte-string/deps.edn b/modules/byte-string/deps.edn index 4cb431a2f..9ac9f3901 100644 --- a/modules/byte-string/deps.edn +++ b/modules/byte-string/deps.edn @@ -2,10 +2,10 @@ :deps {com.google.guava/guava - {:mvn/version "31.0.1-jre"} + {:mvn/version "31.1-jre"} com.google.protobuf/protobuf-java {:mvn/version "3.19.4"} com.fasterxml.jackson.core/jackson-databind - {:mvn/version "2.13.1"}}} + {:mvn/version "2.13.2"}}} diff --git a/modules/cql/.clj-kondo/config.edn b/modules/cql/.clj-kondo/config.edn index 394336cfb..3df2868d4 100644 --- a/modules/cql/.clj-kondo/config.edn +++ b/modules/cql/.clj-kondo/config.edn @@ -10,7 +10,6 @@ blaze.elm.compiler.macros/defaggop clojure.core/defn blaze.elm.compiler.macros/defbinopp clojure.core/defn blaze.elm.compiler.macros/defunopp clojure.core/defn - clojure.test.check.properties/for-all clojure.core/let prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/cql/deps.edn b/modules/cql/deps.edn index d66e97223..727563329 100644 --- a/modules/cql/deps.edn +++ b/modules/cql/deps.edn @@ -5,7 +5,7 @@ {:local/root "../db"} com.fasterxml.jackson.module/jackson-module-jaxb-annotations - {:mvn/version "2.13.1"} + {:mvn/version "2.13.2"} info.cqframework/cql-to-elm {:mvn/version "1.5.6" diff --git a/modules/db-tx-log-kafka/.clj-kondo/config.edn b/modules/db-tx-log-kafka/.clj-kondo/config.edn index 300ebe3db..93c8e7136 100644 --- a/modules/db-tx-log-kafka/.clj-kondo/config.edn +++ b/modules/db-tx-log-kafka/.clj-kondo/config.edn @@ -1,7 +1,6 @@ {:lint-as {blaze.anomaly/when-ok clojure.core/let blaze.test-util/with-system clojure.core/with-open - clojure.test.check.properties/for-all clojure.core/let prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/db/.clj-kondo/config.edn b/modules/db/.clj-kondo/config.edn index bf3019a30..bc9cf5fbf 100644 --- a/modules/db/.clj-kondo/config.edn +++ b/modules/db/.clj-kondo/config.edn @@ -5,7 +5,6 @@ blaze.db.impl.db/with-open-coll clojure.core/with-open blaze.db.test-util/with-system-data clojure.core/with-open blaze.test-util/with-system clojure.core/with-open - clojure.test.check.properties/for-all clojure.core/let prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/fhir-structure/deps.edn b/modules/fhir-structure/deps.edn index f5cf15789..45e616ea6 100644 --- a/modules/fhir-structure/deps.edn +++ b/modules/fhir-structure/deps.edn @@ -14,10 +14,10 @@ {:mvn/version "3.0.5"} com.google.guava/guava - {:mvn/version "31.0.1-jre"} + {:mvn/version "31.1-jre"} com.fasterxml.jackson.dataformat/jackson-dataformat-cbor - {:mvn/version "2.13.1"} + {:mvn/version "2.13.2"} com.taoensso/timbre {:mvn/version "5.1.2"} diff --git a/modules/kv/deps.edn b/modules/kv/deps.edn index de59a1234..27bfdb70d 100644 --- a/modules/kv/deps.edn +++ b/modules/kv/deps.edn @@ -3,7 +3,7 @@ {:local/root "../module-base"} com.google.guava/guava - {:mvn/version "31.0.1-jre"}} + {:mvn/version "31.1-jre"}} :aliases {:test diff --git a/modules/luid/deps.edn b/modules/luid/deps.edn index 8233f049e..8c466b5ed 100644 --- a/modules/luid/deps.edn +++ b/modules/luid/deps.edn @@ -3,7 +3,7 @@ {:local/root "../spec"} com.google.guava/guava - {:mvn/version "31.0.1-jre"}} + {:mvn/version "31.1-jre"}} :aliases {:test diff --git a/modules/page-store/deps.edn b/modules/page-store/deps.edn index 81157f7fc..2c7a08da9 100644 --- a/modules/page-store/deps.edn +++ b/modules/page-store/deps.edn @@ -14,7 +14,7 @@ {:mvn/version "3.0.5"} com.google.guava/guava - {:mvn/version "31.0.1-jre"}} + {:mvn/version "31.1-jre"}} :aliases {:test From 56c02ba94e2399973002be35e70e6eb493300efb Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Mon, 7 Mar 2022 15:02:58 +0100 Subject: [PATCH 13/14] Use Simple Symbols for Protocol Methods Generating code using syntax quote appends the current namespace to simple symbols. However protocol methods should not contain any namespace in reify or defrecord. So we have to use syntax unquote and quote here. --- modules/cql/src/blaze/elm/compiler/macros.clj | 26 +++++++++---------- .../src/blaze/fhir/spec/type/macros.clj | 8 +++--- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/modules/cql/src/blaze/elm/compiler/macros.clj b/modules/cql/src/blaze/elm/compiler/macros.clj index f0d62d2e9..632baa81d 100644 --- a/modules/cql/src/blaze/elm/compiler/macros.clj +++ b/modules/cql/src/blaze/elm/compiler/macros.clj @@ -22,11 +22,11 @@ ~expr-binding expr#] ~@body) (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~operand-binding (core/-eval operand# context# resource# scope#) ~expr-binding expr#] ~@body)) - (-form [~'_] + (~'-form [~'_] (list (quote ~name) (core/-form operand#))))))) `(defmethod core/compile* ~(compile-kw name) [context# expr#] @@ -35,10 +35,10 @@ (let [~operand-binding operand#] ~@body) (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~operand-binding (core/-eval operand# context# resource# scope#)] ~@body)) - (-form [~'_] + (~'-form [~'_] (list (quote ~name) (core/-form operand#)))))))))) @@ -58,11 +58,11 @@ ~op-2-binding operand-2#] ~@body) (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) ~op-2-binding (core/-eval operand-2# context# resource# scope#)] ~@body)) - (-form [~'_] + (~'-form [~'_] (list (quote ~name) (core/-form operand-1#) (core/-form operand-2#))))))))) @@ -75,7 +75,7 @@ operand-2# (core/compile* context# operand-2#) operand-3# (core/compile* context# operand-3#)] (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) ~op-2-binding (core/-eval operand-2# context# resource# scope#) ~op-3-binding (core/-eval operand-3# context# resource# scope#)] @@ -89,7 +89,7 @@ [context# {operands# :operand}] (let [operands# (mapv #(core/compile* context# %) operands#)] (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~operands-binding (mapv #(core/-eval % context# resource# scope#) operands#)] ~@body)))))) @@ -101,7 +101,7 @@ [context# {source# :source}] (let [source# (core/compile* context# source#)] (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~source-binding (core/-eval source# context# resource# scope#)] ~@body)))))) @@ -115,10 +115,10 @@ ~precision-binding (some-> precision# core/to-chrono-unit) ~(or expr-binding '_) expr#] (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~operand-binding (core/-eval operand# context# resource# scope#)] ~@body)) - (-form [~'_] + (~'-form [~'_] (list (quote ~name) (core/-form operand#) precision#)))))) @@ -140,11 +140,11 @@ ~precision-binding chrono-precision#] ~@body) (reify core/Expression - (-eval [~'_ context# resource# scope#] + (~'-eval [~'_ context# resource# scope#] (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) ~op-2-binding (core/-eval operand-2# context# resource# scope#) ~precision-binding chrono-precision#] ~@body)) - (-form [~'_] + (~'-form [~'_] (list (quote ~name) (core/-form operand-1#) (core/-form operand-2#) precision#)))))))) diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj b/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj index cc74d055b..60318ec62 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type/macros.clj @@ -38,8 +38,6 @@ `(.serialize ~(with-meta serializer {:tag `JsonSerializer}) ~x ~gen ~provider)) -(comment (serialize 's 1 'g 'p)) - (defmacro defcomplextype [name [& fields] & {:keys [fhir-type hash-num references field-serializers]}] (let [sink-sym (gensym "sink") @@ -49,8 +47,8 @@ `(do (defrecord ~name [~@fields] p/FhirType - (-type [~'_] ~(or fhir-type (keyword "fhir" (str name)))) - (-hash-into [~'_ ~sink-sym] + (~'-type [~'_] ~(or fhir-type (keyword "fhir" (str name)))) + (~'-hash-into [~'_ ~sink-sym] (.putByte ~sink-sym-tag (byte ~hash-num)) ~@(map-indexed (fn [idx field] @@ -60,7 +58,7 @@ ~field ~sink-sym))) fields)) ~(or references - `(-references [~'_] + `(~'-references [~'_] (-> (transient []) ~@(keep (fn [field] From 87b90dcd4b6c7026d1f71d6c415f9143d952f151 Mon Sep 17 00:00:00 2001 From: Alexander Kiel Date: Mon, 7 Mar 2022 15:55:56 +0100 Subject: [PATCH 14/14] Release v0.16.1 --- CHANGELOG.md | 11 +++++++++++ README.md | 4 ++-- docs/deployment/docker-deployment.md | 4 ++-- docs/deployment/manual-deployment.md | 12 ++++++------ docs/performance/fhir-search.md | 2 +- modules/rest-api/src/blaze/rest_api/capabilities.clj | 2 +- perf-test/gatling/pom.xml | 2 +- pom.xml | 2 +- src/blaze/system.clj | 2 +- 9 files changed, 26 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4629100e7..56092ac3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v0.16.1 + +### Performance Improvements + +* Improve CQL Quantity Creation ([#621](https://github.com/samply/blaze/pull/621)) +* Improve FHIRPath Performance ([#617](https://github.com/samply/blaze/pull/617)) +* Intern Uri, Canonical, Code, Coding and CodeableConcept ([#628](https://github.com/samply/blaze/pull/628)) +* Use Records For HumanName and Address, Intern Meta ([#633](https://github.com/samply/blaze/pull/633)) + +The full changelog can be found [here](https://github.com/samply/blaze/milestone/31?closed=1). + ## v0.16.0 ### New Features diff --git a/README.md b/README.md index 679e10b16..013783a52 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The goal of this project is to provide a FHIR® Store with an internal CQL Evalu Blaze passes all [Touchstone FHIR 4.0.1 Basic Tests][12] and almost all [CQL Tests][3]. Please refer to the [Conformance](docs/conformance.md) section and report any issues you encounter during evaluation. -Latest release: [v0.16.0][5] +Latest release: [v0.16.1][5] ## Quick Start @@ -72,7 +72,7 @@ Unless required by applicable law or agreed to in writing, software distributed [3]: [4]: -[5]: +[5]: [6]: [7]: [8]: diff --git a/docs/deployment/docker-deployment.md b/docs/deployment/docker-deployment.md index 187b84747..81ecd161d 100644 --- a/docs/deployment/docker-deployment.md +++ b/docs/deployment/docker-deployment.md @@ -27,7 +27,7 @@ Blaze should log something like this: 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:64] - JVM version: 16.0.2 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:65] - Maximum available memory: 1738 MiB 2021-06-27T11:02:37.835Z ee086ef908c1 main INFO [blaze.core:66] - Number of available processors: 8 -2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.16.0 in 8.2 seconds +2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.16.1 in 8.2 seconds ``` In order to test connectivity, query the health endpoint: @@ -47,7 +47,7 @@ that should return: ```json { "name": "Blaze", - "version": "0.16.0" + "version": "0.16.1" } ``` diff --git a/docs/deployment/manual-deployment.md b/docs/deployment/manual-deployment.md index e6e7e0d3e..375dfa0b3 100644 --- a/docs/deployment/manual-deployment.md +++ b/docs/deployment/manual-deployment.md @@ -2,12 +2,12 @@ The installation works under Windows, Linux and macOS. The only dependency is an installed OpenJDK 11. Blaze is tested with [AdoptOpenJDK][1]. -Blaze runs on the JVM and comes as single JAR file. Download the most recent version [here](https://github.com/samply/blaze/releases/tag/v0.16.0). Look for `blaze-0.16.0-standalone.jar`. +Blaze runs on the JVM and comes as single JAR file. Download the most recent version [here](https://github.com/samply/blaze/releases/tag/v0.16.1). Look for `blaze-0.16.1-standalone.jar`. After the download, you can start blaze with the following command (Linux, macOS): ```sh -java -jar blaze-0.16.0-standalone.jar -m blaze.core +java -jar blaze-0.16.1-standalone.jar -m blaze.core ``` Blaze will run with an in-memory, volatile database for testing and demo purposes. @@ -17,14 +17,14 @@ Blaze can be run with durable storage by setting the environment variables `STOR Under Linux/macOS: ```sh -STORAGE=standalone java -jar blaze-0.16.0-standalone.jar -m blaze.core +STORAGE=standalone java -jar blaze-0.16.1-standalone.jar -m blaze.core ``` Under Windows, you need to set the Environment variables in the PowerShell before starting Blaze: ```powershell $Env:STORAGE="standalone" -java -jar blaze-0.16.0-standalone.jar -m blaze.core +java -jar blaze-0.16.1-standalone.jar -m blaze.core ``` This will create three directories called `index`, `transaction` and `resource` inside the current working directory, one for each database part used. @@ -42,7 +42,7 @@ The output should look like this: 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:64] - JVM version: 16.0.2 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:65] - Maximum available memory: 1738 MiB 2021-06-27T11:02:37.835Z ee086ef908c1 main INFO [blaze.core:66] - Number of available processors: 8 -2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.16.0 in 8.2 seconds +2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.16.1 in 8.2 seconds ``` In order to test connectivity, query the health endpoint: @@ -62,7 +62,7 @@ that should return: ```json { "name": "Blaze", - "version": "0.16.0" + "version": "0.16.1" } ``` diff --git a/docs/performance/fhir-search.md b/docs/performance/fhir-search.md index 71fef2a3c..34c548512 100644 --- a/docs/performance/fhir-search.md +++ b/docs/performance/fhir-search.md @@ -46,7 +46,7 @@ blazectl download --server http://localhost:8080/fhir Observation -q "code=http: | E5-2687W v4 | 128 | 4 | 1 | 29 M | 28 M | 29463-7 | 1.3 M | 35 | | E5-2687W v4 | 128 | 30 | 10 | 292 M | 278 M | 17861-6 | 1.7 M | 48 | | E5-2687W v4 | 128 | 30 | 10 | 292 M | 278 M | 39156-5 | 9.7 M | 284 | -| E5-2687W v4 | 128 | 40 | 10 | 292 M | 278 M | 29463-7 | 13 M | 410 | +| E5-2687W v4 | 128 | 30 | 10 | 292 M | 278 M | 29463-7 | 13 M | 410 | According to the measurements the time needed by Blaze to deliver resources only depends on the number of hits and equals roughly in **30 seconds per 1 million hits**. diff --git a/modules/rest-api/src/blaze/rest_api/capabilities.clj b/modules/rest-api/src/blaze/rest_api/capabilities.clj index e00386c61..1a1b37652 100644 --- a/modules/rest-api/src/blaze/rest_api/capabilities.clj +++ b/modules/rest-api/src/blaze/rest_api/capabilities.clj @@ -111,7 +111,7 @@ :copyright #fhir/markdown"Copyright 2019 - 2022 The Samply Community\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License." :kind #fhir/code"instance" - :date #fhir/dateTime"2022-02-21" + :date #fhir/dateTime"2022-03-07" :software {:name "Blaze" :version version} diff --git a/perf-test/gatling/pom.xml b/perf-test/gatling/pom.xml index f69c0f731..9bf6d6d88 100644 --- a/perf-test/gatling/pom.xml +++ b/perf-test/gatling/pom.xml @@ -5,7 +5,7 @@ samply.blaze gatling - 0.16.0 + 0.16.1 1.8 diff --git a/pom.xml b/pom.xml index 008b98077..ee69ef74c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 samply blaze - 0.16.0 + 0.16.1 blaze A FHIR Store with internal, fast CQL Evaluation Engine diff --git a/src/blaze/system.clj b/src/blaze/system.clj index be83a64f4..c91fe850e 100644 --- a/src/blaze/system.clj +++ b/src/blaze/system.clj @@ -85,7 +85,7 @@ (def ^:private root-config - {:blaze/version "0.16.0" + {:blaze/version "0.16.1" :blaze/clock {}