From eaa25b49d6aefd508ef8b2d4a6b3c0a4d7af9d07 Mon Sep 17 00:00:00 2001 From: Cam Saul <cammsaul@gmail.com> Date: Mon, 19 Nov 2018 18:53:16 -0800 Subject: [PATCH] Fail gracefully when migrating invalid BigQuery legacy SQL questions :skull: --- src/metabase/db/migrations.clj | 31 ++++++++++++++++++---------- test/metabase/db/migrations_test.clj | 13 ++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/metabase/db/migrations.clj b/src/metabase/db/migrations.clj index d9938492df0..918ce928076 100644 --- a/src/metabase/db/migrations.clj +++ b/src/metabase/db/migrations.clj @@ -279,17 +279,26 @@ (doseq [database-id (db/select-ids Database :engine "bigquery")] ;; For each Card belonging to that BigQuery database... (doseq [{query :dataset_query, card-id :id} (db/select [Card :id :dataset_query] :database_id database-id)] - ;; If the Card isn't native, ignore it - (when (= (keyword (:type query)) :native) - (let [sql (get-in query [:native :query])] - ;; if the Card already contains a #standardSQL or #legacySQL (both are case-insenstive) directive, ignore it - (when-not (re-find #"(?i)#(standard|legacy)sql" sql) - ;; if it doesn't have a directive it would have (under old behavior) defaulted to legacy SQL, so give it a - ;; #legacySQL directive... - (let [updated-sql (str "#legacySQL\n" sql)] - ;; and save the updated dataset_query map - (db/update! Card (u/get-id card-id) - :dataset_query (assoc-in query [:native :query] updated-sql))))))))) + (try + ;; If the Card isn't native, ignore it + (when (= (keyword (:type query)) :native) + ;; there apparently are cases where we have a `:native` query with no `:query`. See #8924 + (when-let [sql (get-in query [:native :query])] + ;; if the Card already contains a #standardSQL or #legacySQL (both are case-insenstive) directive, ignore it + (when-not (re-find #"(?i)#(standard|legacy)sql" sql) + ;; if it doesn't have a directive it would have (under old behavior) defaulted to legacy SQL, so give it a + ;; #legacySQL directive... + (let [updated-sql (str "#legacySQL\n" sql)] + ;; and save the updated dataset_query map + (db/update! Card (u/get-id card-id) + :dataset_query (assoc-in query [:native :query] updated-sql)))))) + ;; if for some reason something above fails (as in #8924) let's log the error and proceed. It's not mission + ;; critical that we migrate existing queries anyway, and for ones that are impossible to migrate (e.g. ones + ;; that are invalid in the first place) it's best to fail gracefully and proceed rather than nuke someone's MB + ;; instance + (catch Throwable e + (log/error e (trs "Error adding legacy SQL directive to BigQuery saved Question"))))))) + ;; Before 0.30.0, we were storing the LDAP user's password in the `core_user` table (though it wasn't used). This ;; migration clears those passwords and replaces them with a UUID. This is similar to a new account setup, or how we diff --git a/test/metabase/db/migrations_test.clj b/test/metabase/db/migrations_test.clj index 3c8c3b5e14e..c6430ed6a25 100644 --- a/test/metabase/db/migrations_test.clj +++ b/test/metabase/db/migrations_test.clj @@ -47,6 +47,19 @@ (->> (db/select-field->field :name :dataset_query Card :id [:in (map u/get-id [card-1 card-2])]) (m/map-vals #(update % :database integer?))))) +;; if for some reason we have a BigQuery native query that does not actually have any SQL, ignore it rather than +;; barfing (#8924) (No idea how this was possible, but clearly it was) +(expect + {:database true, :type :native, :native {:query 1000}} + (tt/with-temp* [Database [database {:engine "bigquery"}] + Card [card {:database_id (u/get-id database) + :dataset_query {:database (u/get-id database) + :type :native + :native {:query 1000}}}]] + (#'migrations/add-legacy-sql-directive-to-bigquery-sql-cards) + (-> (db/select-one-field :dataset_query Card :id (u/get-id card)) + (update :database integer?)))) + ;; Test clearing of LDAP user local passwords (expect [false true] -- GitLab