<commit_before>(ns metabase.api.meta.db
  "/api/meta/db endpoints."
  (:require [compojure.core :refer [GET POST PUT DELETE]]
            [korma.core :refer :all]
            [medley.core :as medley]
            [metabase.api.common :refer :all]
            [metabase.db :refer :all]
            [metabase.driver :as driver]
            [metabase.driver.postgres.sync :as pgsync]
            (metabase.models common
                             [hydrate :refer [hydrate]]
                             [database :refer [Database]]
                             [field :refer [Field]]
                             [org :refer [org-can-read org-can-write]]
                             [table :refer [Table]])))

(defendpoint GET "/" [org]
  (check-403 (org-can-read org))
  (-> (sel :many Database :organization_id org (order :name))
      (hydrate :organization)))

(defendpoint POST "/" [:as {{:keys [org] :as body} :body}]
  (check-403 (org-can-write org))
  (->> (-> body
           (select-keys [:name :engine :details])
           (assoc :organization_id org))
       (medley/mapply ins Database)))

(defendpoint GET "/form_input" []
  {:timezones metabase.models.common/timezones
   :engines driver/available-drivers})

(defendpoint GET "/:id" [id]
  (->404 (sel :one Database :id id)
         (hydrate :organization)))

(defendpoint PUT "/:id" [id :as {{:keys [name engine details]} :body}]
  (println name engine details)
  (write-check Database id)
  (check-500 (upd Database id :name name :engine engine :details details)))

(defendpoint DELETE "/:id" [id]
  (write-check Database id)
  (del Database :id id))

(defendpoint GET "/:id/autocomplete_suggestions" [id prefix]
  (read-check Database id)
  (let [prefix-len (count prefix)
        table-id->name (->> (sel :many [Table :id :name] :db_id id)                                             ; fetch all name + ID of all Tables for this DB
                            (map (fn [{:keys [id name]}]                                                         ; make a map of Table ID -> Table Name
                                   {id name}))
                            (apply merge {}))
        matching-tables (->> (vals table-id->name)                                                              ; get all Table names that start with PREFIX
                             (filter (fn [^String table-name]
                                       (= prefix (.substring table-name 0 prefix-len))))
                             (map (fn [table-name]                                                               ; return them in the format [table_name "Table"]
                                    [table-name "Table"])))
        fields (->> (sel :many [Field :name :base_type :special_type :table_id]                                 ; get all Fields with names that start with PREFIX
                         :table_id [in (keys table-id->name)]                                                   ; whose Table is in this DB
                         :name [like (str prefix "%")])
                    (map (fn [{:keys [name base_type special_type table_id]}]                                    ; return them in the format
                           [name (str (table-id->name table_id) " " base_type (when special_type                ; [field_name "table_name base_type special_type"]
                                                                                (str " " special_type)))])))]
    (concat matching-tables fields)))                                                                           ; return combined seq of Fields + Tables

(defendpoint GET "/:id/tables" [id]
  (sel :many Table :db_id id (order :name)))

(defendpoint POST "/:id/sync" [id]
  (let-404 [db (sel :one Database :id id)]   ; TODO - run sync-tables asynchronously
           (pgsync/sync-tables db))          ; TODO - this only works for Postgres right now (since that's the only driver we have)
  {:status :ok})

(define-routes)<commit_msg>Call correct driver implementation for sync DB<commit_after>(ns metabase.api.meta.db
  "/api/meta/db endpoints."
  (:require [compojure.core :refer [GET POST PUT DELETE]]
            [korma.core :refer :all]
            [medley.core :as medley]
            [metabase.api.common :refer :all]
            [metabase.db :refer :all]
            [metabase.driver :as driver]
            [metabase.driver.sync :as sync]
            (metabase.models common
                             [hydrate :refer [hydrate]]
                             [database :refer [Database]]
                             [field :refer [Field]]
                             [org :refer [org-can-read org-can-write]]
                             [table :refer [Table]])))

(defendpoint GET "/" [org]
  (check-403 (org-can-read org))
  (-> (sel :many Database :organization_id org (order :name))
      (hydrate :organization)))

(defendpoint POST "/" [:as {{:keys [org] :as body} :body}]
  (check-403 (org-can-write org))
  (->> (-> body
           (select-keys [:name :engine :details])
           (assoc :organization_id org))
       (medley/mapply ins Database)))

(defendpoint GET "/form_input" []
  {:timezones metabase.models.common/timezones
   :engines driver/available-drivers})

(defendpoint GET "/:id" [id]
  (->404 (sel :one Database :id id)
         (hydrate :organization)))

(defendpoint PUT "/:id" [id :as {{:keys [name engine details]} :body}]
  (println name engine details)
  (write-check Database id)
  (check-500 (upd Database id :name name :engine engine :details details)))

(defendpoint DELETE "/:id" [id]
  (write-check Database id)
  (del Database :id id))

(defendpoint GET "/:id/autocomplete_suggestions" [id prefix]
  (read-check Database id)
  (let [prefix-len (count prefix)
        table-id->name (->> (sel :many [Table :id :name] :db_id id)                                             ; fetch all name + ID of all Tables for this DB
                            (map (fn [{:keys [id name]}]                                                         ; make a map of Table ID -> Table Name
                                   {id name}))
                            (apply merge {}))
        matching-tables (->> (vals table-id->name)                                                              ; get all Table names that start with PREFIX
                             (filter (fn [^String table-name]
                                       (= prefix (.substring table-name 0 prefix-len))))
                             (map (fn [table-name]                                                               ; return them in the format [table_name "Table"]
                                    [table-name "Table"])))
        fields (->> (sel :many [Field :name :base_type :special_type :table_id]                                 ; get all Fields with names that start with PREFIX
                         :table_id [in (keys table-id->name)]                                                   ; whose Table is in this DB
                         :name [like (str prefix "%")])
                    (map (fn [{:keys [name base_type special_type table_id]}]                                    ; return them in the format
                           [name (str (table-id->name table_id) " " base_type (when special_type                ; [field_name "table_name base_type special_type"]
                                                                                (str " " special_type)))])))]
    (concat matching-tables fields)))                                                                           ; return combined seq of Fields + Tables

(defendpoint GET "/:id/tables" [id]
  (sel :many Table :db_id id (order :name)))

(defendpoint POST "/:id/sync" [id]
  (let-404 [db (sel :one Database :id id)]   ; TODO - run sync-tables asynchronously
           (sync/sync-tables db))
  {:status :ok})

(define-routes)
{'fraction_non_alphanumeric': 0.11713995943204868, 'fraction_numerical': 0.004056795131845842, 'mean_word_length': 1.4103269172013444, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5082146', 'n_tokens_mistral': 2099, 'n_tokens_neox': 2028, 'n_words': 652}