diff --git a/src/metabase/driver/cubejs.clj b/src/metabase/driver/cubejs.clj index 73994b7..d8adaf4 100644 --- a/src/metabase/driver/cubejs.clj +++ b/src/metabase/driver/cubejs.clj @@ -9,9 +9,6 @@ [metabase.driver.cubejs.query-processor :as cubejs.qp] [toucan.db :as db])) -;; Is there any better? https://github.com/metabase/metabase/blob/master/src/metabase/types.clj#L81 -(def cubejs-time->metabase-type - :type/DateTime) ;; In case of a full table query the granularity is :default so we have to change it manually. (def default-cubejs-granularity @@ -27,11 +24,6 @@ [measure metrics] (some (fn [metric] (= (:name measure) (:name metric))) metrics)) -(def json-type->base-type - {:string :type/Text - :number :type/Float - :time cubejs-time->metabase-type}) - (defn- get-cubes "Get all the cubes from the Cube.js REST API." [database] @@ -47,8 +39,8 @@ {:name (:name field) :database-type (:type field) :field-comment type - :base-type (json-type->base-type (keyword (:type field)))} - (if (= (:type field) cubejs-time->metabase-type) {:special-type :type/CreationTime})))) + :base-type (cube.utils/json-type->base-type (keyword (:type field)))} + (if (= (:type field) cube.utils/cubejs-time->metabase-type) {:special-type :type/CreationTime})))) (defn- get-field "Returns the name and the type for the given field ID." diff --git a/src/metabase/driver/cubejs/query_processor.clj b/src/metabase/driver/cubejs/query_processor.clj index 0b6b2ff..b0450ec 100644 --- a/src/metabase/driver/cubejs/query_processor.clj +++ b/src/metabase/driver/cubejs/query_processor.clj @@ -4,7 +4,30 @@ [cheshire.core :as json] [metabase.driver.cubejs.utils :as cube.utils])) +(defn- get-types + "Extract the types for each field in the response from the annotation block." + [annotation] + (into {} + (for [fields (vals annotation)] + (into {} + (for [[name info] fields] + {name ((keyword (:type info)) cube.utils/json-type->base-type)}))))) + +(defn- update-row-values + [row cols] + (reduce-kv + (fn [row key val] + (assoc row key (if (some #(= key %) cols) (cube.utils/string->number val) val))) {} row)) + +(defn- convert-values + "Convert the values in the rows to the correct type." + [rows types] + ;; Get the number fields from the types. + (let [num-cols (map first (filter #(= (second %) :type/Number) types))] + (map #(update-row-values % num-cols) rows))) + (defn- extract-fields + "Extract the values from the map and returns them as a list." [rows fields] (for [row rows] (for [field fields] @@ -14,6 +37,9 @@ (let [query (if (:query native-query) (if (:mbql? native-query) (json/generate-string (:query native-query)) (:query native-query))) resp (cube.utils/make-request "v1/load" query nil) rows (:data (:body resp)) + annotation (:annotation (:body resp)) + types (get-types annotation) + rows (convert-values rows types) cols (if (:aggregation? native-query) (keys (first rows))) result (if (:aggregation? native-query) {:columns cols :rows (extract-fields rows cols)} {:rows (for [row rows] (into (ordered-map/ordered-map) row))})] result)) \ No newline at end of file diff --git a/src/metabase/driver/cubejs/utils.clj b/src/metabase/driver/cubejs/utils.clj index 52ed696..e479efb 100644 --- a/src/metabase/driver/cubejs/utils.clj +++ b/src/metabase/driver/cubejs/utils.clj @@ -3,6 +3,21 @@ [metabase.query-processor.store :as qp.store] [clj-http.client :as client])) + +;; Is there any better? https://github.com/metabase/metabase/blob/master/src/metabase/types.clj#L81 +(def cubejs-time->metabase-type + :type/DateTime) + +(def json-type->base-type + {:string :type/Text + :number :type/Number + :time cubejs-time->metabase-type}) + +(defn string->number + "Convert the string to Long or Double." + [string] + (if (.contains string ".") (Double/parseDouble string) (Long/parseLong string))) + (defn- get-cube-api-url "Returns the Cube.js API URL from the config." []