├── README.md ├── csv ├── project.clj ├── resources │ └── metabase-plugin.yaml ├── src │ └── metabase │ │ └── driver │ │ └── csv.clj └── test │ └── metabase │ └── driver │ └── csv_test.clj ├── release └── csv.metabase-driver.jar └── samples ├── animais.csv ├── animals.csv └── pessoas.csv /README.md: -------------------------------------------------------------------------------- 1 | # csv-metabase-driver 2 | A CSV [metabase](https://www.metabase.com) driver based on incredible [csvjdbc](http://csvjdbc.sourceforge.net) driver. I've been [modified it](https://github.com/Markenson/csvjdbc4metabase) to work with metabase. 3 | 4 | # Installation 5 | Put [this file](https://github.com/Markenson/csv-metabase-driver/releases/download/v1.3.1/csv.metabase-driver.jar) on your metabase/plugins directory and restart Metabase. You'll see a CSV driver option on database creation. 6 | 7 | You could see [this video](https://youtu.be/M4ccnTXiDtw) too. 8 | 9 | # How to configure it 10 | Check [how to load a CSV file by filesystem](https://github.com/Markenson/csv-metabase-driver/issues/1) and [how to load a CSV file by HTTP](https://github.com/Markenson/csv-metabase-driver/releases/tag/1.1.0) for more information. 11 | 12 | If your data contains **date values** check [this video](https://youtu.be/qrTux2jIwns). 13 | 14 | Maybe you want to see [this one](https://youtu.be/pMiIXPaelyg) about data types. 15 | 16 | # If you need built it 17 | 18 | ## with ansible 19 | 20 | follow [these instructions](https://github.com/Markenson/dev-env/blob/main/README.md#to-build-csv-metabase-driver) 21 | 22 | ## by hand 23 | 24 | read and understand steps below 25 | 26 | [steps for install clojure](https://github.com/Markenson/dev-env/blob/main/roles/clojure/tasks/main.yaml) 27 | 28 | [steps for compile driver](https://github.com/Markenson/dev-env/blob/main/roles/csv-metabase-driver/tasks/main.yaml) 29 | -------------------------------------------------------------------------------- /csv/project.clj: -------------------------------------------------------------------------------- 1 | (defproject metabase/csv-driver "1.0.1-SNAPSHOT" 2 | :min-lein-version "2.5.0" 3 | 4 | :repositories {"sonatype snapshots" "https://oss.sonatype.org/content/repositories/snapshots"} 5 | :dependencies 6 | [[br.com.markenson/csvjdbc "1.3.1-metabase-SNAPSHOT"]] 7 | 8 | :profiles 9 | {:provided 10 | {:dependencies [[metabase-core "1.0.0-SNAPSHOT"]]} 11 | 12 | :uberjar 13 | {:auto-clean true 14 | :aot :all 15 | :javac-options ["-target" "1.8", "-source" "1.8"] 16 | :target-path "target/%s" 17 | :uberjar-name "csv.metabase-driver.jar"}}) 18 | -------------------------------------------------------------------------------- /csv/resources/metabase-plugin.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | name: Metabase CSV Driver 3 | version: 1.0.0-SNAPSHOT 4 | description: Allows Metabase to connect to CSV files. 5 | driver: 6 | name: csv 7 | display-name: CSV 8 | lazy-load: true 9 | parent: sql-jdbc 10 | connection-properties: 11 | - name: csv 12 | display-name: Directory 13 | placeholder: /dir/with/csv/files 14 | required: true 15 | - name: separator 16 | display-name: Separator 17 | - name: charset 18 | display-name: Charset 19 | - name: advanced 20 | display-name: Advanced 21 | init: 22 | - step: load-namespace 23 | namespace: metabase.driver.csv 24 | - step: register-jdbc-driver 25 | class: org.relique.jdbc.csv.CsvDriver 26 | -------------------------------------------------------------------------------- /csv/src/metabase/driver/csv.clj: -------------------------------------------------------------------------------- 1 | (ns metabase.driver.csv 2 | (:require [clj-time 3 | [coerce :as tcoerce] 4 | [format :as tformat]] 5 | [clojure.string :as str] 6 | [honeysql 7 | [core :as hsql] 8 | [format :as hformat]] 9 | [metabase 10 | [config :as config] 11 | [driver :as driver]] 12 | [metabase.driver 13 | [common :as driver.common] 14 | [sql :as sql]] 15 | [clojure.java.jdbc :as jdbc] 16 | [metabase.driver.sql-jdbc 17 | [connection :as sql-jdbc.conn] 18 | [sync :as sql-jdbc.sync]] 19 | [metabase.driver.sql.query-processor :as sql.qp] 20 | [metabase.util 21 | [date-2 :as du] 22 | [honeysql-extensions :as hx]] 23 | [schema.core :as s]) 24 | (:import [java.sql Time Timestamp] 25 | [java.util Calendar])) 26 | 27 | (def ^:private database-type->base-type 28 | (sql-jdbc.sync/pattern-based-database-type->base-type 29 | [ 30 | [#"String" :type/Text] 31 | [#"Asciistream" :type/Text] 32 | [#"BigDecimal" :type/Decimal] 33 | [#"Boolean" :type/Boolean] 34 | [#"Byte" :type/Byte] 35 | [#"Date" :type/Date] 36 | [#"Double" :type/Float] 37 | [#"Float" :type/Float] 38 | [#"Integer" :type/Integer] 39 | [#"Long" :type/BigInteger] 40 | [#"Short" :type/Integer] 41 | [#"String" :type/String] 42 | [#"Timestamp" :type/DateTime] 43 | [#"Time" :type/Time] 44 | ])) 45 | 46 | (defn week-of-year 47 | [date] 48 | (let [cal (Calendar/getInstance)] 49 | (.setTime cal (.toDate date)) 50 | (.get cal Calendar/WEEK_OF_YEAR))) 51 | 52 | (defmethod sql.qp/date [:csv :day] [_ _ expr] (hsql/call :substring expr 1 10)) 53 | (defmethod sql.qp/date [:csv :month] [_ _ expr] (hsql/call :substring expr 1 7)) 54 | (defmethod sql.qp/date [:csv :year] [_ _ expr] (hsql/call :year expr)) 55 | (defmethod sql.qp/date [:csv :second] [_ _ expr] (hsql/call :substring expr 1 10)) 56 | (defmethod sql.qp/date [:csv :minute] [_ _ expr] (hsql/call :substring expr 1 16)) 57 | (defmethod sql.qp/date [:csv :hour] [_ _ expr] (hsql/call :substring expr 1 13)) 58 | (defmethod sql.qp/date [:csv :hour-of-day] [_ _ expr] (hsql/call :substring expr 1 13)) 59 | (defmethod sql.qp/date [:csv :week] [_ _ expr] (:week-of-year expr)) 60 | 61 | (defmethod sql-jdbc.sync/database-type->base-type :csv [_ database-type] 62 | (database-type->base-type database-type)) 63 | 64 | 65 | (defn is-http [path] (if (clojure.string/starts-with? (clojure.string/lower-case path) "http") true false)) 66 | 67 | (defmethod sql-jdbc.conn/connection-details->spec :csv [_ {:keys [csv separator charset advanced] 68 | :or {csv "arquivo.csv"} 69 | :as details}] 70 | 71 | (def strHttp (if (is-http csv) ":class:br.markenson.com.csvjdbc4metabase.readers.HttpCSVReader" "")) 72 | 73 | (def customBaseUrl (if (is-http csv) (str "&customBaseUrl=" csv) "")) 74 | 75 | (merge {:classname "org.relique.jdbc.csv.CsvDriver" 76 | :subprotocol (str "relique:csv" strHttp) 77 | :subname (str (if (is-http csv) "" csv) "?separator=" separator "&charset=" charset customBaseUrl advanced) 78 | } 79 | (dissoc details :csv :separator :charset :customBaseUrl :advanced)) 80 | 81 | ) 82 | -------------------------------------------------------------------------------- /csv/test/metabase/driver/csv_test.clj: -------------------------------------------------------------------------------- 1 | (ns metabase.driver.csv-test 2 | (:require [expectations :refer [expect]] 3 | [metabase.test.data.datasets :refer [expect-with-driver]] 4 | [metabase.test.util :as tu])) 5 | 6 | (expect-with-driver :csv 7 | "UTC" 8 | (tu/db-timezone-id)) 9 | -------------------------------------------------------------------------------- /release/csv.metabase-driver.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Markenson/csv-metabase-driver/be96ef447e6a9615c832481f850fdf5906cd4d1b/release/csv.metabase-driver.jar -------------------------------------------------------------------------------- /samples/animais.csv: -------------------------------------------------------------------------------- 1 | id^nome^sexo 2 | 1^sol^F 3 | 2^maia^F 4 | 3^freddie^M -------------------------------------------------------------------------------- /samples/animals.csv: -------------------------------------------------------------------------------- 1 | id^name^sex^daily_needs^birthday 2 | 1^sol^F^4^17/02/2018 3 | 2^maia^F^3^30/05/2019 4 | 3^freddie^M^2^08/10/2019 5 | -------------------------------------------------------------------------------- /samples/pessoas.csv: -------------------------------------------------------------------------------- 1 | id^nome^sexo 2 | 1^joao^M 3 | 2^maria^F 4 | 3^jose^M --------------------------------------------------------------------------------