diff --git a/.docker/clickhouse/single_node_tls/Dockerfile b/.docker/clickhouse/single_node_tls/Dockerfile index b027edb..c6be222 100644 --- a/.docker/clickhouse/single_node_tls/Dockerfile +++ b/.docker/clickhouse/single_node_tls/Dockerfile @@ -1,4 +1,4 @@ -FROM clickhouse/clickhouse-server:24.3-alpine +FROM clickhouse/clickhouse-server:24.4-alpine COPY .docker/clickhouse/single_node_tls/certificates /etc/clickhouse-server/certs RUN chown clickhouse:clickhouse -R /etc/clickhouse-server/certs \ && chmod 600 /etc/clickhouse-server/certs/* \ diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index b20598d..ce65907 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -9,15 +9,18 @@ on: - "**.md" pull_request: +env: + METABASE_VERSION: v0.49.12 + jobs: - check: + check-local-current-version: runs-on: ubuntu-latest steps: - name: Checkout Metabase Repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: metabase/metabase - ref: v0.49.11 + ref: ${{ env.METABASE_VERSION }} - name: Remove incompatible tests # dataset-definition-test tests test data definition, @@ -25,13 +28,81 @@ jobs: run: | echo "(ns metabase.test.data.dataset-definition-test)" > test/metabase/test/data/dataset_definition_test.clj + - name: Checkout Driver Repo + uses: actions/checkout@v2 + + - name: Prepare JDK 17 + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "17" + + - name: Add ClickHouse TLS instance to /etc/hosts + run: | + sudo echo "127.0.0.1 server.clickhouseconnect.test" | sudo tee -a /etc/hosts + + - name: Start ClickHouse in Docker + uses: hoverkraft-tech/compose-action@v2.0.0 + with: + compose-file: "modules/drivers/clickhouse/docker-compose.yml" + down-flags: "--volumes" + services: | + clickhouse + clickhouse_tls + clickhouse_cluster_node1 + clickhouse_cluster_node2 + nginx + + - name: Install Clojure CLI + run: | + curl -O https://download.clojure.org/install/linux-install-1.11.1.1182.sh && + sudo bash ./linux-install-1.11.1.1182.sh + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "yarn" + + # - name: Get M2 cache + # uses: actions/cache@v4 + # with: + # path: | + # ~/.m2 + # ~/.gitlibs + # key: ${{ runner.os }}-clickhouse-${{ hashFiles('**/deps.edn') }} + + - name: Prepare stuff for pulses + run: yarn build-static-viz + + # Use custom deps.edn containing "user/clickhouse" alias to include driver sources + - name: Prepare deps.edn + run: | + mkdir -p /home/runner/.config/clojure + cat modules/drivers/clickhouse/.github/deps.edn | sed -e "s|PWD|$PWD|g" > /home/runner/.config/clojure/deps.edn + + - name: Run all tests with the latest ClickHouse version + env: + DRIVERS: clickhouse + run: | + clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:user/clickhouse + + check-local-older-version: + runs-on: ubuntu-latest + steps: + - name: Checkout Metabase Repo + uses: actions/checkout@v4 + with: + repository: metabase/metabase + ref: ${{ env.METABASE_VERSION }} + - name: Checkout Driver Repo uses: actions/checkout@v2 with: path: modules/drivers/clickhouse - name: Prepare JDK 17 - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" @@ -41,14 +112,19 @@ jobs: sudo echo "127.0.0.1 server.clickhouseconnect.test" | sudo tee -a /etc/hosts - name: Start ClickHouse in Docker - uses: isbang/compose-action@v1.4.1 + uses: hoverkraft-tech/compose-action@v2.0.0 with: compose-file: "modules/drivers/clickhouse/docker-compose.yml" down-flags: "--volumes" + # FIXME: We only need to run a few specific tests with `clickhouse_older_version` + # Currently, we run all tests with it, which is unnecessary. services: | - clickhouse clickhouse_older_version + clickhouse clickhouse_tls + clickhouse_cluster_node1 + clickhouse_cluster_node2 + nginx - name: Install Clojure CLI run: | @@ -56,18 +132,18 @@ jobs: sudo bash ./linux-install-1.11.1.1182.sh - name: Setup Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: - node-version: "18" + node-version: "20" cache: "yarn" - - name: Get M2 cache - uses: actions/cache@v2 - with: - path: | - ~/.m2 - ~/.gitlibs - key: ${{ runner.os }}-clickhouse-${{ hashFiles('**/deps.edn') }} + # - name: Get M2 cache + # uses: actions/cache@v4 + # with: + # path: | + # ~/.m2 + # ~/.gitlibs + # key: ${{ runner.os }}-clickhouse-${{ hashFiles('**/deps.edn') }} - name: Prepare stuff for pulses run: yarn build-static-viz @@ -83,13 +159,27 @@ jobs: DRIVERS: clickhouse MB_CLICKHOUSE_TEST_PORT: 8124 run: | - clojure -X:dev:drivers:drivers-dev:test:user/clickhouse :only metabase.driver.clickhouse-test + clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:user/clickhouse :only metabase.driver.clickhouse-test - - name: Run all tests with the latest ClickHouse version - env: - DRIVERS: clickhouse + build-jar: + runs-on: ubuntu-latest + needs: [ 'check-local-current-version', 'check-local-older-version' ] + steps: + - name: Checkout Metabase Repo + uses: actions/checkout@v4 + with: + repository: metabase/metabase + ref: ${{ env.METABASE_VERSION }} + + - name: Checkout Driver Repo + uses: actions/checkout@v4 + with: + path: modules/drivers/clickhouse + + - name: Install Clojure CLI run: | - clojure -X:dev:drivers:drivers-dev:test:user/clickhouse + curl -O https://download.clojure.org/install/linux-install-1.11.1.1182.sh && + sudo bash ./linux-install-1.11.1.1182.sh - name: Build ClickHouse driver run: | @@ -98,14 +188,7 @@ jobs: ls -lah resources/modules - name: Archive driver JAR - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: clickhouse.metabase-driver.jar path: resources/modules/clickhouse.metabase-driver.jar - - - name: Report test results - uses: mikepenz/action-junit-report@v2.8.1 - if: always() - with: - report_paths: "**/target/junit/*.xml" - github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4158ca2..80e20b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,16 @@ -# 1.4.1 +# 1.5.0 + +Metabase 0.49.12+ only. + +### New features + +* Added [Metabase CSV Uploads feature](https://www.metabase.com/docs/latest/databases/uploads) support, which is currently enabled with ClickHouse Cloud only. On-premise deployments support will be added in the next release. ([calherries](https://github.com/calherries), [#236](https://github.com/ClickHouse/metabase-clickhouse-driver/pull/236), [#238](https://github.com/ClickHouse/metabase-clickhouse-driver/pull/238)) +* Added [Metabase connection impersonation feature](https://www.metabase.com/learn/permissions/impersonation) support. This feature will be enabled by the driver only if ClickHouse version 24.4+ is detected. ([#219](https://github.com/ClickHouse/metabase-clickhouse-driver/issues/219)) + +### Improvements + +* Proper role setting support on cluster deployments (related issue: [#192](https://github.com/ClickHouse/metabase-clickhouse-driver/issues/192)). +* Bump the JDBC driver to [0.6.0-patch5](https://github.com/ClickHouse/clickhouse-java/releases/tag/v0.6.0-patch5). ### Bug fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b1508f..ad32024 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ Please refer to the extensive documentation available on the Metabase website: [ ClickHouse driver's code should be inside the main Metabase repository checkout in `modules/drivers/clickhouse` directory. -Additionally, you need to tweak Metabase `deps.edn` a bit. +Additionally, you need to tweak Metabase's `deps.edn` a bit. The easiest way to set up a development environment is as follows (mostly the same as in the [CI](https://github.com/enqueue/metabase-clickhouse-driver/blob/master/.github/workflows/check.yml)): @@ -41,7 +41,7 @@ mkdir -p ~/.clojure cat modules/drivers/clickhouse/.github/deps.edn | sed -e "s|PWD|$PWD|g" > ~/.clojure/deps.edn ``` -Modifying `~/.clojure/deps.edn` will create two useful profiles: `user/clickhouse` that adds driver's sources to the classpath, and `user/test` that includes all the Metabase tests that are guaranteed to work with the driver. +Modifying `~/.clojure/deps.edn` will create a new profile: `user/clickhouse`, that adds driver's sources to the class path, and includes all the Metabase tests that are guaranteed to work with the driver. * Install the Metabase dependencies: @@ -63,32 +63,46 @@ Required for TLS tests. sudo -- sh -c "echo 127.0.0.1 server.clickhouseconnect.test >> /etc/hosts" ``` -* Start ClickHouse as a Docker container +* Start Docker containers ```bash -docker compose -f modules/drivers/clickhouse/docker-compose.yml up -d clickhouse +docker compose -f modules/drivers/clickhouse/docker-compose.yml up -d ``` +Here's an overview of the started containers, which have the ports exposed to the `localhost` (see [docker-compose.yml](./docker-compose.yml)): + +- Metabase with the ClickHouse driver loaded from the JAR file (port: 3000) +- Current ClickHouse version (port: 8123) - the main instance for all tests. +- Current ClickHouse cluster with two nodes (+ nginx as an LB, port: 8127) - required for the set role tests (verifying that the role is set correctly via the query parameters). +- Current ClickHouse version with TLS support (port: 8443) - required for the TLS tests. +- Older ClickHouse version (port: 8124) - required for the string functions tests (switch between UTF8 (current) and non-UTF8 (pre-23.8) versions), as well as to verify that certain features, such as connection impersonation, are disabled on the older server versions. + Now, you should be able to run the tests: ```bash -DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse:user/test +DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse ``` -you can see that we have our profiles `:user/clickhouse:user/test` added to the command above, and with `DRIVERS=clickhouse` we instruct Metabase to run the tests only for ClickHouse. +you can see that we have our `:user/clickhouse` profile added to the command above, and with `DRIVERS=clickhouse` we instruct Metabase to run the tests only for ClickHouse. NB: Omitting `DRIVERS` will run the tests for all the built-in database drivers. If you want to run tests for only a specific namespace: ```bash -DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse:user/test :only metabase.driver.clickhouse-test +DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse :only metabase.driver.clickhouse-test ``` or even a single test: ```bash -DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse:user/test :only metabase.driver.clickhouse-test/clickhouse-nullable-arrays +DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse :only metabase.driver.clickhouse-test/clickhouse-nullable-arrays +``` + +Testing the driver with the older ClickHouse version (see [docker-compose.yml](./docker-compose.yml)): + +```bash +MB_CLICKHOUSE_TEST_PORT=8124 DRIVERS=clickhouse clojure -X:dev:drivers:drivers-dev:test:user/clickhouse :only metabase.driver.clickhouse-test ``` ## Building a jar diff --git a/README.md b/README.md index fcabf2e..c1b595d 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ docker run -d -p 3000:3000 \ | 0.47.7+ | 1.2.5 | | 0.48.x | 1.3.4 | | 0.49.x | 1.4.0 | +| 0.49.12+ | 1.5.0 | ## Creating a Metabase Docker image with ClickHouse driver diff --git a/deps.edn b/deps.edn index 28f38d9..2a7843c 100644 --- a/deps.edn +++ b/deps.edn @@ -3,7 +3,7 @@ :deps {com.clickhouse/clickhouse-jdbc$http - {:mvn/version "0.4.6" + {:mvn/version "0.6.0-patch5" :exclusions [com.clickhouse/clickhouse-cli-client$shaded com.clickhouse/clickhouse-grpc-client$shaded]} com.widdindustries/cljc.java-time {:mvn/version "0.1.21"}}} diff --git a/docker-compose.cluster.yml b/docker-compose.cluster.yml deleted file mode 100644 index 2b610ca..0000000 --- a/docker-compose.cluster.yml +++ /dev/null @@ -1,58 +0,0 @@ -version: '3.8' - -services: - clickhouse1: - image: 'clickhouse/clickhouse-server:${CLICKHOUSE_VERSION-24.3-alpine}' - ulimits: - nofile: - soft: 262144 - hard: 262144 - hostname: clickhouse1 - container_name: metabase-clickhouse-server-node-1 - ports: - - '8124:8123' - - '9000:9000' - - '9181:9181' - volumes: - - './.docker/clickhouse/cluster/server1_config.xml:/etc/clickhouse-server/config.xml' - - './.docker/clickhouse/cluster/server1_macros.xml:/etc/clickhouse-server/config.d/macros.xml' - - './.docker/clickhouse/users.xml:/etc/clickhouse-server/users.xml' - - clickhouse2: - image: 'clickhouse/clickhouse-server:${CLICKHOUSE_VERSION-24.3-alpine}' - ulimits: - nofile: - soft: 262144 - hard: 262144 - hostname: clickhouse2 - container_name: metabase-clickhouse-server-node-2 - ports: - - '8125:8123' - - '9001:9000' - - '9182:9181' - volumes: - - './.docker/clickhouse/cluster/server2_config.xml:/etc/clickhouse-server/config.xml' - - './.docker/clickhouse/cluster/server2_macros.xml:/etc/clickhouse-server/config.d/macros.xml' - - './.docker/clickhouse/users.xml:/etc/clickhouse-server/users.xml' - - # Using Nginx as a cluster entrypoint and a round-robin load balancer for HTTP requests - nginx: - image: 'nginx:1.23.1-alpine' - hostname: nginx - ports: - - '8123:8123' - volumes: - - './.docker/nginx/local.conf:/etc/nginx/conf.d/local.conf' - container_name: metabase-nginx - - metabase: - image: metabase/metabase:v0.49.0-RC1 - container_name: metabase-with-clickhouse-driver-cluster - environment: - 'MB_HTTP_TIMEOUT': '5000' - 'JAVA_TIMEZONE': 'UTC' - ports: - - '3000:3000' - volumes: - - '../../../resources/modules/clickhouse.metabase-driver.jar:/plugins/clickhouse.jar' - - './.docker/clickhouse/single_node_tls/certificates/ca.crt:/certs/ca.crt' diff --git a/docker-compose.yml b/docker-compose.yml index 04f0e81..4ab095c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,12 @@ version: '3.8' services: + + ########################################################################################################## + # ClickHouse single node (CH driver + Metabase tests) + ########################################################################################################## + clickhouse: - image: 'clickhouse/clickhouse-server:24.3-alpine' + image: 'clickhouse/clickhouse-server:24.4-alpine' container_name: 'metabase-driver-clickhouse-server' ports: - '8123:8123' @@ -14,7 +19,32 @@ services: - './.docker/clickhouse/single_node/config.xml:/etc/clickhouse-server/config.xml' - './.docker/clickhouse/single_node/users.xml:/etc/clickhouse-server/users.xml' + ########################################################################################################## + # ClickHouse single node (CH driver TLS tests only) + ########################################################################################################## + + clickhouse_tls: + build: + context: ./ + dockerfile: .docker/clickhouse/single_node_tls/Dockerfile + container_name: 'metabase-driver-clickhouse-server-tls' + ports: + - '8443:8443' + - '9440:9440' + ulimits: + nofile: + soft: 262144 + hard: 262144 + volumes: + - './.docker/clickhouse/single_node_tls/config.xml:/etc/clickhouse-server/config.xml' + - './.docker/clickhouse/single_node_tls/users.xml:/etc/clickhouse-server/users.xml' + hostname: server.clickhouseconnect.test + + ########################################################################################################## + # Older ClickHouse version (CH driver tests only) # For testing pre-23.8 string functions switch between UTF8 and non-UTF8 versions (see clickhouse_qp.clj) + ########################################################################################################## + clickhouse_older_version: image: 'clickhouse/clickhouse-server:23.3-alpine' container_name: 'metabase-driver-clickhouse-server-older-version' @@ -29,29 +59,66 @@ services: - './.docker/clickhouse/single_node/config.xml:/etc/clickhouse-server/config.xml' - './.docker/clickhouse/single_node/users.xml:/etc/clickhouse-server/users.xml' - clickhouse_tls: - build: - context: ./ - dockerfile: .docker/clickhouse/single_node_tls/Dockerfile - container_name: 'metabase-driver-clickhouse-server-tls' + ########################################################################################################## + # ClickHouse cluster (CH driver SET ROLE tests only) + # See test/metabase/driver/clickhouse_set_role.clj + ########################################################################################################## + + clickhouse_cluster_node1: + image: 'clickhouse/clickhouse-server:${CLICKHOUSE_VERSION-24.4-alpine}' + ulimits: + nofile: + soft: 262144 + hard: 262144 + hostname: clickhouse1 + container_name: metabase-driver-clickhouse-cluster-node-1 ports: - - '8443:8443' - - '9440:9440' + - '8125:8123' + - '9002:9000' + - '9181:9181' + volumes: + - './.docker/clickhouse/cluster/server1_config.xml:/etc/clickhouse-server/config.xml' + - './.docker/clickhouse/cluster/server1_macros.xml:/etc/clickhouse-server/config.d/macros.xml' + - './.docker/clickhouse/users.xml:/etc/clickhouse-server/users.xml' + + clickhouse_cluster_node2: + image: 'clickhouse/clickhouse-server:${CLICKHOUSE_VERSION-24.4-alpine}' ulimits: nofile: soft: 262144 hard: 262144 + hostname: clickhouse2 + container_name: metabase-driver-clickhouse-cluster-node-2 + ports: + - '8126:8123' + - '9003:9000' + - '9182:9181' volumes: - - './.docker/clickhouse/single_node_tls/config.xml:/etc/clickhouse-server/config.xml' - - './.docker/clickhouse/single_node_tls/users.xml:/etc/clickhouse-server/users.xml' - hostname: server.clickhouseconnect.test + - './.docker/clickhouse/cluster/server2_config.xml:/etc/clickhouse-server/config.xml' + - './.docker/clickhouse/cluster/server2_macros.xml:/etc/clickhouse-server/config.d/macros.xml' + - './.docker/clickhouse/users.xml:/etc/clickhouse-server/users.xml' + + # Using Nginx as a cluster entrypoint and a round-robin load balancer for HTTP requests + # See .docker/nginx/local.conf for the configuration + nginx: + image: 'nginx:1.23.1-alpine' + hostname: nginx + ports: + - '8127:8123' + volumes: + - './.docker/nginx/local.conf:/etc/nginx/conf.d/local.conf' + container_name: metabase-nginx + + ########################################################################################################## + # Metabase + ########################################################################################################## metabase: - image: metabase/metabase:v0.49.6 + image: metabase/metabase-enterprise:v1.49.12 container_name: metabase-with-clickhouse-driver environment: 'MB_HTTP_TIMEOUT': '5000' - 'JAVA_TIMEZONE': 'UTC' + 'JAVA_TIMEZONE': 'UTC' ports: - '3000:3000' volumes: diff --git a/resources/metabase-plugin.yaml b/resources/metabase-plugin.yaml index 41c62ae..0dfb855 100644 --- a/resources/metabase-plugin.yaml +++ b/resources/metabase-plugin.yaml @@ -1,6 +1,6 @@ info: name: Metabase ClickHouse Driver - version: 1.4.1 + version: 1.5.0 description: Allows Metabase to connect to ClickHouse databases. contact-info: name: ClickHouse diff --git a/src/metabase/driver/clickhouse.clj b/src/metabase/driver/clickhouse.clj index 2684ca2..b262f0f 100644 --- a/src/metabase/driver/clickhouse.clj +++ b/src/metabase/driver/clickhouse.clj @@ -9,6 +9,7 @@ [metabase.driver.clickhouse-introspection] [metabase.driver.clickhouse-nippy] [metabase.driver.clickhouse-qp] + [metabase.driver.clickhouse-version :as clickhouse-version] [metabase.driver.ddl.interface :as ddl.i] [metabase.driver.sql :as driver.sql] [metabase.driver.sql-jdbc [common :as sql-jdbc.common] @@ -25,9 +26,10 @@ (driver/register! :clickhouse :parent :sql-jdbc) (defmethod driver/display-name :clickhouse [_] "ClickHouse") -(def ^:private product-name "metabase/1.4.1") +(def ^:private product-name "metabase/1.5.0") -(defmethod driver/prettify-native-form :clickhouse [_ native-form] +(defmethod driver/prettify-native-form :clickhouse + [_ native-form] (sql.u/format-sql-and-fix-params :mysql native-form)) (doseq [[feature supported?] {:standard-deviation-aggregations true @@ -35,11 +37,9 @@ :set-timezone false :convert-timezone false :test/jvm-timezone-setting false - :connection-impersonation false :schemas true :datetime-diff true :upload-with-auto-pk false}] - (defmethod driver/database-supports? [:clickhouse feature] [_driver _feature _db] supported?)) (def ^:private default-connection-details @@ -63,7 +63,13 @@ :ssl (boolean ssl) :use_no_proxy (boolean use-no-proxy) :use_server_time_zone_for_dates true - :product_name product-name} + :product_name product-name + ;; addresses breaking changes from the 0.5.0 JDBC driver release + ;; see https://github.com/ClickHouse/clickhouse-java/releases/tag/v0.5.0 + ;; and https://github.com/ClickHouse/clickhouse-java/issues/1634#issuecomment-2110392634 + :databaseTerm "schema" + :remember_last_set_roles true + :http_connection_provider "HTTP_URL_CONNECTION"} (sql-jdbc.common/handle-additional-options details :separator-style :url)))) (def ^:private ^{:arglists '([db-details])} cloud? @@ -127,22 +133,11 @@ (defmethod driver/db-start-of-week :clickhouse [_] :monday) -(defmethod ddl.i/format-name :clickhouse [_ table-or-field-name] +(defmethod ddl.i/format-name :clickhouse + [_ table-or-field-name] (str/replace table-or-field-name #"-" "_")) -(def ^:private version-query - "WITH s AS (SELECT version() AS ver, splitByChar('.', ver) AS verSplit) SELECT s.ver, toInt32(verSplit[1]), toInt32(verSplit[2]) FROM s") -(defmethod driver/dbms-version :clickhouse - [driver database] - (sql-jdbc.execute/do-with-connection-with-options - driver database nil - (fn [^java.sql.Connection conn] - (with-open [stmt (.prepareStatement conn version-query) - rset (.executeQuery stmt)] - (when (.next rset) - {:version (.getString rset 1) - :semantic-version {:major (.getInt rset 2) - :minor (.getInt rset 3)}}))))) +;;; ------------------------------------------ Connection Impersonation ------------------------------------------ (defmethod driver/upload-type->database-type :clickhouse [_driver upload-type] @@ -223,6 +218,12 @@ ;;; ------------------------------------------ User Impersonation ------------------------------------------ +(defmethod driver/database-supports? [:clickhouse :connection-impersonation] + [_driver _feature db] + (if db + (clickhouse-version/is-at-least? 24 4 db) + false)) + (defmethod driver.sql/set-role-statement :clickhouse [_ role] (format "SET ROLE %s;" role)) diff --git a/src/metabase/driver/clickhouse_introspection.clj b/src/metabase/driver/clickhouse_introspection.clj index baec12a..4d6e9fd 100644 --- a/src/metabase/driver/clickhouse_introspection.clj +++ b/src/metabase/driver/clickhouse_introspection.clj @@ -12,32 +12,32 @@ (def ^:private database-type->base-type (sql-jdbc.sync/pattern-based-database-type->base-type - [[#"Array" :type/Array] - [#"Bool" :type/Boolean] - [#"DateTime64" :type/DateTime] - [#"DateTime" :type/DateTime] - [#"Date" :type/Date] - [#"Date32" :type/Date] - [#"Decimal" :type/Decimal] - [#"Enum8" :type/Text] - [#"Enum16" :type/Text] + [[#"Array" :type/Array] + [#"Bool" :type/Boolean] + [#"DateTime64" :type/DateTime] + [#"DateTime" :type/DateTime] + [#"Date" :type/Date] + [#"Date32" :type/Date] + [#"Decimal" :type/Decimal] + [#"Enum8" :type/Text] + [#"Enum16" :type/Text] [#"FixedString" :type/TextLike] - [#"Float32" :type/Float] - [#"Float64" :type/Float] - [#"Int8" :type/Integer] - [#"Int16" :type/Integer] - [#"Int32" :type/Integer] - [#"Int64" :type/BigInteger] - [#"IPv4" :type/IPAddress] - [#"IPv6" :type/IPAddress] - [#"Map" :type/Dictionary] - [#"String" :type/Text] - [#"Tuple" :type/*] - [#"UInt8" :type/Integer] - [#"UInt16" :type/Integer] - [#"UInt32" :type/Integer] - [#"UInt64" :type/BigInteger] - [#"UUID" :type/UUID]])) + [#"Float32" :type/Float] + [#"Float64" :type/Float] + [#"Int8" :type/Integer] + [#"Int16" :type/Integer] + [#"Int32" :type/Integer] + [#"Int64" :type/BigInteger] + [#"IPv4" :type/IPAddress] + [#"IPv6" :type/IPAddress] + [#"Map" :type/Dictionary] + [#"String" :type/Text] + [#"Tuple" :type/*] + [#"UInt8" :type/Integer] + [#"UInt16" :type/Integer] + [#"UInt32" :type/Integer] + [#"UInt64" :type/BigInteger] + [#"UUID" :type/UUID]])) (defn- normalize-db-type [db-type] diff --git a/src/metabase/driver/clickhouse_qp.clj b/src/metabase/driver/clickhouse_qp.clj index 5381f71..cdcf3cf 100644 --- a/src/metabase/driver/clickhouse_qp.clj +++ b/src/metabase/driver/clickhouse_qp.clj @@ -5,14 +5,12 @@ [honey.sql :as sql] [java-time.api :as t] [metabase [util :as u]] - [metabase.driver :as driver] [metabase.driver.clickhouse-nippy] + [metabase.driver.clickhouse-version :as clickhouse-version] [metabase.driver.sql-jdbc [execute :as sql-jdbc.execute]] [metabase.driver.sql.query-processor :as sql.qp :refer [add-interval-honeysql-form]] [metabase.driver.sql.util.unprepare :as unprepare] - [metabase.lib.metadata :as lib.metadata] [metabase.mbql.util :as mbql.u] - [metabase.query-processor.store :as qp.store] [metabase.util.date-2 :as u.date] [metabase.util.honey-sql-2 :as h2x] [metabase.util.log :as log]) @@ -29,19 +27,7 @@ ;; (set! *warn-on-reflection* true) ;; isn't enabled because of Arrays/toString call -(defmethod sql.qp/quote-style :clickhouse [_] :mysql) - -(defn- clickhouse-version [] - (let [db (lib.metadata/database (qp.store/metadata-provider))] - (qp.store/cached ::clickhouse-version (driver/dbms-version :clickhouse db)))) - -(defn- with-min-version [major minor default-fn fallback-fn] - (let [version (clickhouse-version)] - (if (or (> (get-in version [:semantic-version :major]) major) - (and (= (get-in version [:semantic-version :major]) major) - (>= (get-in version [:semantic-version :minor]) minor))) - default-fn - fallback-fn))) +(defmethod sql.qp/quote-style :clickhouse [_] :mysql) (defmethod sql.qp/date [:clickhouse :day-of-week] [_ _ expr] @@ -301,12 +287,16 @@ (defmethod sql.qp/->honeysql [:clickhouse :starts-with] [_ [_ field value options]] - (let [starts-with (with-min-version 23 8 :'startsWithUTF8 :'startsWith)] + (let [starts-with (clickhouse-version/with-min 23 8 + (constantly :'startsWithUTF8) + (constantly :'startsWith))] (clickhouse-string-fn starts-with field value options))) (defmethod sql.qp/->honeysql [:clickhouse :ends-with] [_ [_ field value options]] - (let [ends-with (with-min-version 23 8 :'endsWithUTF8 :'endsWith)] + (let [ends-with (clickhouse-version/with-min 23 8 + (constantly :'endsWithUTF8) + (constantly :'endsWith))] (clickhouse-string-fn ends-with field value options))) (defmethod sql.qp/->honeysql [:clickhouse :contains] diff --git a/src/metabase/driver/clickhouse_version.clj b/src/metabase/driver/clickhouse_version.clj new file mode 100644 index 0000000..564bb1c --- /dev/null +++ b/src/metabase/driver/clickhouse_version.clj @@ -0,0 +1,61 @@ +"Provides the info about the ClickHouse version. Extracted from the main clickhouse.clj file, + as both Driver and QP overrides require access to it, avoiding circular dependencies." +(ns metabase.driver.clickhouse-version + (:require [clojure.core.memoize :as memoize] + [metabase.driver :as driver] + [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn] + [metabase.driver.sql-jdbc.execute :as sql-jdbc.execute] + [metabase.driver.util :as driver.u] + [metabase.lib.metadata :as lib.metadata] + [metabase.query-processor.store :as qp.store])) + +(set! *warn-on-reflection* true) + +;; cache the results for 60 minutes; +;; TTL is here only to eventually clear out old entries/keep it from growing too large +(def ^:private default-cache-ttl (* 60 60 1000)) + +(def ^:private clickhouse-version-query + (str "WITH s AS (SELECT version() AS ver, splitByChar('.', ver) AS verSplit) " + "SELECT s.ver, toInt32(verSplit[1]), toInt32(verSplit[2]) FROM s")) + +(def ^:private ^{:arglists '([db-details])} get-clickhouse-version + (memoize/ttl + (fn [db-details] + (sql-jdbc.execute/do-with-connection-with-options + :clickhouse + (sql-jdbc.conn/connection-details->spec :clickhouse db-details) + nil + (fn [^java.sql.Connection conn] + (with-open [stmt (.prepareStatement conn clickhouse-version-query) + rset (.executeQuery stmt)] + (when (.next rset) + {:version (.getString rset 1) + :semantic-version {:major (.getInt rset 2) + :minor (.getInt rset 3)}}))))) + :ttl/threshold default-cache-ttl)) + +(defmethod driver/dbms-version :clickhouse + [_driver db] + (get-clickhouse-version (:details db))) + +(defn is-at-least? + "Is ClickHouse version at least `major.minor` (e.g., 24.4)?" + ([major minor] + ;; used from the QP overrides; we don't have access to the DB object + (is-at-least? major minor (lib.metadata/database (qp.store/metadata-provider)))) + ([major minor db] + ;; used from the Driver overrides; we have access to the DB object + (let [version (driver/dbms-version :clickhouse db) + semantic (:semantic-version version)] + (driver.u/semantic-version-gte [major minor] [(:major semantic) (:minor semantic)])))) + +(defn with-min + "Execute `f` if the ClickHouse version is greater or equal to `major.minor` (e.g., 24.4); + otherwise, execute `fallback-f`, if it's provided." + ([major minor f] + (with-min major minor f nil)) + ([major minor f fallback-f] + (if (is-at-least? major minor) + (f) + (when (not (nil? fallback-f)) (fallback-f))))) diff --git a/test/metabase/driver/clickhouse_impersonation_test.clj b/test/metabase/driver/clickhouse_impersonation_test.clj new file mode 100644 index 0000000..f9973cb --- /dev/null +++ b/test/metabase/driver/clickhouse_impersonation_test.clj @@ -0,0 +1,174 @@ +(ns metabase.driver.clickhouse-test + "SET ROLE (connection impersonation feature) tests on with single node or on-premise cluster setups." + #_{:clj-kondo/ignore [:unsorted-required-namespaces]} + (:require [clojure.test :refer :all] + [metabase-enterprise.advanced-permissions.api.util-test :as advanced-perms.api.tu] + [metabase.driver :as driver] + [metabase.driver.sql :as driver.sql] + [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn] + [metabase.driver.sql-jdbc.execute :as sql-jdbc.execute] + [metabase.models [database :refer [Database]]] + [metabase.query-processor.store :as qp.store] + [metabase.sync :as sync] + [metabase.test :as mt] + [metabase.test.data.clickhouse :as ctd] + [metabase.util :as u] + [toucan2.tools.with-temp :as t2.with-temp])) + +(set! *warn-on-reflection* true) + +(defn- set-role-test! + [details-map] + (let [default-role (driver.sql/default-database-role :clickhouse nil) + spec (sql-jdbc.conn/connection-details->spec :clickhouse details-map)] + (testing "default role is NONE" + (is (= default-role "NONE"))) + (testing "does not throw with an existing role" + (sql-jdbc.execute/do-with-connection-with-options + :clickhouse spec nil + (fn [^java.sql.Connection conn] + (driver/set-role! :clickhouse conn "metabase_test_role"))) + (is true)) + (testing "does not throw with the default role" + (sql-jdbc.execute/do-with-connection-with-options + :clickhouse spec nil + (fn [^java.sql.Connection conn] + (driver/set-role! :clickhouse conn default-role) + (fn [^java.sql.Connection conn] + (driver/set-role! :clickhouse conn default-role) + (with-open [stmt (.prepareStatement conn "SELECT * FROM `metabase_test_role_db`.`some_table` ORDER BY i ASC;") + rset (.executeQuery stmt)] + (is (.next rset) true) + (is (.getInt rset 1) 42) + (is (.next rset) true) + (is (.getInt rset 1) 144) + (is (.next rset) false))))) + (is true)))) + +(defn- set-role-throws-test! + [details-map] + (testing "throws when assigning a non-existent role" + (is (thrown? Exception + (sql-jdbc.execute/do-with-connection-with-options + :clickhouse (sql-jdbc.conn/connection-details->spec :clickhouse details-map) nil + (fn [^java.sql.Connection conn] + (driver/set-role! :clickhouse conn "asdf"))))))) + +(defn- do-with-new-metadata-provider + [details thunk] + (t2.with-temp/with-temp + [Database db {:engine :clickhouse :details details}] + (qp.store/with-metadata-provider (u/the-id db) (thunk db)))) + +(deftest clickhouse-set-role + (mt/test-driver + :clickhouse + (let [user-details {:user "metabase_test_user"} + ;; See docker-compose.yml for the port mappings + ;; 24.4+ + single-node-port-details {:port 8123} + single-node-details (merge user-details single-node-port-details) + cluster-port-details {:port 8127} + cluster-details (merge user-details cluster-port-details)] + (testing "single node" + (testing "should support the impersonation feature" + (t2.with-temp/with-temp + [Database db {:engine :clickhouse :details {:user "default" :port 8123}}] + (is (driver/database-supports? :clickhouse :connection-impersonation db) true))) + (let [statements ["CREATE DATABASE IF NOT EXISTS `metabase_test_role_db`;" + "CREATE OR REPLACE TABLE `metabase_test_role_db`.`some_table` (i Int32) ENGINE = MergeTree ORDER BY (i);" + "INSERT INTO `metabase_test_role_db`.`some_table` VALUES (42), (144);" + "CREATE ROLE IF NOT EXISTS `metabase_test_role`;" + "CREATE USER IF NOT EXISTS `metabase_test_user` NOT IDENTIFIED;" + "GRANT SELECT ON `metabase_test_role_db`.* TO `metabase_test_role`;" + "GRANT `metabase_test_role` TO `metabase_test_user`;"]] + (ctd/exec-statements statements single-node-port-details) + (do-with-new-metadata-provider + single-node-details + (fn [_db] + (set-role-test! single-node-details) + (set-role-throws-test! single-node-details))))) + (testing "on-premise cluster" + (testing "should support the impersonation feature" + (t2.with-temp/with-temp + [Database db {:engine :clickhouse :details {:user "default" :port 8127}}] + (is (driver/database-supports? :clickhouse :connection-impersonation db) true))) + (let [statements ["CREATE DATABASE IF NOT EXISTS `metabase_test_role_db` ON CLUSTER '{cluster}';" + "CREATE OR REPLACE TABLE `metabase_test_role_db`.`some_table` ON CLUSTER '{cluster}' (i Int32) + ENGINE ReplicatedMergeTree('/clickhouse/{cluster}/tables/{database}/{table}/{shard}', '{replica}') + ORDER BY (i);" + "INSERT INTO `metabase_test_role_db`.`some_table` VALUES (42), (144);" + "CREATE ROLE IF NOT EXISTS `metabase_test_role` ON CLUSTER '{cluster}';" + "CREATE USER IF NOT EXISTS `metabase_test_user` ON CLUSTER '{cluster}' NOT IDENTIFIED;" + "GRANT ON CLUSTER '{cluster}' SELECT ON `metabase_test_role_db`.* TO `metabase_test_role`;" + "GRANT ON CLUSTER '{cluster}' `metabase_test_role` TO `metabase_test_user`;"]] + (ctd/exec-statements statements cluster-port-details) + (do-with-new-metadata-provider + cluster-details + (fn [_db] + (set-role-test! cluster-details) + (set-role-throws-test! cluster-details))))) + (testing "older ClickHouse version" ;; 23.3 + (testing "should NOT support the impersonation feature" + (t2.with-temp/with-temp + [Database db {:engine :clickhouse :details {:user "default" :port 8124}}] + (is (driver/database-supports? :clickhouse :connection-impersonation db) true))))))) + +(deftest conn-impersonation-test-clickhouse + (mt/test-driver + :clickhouse + (mt/with-premium-features #{:advanced-permissions} + (let [table-name (str "metabase_impersonation_test.test_" (System/currentTimeMillis)) + select-query (format "SELECT * FROM %s;" table-name) + cluster-port {:port 8127} + cluster-details {:engine :clickhouse + :details {:user "metabase_impersonation_test_user" + :dbname "metabase_impersonation_test" + :port 8127}} + ddl-statements ["CREATE DATABASE IF NOT EXISTS metabase_impersonation_test ON CLUSTER '{cluster}';" + (format "CREATE TABLE %s ON CLUSTER '{cluster}' (s String) + ENGINE ReplicatedMergeTree('/clickhouse/{cluster}/tables/{database}/{table}/{shard}', '{replica}') + ORDER BY (s);" table-name)] + insert-statements [(format "INSERT INTO %s VALUES ('a'), ('b'), ('c');" table-name)] + grant-statements ["CREATE USER IF NOT EXISTS metabase_impersonation_test_user ON CLUSTER '{cluster}' NOT IDENTIFIED;" + "CREATE ROLE IF NOT EXISTS row_a ON CLUSTER '{cluster}';" + "CREATE ROLE IF NOT EXISTS row_b ON CLUSTER '{cluster}';" + "CREATE ROLE IF NOT EXISTS row_c ON CLUSTER '{cluster}';" + "GRANT ON CLUSTER '{cluster}' row_a, row_b, row_c TO metabase_impersonation_test_user;" + (format "GRANT ON CLUSTER '{cluster}' SELECT ON %s TO metabase_impersonation_test_user;" table-name) + (format "CREATE ROW POLICY OR REPLACE policy_row_a ON CLUSTER '{cluster}' + ON %s FOR SELECT USING s = 'a' TO row_a;" table-name) + (format "CREATE ROW POLICY OR REPLACE policy_row_b ON CLUSTER '{cluster}' + ON %s FOR SELECT USING s = 'b' TO row_b;" table-name) + (format "CREATE ROW POLICY OR REPLACE policy_row_c ON CLUSTER '{cluster}' + ON %s FOR SELECT USING s = 'c' TO row_c;" table-name)]] + (ctd/exec-statements ddl-statements cluster-port {"wait_end_of_query" "1"}) + (ctd/exec-statements insert-statements cluster-port {"wait_end_of_query" "1" + "insert_quorum" "2"}) + (ctd/exec-statements grant-statements cluster-port {"wait_end_of_query" "1"}) + (t2.with-temp/with-temp [Database db cluster-details] + (mt/with-db db (sync/sync-database! db) + + (defn- check-impersonation + [roles expected] + (advanced-perms.api.tu/with-impersonations + {:impersonations [{:db-id (mt/id) :attribute "impersonation_attr"}] + :attributes {"impersonation_attr" roles}} + (is (= expected + (-> {:query select-query} + mt/native-query + mt/process-query + mt/rows))))) + + (is (= [["a"] ["b"] ["c"]] + (-> {:query select-query} + mt/native-query + mt/process-query + mt/rows))) + + (check-impersonation "row_a" [["a"]]) + (check-impersonation "row_b" [["b"]]) + (check-impersonation "row_c" [["c"]]) + (check-impersonation "row_a,row_c" [["a"] ["c"]]) + (check-impersonation "row_b,row_c" [["b"] ["c"]]) + (check-impersonation "row_a,row_b,row_c" [["a"] ["b"] ["c"]]))))))) diff --git a/test/metabase/driver/clickhouse_test.clj b/test/metabase/driver/clickhouse_test.clj index 7d60f29..6c7290c 100644 --- a/test/metabase/driver/clickhouse_test.clj +++ b/test/metabase/driver/clickhouse_test.clj @@ -8,30 +8,36 @@ [metabase.driver :as driver] [metabase.driver.clickhouse :as clickhouse] [metabase.driver.clickhouse-data-types-test] + [metabase.driver.clickhouse-impersonation-test] [metabase.driver.clickhouse-introspection-test] [metabase.driver.clickhouse-substitution-test] [metabase.driver.clickhouse-temporal-bucketing-test] - [metabase.driver.sql :as driver.sql] [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn] - [metabase.driver.sql-jdbc.execute :as sql-jdbc.execute] + [metabase.models [database :refer [Database]]] [metabase.query-processor :as qp] [metabase.query-processor.test-util :as qp.test] [metabase.test :as mt] [metabase.test.data :as data] [metabase.test.data [interface :as tx]] [metabase.test.data.clickhouse :as ctd] - [taoensso.nippy :as nippy])) + [taoensso.nippy :as nippy] + [toucan2.tools.with-temp :as t2.with-temp])) (set! *warn-on-reflection* true) + (use-fixtures :once ctd/create-test-db!) (deftest ^:parallel clickhouse-version (mt/test-driver :clickhouse - (let [version (driver/dbms-version :clickhouse (mt/db))] - (is (number? (get-in version [:semantic-version :major]))) - (is (number? (get-in version [:semantic-version :minor]))) - (is (string? (get version :version)))))) + (t2.with-temp/with-temp + [Database db + {:engine :clickhouse + :details (tx/dbdef->connection-details :clickhouse :db {:database-name "default"})}] + (let [version (driver/dbms-version :clickhouse db)] + (is (number? (get-in version [:semantic-version :major]))) + (is (number? (get-in version [:semantic-version :minor]))) + (is (string? (get version :version))))))) (deftest ^:parallel clickhouse-server-timezone (mt/test-driver @@ -143,34 +149,6 @@ (let [value (com.clickhouse.data.value.UnsignedLong/valueOf "84467440737095")] (is (= value (nippy/thaw (nippy/freeze value)))))))) -(deftest clickhouse-set-role - (mt/test-driver - :clickhouse - (let [default-role (driver.sql/default-database-role :clickhouse nil) - details (merge {:user "metabase_test_user"} - (tx/dbdef->connection-details :clickhouse :db {:database-name "default"})) - spec (sql-jdbc.conn/connection-details->spec :clickhouse details)] - (testing "default role is NONE" - (is (= default-role "NONE"))) - (testing "does not throw with an existing role" - (sql-jdbc.execute/do-with-connection-with-options - :clickhouse spec nil - (fn [^java.sql.Connection conn] - (driver/set-role! :clickhouse conn "metabase_test_role"))) - (is true)) - (testing "does not throw with the default role" - (sql-jdbc.execute/do-with-connection-with-options - :clickhouse spec nil - (fn [^java.sql.Connection conn] - (driver/set-role! :clickhouse conn default-role))) - (is true)) - (testing "throws when assigning a non-existent role" - (is (thrown? Exception - (sql-jdbc.execute/do-with-connection-with-options - :clickhouse spec nil - (fn [^java.sql.Connection conn] - (driver/set-role! :clickhouse conn "asdf"))))))))) - (deftest ^:parallel clickhouse-query-formatting (mt/test-driver :clickhouse diff --git a/test/metabase/test/data/clickhouse.clj b/test/metabase/test/data/clickhouse.clj index 4a1deb0..7b3ab1f 100644 --- a/test/metabase/test/data/clickhouse.clj +++ b/test/metabase/test/data/clickhouse.clj @@ -6,6 +6,7 @@ [clojure.test :refer :all] [metabase.driver.ddl.interface :as ddl.i] [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn] + [metabase.driver.sql-jdbc.execute :as sql-jdbc.execute] [metabase.driver.sql.util :as sql.u] [metabase.models [database :refer [Database]]] [metabase.query-processor.test-util :as qp.test] @@ -17,7 +18,8 @@ [metabase.test.data.sql-jdbc [execute :as execute] [load-data :as load-data]] - [toucan2.tools.with-temp :as t2.with-temp])) + [toucan2.tools.with-temp :as t2.with-temp]) + (:import [com.clickhouse.jdbc.internal ClickHouseStatementImpl])) (sql-jdbc.tx/add-test-extensions! :clickhouse) @@ -30,7 +32,10 @@ :ssl false :use_no_proxy false :use_server_time_zone_for_dates true - :product_name "metabase/1.4.1"}) + :product_name "metabase/1.5.0" + :databaseTerm "schema" + :remember_last_set_roles true + :http_connection_provider "HTTP_URL_CONNECTION"}) (defmethod sql.tx/field-base-type->sql-type [:clickhouse :type/Boolean] [_ _] "Boolean") (defmethod sql.tx/field-base-type->sql-type [:clickhouse :type/BigInteger] [_ _] "Int64") @@ -76,8 +81,8 @@ [field] (let [{:keys [field-name base-type pk?]} field ch-type (if (map? base-type) - (:native base-type) - (sql.tx/field-base-type->sql-type :clickhouse base-type)) + (:native base-type) + (sql.tx/field-base-type->sql-type :clickhouse base-type)) col-name (quote-name field-name) fmt (if (or pk? (disallowed-as-nullable? ch-type)) "%s %s" "%s Nullable(%s)")] (format fmt col-name ch-type))) @@ -111,7 +116,7 @@ (defmethod sql.tx/pk-sql-type :clickhouse [_] "Int32") -(defmethod sql.tx/add-fk-sql :clickhouse [& _] nil) ; TODO - fix me +(defmethod sql.tx/add-fk-sql :clickhouse [& _] nil) (defmethod sql.tx/session-schema :clickhouse [_] "default") @@ -128,19 +133,40 @@ [f] (when (not @test-db-initialized?) (let [details (tx/dbdef->connection-details :clickhouse :db {:database-name "metabase_test"})] + (println "Executing create-test-db! with details:" details) (jdbc/with-db-connection - [conn (sql-jdbc.conn/connection-details->spec :clickhouse (merge {:engine :clickhouse} details))] + [spec (sql-jdbc.conn/connection-details->spec :clickhouse (merge {:engine :clickhouse} details))] (let [statements (as-> (slurp "modules/drivers/clickhouse/test/metabase/test/data/datasets.sql") s (str/split s #";") (map str/trim s) (filter seq s))] - (jdbc/db-do-commands conn statements) + (jdbc/db-do-commands spec statements) (reset! test-db-initialized? true))))) (f)) +#_{:clj-kondo/ignore [:warn-on-reflection]} +(defn exec-statements + ([statements details-map] + (exec-statements statements details-map nil)) + ([statements details-map clickhouse-settings] + (sql-jdbc.execute/do-with-connection-with-options + :clickhouse + (sql-jdbc.conn/connection-details->spec :clickhouse (merge {:engine :clickhouse} details-map)) + {:write? true} + (fn [^java.sql.Connection conn] + (doseq [statement statements] + (println "Executing:" statement) + (with-open [jdbcStmt (.createStatement conn)] + (let [^ClickHouseStatementImpl clickhouseStmt (.unwrap jdbcStmt ClickHouseStatementImpl) + request (.getRequest clickhouseStmt)] + (when clickhouse-settings + (doseq [[k v] clickhouse-settings] (.set request k v))) + (with-open [_response (-> request + (.query ^String statement) + (.executeAndWait))])))))))) + (defn do-with-test-db "Execute a test function using the test dataset" - {:style/indent 0} [f] (t2.with-temp/with-temp [Database database diff --git a/test/metabase/test/data/datasets.sql b/test/metabase/test/data/datasets.sql index f13356e..4f58ddf 100644 --- a/test/metabase/test/data/datasets.sql +++ b/test/metabase/test/data/datasets.sql @@ -158,11 +158,6 @@ CREATE DATABASE `metabase_db_scan_test`; CREATE TABLE `metabase_db_scan_test`.`table1` (i Int32) ENGINE = Memory; CREATE TABLE `metabase_db_scan_test`.`table2` (i Int64) ENGINE = Memory; --- SET ROLE tests -CREATE ROLE IF NOT EXISTS `metabase_test_role`; -CREATE USER IF NOT EXISTS `metabase_test_user` NOT IDENTIFIED; -GRANT `metabase_test_role` TO `metabase_test_user`; - -- Base type matching tests CREATE TABLE `metabase_test`.`enums_base_types` ( c1 Nullable(Enum8('America/New_York')),