Skip to content
Snippets Groups Projects
Unverified Commit d551db35 authored by github-automation-metabase's avatar github-automation-metabase Committed by GitHub
Browse files

[QP] Fix query caching for pivot queries (#48962) (#49028)


This was throwing errors trying to `nippy/freeze!` an Atom.

That was because in certain circumstances a pMBQL query can end up in
`(:json_query metadata)` for a query, and those can contain an atom
due to `metabase.lib.cache` and both `CachedMetadataProvider` and
`InvocationTracker`.

I added `lib.query/serializable` as a single location to strip out
anything that isn't serializable, such as atoms. (And the entire
`:lib/metadata`, which is a wasted effort to serialize.)

Co-authored-by: default avatarBraden Shepherdson <braden@metabase.com>
parent ba76c841
Branches
Tags
No related merge requests found
......@@ -62,6 +62,13 @@
(not (contains? mmeta :lib/__cache))
(assoc :lib/__cache (Collections/synchronizedMap (WeakHashMap.))))))))
(defn discard-query-cache
"Removes the cache from the given query. Does nothing if no cache is present."
[query]
#?(:cljs query
:clj (when query
(vary-meta query dissoc :lib/__cache))))
(defn- side-channel-cache*
"(CLJS only; this is a pass-through in CLJ.)
......
......@@ -421,3 +421,12 @@
[a-query stage-number card-id f & args]
(let [{q :query, n :stage-number} (wrap-native-query-with-mbql a-query stage-number card-id)]
(apply f q n args)))
(defn serializable
"Given a query, ensure it doesn't have any keys or structures that aren't safe for serialization.
For example, any Atoms or Delays or should be removed."
[a-query]
(-> a-query
(dissoc a-query :lib/metadata)
lib.cache/discard-query-cache))
......@@ -11,6 +11,7 @@
[java-time.api :as t]
[medley.core :as m]
[metabase.config :as config]
[metabase.lib.query :as lib.query]
[metabase.public-settings :as public-settings]
[metabase.query-processor.middleware.cache-backend.db :as backend.db]
[metabase.query-processor.middleware.cache-backend.interface :as i]
......@@ -57,7 +58,8 @@
"Add `object` (e.g. a result row or metadata) to the current cache entry."
[object]
(when *in-fn*
(*in-fn* object)))
(*in-fn* (cond-> object
(map? object) (m/update-existing :json_query lib.query/serializable)))))
(def ^:private ^:dynamic *result-fn*
"The `result-fn` provided by [[impl/do-with-serialization]]."
......@@ -136,7 +138,7 @@
(let [normal-format? (and (map? (unreduced result))
(seq (get-in (unreduced result) [:data :cols])))
result* (-> (if normal-format?
(merge-with merge @final-metadata (unreduced result))
(m/deep-merge @final-metadata (unreduced result))
(unreduced result))
(assoc :cache/details {:hash query-hash :cached true :updated_at last-ran}))]
(rf (cond-> result*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment