Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: strings API fns #438

Closed
wants to merge 56 commits into from
Closed
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
70550ec
Update deps to latest compatible versions
cap10morgan Mar 10, 2023
212c95b
Update to malli 0.10.4
cap10morgan Mar 23, 2023
549d8e6
Use string keys & @context only in json-ld.api fns
cap10morgan Mar 23, 2023
c135a44
Add some more kw->string key fixes
cap10morgan Mar 23, 2023
438e6d7
Fix history query schema
cap10morgan Mar 23, 2023
5e8d740
Add transaction & query result schemas
cap10morgan Mar 23, 2023
e68ef93
Fix history query results schema
cap10morgan Mar 26, 2023
b414b8b
stringified context - subject crawl reparse
dpetran Mar 23, 2023
0c5b74b
Merge branch 'main' into feature/strings-api
cap10morgan Apr 7, 2023
f1e42b7
Update some tests for strings-api changes
cap10morgan Apr 10, 2023
b295854
Fix list containers for strings-api
cap10morgan Apr 10, 2023
57a76cf
Fix more analytical query handling for strings-api
cap10morgan Apr 10, 2023
c065ba9
Update query response formatting for strings-api
cap10morgan Apr 10, 2023
84d0294
Fix simple subj crawl queries for strings-api
cap10morgan Apr 10, 2023
d96e21c
Reformat dev/user.clj
cap10morgan Apr 10, 2023
a8e11a8
Fix indentation of f.d.query.jld.resp/flakes->res
cap10morgan Apr 10, 2023
3d8a0b9
Use {"defaults" {"@context" ...}} in ledger create too
cap10morgan Apr 11, 2023
0307fd4
Fix sequential context schema
cap10morgan Apr 11, 2023
6fa009e
Add basic transact opts schema
cap10morgan Apr 11, 2023
a98bcb4
Fix commit opts transformation bug
cap10morgan Apr 11, 2023
845852a
Update history query tests for strings-api
cap10morgan Apr 11, 2023
dfbd0f8
Fix issues in history queries surfaced by tests
cap10morgan Apr 11, 2023
b3982f8
Merge branch 'main' into feature/strings-api
cap10morgan Apr 11, 2023
dd8aa8b
Allow single result vec in query responses
cap10morgan Apr 11, 2023
1a3ba7e
Put most common query result type first in schema
cap10morgan Apr 12, 2023
7c13475
Convert policy code to use string compact IRIs
cap10morgan Apr 14, 2023
697e8c5
Stringify delete-where transactions
cap10morgan Apr 17, 2023
3c8a142
Use :list for jld.transact/list-value?
cap10morgan Apr 17, 2023
01966d5
Use "@list" instead of "list" in tests
cap10morgan Apr 17, 2023
7384f33
Stringify most query tests
cap10morgan Apr 17, 2023
4a5347c
Stringify transact tests
cap10morgan Apr 17, 2023
f0d8dc1
Stringify SHACL tests
cap10morgan Apr 17, 2023
6d38c58
Fix result formatting
dpetran Apr 17, 2023
79df9e8
Convert transact test to use strings api
dpetran Apr 17, 2023
61efbd2
Merge branch 'main' into feature/strings-api
cap10morgan Apr 17, 2023
1cc45b2
Remove unneeded ExceptionInfo import
cap10morgan Apr 17, 2023
cd7b20c
Change "context" to "@context" in JS tests
cap10morgan Apr 18, 2023
e3e68bb
Use constants for a couple of things in f.d.db.json-ld
cap10morgan Apr 18, 2023
493556e
Use keyword keys internally for queries
cap10morgan Apr 18, 2023
378cf8d
Update deps to latest compatible versions
cap10morgan Apr 18, 2023
9e9a6e4
Correct bad defmulti indentation
cap10morgan Apr 18, 2023
6ae337f
Fix json-ld.api-test indentation
cap10morgan Apr 20, 2023
f0d42bb
Add Clojure SDK basics & tests
cap10morgan Apr 20, 2023
2418301
Remove old comment in test
cap10morgan Apr 20, 2023
3e11f79
Merge branch 'feature/clojure-sdk' into feature/strings-api
cap10morgan Apr 20, 2023
e5aa705
Humanize query validation errors
cap10morgan Apr 20, 2023
507e548
Allow map values in contexts
cap10morgan Apr 20, 2023
a8a0ffc
Use @set instead of set in container specifier in a test
cap10morgan Apr 20, 2023
e4f29a7
Reconcile query arities between db protocol & API
cap10morgan Apr 20, 2023
b19e945
Add support for multi-queries in CLJ SDK
cap10morgan Apr 20, 2023
caffde5
Add history queries to CLJ SDK & tests
cap10morgan Apr 20, 2023
5a42c08
Merge branch 'main' into feature/strings-api
cap10morgan Apr 21, 2023
aee6833
Merge branch 'main' into feature/strings-api
cap10morgan Apr 21, 2023
ea1588b
Stringify new policy subj-flakes test
cap10morgan Apr 21, 2023
54e972f
Fix default context comparison in a test
cap10morgan Apr 21, 2023
7c502a1
Fix default context comparison in another test
cap10morgan Apr 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
byte-streams/byte-streams {:mvn/version "0.2.4"}
cheshire/cheshire {:mvn/version "5.11.0"}
instaparse/instaparse {:mvn/version "1.4.12"}
metosin/malli {:mvn/version "0.9.2"}
metosin/malli {:mvn/version "0.10.4"}
com.fluree/json-ld {:git/url "https://github.com/fluree/json-ld.git"
:sha "a909330e33196504ef8a5411aaa0409ab72aaa35"}

