Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More acceptance tests relevant to table permissions #101

Merged
merged 8 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/macaw/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,12 @@

(defn query->tables
"Given a parsed query (i.e., a [subclass of] `Statement`) return a set of all the table identifiers found within it."
[statement & {:keys [mode] :as opts}]
[sql & {:keys [mode] :as opts}]
(case mode
:ast-walker-1 (raw-components (:tables (query->components statement opts)))
:ast-walker-1 (-> (parsed-query sql)
(query->components opts)
:tables
raw-components)
:basic-select :macaw.error/not-implemented))

(defn replace-names
Expand Down
96 changes: 53 additions & 43 deletions test/macaw/acceptance_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
(def broken-queries
"The DANGER ZONE
This map gives a pattern in the exception message we expect to receive when trying to analyze the given fixture."
{:broken/between #"Encountered unexpected token: \"BETWEEN\""
:broken/filter-where #"Encountered unexpected token: \"\(\""})
{:broken/between #"Encountered unexpected token: \"BETWEEN\""
:broken/filter-where #"Encountered unexpected token: \"\(\""
:sqlserver/execute #"Not supported yet"
:sqlserver/executesql #"Not supported yet"
:oracle/open-for #"Encountered unexpected token: \"OPEN\""})

(defn- fixture-analysis [fixture]
(some-> fixture (ct/fixture->filename "acceptance" ".analysis.edn") io/resource slurp read-string))
Expand All @@ -35,23 +38,34 @@
#{:ast-walker-1
:basic-select})

(def ^:private not-implemented?
#{:basic-select})
(def global-overrides
{:basic-select :macaw.error/not-implemented})
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsmacdonald You should be able to just remove this entry to start TDD-ing the new walker.


(defn- validate-analysis [correct override actual]
(let [expected (or override correct)]
(when override
(if (vector? correct)
(is (not= correct (ct/sorted actual)) "Override is still needed")
(is (not= correct actual) "Override is still needed")))
(testing "Override is still needed"
(if (and (vector? correct) (not (keyword actual)))
(is (not= correct (ct/sorted actual)))
(is (not= correct actual)))))

(if (vector? expected)
(if (and (vector? expected) (not (keyword actual)))
(is (= expected (ct/sorted actual)))
(is (= expected actual)))))
(when (not= expected actual)
(is (= expected actual))))))

(defn- when-keyword [x]
(when (keyword? x)
x))

(defn- get-override [expected-cs mode ck]
(or (get-in expected-cs [:overrides mode ck])
(get-in expected-cs [:overrides ck])))
(or (get global-overrides mode)
(get-in expected-cs [:overrides mode :error])
(get-in expected-cs [:overrides :error])
(get-in expected-cs [:overrides mode ck])
(get-in expected-cs [:overrides ck])
(when-keyword (get-in expected-cs [:overrides mode]))
(when-keyword (get expected-cs :overrides))))

(defn- test-fixture
"Test that we can parse a given fixture, and compare against expected analysis and rewrites, where they are defined."
Expand All @@ -63,33 +77,29 @@
expected-rw (fixture-rewritten fixture)
base-opts {:non-reserved-words [:final]}
opts-mode (fn [mode] (assoc base-opts :mode mode))]

