Logic related to fetching and working with the connection details for the application database. These are provided by
environment variables -- either as a single JDBC connection URL string ( There are three ways you can specify application JDBC connection information for Metabase:
This namespace exposes the vars [[db-type]] and [[data-source]] based on the aforementioned environment variables. Normally you should use the equivalent functions in [[metabase.db.connection]] which can be overridden rather than using this namespace directly. | (ns metabase.db.env (:require [clojure.java.io :as io] [clojure.string :as str] [metabase.config :as config] [metabase.db.data-source :as mdb.data-source] [metabase.util :as u] [metabase.util.log :as log] [metabase.util.malli :as mu])) |
(set! *warn-on-reflection* true) | |
[[env->db-type]] | |
(defn- raw-connection-string->type [s] (when (seq s) (when-let [[_protocol subprotocol] (re-find #"^(?:jdbc:)?([^:]+):" s)] (condp = subprotocol "postgresql" :postgres (keyword subprotocol))))) | |
(mu/defn- env->db-type :- [:enum :postgres :mysql :h2] [{:keys [mb-db-connection-uri mb-db-type]}] (or (some-> mb-db-connection-uri raw-connection-string->type) mb-db-type)) | |
[[env->DataSource]] | |
Takes a filename and converts it to H2-compatible filename. | (defn- get-db-file [db-file-name] ;; H2 wants file path to always be absolute (str "file:" (.getAbsolutePath (io/file db-file-name)))) |
(defn- env->db-file [{:keys [mb-db-in-memory mb-db-file]}] (if mb-db-in-memory ;; In-memory (i.e. test) DB "mem:metabase" ;; File-based DB (get-db-file mb-db-file))) | |
(def ^:private h2-connection-properties ;; see https://h2database.com/html/features.html for explanation of options {;; DB_CLOSE_DELAY=-1 = don't close the Database until the JVM shuts down :DB_CLOSE_DELAY -1 ;; we need to enable MVCC for Quartz JDBC backend to work! Quartz depends on row-level locking, which means without ;; MVCC we "will experience dead-locks". MVCC is the default for everyone using the MVStore engine anyway so this ;; only affects people still with legacy PageStore databases :MVCC true ;; Tell H2 to defrag when Metabase is shut down -- can reduce DB size by multiple GIGABYTES -- see #6510 :DEFRAG_ALWAYS true ;; LOCK_TIMEOUT=60000 = wait up to one minute to acquire table lock instead of default of 1 second :LOCK_TIMEOUT 60000}) | |
Connection details that can be used when pretending the Metabase DB is itself a | (defn- broken-out-details [db-type {:keys [mb-db-dbname mb-db-host mb-db-pass mb-db-port mb-db-user mb-db-azure-managed-identity-client-id] :as env-vars}] (if (= db-type :h2) (assoc h2-connection-properties :db (env->db-file env-vars)) {:host mb-db-host :port mb-db-port :db mb-db-dbname :user mb-db-user :password mb-db-pass :azure-managed-identity-client-id mb-db-azure-managed-identity-client-id})) |
(defn- env->DataSource [db-type {:keys [mb-db-connection-uri mb-db-user mb-db-pass mb-db-azure-managed-identity-client-id], :as env-vars}] (if mb-db-connection-uri (mdb.data-source/raw-connection-string->DataSource mb-db-connection-uri mb-db-user mb-db-pass mb-db-azure-managed-identity-client-id) (mdb.data-source/broken-out-details->DataSource db-type (broken-out-details db-type env-vars)))) | |
exports: [[db-type]], [[db-file]], and [[data-source]] created using environment variables. | |
(defmulti ^:private env-defaults {:arglists '([db-type])} keyword) | |
(defmethod env-defaults :h2 [_db-type] nil) | |
(defmethod env-defaults :mysql [_db-type] {:mb-db-host "localhost" :mb-db-port 3306}) | |
(defmethod env-defaults :postgres [_db-type] {:mb-db-host "localhost" :mb-db-port 5432}) | |
(defn- env* [db-type] (merge-with (fn [env-value default-value] (if (nil? env-value) default-value env-value)) {:mb-db-type db-type :mb-db-in-memory (config/config-bool :mb-db-in-memory) :mb-db-file (config/config-str :mb-db-file) :mb-db-connection-uri (config/config-str :mb-db-connection-uri) :mb-db-host (config/config-str :mb-db-host) :mb-db-port (config/config-int :mb-db-port) :mb-db-dbname (config/config-str :mb-db-dbname) :mb-db-user (config/config-str :mb-db-user) :mb-db-pass (config/config-str :mb-db-pass) :mb-db-azure-managed-identity-client-id (config/config-str :mb-db-azure-managed-identity-client-id)} (env-defaults db-type))) | |
Metabase Datatbase environment. Used to setup application-db and audit-db for enterprise users. | (def env (env* (config/config-kw :mb-db-type))) |
Keyword type name of the application DB details specified by environment variables. Matches corresponding driver
name e.g. | (def db-type (env->db-type env)) |
(when (= db-type :h2) (log/warn (u/format-color :red ;; Unfortunately this can't be i18n'ed because the application DB hasn't been initialized yet at the time we log ;; this and thus the site locale is unavailable. (str/join " " ["WARNING: Using Metabase with an H2 application database is not recommended for production deployments." "For production deployments, we highly recommend using Postgres, MySQL, or MariaDB instead." "If you decide to continue to use H2, please be sure to back up the database file regularly." "For more information, see https://metabase.com/docs/latest/operations-guide/migrating-from-h2.html"])))) | |
Path to our H2 DB file from env var or app config. | (defn db-file [] (env->db-file env)) |
If someone is using Postgres and specifies | (when-let [raw-connection-string (not-empty (:mb-db-connection-uri env))] (when (and (= db-type :postgres) (str/includes? raw-connection-string "ssl=true") (not (str/includes? raw-connection-string "sslmode=require"))) ;; Unfortunately this can't be i18n'ed because the application DB hasn't been initialized yet at the time we log ;; this and thus the site locale is unavailable. (log/warn (str/join " " ["Warning: Postgres connection string with `ssl=true` detected." "You may need to add `?sslmode=require` to your application DB connection string." "If Metabase fails to launch, please add it and try again." "See https://github.com/metabase/metabase/issues/8908 for more details."])))) |
A [[javax.sql.DataSource]] ultimately derived from the environment variables. | (def ^javax.sql.DataSource data-source (env->DataSource db-type env)) |