;; logging
org.clojure/tools.logging {:mvn/version "1.2.4"}
ch.qos.logback/logback-classic {:mvn/version "1.4.5"}
org.slf4j/slf4j-api {:mvn/version "2.0.5"}
org.slf4j/slf4j-api {:mvn/version "2.0.6"}

;; Lucene
clucie/clucie {:mvn/version "0.4.2"}
Expand All @@ -43,23 +43,23 @@

:aliases
{:build
{:deps {io.github.clojure/tools.build {:git/tag "v0.8.5"
:git/sha "b73ff34"}
{:deps {io.github.clojure/tools.build {:git/tag "v0.9.4"
:git/sha "b0ee58b"}
slipset/deps-deploy {:mvn/version "0.2.0"}}
:ns-default build}

:dev
{:extra-paths ["dev" "test" "dev-resources" "src-cljs" "src-nodejs" "src-docs"]
:extra-deps {org.clojure/tools.namespace {:mvn/version "1.3.0"}
:extra-deps {org.clojure/tools.namespace {:mvn/version "1.4.2"}
criterium/criterium {:mvn/version "0.4.6"}
figwheel-sidecar/figwheel-sidecar {:mvn/version "0.5.20"}
thheller/shadow-cljs {:mvn/version "2.20.12"}
com.magnars/test-with-files {:mvn/version "2021-02-17"}}}
thheller/shadow-cljs {:mvn/version "2.22.0"}
com.magnars/test-with-files {:mvn/version "2021-02-17"}}}

:cljtest
{:extra-paths ["test" "dev-resources"]
:extra-deps {lambdaisland/kaocha {:mvn/version "1.71.1119"}
org.clojure/test.check {:mvn/version "1.1.1"}
:extra-deps {lambdaisland/kaocha {:mvn/version "1.80.1274"}
org.clojure/test.check {:mvn/version "1.1.1"}
io.github.cap10morgan/test-with-files {:git/tag "v1.0.0"
:git/sha "9181a2e"}}
:exec-fn kaocha.runner/exec-fn
Expand Down Expand Up @@ -91,20 +91,20 @@
:main-opts ["-m" "cloverage.coverage" "-p" "src" "-s" "test" "--output" "scanning_results/coverage"]}

:eastwood
{:extra-deps {jonase/eastwood {:mvn/version "1.3.0"}}
:main-opts ["-m" "eastwood.lint"
{:source-paths ["src" "src-docs"]
:test-paths ["test"]
;; TODO: Un-exclude this when it stops triggering false
;; positives on "UnsupportedOperationException empty is
;; not supported on Flake" when using the #Flake data
;; reader - WSM 2023-02-01
:exclude-linters [:implicit-dependencies]}]}
{:extra-deps {jonase/eastwood {:mvn/version "1.3.0"}}
:main-opts ["-m" "eastwood.lint"
{:source-paths ["src" "src-docs"]
:test-paths ["test"]
;; TODO: Un-exclude this when it stops triggering false
;; positives on "UnsupportedOperationException empty is
;; not supported on Flake" when using the #Flake data
;; reader - WSM 2023-02-01
:exclude-linters [:implicit-dependencies]}]}

:ancient
{:extra-deps {com.github.liquidz/antq {:mvn/version "RELEASE"}}
:main-opts ["-m" "antq.core"]}

:clj-kondo
{:extra-deps {clj-kondo/clj-kondo {:mvn/version "2022.11.02"}}
{:extra-deps {clj-kondo/clj-kondo {:mvn/version "2023.02.17"}}
:main-opts ["-m" "clj-kondo.main" "--lint" "src" "--config" ".clj-kondo/config.edn"]}}}
56 changes: 28 additions & 28 deletions dev/user.clj
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"8ce4eca704d653dec594703c81a84c403c39f262e54ed014ed857438933a2e1c")


(def did (did/private->did-map default-private-key ))
(def did (did/private->did-map default-private-key))

(def default-context
{:id "@id"
Expand All @@ -71,37 +71,37 @@
(def ledger @(fluree/create file-conn "user/test"))

(def db1 @(fluree/stage
(fluree/db ledger)
[{:context {:ex "http://example.org/ns/"}
:id :ex/brian,
:type :ex/User,
:schema/name "Brian"
:schema/email "[email protected]"
:schema/age 50
:ex/favNums 7
}
{:context {:ex "http://example.org/ns/"}
:id :ex/alice,
:type :ex/User,
:schema/name "Alice"
:schema/email "[email protected]"
:schema/age 50
:ex/favNums [42, 76, 9]
}
{:context {:ex "http://example.org/ns/"}
:id :ex/cam,
:type :ex/User,
:schema/name "Cam"
:schema/email "[email protected]"
:schema/age 34
:ex/favNums [5, 10]
:ex/friend [:ex/brian :ex/alice]}]))
(fluree/db ledger)
[{:context {:ex "http://example.org/ns/"}
:id :ex/brian,
:type :ex/User,
:schema/name "Brian"
:schema/email "[email protected]"
:schema/age 50
:ex/favNums 7}

{:context {:ex "http://example.org/ns/"}
:id :ex/alice,
:type :ex/User,
:schema/name "Alice"
:schema/email "[email protected]"
:schema/age 50
:ex/favNums [42, 76, 9]}

{:context {:ex "http://example.org/ns/"}
:id :ex/cam,
:type :ex/User,
:schema/name "Cam"
:schema/email "[email protected]"
:schema/age 34
:ex/favNums [5, 10]
:ex/friend [:ex/brian :ex/alice]}]))

(def db2 @(fluree/commit! ledger db1 {:message "hi"}))

@(fluree/load file-conn (-> ledger :alias))
@(fluree/load file-conn (-> ledger :alias)))


)