(if-let [expected-msg (broken-queries fixture)]
(testing (str prefix " analysis cannot be parsed")
(is (thrown-with-msg? Exception expected-msg (ct/components sql base-opts)))
(doseq [m test-modes]
(is (thrown-with-msg? Exception expected-msg (ct/tables sql (opts-mode m))))))
(do
(let [m :ast-walker-1
opts (opts-mode m)]
(when-let [cs (testing (str prefix " analysis does not throw")
(is (ct/components sql opts)))]
(doseq [[ck cv] (dissoc expected-cs :overrides)]
(assert sql "Fixture exists")
(doseq [m test-modes
:let [opts (opts-mode m)]]
(if (= m :ast-walker-1)
;; Legacy testing path for `components`, which only supports the original walker, and throws exceptions.
(if-let [expected-msg (broken-queries fixture)]
(testing (str prefix " analysis cannot be parsed")
(is (thrown-with-msg? Exception expected-msg (ct/components sql opts))))
(let [cs (testing (str prefix " analysis does not throw")
(is (ct/components sql opts)))]
(doseq [[ck cv] (dissoc expected-cs :overrides :error)]
(testing (str prefix " analysis is correct: " (name ck))
(let [actual-cv (get-component cs ck)
override (get-override expected-cs m ck)]
(validate-analysis cv override actual-cv))))))

(doseq [m test-modes]
(when-let [ts (testing (str prefix " table analysis does not throw for mode " m)
(is (ct/tables sql (opts-mode m))))]
(if (not-implemented? m)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rework to this function is essentially to get rid of this override hidden in the test, so that :error values in the expectations can do all the driving.

(testing (str m " is not implemented yet")
(is (= :macaw.error/not-implemented ts)))
(when-let [correct (get expected-cs :tables)]
(testing (str prefix " table analysis is correct for mode " m)
(let [override (get-override expected-cs m :tables)]
(validate-analysis correct override ts)))))))))
;; Testing path for newer modes.
(let [correct (:error expected-cs (:tables expected-cs))
override (get-override expected-cs m :tables)
;; For now, we only support (and test) :tables
tables (testing (str prefix " table analysis does not throw for mode " m)
(is (ct/tables sql opts)))]
(testing (str prefix " table analysis is correct for mode " m)
(validate-analysis correct override tables)))))

(when renames
(let [broken? (:broken? renames)
Expand Down Expand Up @@ -128,14 +138,14 @@
(create-fixture-tests!)

(comment
;; Unload all the tests, useful for flushing stale fixture tests
(doseq [[sym ns-var] (ns-interns *ns*)]
(when (:test (meta ns-var))
(ns-unmap *ns* sym)))
;; Unload all the tests, useful for flushing stale fixture tests
(doseq [[sym ns-var] (ns-interns *ns*)]
(when (:test (meta ns-var))
(ns-unmap *ns* sym)))

(test-fixture :compound/cte)
(test-fixture :compound/cte-nonambiguous)
(test-fixture :literal/with-table)
(test-fixture :literal/without-table)
(test-fixture :compound/cte)
(test-fixture :compound/cte-nonambiguous)
(test-fixture :literal/with-table)
(test-fixture :literal/without-table)

(test-fixture :broken/filter-where))
(test-fixture :broken/filter-where))
2 changes: 1 addition & 1 deletion test/macaw/core_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

(defn tables [sql & {:as opts}]
(let [opts (update opts :mode #(or % :ast-walker-1))]
(m/query->tables (m/parsed-query sql opts) opts)))
(m/query->tables sql opts)))

(def raw-components #(let [xs (empty %)] (into xs (keep :component) %)))
(def columns (comp raw-components :columns components))
Expand Down
12 changes: 12 additions & 0 deletions test/resources/acceptance/bigquery__table_wildcard.analysis.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{:source-columns []
:tables ::not-sure-what-we-should-do-if-we-continue-supporting-this

:overrides
{:basic-select
;; do not allow wildcard selects
{:error :macaw.error/illegal-expression}

;; Just plain old wacky
:source-columns [{:table "`project_id.dataset_id.table_*`", :column "_TABLE_SUFFIX"}]
;; Kinda makes sense, but very raw, and Metabase won't handle it.
:tables [{:table "`project_id.dataset_id.table_*`"}]}}
7 changes: 7 additions & 0 deletions test/resources/acceptance/bigquery__table_wildcard.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
SELECT
*
FROM
`project_id.dataset_id.table_*`
WHERE
_TABLE_SUFFIX BETWEEN '20230101' AND '20230131'
LIMIT 1000;
5 changes: 5 additions & 0 deletions test/resources/acceptance/broken__between.analysis.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{:source-columns [{:table "usage-stats" :column "instance_started"}
{:table "usage-stats" :column "month_started"}
{:table "usage-stats" :column "instance_finished"}]
:tables [{:table "usage_stats"}]
:overrides :macaw.error/unable-to-parse}
5 changes: 5 additions & 0 deletions test/resources/acceptance/broken__filter_where.analysis.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{:source-columns [{:table "execution" :column "error"}
{:table "execution" :column "instance_id"}
{:table "execution" :column "running_time"}]
:tables [{:table "execution"}]
:overrides :macaw.error/unable-to-parse}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

;; See https://github.com/metabase/metabase/issues/42586
:overrides
;; TODO currently each table gets hidden by the other CTE
{:tables []
:source-columns []}}
{:ast-walker-1
;; TODO currently each table gets hidden by the other CTE
{:tables []
:source-columns []}}}
Comment on lines +7 to +10
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels good to scope the one known false negative 😮‍💨

5 changes: 5 additions & 0 deletions test/resources/acceptance/oracle__open_for.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OPEN ccur FOR
'select c.category
from ' || TABLE_NAME || ' c
where c.deptid=' || PI_N_Dept ||
' and c.category not in ('|| sExcludeCategories ||')';
4 changes: 4 additions & 0 deletions test/resources/acceptance/reserved__final.analysis.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:source-columns [{:table "invoice" :column "amount_paid_cents"}
{:table "invoice" :column "id"}
{:table "invoice" :column "is_deleted"}]
:tables [{:table "invoice"}]}
5 changes: 1 addition & 4 deletions test/resources/acceptance/shadow__subselect.analysis.edn
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,4 @@
{:source-columns #{{:table "departments" :column "id"}
{:table "departments" :column "name"}
{:column "first_name"}
{:column "last_name"}}

:basic-select
{:tables ::not-implemented}}}
{:column "last_name"}}}}
5 changes: 5 additions & 0 deletions test/resources/acceptance/simple__select_into.analysis.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{:source-columns [{:table "user" :column "id"}
{:table "user" :column "name"}]
:tables [{:table "user"}]
:overrides
{:basic-select :macaw.error/illegal-expression}}
3 changes: 3 additions & 0 deletions test/resources/acceptance/simple__select_into.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SELECT id, name
INTO new_user_summary
FROM user;
3 changes: 3 additions & 0 deletions test/resources/acceptance/simple__select_star.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{:has-wildcard? true
:source-columns []
:tables [{:table "t"}]}
1 change: 1 addition & 0 deletions test/resources/acceptance/simple__select_star.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM t;
2 changes: 2 additions & 0 deletions test/resources/acceptance/sqlserver__execute.analysis.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{:error :macaw.error/illegal-expression
:overrides :macaw.error/unable-to-parse}
1 change: 1 addition & 0 deletions test/resources/acceptance/sqlserver__execute.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
EXECUTE stmt;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{:error :macaw.error/illegal-expression
:overrides :macaw.error/unable-to-parse}
1 change: 1 addition & 0 deletions test/resources/acceptance/sqlserver__executesql.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
EXEC sp_executesql @SQL
Loading