Last active
May 8, 2024 02:35
-
-
Save camsaul/bb46f320b557f8de05e08c0f91d6efa7 to your computer and use it in GitHub Desktop.
Load Clojure namespace dependency graph into a Postgres database
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns metabase.deps-graph | |
(:require | |
[clojure.tools.namespace.dependency :as ns.deps] | |
[clojure.tools.namespace.find :as ns.find] | |
[clojure.tools.namespace.parse :as ns.parse] | |
[clojure.java.io :as io])) | |
(set! *warn-on-reflection* true) | |
(defn- find-ns-decls [] | |
(ns.find/find-ns-decls [(io/file "/home/cam/metabase/src/metabase")])) | |
(defn- module [ns-symb] | |
(some-> (re-find #"^metabase\.[^.]+" (str ns-symb)) symbol)) | |
(defn- ns-decls [] | |
(for [decl (find-ns-decls) | |
:let [ns-symb (ns.parse/name-from-ns-decl decl) | |
deps (ns.parse/deps-from-ns-decl decl)]] | |
{:namespace ns-symb | |
:module (module ns-symb) | |
:deps (into #{} | |
(map (fn [dep-symb] | |
{:namespace dep-symb})) | |
deps)})) | |
(defn- load-data! [] | |
(with-open [conn (java.sql.DriverManager/getConnection "jdbc:postgresql://localhost:5432/metabase_namespaces?user=cam&password=cam")] | |
(with-open [stmt (.createStatement conn)] | |
(doseq [^String sql ["DROP TABLE IF EXISTS namespace;" | |
"CREATE TABLE namespace (namespace VARCHAR NOT NULL UNIQUE, module VARCHAR NOT NULL);" | |
"DROP TABLE IF EXISTS dependency;" | |
"CREATE TABLE dependency (namespace VARCHAR NOT NULL, depends_on VARCHAR NOT NULL);" | |
"ALTER TABLE dependency ADD CONSTRAINT unique_dependency UNIQUE (namespace, depends_on);"]] | |
(println sql) | |
(.execute stmt sql))) | |
(with-open [namespace-stmt (.prepareStatement conn "INSERT INTO namespace (namespace, module) VALUES (?, ?);") | |
deps-stmt (.prepareStatement conn "INSERT INTO dependency (namespace, depends_on) VALUES (?, ?);")] | |
(doseq [decl (ns-decls)] | |
(println "Load" (:namespace decl)) | |
(.setString namespace-stmt 1 (str (:namespace decl))) | |
(.setString namespace-stmt 2 (str (:module decl))) | |
(.execute namespace-stmt) | |
(doseq [dep (:deps decl)] | |
(.setString deps-stmt 1 (str (:namespace decl))) | |
(.setString deps-stmt 2 (str (:namespace dep))) | |
(.execute deps-stmt)))))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cnt | depends_on | |
-----+------------------------- | |
2 | metabase.search.util | |
1 | metabase.search.config | |
1 | metabase.search.filter | |
1 | metabase.search.scoring | |
(4 rows) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
WITH deps AS ( | |
SELECT | |
dependency.namespace, | |
n1.module AS module, | |
dependency.depends_on, | |
n2.module AS depends_on_module | |
FROM | |
dependency | |
LEFT JOIN | |
namespace n1 | |
ON | |
dependency.namespace = n1.namespace | |
LEFT JOIN | |
namespace n2 | |
ON | |
dependency.depends_on = n2.namespace | |
WHERE | |
n1.module IS NOT NULL | |
AND | |
n2.module IS NOT NULL | |
) | |
SELECT | |
count(*) AS cnt, | |
depends_on | |
FROM deps | |
WHERE depends_on_module = 'metabase.search' | |
AND module <> 'metabase.search' | |
GROUP BY depends_on | |
ORDER BY cnt DESC; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment