From f041c24d0fec4e19e8bfb6037bde1506dea28615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cam=20Sau=CC=88l?= <cammsaul@gmail.com> Date: Tue, 7 Jul 2015 01:31:29 -0700 Subject: [PATCH] associate default-fields directly on entity --- src/metabase/db.clj | 11 ++--------- src/metabase/models/interface.clj | 16 ++++++++++++---- src/metabase/models/query_execution.clj | 16 +--------------- src/metabase/models/user.clj | 15 +++------------ 4 files changed, 18 insertions(+), 40 deletions(-) diff --git a/src/metabase/db.clj b/src/metabase/db.clj index 93ef900232e..4112655f812 100644 --- a/src/metabase/db.clj +++ b/src/metabase/db.clj @@ -253,13 +253,6 @@ ;; ## SEL -(defmulti default-fields - "The default fields that should be used for ENTITY by calls to `sel` if none are specified." - identity) - -(defmethod default-fields :default [_] - nil) ; by default return nil, which we'll take to mean "everything" - (defmacro sel "Wrapper for korma `select` that calls `post-select` on results and provides a few other conveniences. @@ -374,8 +367,8 @@ `(let [[entity# field-keys#] (destructure-entity ~entity) ; pull out field-keys if passed entity vector like `[entity & field-keys]` entity# (entity->korma entity#) ; entity## is the actual entity like `metabase.models.user/User` that we can dispatch on entity-select-form# (-> entity# ; entity-select-form# is the tweaked version we'll pass to korma `select` - (assoc :fields (or field-keys# - (default-fields entity#))))] ; tell korma which fields to grab. If `field-keys` weren't passed in vector do lookup at runtime + (assoc :fields (or field-keys# ; tell korma which fields to grab. If `field-keys` weren't passed in vector do lookup at runtime + (:metabase.models.interface/default-fields entity#))))] (when (config/config-bool :mb-db-logging) (log/debug "DB CALL: " (:name entity#) (or (:fields entity-select-form#) "*") diff --git a/src/metabase/models/interface.clj b/src/metabase/models/interface.clj index e60cda9709d..85d79df5db2 100644 --- a/src/metabase/models/interface.clj +++ b/src/metabase/models/interface.clj @@ -1,5 +1,6 @@ (ns metabase.models.interface - (:require [clojure.tools.logging :as log] + (:require (clojure.tools [logging :as log] + [macro :refer [macrolet]]) [clojure.walk :refer [macroexpand-all]] [korma.core :as k] [medley.core :as m] @@ -44,7 +45,9 @@ (when (metabase.config/config-bool :mb-db-logging) (clojure.tools.logging/debug "DB CALL: " (:name entity) id))) - (let [[obj] (k/select entity (k/where {:id id}) (k/limit 1))] + (let [[obj] (k/select (assoc entity :fields (::default-fields entity)) + (k/where {:id id}) + (k/limit 1))] (when obj (->> obj (internal-post-select entity) @@ -56,14 +59,19 @@ [`(~k ~obj) `(update-in [~k] ~f)]) (seq kvs)))) +(defmacro macrolet-entity-map [entity & entity-forms] + `(macrolet [(~'default-fields [m# & fields#] `(assoc ~m# ::default-fields [~@(map keyword fields#)])) + (~'hydration-keys [m# & fields#] `(assoc ~m# :hydration-keys #{~@(map keyword fields#)}))] + (-> (k/create-entity ~(name entity)) + ~@entity-forms))) + (defmacro defentity "Similar to korma `defentity`, but creates a new record type where you can specify protocol implementations." [entity entity-forms & specs] {:pre [vector? entity-forms]} (let [entity-symb (symbol (format "%sEntity" (name entity))) internal-post-select-symb (symbol (format "internal-post-select-%s" (name entity))) - entity-map (eval `(-> (k/create-entity ~(name entity)) - ~@entity-forms)) + entity-map (eval `(macrolet-entity-map ~entity ~@entity-forms)) type-fns (resolve-type-fns (:metabase.db/types entity-map))] `(do (defrecord ~entity-symb [] diff --git a/src/metabase/models/query_execution.clj b/src/metabase/models/query_execution.clj index 60f2beac7a1..57dfb1258ea 100644 --- a/src/metabase/models/query_execution.clj +++ b/src/metabase/models/query_execution.clj @@ -9,6 +9,7 @@ (defentity QueryExecution [(table :query_queryexecution) + (default-fields id uuid version json_query raw_query status started_at finished_at running_time error result_rows) (types {:json_query :json :result_data :json :status :keyword})] @@ -18,18 +19,3 @@ ;; sadly we have 2 ways to reference the row count :( (assoc query-execution :row_count (or result_rows 0)))) - -;; default fields to return for `sel QueryExecution -;; specifically excludes stored data columns -(defmethod default-fields QueryExecution [_] - [:id - :uuid - :version - :json_query - :raw_query - :status - :started_at - :finished_at - :running_time - :error - :result_rows]) diff --git a/src/metabase/models/user.clj b/src/metabase/models/user.clj index 38c2be4ac72..6052aa650aa 100644 --- a/src/metabase/models/user.clj +++ b/src/metabase/models/user.clj @@ -10,25 +10,16 @@ (defentity User [(table :core_user) - (assoc :hydration-keys #{:author :creator :user})] + (default-fields id email date_joined first_name last_name last_login is_superuser) + (hydration-keys author creator user)] IEntityPostSelect (post-select [_ user] (assoc user :common_name (str (:first_name user) " " (:last_name user))))) -;; fields to return for Users other `*than current-user*` -(defmethod default-fields User [_] - [:id - :email - :date_joined - :first_name - :last_name - :last_login - :is_superuser]) - (def ^:const current-user-fields "The fields we should return for `*current-user*` (used by `metabase.middleware.current-user`)" - (concat (default-fields User) + (concat (:metabase.models.interface/default-fields User) [:is_active :is_staff])) ; but not `password` ! -- GitLab