;; TODO - general
;; if an subject is a component, do we allow it to be explicitly assigned as a ref to another component?
Expand Down
156 changes: 77 additions & 79 deletions src/fluree/db/api/query.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[fluree.db.query.range :as query-range]
[fluree.db.util.core :as util]
[fluree.db.util.async :as async-util :refer [<? go-try]]
[fluree.db.util.log :as log]
[fluree.db.json-ld.policy :as perm]
[fluree.db.json-ld.credential :as cred]))

Expand All @@ -23,15 +24,15 @@
(pr-str query-map))
{:status 400
:error :db/invalid-query}))

(let [{:keys [opts]} query-map
(let [{:strs [opts]} query-map
db* (if-let [policy-opts (perm/policy-opts opts)]
(<? (perm/wrap-policy db policy-opts))
db)
{:keys [context history t commit-details] :as _parsed} (history/history-query-parser query-map)
{:strs [context history t commit-details] :as parsed} (history/history-query-parser query-map)
_ (log/debug "parsed history query:" parsed)

;; from and to are positive ints, need to convert to negative or fill in default values
{:keys [from to at]} t
{:strs [from to at]} t
[from-t to-t] (if at
(let [t (cond (= "latest" at) (:t db*)
(string? at) (<? (time-travel/datetime->t db* at))
Expand All @@ -55,18 +56,18 @@
flake-slice-ch (query-range/time-range db* idx = pattern {:from-t from-t :to-t to-t})
flake-ch (async/chan 1 cat)

_ (async/pipe flake-slice-ch flake-ch)
_ (async/pipe flake-slice-ch flake-ch)

flakes (async/<! (async/into [] flake-ch))
flakes (async/<! (async/into [] flake-ch))

history-results-chan (history/history-flakes->json-ld db* parsed-context error-ch flakes)]

(if commit-details
;; annotate with commit details
(async/alt!
(async/into [] (history/add-commit-details db* parsed-context error-ch history-results-chan))
([result] result)
error-ch ([e] e))
(async/into [] (history/add-commit-details db* parsed-context error-ch history-results-chan))
([result] result)
error-ch ([e] e))

;; we're already done
(async/alt!
Expand All @@ -84,13 +85,12 @@
"Execute a query against a database source, or optionally
additional sources if the query spans multiple data sets.
Returns core async channel containing result or exception."
[sources query]
[sources {:strs [opts t] :as query}]
(go-try
(let [{query :subject, issuer :issuer}
(or (<? (cred/verify query))
{:subject query})

{:keys [opts t]} query
db (if (async-util/channel? sources) ;; only support 1 source currently
(<? sources)
sources)
Expand All @@ -105,16 +105,34 @@
(assoc-in [:policy :cache] (atom {})))
opts* (-> opts
(assoc :issuer issuer)
(dissoc :meta))
(dissoc "meta"))
start #?(:clj (System/nanoTime)
:cljs (util/current-time-millis))
result (<? (fql/query db** (assoc query :opts opts*)))]
(if (:meta opts)
{:status 200
:result result
:time (util/response-time-formatted start)}
result (<? (fql/query db** (assoc query "opts" opts*)))]
(if (get opts "meta")
{"status" 200
"result" result
"time" (util/response-time-formatted start)}
result))))

(defn- multi-query-map
"Processes each query in a multi-query and associates them into `m` under the
`alias` key. `global-opts` is first so closures can be created around that for
the whole multi-query."
[global-opts m alias query]
(let [query-opts (get query "opts")
_ (when (perm/policy-opts query-opts)
(throw (ex-info "Applying policy via `:opts` on individual queries in a multi-query is not supported."
{:status 400
:error :db/invalid-query})))
query-meta (get query-opts "meta")
default-meta (get global-opts "meta")
meta? (or default-meta query-meta)
remove-meta? (and meta? (not query-meta)) ;; query didn't ask for meta, but multiquery did so must strip it
opts* {"meta" meta? ::remove-meta? remove-meta?}
query* (assoc query "opts" opts*)]
(assoc m alias query*)))

(defn multi-query
"Performs multiple queries in a map, with the key being the alias for the query
and the value being the query itself. Each query result will be in a response
Expand All @@ -132,67 +150,47 @@
- errors - map of query alias to their respective error"
[source flureeQL]
(go-try
(let [global-opts (:opts flureeQL)
db (if-let [policy-opts (perm/policy-opts global-opts)]
(let [global-opts (get flureeQL "opts")
db (if-let [policy-opts (perm/policy-opts global-opts)]
(<? (perm/wrap-policy source policy-opts))
source)
global-context-type (:context-type global-opts)

global-meta (:meta global-opts) ;; if true, need to collect meta for each query to total up
;; update individual queries for :meta if not otherwise specified
queries (reduce-kv
(fn [acc alias query]
(let [query-opts (:opts query)]
(if-let [policy-opts (perm/policy-opts query-opts)]
(throw (ex-info "Applying policy via `:opts` on individual queries in a multi-query is not supported."
{:status 400
:error :db/invalid-query}))
(let [query-meta (:meta query-opts)
context-type (-> query-opts
:context-type
(or global-context-type))
meta? (or global-meta query-meta)
remove-meta? (and meta? (not query-meta)) ;; query didn't ask for meta, but multiquery did so must strip it
opts* (-> (:opts query)
(assoc :meta meta? :-remove-meta? remove-meta?)
(cond-> context-type (assoc :context-type context-type)))
query* (assoc query :opts opts*)]
(assoc acc alias query*)))))
{} (dissoc flureeQL :opts))
start-time #?(:clj (System/nanoTime) :cljs (util/current-time-millis))
;; kick off all queries in parallel, each alias now mapped to core async channel
pending-resp (map (fn [[alias q]] [alias (query db q)]) queries)]
(loop [[[alias port] & r] pending-resp
status-global nil ;; overall status.
response {}]
(if (nil? port) ;; done?
(if global-meta
{:result response
:status status-global
:time (util/response-time-formatted start-time)}
response)
(let [{:keys [meta -remove-meta?]} (get-in queries [alias :opts])
res (async/<! port)
error? (:error res) ;; if error key is present in response, it is an error
status-global* (when meta
(let [status (:status res)]
(cond
(nil? status-global)
status

(= status-global status)
status

;; any 200 response with any other is a 207
(or (= 200 status) (= 200 status-global) (= 207 status-global))
207

;; else take the max status
:else
(max status status-global))))
response* (if error?
(assoc-in response [:errors alias] res)
(assoc response alias (if -remove-meta?
(:result res)
res)))]
(recur r status-global* response*)))))))
queries (reduce-kv (partial multi-query-map global-opts)
{} (dissoc flureeQL "opts"))
_ (log/debug "multi-query queries:" queries)
start-time #?(:clj (System/nanoTime) :cljs (util/current-time-millis))
;; kick off all queries in parallel, each alias now mapped to core async channel
pending-resp (map (fn [[alias q]] [alias (query db q)]) queries)]
(loop [[[alias port] & r] pending-resp
status-global nil ;; overall status.
response {}]
(if (nil? port) ;; done?
(if (get global-opts "meta")
{"result" response
"status" status-global
"time" (util/response-time-formatted start-time)}
response)
(let [{:strs [meta] remove-meta? ::remove-meta?} (get-in queries [alias "opts"])
res (async/<! port)
error? (:error res) ;; if error key is present in response, it is an error
status-global* (when meta
(let [status (get res "status")]
(cond
(nil? status-global)
status

(= status-global status)
status

;; any 200 response with any other is a 207
(or (= 200 status) (= 200 status-global) (= 207 status-global))
207

;; else take the max status
:else
(max status status-global))))
response* (if error?
(assoc-in response ["errors" alias] res)
(assoc response alias (if remove-meta?
(get res "result")
res)))]
(recur r status-global* response*)))))))
Loading