sql

James Amberger 2024-08-08T18:41:02.076409Z

Submitted in hope of helping anyone who has to use an Oracle db and wants to run one locally during dev with [testcontainers](http://testcontainers.org): a text fixture that is ready to take your sql files for initializing tables/loading data/etc.

đź‘€ 1
James Amberger 2024-08-08T18:41:27.001209Z

(ns oracle-testcontainer
  "Put your sql files in ./sql and they will be run on DB init in the container"
  #_{:clj-kondo/ignore [:refer-all]}
  (:require
   [clj-test-containers.core :as tc]
   [ :as io]
   [clojure.test :refer [are deftest is use-fixtures]]
   [next.jdbc :as jdbc])
  (:import
   [org.testcontainers.oracle OracleContainer]))

(def ^:dynamic datasource nil)
(def oracle-username "test")
(def oracle-password "test")

(defn config-oracle [username password]
  #_{:clj-kondo/ignore [:inline-def]}
  (def oracle-username username)
  #_{:clj-kondo/ignore [:inline-def]}
  (def oracle-password password))

(defn spit-sql-init
  "The Oracle docker container will run this SQL on init, before any other
  SQL you provide and prepares it to create tables, add data, etc."
  ([] (spit-sql-init oracle-username oracle-password))
  ([username password]
   (spit
    "sql/0-init.sql"
    (format
     "alter session set container=FREEPDB1; -- FREEPDB1 is an oracle default
       create user %s identified by %s;
       grant connect, resource to %s;
       grant unlimited tablespace to %s;"
     username
     password
     username
     username))))

(use-fixtures
  :once
  (fn [f]
    (config-oracle "HRIS" "HRIS")
    (spit-sql-init)
    (let [% (loop [c {:container (OracleContainer.
                                   "gvenzl/oracle-free:slim-faststart"),
                      :exposed-ports [1521]}
                   s (seq (.list (io/file "sql")))]
              (if-let [f (first s)]
                (recur (tc/copy-file-to-container!
                         c
                         {:path f,
                          :container-path (str "/container-entrypoint-initdb.d/"
                                               f),
                          :type :host-path})
                       (next s))
                c))
          container (tc/start! %)
          ds (jdbc/get-datasource
               {:dbtype "oracle",
                :dbname "FREEPDB1", ; default for Oracle Free docker image
                :user oracle-username,
                :password oracle-password,
                :host (:host container),
                :port (get (:mapped-ports container) 1521)})]
      (binding [datasource ds] (f))
      (tc/stop! container))))

James Amberger 2024-08-08T20:23:17.810389Z

I”ll lift that loop out to a function when i have time cause you’ll likely want to start the container just for your dev loop too