diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..c587ff1 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,82 @@ +# [Choice] Java version (use -bullseye variants on local arm64/Apple Silicon): 11, 17, 11-bullseye, 17-bullseye, 11-buster, 17-buster +ARG VARIANT=17 +FROM mcr.microsoft.com/vscode/devcontainers/java:0-${VARIANT} + +# [Optional] Clojure version +ARG CLOJURE_VERSION=1.10.3 + +# [Optional] Clojure tools version +ARG CLOJURE_CLI_VERSION=1.10.3.1075 + +# [Optional] Leiningen version +ARG LEININGEN_VERSION="stable" + +# [Optional] POLYLITH version +ARG POLYLITH_VERSION="0.2.13-alpha" + +# [Optional] Boot version +ENV BOOT_VERSION=2.8.3 + +# [Optional] Clojure version used by Boot +ENV BOOT_CLOJURE_VERSION=${CLOJURE_VERSION} + +# [Option] Install Clojure CLI tool +ARG INSTALL_CLOJURE_CLI="true" + +# [Option] Install Boot +ARG INSTALL_BOOT="true" + +# [Option] Install Leiningen +ARG INSTALL_LEININGEN="true" + +# [Option] Install Polylith +ARG INSTALL_POLYLITH="true" + +RUN if [ "${INSTALL_CLOJURE_CLI}" = "true" ]; then \ + apt-get update \ + && apt-get -y install rlwrap \ + && curl -OL "https://download.clojure.org/install/linux-install-${CLOJURE_CLI_VERSION}.sh" \ + && chmod +x linux-install-${CLOJURE_CLI_VERSION}.sh \ + && /linux-install-${CLOJURE_CLI_VERSION}.sh \ + && rm /linux-install-${CLOJURE_CLI_VERSION}.sh \ + && su vscode -c "clj --version"; fi + +RUN if [ "${INSTALL_BOOT}" = "true" ]; then \ + curl -OL "https://github.com/boot-clj/boot-bin/releases/download/latest/boot.sh" \ + && chmod +x boot.sh \ + && mv boot.sh /usr/local/sbin/boot \ + && su vscode -c "boot -u"; fi + +RUN if [ "${INSTALL_LEININGEN}" = "true" ]; then \ + curl -OL "https://raw.githubusercontent.com/technomancy/leiningen/${LEININGEN_VERSION}/bin/lein" \ + && chmod +x lein \ + && mv lein /usr/local/sbin; fi + +# Cache Clojure and dependencies +RUN if [ "${INSTALL_LEININGEN}" = "true" ]; then \ + su vscode -c " cd ~ \ + && echo '(defproject dummy \"\" :dependencies [[org.clojure/clojure \"'${CLOJURE_VERSION}'\"]])' > project.clj \ + && lein deps \ + && rm project.clj"; fi + +RUN if [ "${INSTALL_POLYLITH}" = "true" ]; then \ + curl -OL "https://github.com/polyfy/polylith/releases/download/v${POLYLITH_VERSION}/poly-${POLYLITH_VERSION}.jar" \ + && mkdir -p /usr/local/polylith \ + && mv poly-$POLYLITH_VERSION.jar /usr/local/polylith \ + && echo '#!/bin/sh\nARGS=""\nwhile [ "$1" != "" ] ; do\n ARGS="$ARGS $1"\n shift\ndone\nexec "java" $JVM_OPTS "-jar" "/usr/local/polylith/poly-'$POLYLITH_VERSION'.jar" $ARGS\n' > /usr/local/sbin/poly \ + && chmod +x /usr/local/sbin/poly \ + && /usr/local/sbin/poly version; fi + +# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 +ARG NODE_VERSION="lts/*" +RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + +# [Optional] Uncomment this line to install global node packages. +# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 + +# Clean up package lists +RUN apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..ac990d3 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,47 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/clojure +{ + "name": "Clojure (Community)", + "build": { + "dockerfile": "Dockerfile", + "args": { + // Update the VARIANT arg to pick a Java version. + // Append -bullseye or -buster to pin to an OS version. + // Use the -bullseye variants on local arm64/Apple Silicon. + "VARIANT": "17", + // Options + "CLOJURE_VERSION": "1.10.3", + "INSTALL_CLOJURE_CLI": "true", + "INSTALL_BOOT": "true", + "INSTALL_LEININGEN": "true", + "INSTALL_POLYLITH": "true", + "NODE_VERSION": "lts/*" + } + }, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "vscjava.vscode-java-pack", + "borkdude.clj-kondo", + "betterthantomorrow.calva" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "java -version", + + // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" +} diff --git a/README.md b/README.md index bb574c0..bca9627 100755 --- a/README.md +++ b/README.md @@ -107,3 +107,45 @@ Next, in the settings page of DuckDB of Metabase Web UI you could set your DB fi ``` The same way you could mount the dir with parquet files into container and make SQL queries to this files using directory in your container. + +## How to build the DuckDB .jar plugin yourself + +1. Install VS Code with [DevContainer](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension (see [details](https://code.visualstudio.com/docs/devcontainers/containers)) +2. Create some folder, let's say `duckdb_plugin` +3. Clone the `metabase_duckdb_driver` repository into `duckdb_plugin` folder +4. Copy `.devcontainer` from `duckdb_plugin/metabase_duckdb_driver` into `duckdb_plugin` +5. Clone the `metabase` repository of version you need into `duckdb_plugin` folder +6. Now content of the `duckdb_plugin` folder should looks like this: +``` + .. + .devcontainer + metabase + metabase_duckdb_driver +``` +7. Add duckdb record to the deps file `duckdb_plugin/metabase/modules/drivers/deps.edn` +The end of the file sholud looks like this: +``` + ... + metabase/sqlserver {:local/root "sqlserver"} + metabase/vertica {:local/root "vertica"} + metabase/duckdb {:local/root "duckdb"}}} <- add this! +``` +8. Set the DuckDB version you need in the `duckdb_plugin/metabase_duckdb_driver/deps.edn` +9. Create duckdb driver directory in the cloned metabase sourcecode: +``` +> mkdir -p duckdb_plugin/metabase/modules/drivers/duckdb +``` +10. Copy the `metabase_duckdb_driver` source code into created dir +``` +> cp -rf duckdb_plugin/metabase_duckdb_driver/* duckdb_plugin/metabase/modules/drivers/duckdb/ +``` +11. Open `duckdb_plugin` folder in VSCode using DevContainer extension (vscode will offer to open this folder using devcontainer). Wait until all stuff will be loaded. At the end you will get the terminal opened directly in the VS Code, smth like this: +``` +vscode ➜ /workspaces/duckdb_plugin $ +``` +12. Build the plugin +``` +vscode ➜ /workspaces/duckdb_plugin $ cd metabase +vscode ➜ /workspaces/duckdb_plugin $ clojure -X:build:drivers:build/driver :driver :duckdb +``` +13. jar file of DuckDB plugin will be generated here duckdb_plugin/metabase/resources/modules/duckdb.metabase-driver.jar diff --git a/resources/metabase-plugin.yaml b/resources/metabase-plugin.yaml index 8f8a217..97dd64e 100755 --- a/resources/metabase-plugin.yaml +++ b/resources/metabase-plugin.yaml @@ -1,6 +1,6 @@ info: name: Metabase DuckDB Driver - version: 1.0.0-SNAPSHOT-0.1.11 + version: 1.0.0-SNAPSHOT-0.1.12 description: Allows Metabase to connect to DuckDB databases. contact-info: name: Alexander Golubov diff --git a/src/metabase/driver/duckdb.clj b/src/metabase/driver/duckdb.clj index e518011..72b09ec 100755 --- a/src/metabase/driver/duckdb.clj +++ b/src/metabase/driver/duckdb.clj @@ -1,6 +1,5 @@ (ns metabase.driver.duckdb (:require [clojure.java.jdbc :as jdbc] - [honey.sql :as hsql] [medley.core :as m] [metabase.driver :as driver] [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn]