From 724855886fcc7adcdddf9be360bf1fc1c6fbbb7b Mon Sep 17 00:00:00 2001
From: Cam Saul <1455846+camsaul@users.noreply.github.com>
Date: Tue, 25 Apr 2023 20:27:26 -0700
Subject: [PATCH] MLv2: use kebab-case keys in Clojure & camelCase in JS
 (#30248)

* MLv2: use kebab-case keys in Clojure & camelCase in JS

* Revert changes to tests
---
 .clj-kondo/config.edn                         |   25 +-
 .../advanced_config/file.clj                  |    6 +-
 .../src/metabase-lib/order_by.unit.spec.ts    |   46 +-
 frontend/src/metabase-lib/types.ts            |   25 +-
 .../QueryColumnPicker/QueryColumnPicker.tsx   |   10 +-
 .../QueryColumnPicker.unit.spec.tsx           |    2 +-
 .../notebook/steps/SortStep/SortStep.tsx      |    2 +-
 .../steps/SortStep/SortStep.unit.spec.tsx     |   12 +-
 .../metabase/test/data/bigquery_cloud_sdk.clj |    5 +-
 .../test/metabase/test/data/presto_jdbc.clj   |    8 +-
 src/metabase/analytics/snowplow.clj           |    4 +-
 src/metabase/cmd/env_var_dox.clj              |    2 +-
 src/metabase/domain_entities/converters.cljs  |   10 +-
 src/metabase/lib/aggregation.cljc             |    6 +-
 src/metabase/lib/card.cljc                    |   44 +-
 src/metabase/lib/column_group.cljc            |   20 +-
 src/metabase/lib/convert.cljc                 |    8 +-
 src/metabase/lib/expression.cljc              |   27 +-
 src/metabase/lib/field.cljc                   |   38 +-
 src/metabase/lib/join.cljc                    |    6 +-
 src/metabase/lib/js.cljs                      |    7 +-
 src/metabase/lib/js/metadata.cljs             |   62 +-
 src/metabase/lib/metadata.cljc                |  155 +-
 .../lib/metadata/cached_provider.cljc         |   17 +-
 src/metabase/lib/metadata/calculation.cljc    |   44 +-
 src/metabase/lib/metadata/jvm.clj             |   39 +-
 src/metabase/lib/metric.cljc                  |    2 +-
 src/metabase/lib/order_by.cljc                |    2 +-
 src/metabase/lib/query.cljc                   |   89 +-
 src/metabase/lib/ref.cljc                     |    2 +-
 src/metabase/lib/segment.cljc                 |    2 +-
 src/metabase/lib/stage.cljc                   |   20 +-
 src/metabase/lib/table.cljc                   |    4 +-
 src/metabase/lib/temporal_bucket.cljc         |   45 +-
 src/metabase/lib/types/constants.cljc         |   30 +-
 src/metabase/lib/types/isa.cljc               |   61 +-
 src/metabase/lib/util.cljc                    |   37 +-
 src/metabase/models/interface.clj             |   10 +-
 src/metabase/models/metric.clj                |    2 +-
 src/metabase/models/segment.clj               |    2 +-
 src/metabase/util.cljc                        |  123 +-
 test/metabase/lib/aggregation_test.cljc       |   33 +-
 test/metabase/lib/breakout_test.cljc          |  162 +-
 test/metabase/lib/card_test.cljc              |   54 +-
 test/metabase/lib/column_group_test.cljc      |  180 +-
 test/metabase/lib/dev_test.cljc               |    1 -
 test/metabase/lib/expression_test.cljc        |   27 +-
 test/metabase/lib/field_test.cljc             |   64 +-
 test/metabase/lib/filter_test.cljc            |    1 -
 test/metabase/lib/join_test.cljc              |   17 +-
 test/metabase/lib/metadata/jvm_test.clj       |   13 +-
 test/metabase/lib/metadata_test.cljc          |    8 +-
 test/metabase/lib/metric_test.cljc            |    4 +-
 test/metabase/lib/order_by_test.cljc          |  395 ++-
 test/metabase/lib/query_test.cljc             |   15 +-
 test/metabase/lib/stage_test.cljc             |   36 +-
 test/metabase/lib/temporal_bucket_test.cljc   |    3 +-
 test/metabase/lib/test_metadata.cljc          | 2262 +++++++++--------
 test/metabase/lib/test_util.cljc              |   32 +-
 test/metabase/lib/types/isa_test.cljc         |   92 +-
 test/metabase/util_test.cljc                  |   39 +-
 61 files changed, 2328 insertions(+), 2171 deletions(-)

diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn
index 9c43a27f149..29f439e79fd 100644
--- a/.clj-kondo/config.edn
+++ b/.clj-kondo/config.edn
@@ -162,8 +162,9 @@
    toucan.models/model?          {:message "Use mdb.u/toucan-model? instead of toucan.models/model?"}}
 
   :discouraged-namespace
-  {clojure.tools.logging {:message "Use metabase.util.log instead of clojure.tools.logging directly"}
-   metabase.util.jvm     {:message "All of metabase.util.jvm is re-exported from metabase.util; prefer that"}}
+  {camel-snake-kebab.core {:message "CSK is not Turkish-safe, use the versions in metabase.util instead."}
+   clojure.tools.logging  {:message "Use metabase.util.log instead of clojure.tools.logging directly"}
+   metabase.util.jvm      {:message "All of metabase.util.jvm is re-exported from metabase.util; prefer that"}}
 
   :unresolved-var
   {:exclude
@@ -712,10 +713,16 @@
   ;; to the new stricter rules from day 1
   metabase-lib
   {:linters
-   {:docstring-leading-trailing-whitespace                 {:level :warning}
-    :reduce-without-init                                   {:level :warning}
-    :used-underscored-binding                              {:level :warning}
-    :single-key-in                                         {:level :warning}
-    :keyword-binding                                       {:level :warning}
-    :shadowed-var                                          {:level :warning}
-    :metabase/deftest-not-marked-parallel-or-synchronized  {:level :warning}}}}}
+   {:docstring-leading-trailing-whitespace                {:level :warning}
+    :reduce-without-init                                  {:level :warning}
+    :used-underscored-binding                             {:level :warning}
+    :single-key-in                                        {:level :warning}
+    :keyword-binding                                      {:level :warning}
+    :shadowed-var                                         {:level :warning}
+    :metabase/deftest-not-marked-parallel-or-synchronized {:level :warning}
+
+    ;; eventually we should do this for the whole codebase, but the args are in the opposite order so switching them
+    ;; all at once isn't trivial, at least we can stop using it in new code.
+    :discouraged-var
+    {medley.core/map-keys {:message "Use clojure.core/update-keys"}
+     medley.core/map-vals {:message "Use clojure.core/update-vals"}}}}}}
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj
index 02a459becc9..a8c0f346cbd 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/file.clj
@@ -91,14 +91,14 @@
   {{env user-dir}}
   ```"
   (:require
-   [camel-snake-kebab.core :as csk]
    [clojure.edn :as edn]
    [clojure.spec.alpha :as s]
    [clojure.string :as str]
    [clojure.walk :as walk]
    [environ.core :as env]
    [metabase-enterprise.advanced-config.file.databases]
-   [metabase-enterprise.advanced-config.file.interface :as advanced-config.file.i]
+   [metabase-enterprise.advanced-config.file.interface
+    :as advanced-config.file.i]
    [metabase-enterprise.advanced-config.file.settings]
    [metabase-enterprise.advanced-config.file.users]
    [metabase.driver.common.parameters]
@@ -183,7 +183,7 @@
 
 (defmethod expand-parsed-template-form 'env
   [[_template-type env-var-name]]
-  (get *env* (csk/->kebab-case-keyword env-var-name)))
+  (get *env* (keyword (u/->kebab-case-en env-var-name))))
 
 (defmulti ^:private expand-template-str-part
   {:arglists '([part])}
diff --git a/frontend/src/metabase-lib/order_by.unit.spec.ts b/frontend/src/metabase-lib/order_by.unit.spec.ts
index 987a4fc68f9..c5a31660483 100644
--- a/frontend/src/metabase-lib/order_by.unit.spec.ts
+++ b/frontend/src/metabase-lib/order_by.unit.spec.ts
@@ -37,17 +37,17 @@ describe("order by", () => {
       expect(ML.displayInfo(query, ordersID)).toEqual(
         expect.objectContaining({
           name: "ID",
-          display_name: "ID",
-          effective_type: "type/BigInteger",
-          semantic_type: "type/PK",
-          is_calculated: false,
-          is_from_join: false,
-          is_from_previous_stage: false,
-          is_implicitly_joinable: false,
+          displayName: "ID",
+          effectiveType: "type/BigInteger",
+          semanticType: "type/PK",
+          isCalculated: false,
+          isFromJoin: false,
+          isFromPreviousStage: false,
+          isImplicitlyJoinable: false,
           table: {
             name: "ORDERS",
-            display_name: "Orders",
-            is_source_table: true,
+            displayName: "Orders",
+            isSourceTable: true,
           },
         }),
       );
@@ -59,17 +59,17 @@ describe("order by", () => {
       expect(ML.displayInfo(query, productsTitle)).toEqual(
         expect.objectContaining({
           name: "TITLE",
-          display_name: "Title",
-          effective_type: "type/Text",
-          semantic_type: "type/Category",
-          is_calculated: false,
-          is_from_join: false,
-          is_from_previous_stage: false,
-          is_implicitly_joinable: true,
+          displayName: "Title",
+          effectiveType: "type/Text",
+          semanticType: "type/Category",
+          isCalculated: false,
+          isFromJoin: false,
+          isFromPreviousStage: false,
+          isImplicitlyJoinable: true,
           table: {
             name: "PRODUCTS",
-            display_name: "Products",
-            is_source_table: false,
+            displayName: "Products",
+            isSourceTable: false,
           },
         }),
       );
@@ -104,8 +104,8 @@ describe("order by", () => {
         (columnMetadata: ML.ColumnMetadata) => {
           const displayInfo = ML.displayInfo(query, columnMetadata);
           return (
-            displayInfo.display_name === "Title" &&
-            displayInfo.table?.display_name === "Product Model"
+            displayInfo.displayName === "Title" &&
+            displayInfo.table?.displayName === "Product Model"
           );
         },
       );
@@ -113,9 +113,9 @@ describe("order by", () => {
       expect(ML.displayInfo(query, productsTitle as ML.ColumnMetadata)).toEqual(
         expect.objectContaining({
           name: field.name,
-          display_name: field.display_name,
-          effective_type: field.base_type,
-          table: { name: "Product Model", display_name: "Product Model" },
+          displayName: field.display_name,
+          effectiveType: field.base_type,
+          table: { name: "Product Model", displayName: "Product Model" },
         }),
       );
     });
diff --git a/frontend/src/metabase-lib/types.ts b/frontend/src/metabase-lib/types.ts
index 1d571628cb7..806769b0041 100644
--- a/frontend/src/metabase-lib/types.ts
+++ b/frontend/src/metabase-lib/types.ts
@@ -25,32 +25,33 @@ export type ColumnGroup = unknown & { _opaque: typeof ColumnGroup };
 
 export type TableDisplayInfo = {
   name: string;
-  display_name: string;
-  is_source_table: boolean;
-  is_from_join: boolean;
-  is_implicitly_joinable: boolean;
+  displayName: string;
+  isSourceTable: boolean;
+  isFromJoin: boolean;
+  isImplicitlyJoinable: boolean;
 };
 
 type TableInlineDisplayInfo = Pick<
   TableDisplayInfo,
-  "name" | "display_name" | "is_source_table"
+  "name" | "displayName" | "isSourceTable"
 >;
 
 export type ColumnDisplayInfo = {
   name: string;
-  display_name: string;
-  fk_reference_name?: string;
-  semantic_type?: string | null;
-  effective_type: string;
+  displayName: string;
+  fkReferenceName?: string;
+  // TODO -- pretty sure the types were removed?
+  semanticType?: string | null;
+  effectiveType: string;
   is_calculated: boolean;
-  is_from_join: boolean;
-  is_implicitly_joinable: boolean;
+  isFromJoin: boolean;
+  isImplicitlyJoinable: boolean;
   table?: TableInlineDisplayInfo;
 };
 
 export type OrderByClauseDisplayInfo = Pick<
   ColumnDisplayInfo,
-  "name" | "display_name" | "effective_type" | "semantic_type" | "table"
+  "name" | "displayName" | "effectiveType" | "semanticType" | "table"
 > & {
   direction: OrderByDirection;
 };
diff --git a/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.tsx b/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.tsx
index d3d399e8ca2..a4b5c2bee59 100644
--- a/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.tsx
+++ b/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.tsx
@@ -81,7 +81,7 @@ function QueryColumnPicker({
 }
 
 function renderItemName(item: ColumnListItem) {
-  return item.display_name;
+  return item.displayName;
 }
 
 function omitItemDescription() {
@@ -95,17 +95,17 @@ function renderItemIcon(item: ColumnListItem) {
 function getGroupName(groupInfo: Lib.ColumnDisplayInfo | Lib.TableDisplayInfo) {
   const columnInfo = groupInfo as Lib.ColumnDisplayInfo;
   const tableInfo = groupInfo as Lib.TableDisplayInfo;
-  return columnInfo.fk_reference_name || singularize(tableInfo.display_name);
+  return columnInfo.fkReferenceName || singularize(tableInfo.displayName);
 }
 
 function getGroupIcon(groupInfo: Lib.ColumnDisplayInfo | Lib.TableDisplayInfo) {
-  if ((groupInfo as Lib.TableDisplayInfo).is_source_table) {
+  if ((groupInfo as Lib.TableDisplayInfo).isSourceTable) {
     return "table";
   }
-  if (groupInfo.is_from_join) {
+  if (groupInfo.isFromJoin) {
     return "join_left_outer";
   }
-  if (groupInfo.is_implicitly_joinable) {
+  if (groupInfo.isImplicitlyJoinable) {
     return "connections";
   }
   return;
diff --git a/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.unit.spec.tsx b/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.unit.spec.tsx
index 76177cb6345..35def95eec1 100644
--- a/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.unit.spec.tsx
+++ b/frontend/src/metabase/common/components/QueryColumnPicker/QueryColumnPicker.unit.spec.tsx
@@ -62,7 +62,7 @@ describe("QueryColumnPicker", () => {
   it("should allow picking a column", async () => {
     const { sampleColumn, sampleColumnInfo, onSelect, onClose } = setup();
 
-    userEvent.click(screen.getByText(sampleColumnInfo.display_name));
+    userEvent.click(screen.getByText(sampleColumnInfo.displayName));
 
     expect(onSelect).toHaveBeenCalledWith(sampleColumn);
     expect(onClose).toHaveBeenCalled();
diff --git a/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.tsx b/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.tsx
index 056fc8655d1..2795ff83d72 100644
--- a/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.tsx
+++ b/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.tsx
@@ -103,7 +103,7 @@ function SortDisplayName({
       }}
     >
       <Icon name={icon} />
-      <span>{displayInfo.display_name}</span>
+      <span>{displayInfo.displayName}</span>
     </SortDirectionButton>
   );
 }
diff --git a/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.unit.spec.tsx b/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.unit.spec.tsx
index 9565e15afe7..8b99a9c9cd2 100644
--- a/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.unit.spec.tsx
+++ b/frontend/src/metabase/query_builder/components/notebook/steps/SortStep/SortStep.unit.spec.tsx
@@ -58,7 +58,7 @@ describe("SortStep", () => {
 
     setup(createMockNotebookStep({ topLevelQuery: query }));
 
-    expect(screen.getByText(columnInfo.display_name)).toBeInTheDocument();
+    expect(screen.getByText(columnInfo.displayName)).toBeInTheDocument();
     expect(getIcon("arrow_up")).toBeInTheDocument();
     expect(queryIcon("arrow_down")).not.toBeInTheDocument();
   });
@@ -68,7 +68,7 @@ describe("SortStep", () => {
 
     setup(createMockNotebookStep({ topLevelQuery: query }));
 
-    expect(screen.getByText(columnInfo.display_name)).toBeInTheDocument();
+    expect(screen.getByText(columnInfo.displayName)).toBeInTheDocument();
     expect(getIcon("arrow_down")).toBeInTheDocument();
     expect(queryIcon("arrow_up")).not.toBeInTheDocument();
   });
@@ -98,7 +98,7 @@ describe("SortStep", () => {
     userEvent.click(screen.getByText("Created At"));
 
     const orderBy = gerRecentOrderByClause();
-    expect(orderBy.display_name).toBe("Created At");
+    expect(orderBy.displayName).toBe("Created At");
     expect(orderBy.direction).toBe("asc");
   });
 
@@ -112,7 +112,7 @@ describe("SortStep", () => {
 
     const orderBy = gerRecentOrderByClause();
     expect(orderBy.direction).toBe("desc");
-    expect(orderBy.display_name).toBe(columnInfo.display_name);
+    expect(orderBy.displayName).toBe(columnInfo.displayName);
   });
 
   it("should change ordered field", () => {
@@ -121,11 +121,11 @@ describe("SortStep", () => {
       createMockNotebookStep({ topLevelQuery: query }),
     );
 
-    userEvent.click(screen.getByText(columnInfo.display_name));
+    userEvent.click(screen.getByText(columnInfo.displayName));
     userEvent.click(screen.getByText("Created At"));
 
     const orderBy = gerRecentOrderByClause();
-    expect(orderBy.display_name).toBe("Created At");
+    expect(orderBy.displayName).toBe("Created At");
   });
 
   it("should remove an order by", () => {
diff --git a/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj
index e77c86f0202..14c778cbfa8 100644
--- a/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj
+++ b/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj
@@ -90,8 +90,9 @@
 
 ;;; -------------------------------------------------- Loading Data --------------------------------------------------
 
-(defmethod ddl.i/format-name :bigquery-cloud-sdk [_ table-or-field-name]
-  (u/snake-key table-or-field-name))
+(defmethod ddl.i/format-name :bigquery-cloud-sdk
+  [_driver table-or-field-name]
+  (str/replace table-or-field-name #"-" "_"))
 
 (defn- create-dataset! [^String dataset-id]
   {:pre [(seq dataset-id)]}
diff --git a/modules/drivers/presto-jdbc/test/metabase/test/data/presto_jdbc.clj b/modules/drivers/presto-jdbc/test/metabase/test/data/presto_jdbc.clj
index 00d3906eeae..12707babfc5 100644
--- a/modules/drivers/presto-jdbc/test/metabase/test/data/presto_jdbc.clj
+++ b/modules/drivers/presto-jdbc/test/metabase/test/data/presto_jdbc.clj
@@ -15,7 +15,6 @@
    [metabase.test.data.sql-jdbc.execute :as execute]
    [metabase.test.data.sql-jdbc.load-data :as load-data]
    [metabase.test.data.sql.ddl :as ddl]
-   [metabase.util :as u]
    [metabase.util.log :as log])
   (:import
    (java.sql Connection DriverManager PreparedStatement)))
@@ -147,7 +146,7 @@
 
 (defmethod sql.tx/qualified-name-components :presto-jdbc
   ;; use the default schema from the in-memory connector
-  ([_ _db-name]                       [test-catalog-name "default"])
+  ([_ _db-name]                      [test-catalog-name "default"])
   ([_ db-name table-name]            [test-catalog-name "default" (tx/db-qualified-table-name db-name table-name)])
   ([_ db-name table-name field-name] [test-catalog-name "default" (tx/db-qualified-table-name db-name table-name) field-name]))
 
@@ -172,8 +171,9 @@
       (is (= "CREATE TABLE \"test_data\".\"default\".\"categories\" (\"id\" INTEGER, \"name\" VARCHAR) ;"
              (sql.tx/create-table-sql :presto-jdbc db-def table-def))))))
 
-(defmethod ddl.i/format-name :presto-jdbc [_ table-or-field-name]
-  (u/snake-key table-or-field-name))
+(defmethod ddl.i/format-name :presto-jdbc
+  [_driver table-or-field-name]
+  (str/replace table-or-field-name #"-" "_"))
 
 ;; Presto doesn't support FKs, at least not adding them via DDL
 (defmethod sql.tx/add-fk-sql :presto-jdbc
diff --git a/src/metabase/analytics/snowplow.clj b/src/metabase/analytics/snowplow.clj
index dfe298c7009..41cbf222ec6 100644
--- a/src/metabase/analytics/snowplow.clj
+++ b/src/metabase/analytics/snowplow.clj
@@ -1,13 +1,13 @@
 (ns metabase.analytics.snowplow
   "Functions for sending Snowplow analytics events"
   (:require
+   [clojure.string :as str]
    [java-time :as t]
    [medley.core :as m]
    [metabase.config :as config]
    [metabase.models.setting :as setting :refer [defsetting Setting]]
    [metabase.models.user :refer [User]]
    [metabase.public-settings :as public-settings]
-   [metabase.util :as u]
    [metabase.util.date-2 :as u.date]
    [metabase.util.i18n :refer [deferred-tru trs]]
    [metabase.util.log :as log]
@@ -172,7 +172,7 @@
 
 (defn- normalize-kw
   [kw]
-  (-> kw u/snake-key name))
+  (-> kw name (str/replace #"-" "_")))
 
 (defn- payload
   "A SelfDescribingJson object containing the provided event data, which can be included as the payload for an
diff --git a/src/metabase/cmd/env_var_dox.clj b/src/metabase/cmd/env_var_dox.clj
index a9ea7787276..b4bb0d9eae9 100644
--- a/src/metabase/cmd/env_var_dox.clj
+++ b/src/metabase/cmd/env_var_dox.clj
@@ -50,7 +50,7 @@
 (defn- format-prefix
   "Used to build an environment variable."
   [env-var]
-  (str "MB_" (u/screaming-snake-case (name (:name env-var)))))
+  (str "MB_" (u/->SCREAMING_SNAKE_CASE_EN (name (:name env-var)))))
 
 (defn- format-heading
   "Takes an integer and a string and creates a Markdown heading of level n."
diff --git a/src/metabase/domain_entities/converters.cljs b/src/metabase/domain_entities/converters.cljs
index 14b60ad080b..6e73517b335 100644
--- a/src/metabase/domain_entities/converters.cljs
+++ b/src/metabase/domain_entities/converters.cljs
@@ -1,13 +1,13 @@
 (ns metabase.domain-entities.converters
   (:require
-    [camel-snake-kebab.core :as csk]
     [malli.core :as mc]
-    [malli.transform :as mtx]))
+    [malli.transform :as mtx]
+    [metabase.util :as u]))
 
 (defn- decode-map [schema _]
   (let [by-prop (into {} (for [[map-key props] (mc/children schema)]
                            [(or (get props :js/prop)
-                                (csk/->snake_case_string map-key))
+                                (u/->snake_case_en (u/qualified-name map-key)))
                             {:map-key map-key}]))]
     {:enter (fn [x]
               (cond
@@ -16,7 +16,7 @@
                 (into {} (for [prop (js-keys x)
                                :let [js-val  (unchecked-get x prop)
                                      map-key (or (get-in by-prop [prop :map-key])
-                                                 (csk/->kebab-case-keyword prop))]]
+                                                 (keyword (u/->kebab-case-en prop)))]]
                            [map-key js-val]))))
      :leave (fn [x]
               (if (object? x)
@@ -127,7 +127,7 @@
                                                                  :when (:js/prop props)]
                                                              [k (:js/prop props)]))
                                          keyenc   (fn [k] (or (get js-props k)
-                                                              (csk/->snake_case_string k)))]
+                                                              (u/->snake_case_en (u/qualified-name k))))]
                                      {:leave #(encode-map % keyenc)}))}
              :map-of            {:leave #(encode-map % name)}})}))
 
diff --git a/src/metabase/lib/aggregation.cljc b/src/metabase/lib/aggregation.cljc
index 54e7f792935..9e7c1dcf4b6 100644
--- a/src/metabase/lib/aggregation.cljc
+++ b/src/metabase/lib/aggregation.cljc
@@ -17,7 +17,7 @@
   "Given `:metadata/field` column metadata for an aggregation, construct an `:aggregation` reference."
   [metadata :- lib.metadata/ColumnMetadata]
   (let [options {:lib/uuid       (str (random-uuid))
-                 :effective-type ((some-fn :effective_type :base_type) metadata)}
+                 :effective-type ((some-fn :effective-type :base-type) metadata)}
         index   (::aggregation-index metadata)]
     (assert (integer? index) "Metadata for an aggregation reference should include ::aggregation-index")
     [:aggregation options index]))
@@ -51,9 +51,9 @@
      {:lib/source         :source/aggregations
       ::aggregation-index index}
      (when base-type
-       {:base_type base-type})
+       {:base-type base-type})
      (when effective-type
-       {:effective_type effective-type}))))
+       {:effective-type effective-type}))))
 
 ;;; TODO -- merge this stuff into `defop` somehow.
 
diff --git a/src/metabase/lib/card.cljc b/src/metabase/lib/card.cljc
index 99c34a98277..bbb0f57b461 100644
--- a/src/metabase/lib/card.cljc
+++ b/src/metabase/lib/card.cljc
@@ -4,29 +4,37 @@
    [metabase.lib.metadata :as lib.metadata]
    [metabase.lib.metadata.calculation :as lib.metadata.calculation]
    [metabase.lib.query :as lib.query]
-   [metabase.lib.schema :as lib.schema]
    [metabase.lib.schema.id :as lib.schema.id]
+   [metabase.util :as u]
    [metabase.util.humanization :as u.humanization]
    [metabase.util.malli :as mu]))
 
 (defmethod lib.metadata.calculation/display-name-method :metadata/card
   [_query _stage-number card-metadata _style]
-  ((some-fn :display_name :name) card-metadata))
+  ((some-fn :display-name :name) card-metadata))
 
 (defmethod lib.metadata.calculation/metadata-method :metadata/card
-  [_query _stage-number {card-name :name, display-name :display_name, :as card-metadata}]
+  [_query _stage-number {card-name :name, :keys [display-name], :as card-metadata}]
   (cond-> card-metadata
-    (not display-name) (assoc :display_name (u.humanization/name->human-readable-name :simple card-name))))
+    (not display-name) (assoc :display-name (u.humanization/name->human-readable-name :simple card-name))))
 
-(defn- infer-results-metadata [metadata-provider card-query]
-  (lib.metadata.calculation/metadata (lib.query/query metadata-provider (lib.convert/->pMBQL card-query))))
+(mu/defn ^:private infer-results-metadata
+  [metadata-providerable :- lib.metadata/MetadataProviderable
+   card-query            :- :map]
+  (lib.metadata.calculation/metadata (lib.query/query metadata-providerable (lib.convert/->pMBQL card-query))))
 
-(defn- card-metadata-columns
-  [query card]
-  (when-let [result-metadata (or (:result_metadata card)
+(def ^:private Card
+  [:map
+   {:error/message "Card with :dataset-query"}
+   [:dataset-query :map]])
+
+(mu/defn ^:private card-metadata-columns
+  [metadata-providerable :- lib.metadata/MetadataProviderable
+   card                  :- Card]
+  (when-let [result-metadata (or (:result-metadata card)
                                  (:fields card)
-                                 (infer-results-metadata (:lib/metadata query) (:dataset_query card)))]
-    ;; Card `result_metadata` SHOULD be a sequence of column infos, but just to be safe handle a map that
+                                 (infer-results-metadata metadata-providerable (:dataset-query card)))]
+    ;; Card `result-metadata` SHOULD be a sequence of column infos, but just to be safe handle a map that
     ;; contains` :columns` as well.
     (when-let [cols (not-empty (cond
                                  (map? result-metadata)        (:columns result-metadata)
@@ -34,8 +42,8 @@
       (mapv (fn [col]
               (merge
                (when-let [field-id (:id col)]
-                 (lib.metadata/field query field-id))
-               col
+                 (lib.metadata/field metadata-providerable field-id))
+               (update-keys col u/->kebab-case-en)
                {:lib/type                :metadata/field
                 :lib/source              :source/card
                 :lib/card-id             (:id card)
@@ -44,12 +52,12 @@
 
 (mu/defn saved-question-metadata :- [:maybe [:sequential {:min 1} lib.metadata.calculation/ColumnMetadataWithSource]]
   "Metadata associated with a Saved Question with `card-id`."
-  [query   :- ::lib.schema/query
-   card-id :- ::lib.schema.id/card]
-  ;; it seems like in some cases (unit tests) the FE is renaming `:result_metadata` to `:fields`, not 100% sure why
+  [metadata-providerable :- lib.metadata/MetadataProviderable
+   card-id               :- ::lib.schema.id/card]
+  ;; it seems like in some cases (unit tests) the FE is renaming `:result-metadata` to `:fields`, not 100% sure why
   ;; but handle that case anyway. (#29739)
-  (when-let [card (lib.metadata/card query card-id)]
-    (card-metadata-columns query card)))
+  (when-let [card (lib.metadata/card metadata-providerable card-id)]
+    (card-metadata-columns metadata-providerable card)))
 
 (defmethod lib.metadata.calculation/default-columns-method :metadata/card
   [query _stage-number card unique-name-fn]
diff --git a/src/metabase/lib/column_group.cljc b/src/metabase/lib/column_group.cljc
index a8350ddc316..134bcafc72f 100644
--- a/src/metabase/lib/column_group.cljc
+++ b/src/metabase/lib/column_group.cljc
@@ -53,20 +53,20 @@
             (lib.metadata.calculation/display-info query stage-number table)))
         ;; for multi-stage queries return an empty string (#30108)
         (when (next (:stages query))
-          {:display_name ""})
+          {:display-name ""})
         ;; if this is a native query or something else that doesn't have a source Table or source Card then use the
         ;; stage display name.
-        {:display_name (lib.metadata.calculation/display-name query stage-number stage)}))
-     {:is_from_join           false
-      :is_implicitly_joinable false})
+        {:display-name (lib.metadata.calculation/display-name query stage-number stage)}))
+     {:is-from-join           false
+      :is-implicitly-joinable false})
 
     :group-type/join.explicit
     (merge
      (let [join-alias (:join-alias column-group)]
        (when-let [join (lib.join/resolve-join query stage-number join-alias)]
          (lib.metadata.calculation/display-info query stage-number join)))
-     {:is_from_join           true
-      :is_implicitly_joinable false})
+     {:is-from-join           true
+      :is-implicitly-joinable false})
 
     :group-type/join.implicit
     (merge
@@ -78,16 +78,16 @@
            ;; This is very intentional: one table might have several FKs to one foreign table, each with different
            ;; meaning (eg. ORDERS.customer_id vs. ORDERS.supplier_id both linking to a PEOPLE table).
            ;; See #30109 for more details.
-           (assoc field-info :fk_reference_name (lib.util/strip-id (:display_name field-info))))))
-     {:is_from_join           false
-      :is_implicitly_joinable true})))
+           (assoc field-info :fk-reference-name (lib.util/strip-id (:display-name field-info))))))
+     {:is-from-join           false
+      :is-implicitly-joinable true})))
 
 (mu/defn ^:private column-group-info :- [:map [::group-type GroupType]]
   "The value we should use to `group-by` inside [[group-columns]]."
   [{source :lib/source, :as column-metadata} :- lib.metadata/ColumnMetadata]
   (case source
     :source/implicitly-joinable
-    {::group-type :group-type/join.implicit, :fk-field-id (:fk_field_id column-metadata)}
+    {::group-type :group-type/join.implicit, :fk-field-id (:fk-field-id column-metadata)}
 
     :source/joins
     {::group-type :group-type/join.explicit, :join-alias (lib.join/current-join-alias column-metadata)}
diff --git a/src/metabase/lib/convert.cljc b/src/metabase/lib/convert.cljc
index d09f32d83c8..8b3763e52cf 100644
--- a/src/metabase/lib/convert.cljc
+++ b/src/metabase/lib/convert.cljc
@@ -254,6 +254,12 @@
   [input]
   (aggregation->legacy-MBQL input))
 
+(defn- stage-metadata->legacy-metadata [stage-metadata]
+  (into []
+        (comp (map #(update-keys % u/->snake_case_en))
+              (map ->legacy-MBQL))
+        (:columns stage-metadata)))
+
 (defn- chain-stages [{:keys [stages]}]
   ;; :source-metadata aka :lib/stage-metadata is handled differently in the two formats.
   ;; In legacy, an inner query might have both :source-query, and :source-metadata giving the metadata for that nested
@@ -264,7 +270,7 @@
   (let [inner-query (first (reduce (fn [[inner stage-metadata] stage]
                                      [(cond-> (->legacy-MBQL stage)
                                         inner          (assoc :source-query inner)
-                                        stage-metadata (assoc :source-metadata (mapv ->legacy-MBQL (:columns stage-metadata))))
+                                        stage-metadata (assoc :source-metadata (stage-metadata->legacy-metadata stage-metadata)))
                                       ;; Get the :lib/stage-metadata off the original pMBQL stage, not the converted one.
                                       (:lib/stage-metadata stage)])
                                    nil
diff --git a/src/metabase/lib/expression.cljc b/src/metabase/lib/expression.cljc
index 3bc6c3d7ae1..1dd22f978ec 100644
--- a/src/metabase/lib/expression.cljc
+++ b/src/metabase/lib/expression.cljc
@@ -14,6 +14,7 @@
    [metabase.lib.schema.expression :as lib.schema.expression]
    [metabase.lib.schema.temporal-bucketing
     :as lib.schema.temporal-bucketing]
+   [metabase.lib.temporal-bucket :as lib.temporal-bucket]
    [metabase.lib.util :as lib.util]
    [metabase.shared.util.i18n :as i18n]
    [metabase.types :as types]
@@ -23,8 +24,8 @@
   "Given `:metadata/field` column metadata for an expression, construct an `:expression` reference."
   [metadata :- lib.metadata/ColumnMetadata]
   (let [options {:lib/uuid       (str (random-uuid))
-                 :base-type      (:base_type metadata)
-                 :effective-type ((some-fn :effective_type :base_type) metadata)}]
+                 :base-type      (:base-type metadata)
+                 :effective-type ((some-fn :effective-type :base-type) metadata)}]
     [:expression options (:name metadata)]))
 
 (mu/defn resolve-expression :- ::lib.schema.expression/expression
@@ -49,8 +50,8 @@
   [query stage-number [_expression _opts expression-name, :as expression-ref]]
   {:lib/type     :metadata/field
    :name         expression-name
-   :display_name (lib.metadata.calculation/display-name query stage-number expression-ref)
-   :base_type    (lib.metadata.calculation/type-of query stage-number expression-ref)
+   :display-name (lib.metadata.calculation/display-name query stage-number expression-ref)
+   :base-type    (lib.metadata.calculation/type-of query stage-number expression-ref)
    :lib/source   :source/expressions})
 
 (defmethod lib.metadata.calculation/display-name-method :dispatch-type/integer
@@ -133,17 +134,13 @@
    (for [arg args]
      (lib.metadata.calculation/type-of query stage-number arg))))
 
+;;; TODO -- this stuff should probably be moved into [[metabase.lib.temporal-bucket]]
+
 (defn- interval-unit-str [amount unit]
-  (clojure.core/case unit
-    :millisecond (i18n/trun "millisecond" "milliseconds" (clojure.core/abs amount))
-    :second      (i18n/trun "second"      "seconds"      (clojure.core/abs amount))
-    :minute      (i18n/trun "minute"      "minutes"      (clojure.core/abs amount))
-    :hour        (i18n/trun "hour"        "hours"        (clojure.core/abs amount))
-    :day         (i18n/trun "day"         "days"         (clojure.core/abs amount))
-    :week        (i18n/trun "week"        "weeks"        (clojure.core/abs amount))
-    :month       (i18n/trun "month"       "months"       (clojure.core/abs amount))
-    :quarter     (i18n/trun "quarter"     "quarters"     (clojure.core/abs amount))
-    :year        (i18n/trun "year"        "years"        (clojure.core/abs amount))))
+  ;; this uses [[clojure.string/lower-case]] so its in the user's locale in the browser rather than always using
+  ;; English lower-casing rules.
+  #_{:clj-kondo/ignore [:discouraged-var]}
+  (str/lower-case (lib.temporal-bucket/describe-temporal-unit amount unit)))
 
 (mu/defn ^:private interval-display-name  :- ::lib.schema.common/non-blank-string
   "e.g. something like \"- 2 days\""
@@ -253,7 +250,7 @@
                     (-> (lib.metadata.calculation/metadata query stage-number expression-definition)
                         (assoc :lib/source   :source/expressions
                                :name         expression-name
-                               :display_name expression-name)))))))
+                               :display-name expression-name)))))))
 
 (defmethod lib.ref/ref-method :expression
   [expression-clause]
diff --git a/src/metabase/lib/field.cljc b/src/metabase/lib/field.cljc
index cf62c6535af..0ccbca9adb1 100644
--- a/src/metabase/lib/field.cljc
+++ b/src/metabase/lib/field.cljc
@@ -93,9 +93,9 @@
    [_field {:keys [join-alias], :as opts} id-or-name, :as _field-clause] :- :mbql.clause/field]
   (merge
    (when-let [base-type (:base-type opts)]
-     {:base_type base-type})
+     {:base-type base-type})
    (when-let [effective-type ((some-fn :effective-type :base-type) opts)]
-     {:effective_type effective-type})
+     {:effective-type effective-type})
    ;; TODO -- some of the other stuff in `opts` probably ought to be merged in here as well. Also, if the Field is
    ;; temporally bucketed, the base-type/effective-type would probably be affected, right? We should probably be
    ;; taking that into consideration?
@@ -113,9 +113,9 @@
   "If this is a nested column, add metadata about the parent column."
   [query    :- ::lib.schema/query
    metadata :- lib.metadata/ColumnMetadata]
-  (let [parent-metadata     (lib.metadata/field query (:parent_id metadata))
+  (let [parent-metadata     (lib.metadata/field query (:parent-id metadata))
         {parent-name :name} (cond->> parent-metadata
-                              (:parent_id parent-metadata) (add-parent-column-metadata query))]
+                              (:parent-id parent-metadata) (add-parent-column-metadata query))]
     (update metadata :name (fn [field-name]
                              (str parent-name \. field-name)))))
 
@@ -127,7 +127,7 @@
   (if (and temporal-unit
            (contains? lib.schema.temporal-bucketing/datetime-extraction-units temporal-unit))
     :type/Integer
-    ((some-fn :effective_type :base_type) column-metadata)))
+    ((some-fn :effective-type :base-type) column-metadata)))
 
 (defmethod lib.metadata.calculation/type-of-method :metadata/field
   [_query _stage-number column-metadata]
@@ -150,30 +150,30 @@
         metadata       (merge
                         {:lib/type :metadata/field}
                         field-metadata
-                        {:display_name (or (:display-name opts)
+                        {:display-name (or (:display-name opts)
                                            (lib.metadata.calculation/display-name query stage-number field-ref))}
                         (when effective-type
-                          {:effective_type effective-type})
+                          {:effective-type effective-type})
                         (when base-type
-                          {:base_type base-type})
+                          {:base-type base-type})
                         (when temporal-unit
                           {::temporal-unit temporal-unit})
                         (when join-alias
                           {::join-alias join-alias})
                         (when source-field
-                          {:fk_field_id source-field}))]
+                          {:fk-field-id source-field}))]
     (cond->> metadata
-      (:parent_id metadata) (add-parent-column-metadata query))))
+      (:parent-id metadata) (add-parent-column-metadata query))))
 
 ;;; this lives here as opposed to [[metabase.lib.metadata]] because that namespace is more of an interface namespace
 ;;; and moving this there would cause circular references.
 (defmethod lib.metadata.calculation/display-name-method :metadata/field
-  [query stage-number {field-display-name :display_name
+  [query stage-number {field-display-name :display-name
                        field-name         :name
                        temporal-unit      :unit
                        join-alias         :source_alias
-                       fk-field-id        :fk_field_id
-                       table-id           :table_id
+                       fk-field-id        :fk-field-id
+                       table-id           :table-id
                        :as                _field-metadata} style]
   (let [field-display-name (or field-display-name
                                (u.humanization/name->human-readable-name :simple field-name))
@@ -200,7 +200,7 @@
   (if-let [field-metadata (cond-> (resolve-field-metadata query stage-number field-clause)
                             join-alias    (assoc :source_alias join-alias)
                             temporal-unit (assoc :unit temporal-unit)
-                            source-field  (assoc :fk_field_id source-field))]
+                            source-field  (assoc :fk-field-id source-field))]
     (lib.metadata.calculation/display-name query stage-number field-metadata style)
     ;; mostly for the benefit of JS, which does not enforce the Malli schemas.
     (i18n/tru "[Unknown Field]")))
@@ -225,7 +225,7 @@
    (when (= (:lib/source field-metadata) :source/card)
      (when-let [card-id (:lib/card-id field-metadata)]
        (when-let [card (lib.metadata/card query card-id)]
-         {:table {:name (:name card), :display_name (:name card)}})))))
+         {:table {:name (:name card), :display-name (:name card)}})))))
 
 (defmethod lib.temporal-bucket/temporal-bucket-method :field
   [[_tag opts _id-or-name]]
@@ -274,7 +274,7 @@
 
 (defmethod lib.temporal-bucket/available-temporal-buckets-method :metadata/field
   [_query _stage-number field-metadata]
-  (let [effective-type ((some-fn :effective_type :base_type) field-metadata)]
+  (let [effective-type ((some-fn :effective-type :base-type) field-metadata)]
     (cond
       (isa? effective-type :type/DateTime) lib.schema.temporal-bucketing/datetime-bucketing-units
       (isa? effective-type :type/Date)     lib.schema.temporal-bucketing/date-bucketing-units
@@ -310,13 +310,13 @@
     :source/expressions  (lib.expression/column-metadata->expression-ref metadata)
     (let [options          (merge
                             {:lib/uuid       (str (random-uuid))
-                             :base-type      (:base_type metadata)
+                             :base-type      (:base-type metadata)
                              :effective-type (column-metadata-effective-type metadata)}
                             (when-let [join-alias (::join-alias metadata)]
                               {:join-alias join-alias})
                             (when-let [temporal-unit (::temporal-unit metadata)]
                               {:temporal-unit temporal-unit})
-                            (when-let [source-field-id (:fk_field_id metadata)]
+                            (when-let [source-field-id (:fk-field-id metadata)]
                               {:source-field source-field-id})
                             ;; TODO -- binning options.
                             )
@@ -325,7 +325,7 @@
                         (:name metadata)
                         (or (:id metadata) (:name metadata)))])))
 
-(defn- implicit-join-name [query {fk-field-id :fk_field_id, table-id :table_id, :as _field-metadata}]
+(defn- implicit-join-name [query {:keys [fk-field-id table-id], :as _field-metadata}]
   (when (and fk-field-id table-id)
     (when-let [table-metadata (lib.metadata/table query table-id)]
       (let [table-name           (:name table-metadata)
diff --git a/src/metabase/lib/join.cljc b/src/metabase/lib/join.cljc
index b87015678aa..96355fec9ac 100644
--- a/src/metabase/lib/join.cljc
+++ b/src/metabase/lib/join.cljc
@@ -69,7 +69,7 @@
   [query _stage-number {[first-stage] :stages, :as _join} _style]
   (if-let [source-table (:source-table first-stage)]
     (if (integer? source-table)
-      (:display_name (lib.metadata/table query source-table))
+      (:display-name (lib.metadata/table query source-table))
       ;; handle card__<id> source tables.
       (let [card-id (lib.util/string-table-id->card-id source-table)]
         (i18n/tru "Saved Question #{0}" card-id)))
@@ -78,7 +78,7 @@
 (defmethod lib.metadata.calculation/display-info-method :mbql/join
   [query stage-number join]
   (let [display-name (lib.metadata.calculation/display-name query stage-number join)]
-    {:name (or (:alias join) display-name), :display_name display-name}))
+    {:name (or (:alias join) display-name), :display-name display-name}))
 
 (mu/defn ^:private column-from-join-fields :- lib.metadata.calculation/ColumnMetadataWithSource
   "For a column that comes from a join `:fields` list, add or update metadata as needed, e.g. include join name in the
@@ -89,7 +89,7 @@
    join-alias      :- ::lib.schema.common/non-blank-string]
   (let [column-metadata (assoc column-metadata :source_alias join-alias)
         col             (-> (assoc column-metadata
-                                   :display_name (lib.metadata.calculation/display-name query stage-number column-metadata)
+                                   :display-name (lib.metadata.calculation/display-name query stage-number column-metadata)
                                    :lib/source   :source/joins)
                             (with-join-alias join-alias))]
     (assert (= (current-join-alias col) join-alias))
diff --git a/src/metabase/lib/js.cljs b/src/metabase/lib/js.cljs
index c61d51f372e..4705e470f0a 100644
--- a/src/metabase/lib/js.cljs
+++ b/src/metabase/lib/js.cljs
@@ -91,7 +91,7 @@
 (defn ^:export legacy-query
   "Coerce a CLJS pMBQL query back to (1) a legacy query (2) in vanilla JS."
   [query-map]
-  (-> query-map convert/->legacy-MBQL fix-namespaced-values clj->js))
+  (-> query-map convert/->legacy-MBQL fix-namespaced-values (clj->js :keyword-fn u/qualified-name)))
 
 (defn ^:export orderable-columns
   "Return a sequence of Column metadatas about the columns you can add order bys for in a given stage of `a-query.` To
@@ -103,11 +103,14 @@
 
 (defn ^:export display-info
   "Given an opaque Cljs object, return a plain JS object with info you'd need to implement UI for it.
-  See `:metabase.lib.metadata.calculation/display-info` for the keys this might contain."
+  See `:metabase.lib.metadata.calculation/display-info` for the keys this might contain. Note that the JS versions of
+  the keys are converted to the equivalent `camelCase` strings from the original `:kebab-case`."
   ([a-query x]
    (display-info a-query -1 x))
   ([a-query stage-number x]
    (-> (lib.core/display-info a-query stage-number x)
+       (update-keys u/->camelCaseEn)
+       (update :table update-keys u/->camelCaseEn)
        (clj->js :keyword-fn u/qualified-name))))
 
 (defn ^:export order-by-clause
diff --git a/src/metabase/lib/js/metadata.cljs b/src/metabase/lib/js/metadata.cljs
index 7da2ab71315..da57b755909 100644
--- a/src/metabase/lib/js/metadata.cljs
+++ b/src/metabase/lib/js/metadata.cljs
@@ -1,5 +1,6 @@
 (ns metabase.lib.js.metadata
   (:require
+   [clojure.core.protocols]
    [clojure.string :as str]
    [clojure.walk :as walk]
    [goog]
@@ -82,9 +83,9 @@
   (let [excluded-keys-set (excluded-keys object-type)
         parse-field       (parse-field-fn object-type)]
     (comp
-     ;; convert keys to keywords
+     ;; convert keys to kebab-case keywords
      (map (fn [[k v]]
-            [(keyword k) v]))
+            [(keyword (u/->kebab-case-en k)) v]))
      ;; remove [[excluded-keys]]
      (if (empty? excluded-keys-set)
        identity
@@ -138,9 +139,9 @@
   [_object-type]
   (fn [k v]
     (case k
-      :dbms_version       (js->clj v :keywordize-keys true)
+      :dbms-version       (js->clj v :keywordize-keys true)
       :features           (into #{} (map keyword) v)
-      :native_permissions (keyword v)
+      :native-permissions (keyword v)
       v)))
 
 (defmethod parse-objects-default-key :database
@@ -153,16 +154,16 @@
 
 (defmethod excluded-keys :table
   [_object-type]
-  #{:database :fields :segments :metrics :dimension_options})
+  #{:database :fields :segments :metrics :dimension-options})
 
 (defmethod parse-field-fn :table
   [_object-type]
   (fn [k v]
     (case k
-      :entity_type         (keyword v)
-      :field_order         (keyword v)
-      :initial_sync_status (keyword v)
-      :visibility_type     (keyword v)
+      :entity-type         (keyword v)
+      :field-order         (keyword v)
+      :initial-sync-status (keyword v)
+      :visibility-type     (keyword v)
       v)))
 
 (defmethod parse-objects :table
@@ -182,8 +183,8 @@
   [_object-type]
   #{:_comesFromEndpoint
     :database
-    :default_dimension_option
-    :dimension_options
+    :default-dimension-option
+    :dimension-options
     :dimensions
     :metrics
     :table})
@@ -192,13 +193,13 @@
   [_object-type]
   (fn [k v]
     (case k
-      :base_type         (keyword v)
-      :coercion_strategy (keyword v)
-      :effective_type    (keyword v)
+      :base-type         (keyword v)
+      :coercion-strategy (keyword v)
+      :effective-type    (keyword v)
       :fingerprint       (walk/keywordize-keys v)
-      :has_field_values  (keyword v)
-      :semantic_type     (keyword v)
-      :visibility_type   (keyword v)
+      :has-field-values  (keyword v)
+      :semantic-type     (keyword v)
+      :visibility-type   (keyword v)
       v)))
 
 (defmethod parse-objects-default-key :field
@@ -222,12 +223,12 @@
   [_object-type]
   (fn [k v]
     (case k
-      :result_metadata (if ((some-fn sequential? array?) v)
+      :result-metadata (if ((some-fn sequential? array?) v)
                          (parse-fields v)
                          (js->clj v :keywordize-keys true))
       :fields          (parse-fields v)
-      :visibility_type (keyword v)
-      :dataset_query   (js->clj v :keywordize-keys true)
+      :visibility-type (keyword v)
+      :dataset-query   (js->clj v :keywordize-keys true)
       ;; this is not complete, add more stuff as needed.
       v)))
 
@@ -323,19 +324,19 @@
 (defn- tables [metadata database-id]
   (for [[_id table-delay]  (some-> metadata :tables deref)
         :let               [a-table (some-> table-delay deref)]
-        :when              (and a-table (= (:db_id a-table) database-id))]
+        :when              (and a-table (= (:db-id a-table) database-id))]
     a-table))
 
 (defn- fields [metadata table-id]
   (for [[_id field-delay]  (some-> metadata :fields deref)
         :let               [a-field (some-> field-delay deref)]
-        :when              (and a-field (= (:table_id a-field) table-id))]
+        :when              (and a-field (= (:table-id a-field) table-id))]
     a-field))
 
 (defn metadata-provider
   "Use a `metabase-lib/metadata/Metadata` as a [[metabase.lib.metadata.protocols/MetadataProvider]]."
-  [database-id metadata]
-  (let [metadata (parse-metadata metadata)]
+  [database-id unparsed-metadata]
+  (let [metadata (parse-metadata unparsed-metadata)]
     (log/debug "Created metadata provider for metadata")
     (reify lib.metadata.protocols/MetadataProvider
       (database [_this]            (database metadata database-id))
@@ -345,4 +346,15 @@
       (segment  [_this segment-id] (segment  metadata segment-id))
       (card     [_this card-id]    (card     metadata card-id))
       (tables   [_this]            (tables   metadata database-id))
-      (fields   [_this table-id]   (fields   metadata table-id)))))
+      (fields   [_this table-id]   (fields   metadata table-id))
+
+      ;; for debugging: call [[clojure.datafy/datafy]] on one of these to parse all of our metadata and see the whole
+      ;; thing at once.
+      clojure.core.protocols/Datafiable
+      (datafy [_this]
+        (walk/postwalk
+         (fn [form]
+           (if (delay? form)
+             (deref form)
+             form))
+         metadata)))))
diff --git a/src/metabase/lib/metadata.cljc b/src/metabase/lib/metadata.cljc
index 7af8aa81c72..a7cca573ec9 100644
--- a/src/metabase/lib/metadata.cljc
+++ b/src/metabase/lib/metadata.cljc
@@ -1,7 +1,5 @@
 (ns metabase.lib.metadata
   (:require
-   [metabase.lib.dispatch :as lib.dispatch]
-   [metabase.lib.hierarchy :as lib.hierarchy]
    [metabase.lib.metadata.protocols :as lib.metadata.protocols]
    [metabase.lib.schema.common :as lib.schema.common]
    [metabase.lib.schema.id :as lib.schema.id]
@@ -70,19 +68,19 @@
    [:lib/type  [:= :metadata/field]] ; TODO -- should this be changed to `:metadata/column`?
    [:name      ::lib.schema.common/non-blank-string]
    ;; TODO -- ignore `base_type` and make `effective_type` required; see #29707
-   [:base_type ::lib.schema.common/base-type]
+   [:base-type ::lib.schema.common/base-type]
    [:id             {:optional true} ::lib.schema.id/field]
-   [:display_name   {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
-   [:effective_type {:optional true} [:maybe ::lib.schema.common/base-type]]
+   [:display-name   {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
+   [:effective-type {:optional true} [:maybe ::lib.schema.common/base-type]]
    ;; if this is a field from another table (implicit join), this is the field in the current table that should be
    ;; used to perform the implicit join. e.g. if current table is `VENUES` and this field is `CATEGORIES.ID`, then the
    ;; `fk_field_id` would be `VENUES.CATEGORY_ID`. In a `:field` reference this is saved in the options map as
    ;; `:source-field`.
-   [:fk_field_id    {:optional true} [:maybe ::lib.schema.id/field]]
+   [:fk-field-id    {:optional true} [:maybe ::lib.schema.id/field]]
    ;; Join alias of the table we're joining against, if any. Not really 100% clear why we would need this on top
    ;; of [[metabase.lib.join/current-join-alias]], which stores the same info under a namespaced key. I think we can
    ;; remove it.
-   [:source_alias   {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
+   [:source-alias   {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
    ;; what top-level clause in the query this metadata originated from, if it is calculated (i.e., if this metadata
    ;; was generated by [[metabase.lib.metadata.calculation/metadata]])
    [:lib/source     {:optional true} [:ref ::column-source]]
@@ -98,35 +96,43 @@
    [:lib/desired-column-alias {:optional true} [:maybe [:string {:min 1, :max 60}]]]])
 
 (def ^:private CardMetadata
+  "More or less the same as a [[metabase.models.card]], but with kebab-case keys. Note that the `:dataset-query` is not
+  necessarily converted to pMBQL yet. Probably safe to assume it is normalized however. Likewise, `:result-metadata`
+  is probably not quite massaged into a sequence of `ColumnMetadata`s just yet.
+  See [[metabase.lib.card/card-metadata-columns]] that converts these as needed."
   [:map
    [:lib/type [:= :metadata/card]]
-   [:id ::lib.schema.id/card]
-   [:name ::lib.schema.common/non-blank-string]])
+   [:id   ::lib.schema.id/card]
+   [:name ::lib.schema.common/non-blank-string]
+   ;; saved query. This is possibly still a legacy query, but should already be normalized.
+   ;; Call [[metabase.lib.convert/->pMBQL]] on it as needed
+   [:dataset-query   {:optional true} :map]
+   ;; vector of column metadata maps; these are ALMOST the correct shape to be [[ColumnMetadata]], but they're
+   ;; probably missing `:lib/type` and probably using `:snake_case` keys.
+   [:result-metadata {:optional true} [:maybe [:sequential :map]]]])
 
 (def ^:private SegmentMetadata
+  "More or less the same as a [[metabase.models.segment]], but with kebab-case keys."
   [:map
    [:lib/type [:= :metadata/segment]]
-   [:id ::lib.schema.id/segment]
-   [:name ::lib.schema.common/non-blank-string]])
+   [:id       ::lib.schema.id/segment]
+   [:name     ::lib.schema.common/non-blank-string]])
 
 (def ^:private MetricMetadata
+  "More or less the same as a [[metabase.models.metric]], but with kebab-case keys."
   [:map
    [:lib/type [:= :metadata/metric]]
-   [:id ::lib.schema.id/metric]
-   [:name ::lib.schema.common/non-blank-string]])
+   [:id       ::lib.schema.id/metric]
+   [:name     ::lib.schema.common/non-blank-string]])
 
 (def ^:private TableMetadata
+  "More or less the same as a [[metabase.models.table]], but with kebab-case keys."
   [:map
    [:lib/type [:= :metadata/table]]
-   [:id ::lib.schema.id/table]
-   [:name ::lib.schema.common/non-blank-string]
-   [:display_name {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
-   [:schema       {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
-   ;; This is now optional! If the [[MetadataProvider]] provides it, great, but if not we can always make the
-   ;; subsequent request to fetch fields separately.
-   [:fields   {:optional true} [:maybe [:sequential ColumnMetadata]]]
-   [:segments {:optional true} [:maybe [:sequential SegmentMetadata]]]
-   [:metrics  {:optional true} [:maybe [:sequential MetricMetadata]]]])
+   [:id       ::lib.schema.id/table]
+   [:name     ::lib.schema.common/non-blank-string]
+   [:display-name {:optional true} [:maybe ::lib.schema.common/non-blank-string]]
+   [:schema       {:optional true} [:maybe ::lib.schema.common/non-blank-string]]])
 
 (def DatabaseMetadata
   "Malli schema for the DatabaseMetadata as returned by `GET /api/database/:id/metadata` -- what should be available to
@@ -141,60 +147,57 @@
   "Schema for something that satisfies the [[lib.metadata.protocols/MetadataProvider]] protocol."
   [:fn lib.metadata.protocols/metadata-provider?])
 
-(defmulti ^:private ->metadata-provider*
-  {:arglists '([x])}
-  lib.dispatch/dispatch-value
-  :hierarchy lib.hierarchy/hierarchy)
-
-(defmethod ->metadata-provider* :default
-  [x]
-  x)
-
-(defmethod ->metadata-provider* :mbql/query
-  [query]
-  (->metadata-provider* (:lib/metadata query)))
-
-(mu/defn ^:private ->metadata-provider :- MetadataProvider
-  [x :- some?]
-  (if (lib.metadata.protocols/metadata-provider? x)
-    x
-    (->metadata-provider* x)))
+(def MetadataProviderable
+  "Something that can be used to get a MetadataProvider. Either a MetadataProvider, or a map with a MetadataProvider in
+  the key `:lib/metadata` (i.e., a query)."
+  [:or
+   MetadataProvider
+   [:map
+    {:error/message "map with a MetadataProvider in the key :lib/metadata (i.e. a query)"}
+    [:lib/metadata MetadataProvider]]])
+
+(mu/defn ->metadata-provider :- MetadataProvider
+  "Get a MetadataProvider from something that can provide one."
+  [metadata-providerable :- MetadataProviderable]
+  (if (lib.metadata.protocols/metadata-provider? metadata-providerable)
+    metadata-providerable
+    (:lib/metadata metadata-providerable)))
 
 (mu/defn database :- DatabaseMetadata
   "Get metadata about the Database we're querying."
-  [metadata-provider]
-  (lib.metadata.protocols/database (->metadata-provider metadata-provider)))
+  [metadata-providerable :- MetadataProviderable]
+  (lib.metadata.protocols/database (->metadata-provider metadata-providerable)))
 
 (mu/defn tables :- [:sequential TableMetadata]
   "Get metadata about all Tables for the Database we're querying."
-  [metadata-provider]
-  (lib.metadata.protocols/tables (->metadata-provider metadata-provider)))
+  [metadata-providerable :- MetadataProviderable]
+  (lib.metadata.protocols/tables (->metadata-provider metadata-providerable)))
 
 (mu/defn table :- [:or TableMetadata CardMetadata]
   "Find metadata for a specific Table, either by string `table-name`, and optionally `schema`, or by ID."
-  ([metadata-provider
+  ([metadata-providerable :- MetadataProviderable
     table-id :- [:or
                  ::lib.schema.id/table
                  ::lib.schema.id/table-card-id-string]]
    (if-let [card-id (lib.util/string-table-id->card-id table-id)]
-     (lib.metadata.protocols/card  (->metadata-provider metadata-provider) card-id)
-     (lib.metadata.protocols/table (->metadata-provider metadata-provider) table-id)))
+     (lib.metadata.protocols/card  (->metadata-provider metadata-providerable) card-id)
+     (lib.metadata.protocols/table (->metadata-provider metadata-providerable) table-id)))
 
-  ([metadata-provider
-    table-schema      :- [:maybe ::lib.schema.common/non-blank-string]
-    table-name        :- ::lib.schema.common/non-blank-string]
+  ([metadata-providerable :- MetadataProviderable
+    table-schema          :- [:maybe ::lib.schema.common/non-blank-string]
+    table-name            :- ::lib.schema.common/non-blank-string]
    (some (fn [table-metadata]
            (when (and (or (nil? table-schema)
                           (= (:schema table-metadata) table-schema))
                       (= (:name table-metadata) table-name))
              table-metadata))
-         (tables metadata-provider))))
+         (tables metadata-providerable))))
 
 (mu/defn fields :- [:sequential ColumnMetadata]
   "Get metadata about all the Fields belonging to a specific Table."
-  ([metadata-provider
-    table-id          :- ::lib.schema.id/table]
-   (lib.metadata.protocols/fields (->metadata-provider metadata-provider) table-id))
+  ([metadata-providerable :- MetadataProviderable
+    table-id              :- ::lib.schema.id/table]
+   (lib.metadata.protocols/fields (->metadata-provider metadata-providerable) table-id))
 
   ([metadata-provider
     table-schema      :- [:maybe ::lib.schema.common/non-blank-string]
@@ -204,25 +207,25 @@
 
 (mu/defn field :- ColumnMetadata
   "Get metadata about a specific Field in the Database we're querying."
-  ([metadata-provider
-    field-id          :- ::lib.schema.id/field]
-   (lib.metadata.protocols/field (->metadata-provider metadata-provider) field-id))
+  ([metadata-providerable :- MetadataProviderable
+    field-id              :- ::lib.schema.id/field]
+   (lib.metadata.protocols/field (->metadata-provider metadata-providerable) field-id))
 
   ;; TODO -- we need to figure out how to deal with nested fields... should field-name be a varargs thing?
-  ([metadata-provider
-    table-id          :- ::lib.schema.id/table
-    field-name        :- ::lib.schema.common/non-blank-string]
+  ([metadata-providerable :- MetadataProviderable
+    table-id              :- ::lib.schema.id/table
+    field-name            :- ::lib.schema.common/non-blank-string]
    (some (fn [field-metadata]
            (when (= (:name field-metadata) field-name)
              field-metadata))
-         (fields metadata-provider table-id)))
+         (fields metadata-providerable table-id)))
 
-  ([metadata-provider
-    table-schema      :- [:maybe ::lib.schema.common/non-blank-string]
-    table-name        :- ::lib.schema.common/non-blank-string
-    field-name        :- ::lib.schema.common/non-blank-string]
-   (let [table-metadata (table metadata-provider table-schema table-name)]
-     (field metadata-provider (:id table-metadata) field-name))))
+  ([metadata-providerable :- MetadataProviderable
+    table-schema          :- [:maybe ::lib.schema.common/non-blank-string]
+    table-name            :- ::lib.schema.common/non-blank-string
+    field-name            :- ::lib.schema.common/non-blank-string]
+   (let [table-metadata (table metadata-providerable table-schema table-name)]
+     (field metadata-providerable (:id table-metadata) field-name))))
 
 ;;;; Stage metadata
 
@@ -295,18 +298,18 @@
 
 (mu/defn card :- [:maybe CardMetadata]
   "Get metadata for a Card, aka Saved Question, with `card-id`, if it can be found."
-  [metadata-provider
-   card-id :- ::lib.schema.id/card]
-  (lib.metadata.protocols/card (->metadata-provider metadata-provider) card-id))
+  [metadata-providerable :- MetadataProviderable
+   card-id               :- ::lib.schema.id/card]
+  (lib.metadata.protocols/card (->metadata-provider metadata-providerable) card-id))
 
 (mu/defn segment :- [:maybe SegmentMetadata]
   "Get metadata for the Segment with `segment-id`, if it can be found."
-  [metadata-provider
-   segment-id :- ::lib.schema.id/segment]
-  (lib.metadata.protocols/segment (->metadata-provider metadata-provider) segment-id))
+  [metadata-providerable :- MetadataProviderable
+   segment-id            :- ::lib.schema.id/segment]
+  (lib.metadata.protocols/segment (->metadata-provider metadata-providerable) segment-id))
 
 (mu/defn metric :- [:maybe MetricMetadata]
   "Get metadata for the Metric with `metric-id`, if it can be found."
-  [metadata-provider
-   metric-id :- ::lib.schema.id/metric]
-  (lib.metadata.protocols/metric (->metadata-provider metadata-provider) metric-id))
+  [metadata-providerable :- MetadataProviderable
+   metric-id             :- ::lib.schema.id/metric]
+  (lib.metadata.protocols/metric (->metadata-provider metadata-providerable) metric-id))
diff --git a/src/metabase/lib/metadata/cached_provider.cljc b/src/metabase/lib/metadata/cached_provider.cljc
index 2d62bc896ce..505f6730e52 100644
--- a/src/metabase/lib/metadata/cached_provider.cljc
+++ b/src/metabase/lib/metadata/cached_provider.cljc
@@ -2,6 +2,7 @@
   (:require
    [clojure.set :as set]
    [metabase.lib.metadata.protocols :as lib.metadata.protocols]
+   [metabase.util :as u]
    [metabase.util.log :as log]
    #?@(:clj ([pretty.core :as pretty]))))
 
@@ -15,6 +16,18 @@
     (swap! cache assoc-in ks value)
     value))
 
+(defn- store-database! [cache database-metadata]
+  (let [database-metadata (-> database-metadata
+                              (update-keys u/->kebab-case-en)
+                              (assoc :lib/type :metadata/database))]
+    (store-in-cache! cache [:metadata/database] database-metadata)))
+
+(defn- store-metadata! [cache metadata-type id metadata]
+  (let [metadata (-> metadata
+                     (update-keys u/->kebab-case-en)
+                     (assoc :lib/type metadata-type))]
+    (store-in-cache! cache [metadata-type id] metadata)))
+
 (defn- get-in-cache-or-fetch [cache ks fetch-thunk]
   (if-some [cached-value (get-in @cache ks)]
     (when-not (= cached-value ::nil)
@@ -49,8 +62,8 @@
   lib.metadata.protocols/CachedMetadataProvider
   (cached-database [_this]                           (get-in-cache    cache [:metadata/database]))
   (cached-metadata [_this metadata-type id]          (get-in-cache    cache [metadata-type id]))
-  (store-database! [_this database-metadata]         (store-in-cache! cache [:metadata/database] (assoc database-metadata :lib/type :metadata/database)))
-  (store-metadata! [_this metadata-type id metadata] (store-in-cache! cache [metadata-type id]   (assoc metadata :lib/type metadata-type)))
+  (store-database! [_this database-metadata]         (store-database! cache database-metadata))
+  (store-metadata! [_this metadata-type id metadata] (store-metadata! cache metadata-type id metadata))
 
   ;; these only work if the underlying metadata provider is also a [[BulkMetadataProvider]].
   lib.metadata.protocols/BulkMetadataProvider
diff --git a/src/metabase/lib/metadata/calculation.cljc b/src/metabase/lib/metadata/calculation.cljc
index 35cc385b6b7..739d6d151f1 100644
--- a/src/metabase/lib/metadata/calculation.cljc
+++ b/src/metabase/lib/metadata/calculation.cljc
@@ -198,9 +198,9 @@
   (try
     {:lib/type     :metadata/field
      ;; TODO -- effective-type
-     :base_type    (type-of query stage-number x)
+     :base-type    (type-of query stage-number x)
      :name         (column-name query stage-number x)
-     :display_name (display-name query stage-number x)}
+     :display-name (display-name query stage-number x)}
     (catch #?(:clj Throwable :cljs js/Error) e
       (throw (ex-info (i18n/tru "Error calculating metadata {0}" (ex-message e))
                       {:query query, :stage-number stage-number, :x x}
@@ -254,7 +254,7 @@
 
 (mr/register! ::display-info
   [:map
-   [:display_name :string]
+   [:display-name :string]
    ;; for things that have a Table, e.g. a Field
    [:table {:optional true} [:maybe [:ref ::display-info]]]
    ;; these are derived from the `:lib/source`/`:metabase.lib.metadata/column-source`, but instead of using that value
@@ -262,16 +262,16 @@
    ;; e.g. if we consolidate or split some of those keys. This is all the FE really needs to know.
    ;;
    ;; if this is a Column, does it come from a previous stage?
-   [:is_from_previous_stage {:optional true} [:maybe :boolean]]
+   [:is-from-previous-stage {:optional true} [:maybe :boolean]]
    ;; if this is a Column, does it come from a join in this stage?
-   [:is_from_join {:optional true} [:maybe :boolean]]
+   [:is-from-join {:optional true} [:maybe :boolean]]
    ;; if this is a Column, is it 'calculated', i.e. does it come from an expression in this stage?
-   [:is_calculated {:optional true} [:maybe :boolean]]
+   [:is-calculated {:optional true} [:maybe :boolean]]
    ;; if this is a Column, is it an implicitly joinable one? I.e. is it from a different table that we have not
    ;; already joined, but could implicitly join against?
-   [:is_implicitly_joinable {:optional true} [:maybe :boolean]]
+   [:is-implicitly-joinable {:optional true} [:maybe :boolean]]
    ;; For the `:table` field of a Column, is this the source table, or a joined table?
-   [:is_source_table {:optional true} [:maybe :boolean]]])
+   [:is-source-table {:optional true} [:maybe :boolean]]])
 
 (mu/defn display-info :- ::display-info
   "Given some sort of Cljs object, return a map with the info you'd need to implement UI for it. This is mostly meant to
@@ -286,7 +286,9 @@
    (try
      (display-info-method query stage-number x)
      (catch #?(:clj Throwable :cljs js/Error) e
-       (throw (ex-info (i18n/tru "Error calculating display info for {0}: {1}" (lib.dispatch/dispatch-value x) (ex-message e))
+       (throw (ex-info (i18n/tru "Error calculating display info for {0}: {1}"
+                                 (lib.dispatch/dispatch-value x)
+                                 (ex-message e))
                        {:query query, :stage-number stage-number, :x x}
                        e))))))
 
@@ -296,20 +298,20 @@
   [query stage-number x]
   (let [x-metadata (metadata query stage-number x)]
     (merge
-     ;; TODO -- not 100% convinced the FE should actually have access to `:name`, can't it use `:display_name`
+     ;; TODO -- not 100% convinced the FE should actually have access to `:name`, can't it use `:display-name`
      ;; everywhere? Determine whether or not this is the case.
-     (select-keys x-metadata [:name :display_name :semantic_type])
-     ;; don't return `:base_type`, FE should just use `:effective_type` everywhere and not even need to know
-     ;; `:base_type` exists.
-     (when-let [effective-type ((some-fn :effective_type :base_type) x-metadata)]
-       {:effective_type effective-type})
-     (when-let [table-id (:table_id x-metadata)]
+     (select-keys x-metadata [:name :display-name :semantic-type])
+     ;; don't return `:base-type`, FE should just use `:effective-type` everywhere and not even need to know
+     ;; `:base-type` exists.
+     (when-let [effective-type ((some-fn :effective-type :base-type) x-metadata)]
+       {:effective-type effective-type})
+     (when-let [table-id (:table-id x-metadata)]
        {:table (display-info query stage-number (lib.metadata/table query table-id))})
      (when-let [source (:lib/source x-metadata)]
-       {:is_from_previous_stage (= source :source/previous-stage)
-        :is_from_join           (= source :source/joins)
-        :is_calculated          (= source :source/expressions)
-        :is_implicitly_joinable (= source :source/implicitly-joinable)}))))
+       {:is-from-previous-stage (= source :source/previous-stage)
+        :is-from-join           (= source :source/joins)
+        :is-calculated          (= source :source/expressions)
+        :is-implicitly-joinable (= source :source/implicitly-joinable)}))))
 
 (defmethod display-info-method :default
   [query stage-number x]
@@ -318,7 +320,7 @@
 (defmethod display-info-method :metadata/table
   [query stage-number table]
   (merge (default-display-info query stage-number table)
-         {:is_source_table (= (lib.util/source-table query) (:id table))}))
+         {:is-source-table (= (lib.util/source-table query) (:id table))}))
 
 (defmulti default-columns-method
   "Impl for [[default-columns]]. This should mostly be similar to the implementation for [[metadata-method]], but needs
diff --git a/src/metabase/lib/metadata/jvm.clj b/src/metabase/lib/metadata/jvm.clj
index fb45032f539..287b0c06ccd 100644
--- a/src/metabase/lib/metadata/jvm.clj
+++ b/src/metabase/lib/metadata/jvm.clj
@@ -3,6 +3,7 @@
   (:require
    [metabase.lib.metadata.cached-provider :as lib.metadata.cached-provider]
    [metabase.lib.metadata.protocols :as lib.metadata.protocols]
+   [metabase.util :as u]
    [metabase.util.log :as log]
    [potemkin :as p]
    [pretty.core :as pretty]
@@ -17,18 +18,37 @@
     :metadata/metric   :metabase.models.metric/Metric
     :metadata/segment  :metabase.models.segment/Segment))
 
+(defn- instance->metadata [instance metadata-type]
+  (some-> instance
+          (update-keys u/->kebab-case-en)
+          (assoc :lib/type metadata-type)))
+
 (defn- fetch-instance [metadata-type id]
   {:pre [(integer? id)]}
   (let [model (metadata-type->model metadata-type)]
     (log/debugf "Fetching %s %d" model id)
-    (when-some [instance (t2/select-one model :id id)]
-      (assoc instance :lib/type metadata-type))))
+    (instance->metadata (t2/select-one model :id id) metadata-type)))
 
 (defn- bulk-instances [metadata-type ids]
   (let [model (metadata-type->model metadata-type)]
     (log/debugf "Fetching instances of %s with ID in %s" model (pr-str (sort ids)))
     (for [instance (t2/select model :id [:in ids])]
-      (assoc instance :lib/type metadata-type))))
+      (instance->metadata instance metadata-type))))
+
+(defn- tables [database-id]
+  (when-not database-id
+    (throw (ex-info (format "Cannot use %s with %s with a nil Database ID"
+                            `lib.metadata.protocols/tables
+                            `UncachedApplicationDatabaseMetadataProvider)
+                    {})))
+  (log/debugf "Fetching all Tables for Database %d" database-id)
+  (mapv #(instance->metadata % :metadata/table)
+        (t2/select :metabase.models.table/Table :db_id database-id)))
+
+(defn- fields [table-id]
+  (log/debugf "Fetching all Fields for Table %d" table-id)
+  (mapv #(instance->metadata % :metadata/field)
+        (t2/select :metabase.models.field/Field :table_id table-id)))
 
 (p/deftype+ UncachedApplicationDatabaseMetadataProvider [database-id]
   lib.metadata.protocols/MetadataProvider
@@ -47,19 +67,10 @@
   (segment [_this segment-id] (fetch-instance :metadata/segment segment-id))
 
   (tables [_this]
-    (when-not database-id
-      (throw (ex-info (format "Cannot use %s with %s with a nil Database ID"
-                              `lib.metadata.protocols/tables
-                              `UncachedApplicationDatabaseMetadataProvider)
-                      {})))
-    (log/debugf "Fetching all Tables for Database %d" database-id)
-    (mapv #(assoc % :lib/type :metadata/table)
-          (t2/select :metabase.models.table/Table :db_id database-id)))
+    (tables database-id))
 
   (fields [_this table-id]
-    (log/debugf "Fetching all Fields for Table %d" table-id)
-    (mapv #(assoc % :lib/type :metadata/field)
-          (t2/select :metabase.models.field/Field :table_id table-id)))
+    (fields table-id))
 
   lib.metadata.protocols/BulkMetadataProvider
   (bulk-metadata [_this metadata-type ids]
diff --git a/src/metabase/lib/metric.cljc b/src/metabase/lib/metric.cljc
index d062d3c302f..89ce5c3e8f2 100644
--- a/src/metabase/lib/metric.cljc
+++ b/src/metabase/lib/metric.cljc
@@ -43,7 +43,7 @@
 
 (defmethod lib.metadata.calculation/display-name-method :metadata/metric
   [_query _stage-number metric-metadata _style]
-  (or ((some-fn :display_name :name) metric-metadata)
+  (or ((some-fn :display-name :name) metric-metadata)
       (i18n/tru "[Unknown Metric]")))
 
 (defmethod lib.metadata.calculation/display-name-method :metric
diff --git a/src/metabase/lib/order_by.cljc b/src/metabase/lib/order_by.cljc
index 8d4cb30238c..ca19b80b04e 100644
--- a/src/metabase/lib/order_by.cljc
+++ b/src/metabase/lib/order_by.cljc
@@ -118,7 +118,7 @@
     stage-number :- :int]
    (not-empty (get (lib.util/query-stage query stage-number) :order-by))))
 
-(defn- orderable-column? [{base-type :base_type, :as _column-metadata}]
+(defn- orderable-column? [{:keys [base-type], :as _column-metadata}]
   (some (fn [orderable-base-type]
           (isa? base-type orderable-base-type))
         lib.schema.expression/orderable-types))
diff --git a/src/metabase/lib/query.cljc b/src/metabase/lib/query.cljc
index 0d62ec97c19..e3cd672105f 100644
--- a/src/metabase/lib/query.cljc
+++ b/src/metabase/lib/query.cljc
@@ -11,6 +11,8 @@
    [metabase.lib.schema :as lib.schema]
    [metabase.lib.schema.id :as lib.schema.id]
    [metabase.lib.util :as lib.util]
+   [metabase.shared.util.i18n :as i18n]
+   [metabase.util.log :as log]
    [metabase.util.malli :as mu]))
 
 (defmethod lib.normalize/normalize :mbql/query
@@ -29,49 +31,55 @@
   [query stage-number x style]
   (lib.metadata.calculation/display-name query stage-number (lib.util/query-stage x stage-number) style))
 
-(defn query-with-stages
+(mu/defn query-with-stages :- ::lib.schema/query
   "Create a query from a sequence of stages."
-  ([metadata-provider stages]
-   (query-with-stages (:id (lib.metadata/database metadata-provider)) metadata-provider stages))
+  ([metadata-providerable stages]
+   (query-with-stages (:id (lib.metadata/database metadata-providerable)) metadata-providerable stages))
 
-  ([database-id metadata-provider stages]
+  ([database-id           :- ::lib.schema.id/database
+    metadata-providerable :- lib.metadata/MetadataProviderable
+    stages]
    {:lib/type     :mbql/query
-    :lib/metadata metadata-provider
+    :lib/metadata (lib.metadata/->metadata-provider metadata-providerable)
     :database     database-id
-    :stages       (mapv lib.options/ensure-uuid stages)}))
+    :stages       stages}))
 
-(defn query-with-stage
+(mu/defn query-with-stage
   "Create a query from a specific stage."
-  ([metadata-provider stage]
-   (query-with-stages metadata-provider [stage]))
+  ([metadata-providerable stage]
+   (query-with-stages metadata-providerable [stage]))
 
-  ([database-id metadata-provider stage]
-   (query-with-stages database-id metadata-provider [stage])))
+  ([database-id           :- ::lib.schema.id/database
+    metadata-providerable :- lib.metadata/MetadataProviderable
+    stage]
+   (query-with-stages database-id metadata-providerable [stage])))
 
-(defn- query-from-existing [metadata-provider query]
+(mu/defn ^:private query-from-existing :- ::lib.schema/query
+  [metadata-providerable :- lib.metadata/MetadataProviderable
+   query                 :- lib.util/LegacyOrPMBQLQuery]
   (let [query (lib.util/pipeline query)]
-    (query-with-stages metadata-provider (:stages query))))
+    (query-with-stages metadata-providerable (:stages query))))
 
 (defmulti ^:private ->query
   "Implementation for [[query]]."
-  {:arglists '([metadata-provider x])}
-  (fn [_metadata-provider x]
+  {:arglists '([metadata-providerable x])}
+  (fn [_metadata-providerable x]
     (lib.dispatch/dispatch-value x))
   :hierarchy lib.hierarchy/hierarchy)
 
 (defmethod ->query :dispatch-type/map
-  [metadata-provider query]
-  (query-from-existing metadata-provider query))
+  [metadata-providerable query]
+  (query-from-existing metadata-providerable query))
 
 ;;; this should already be a query in the shape we want, but let's make sure it has the database metadata that was
 ;;; passed in
 (defmethod ->query :mbql/query
-  [metadata-provider query]
-  (assoc query :lib/metadata metadata-provider))
+  [metadata-providerable query]
+  (assoc query :lib/metadata (lib.metadata/->metadata-provider metadata-providerable)))
 
 (defmethod ->query :metadata/table
-  [metadata-provider table-metadata]
-  (query-with-stages metadata-provider
+  [metadata-providerable table-metadata]
+  (query-with-stages metadata-providerable
                      [{:lib/type     :mbql.stage/mbql
                        :source-table (:id table-metadata)}]))
 
@@ -79,23 +87,25 @@
   "Create a new MBQL query from anything that could conceptually be an MBQL query, like a Database or Table or an
   existing MBQL query or saved question or whatever. If the thing in question does not already include metadata, pass
   it in separately -- metadata is needed for most query manipulation operations."
-  [metadata-provider :- lib.metadata/MetadataProvider
+  [metadata-providerable :- lib.metadata/MetadataProviderable
    x]
-  (->query metadata-provider x))
+  (->query metadata-providerable x))
 
 ;;; TODO -- the stuff below will probably change in the near future, please don't read too much in to it.
 (mu/defn native-query :- ::lib.schema/query
   "Create a new native query.
 
   Native in this sense means a pMBQL query with a first stage that is a native query."
-  ([metadata-provider :- lib.metadata/MetadataProvider
+  ([metadata-providerable :- lib.metadata/MetadataProviderable
     inner-query]
-   (native-query metadata-provider nil inner-query))
+   (native-query metadata-providerable nil inner-query))
 
-  ([metadata-provider :- lib.metadata/MetadataProvider
-    results-metadata  :- lib.metadata/StageMetadata
+  ;; TODO not sure if `results-metadata` should be StageMetadata (i.e., a map roughly matching the shape you get from
+  ;; the QP) or a sequence of ColumnMetadatas, like what would be saved in Card `result_metadata`.
+  ([metadata-providerable :- lib.metadata/MetadataProviderable
+    results-metadata      :- lib.metadata/StageMetadata
     inner-query]
-   (query-with-stages metadata-provider
+   (query-with-stages metadata-providerable
                       [(-> {:lib/type           :mbql.stage/native
                             :lib/stage-metadata results-metadata
                             :native             inner-query}
@@ -103,19 +113,24 @@
 
 (mu/defn saved-question-query :- ::lib.schema/query
   "Convenience for creating a query from a Saved Question (i.e., a Card)."
-  [metadata-provider :- lib.metadata/MetadataProvider
-   {mbql-query :dataset_query, metadata :result_metadata}]
+  [metadata-providerable :- lib.metadata/MetadataProviderable
+   {mbql-query :dataset-query, metadata :result-metadata, :as saved-question}]
+  (assert mbql-query (i18n/tru "Saved Question is missing query"))
+  (when-not metadata
+    (log/warn (i18n/trs "Saved Question {0} {1} is missing result metadata"
+                        (:id saved-question)
+                        (pr-str (:name saved-question-query)))))
   (let [mbql-query (cond-> (assoc (lib.convert/->pMBQL mbql-query)
-                                  :lib/metadata metadata-provider)
+                                  :lib/metadata (lib.metadata/->metadata-provider metadata-providerable))
                      metadata
-                     (lib.util/update-query-stage -1 assoc :lib/stage-metadata metadata))]
-    (query metadata-provider mbql-query)))
+                     (lib.util/update-query-stage -1 assoc :lib/stage-metadata (lib.util/->stage-metadata metadata)))]
+    (query metadata-providerable mbql-query)))
 
 (mu/defn query-from-legacy-inner-query :- ::lib.schema/query
   "Create a pMBQL query from a legacy inner query."
-  [metadata-provider :- lib.metadata/MetadataProvider
-   database-id       :- ::lib.schema.id/database
-   inner-query       :- :map]
+  [metadata-providerable :- lib.metadata/MetadataProviderable
+   database-id           :- ::lib.schema.id/database
+   inner-query           :- :map]
   (->> (lib.convert/legacy-query-from-inner-query database-id inner-query)
        lib.convert/->pMBQL
-       (query metadata-provider)))
+       (query metadata-providerable)))
diff --git a/src/metabase/lib/ref.cljc b/src/metabase/lib/ref.cljc
index 2038026e1ba..acde87f12d9 100644
--- a/src/metabase/lib/ref.cljc
+++ b/src/metabase/lib/ref.cljc
@@ -14,5 +14,5 @@
 (mu/defn ref :- ::lib.schema.ref/ref
   "Create a fresh ref that can be added to a query, e.g. a `:field`, `:aggregation`, or `:expression` reference. Will
   create a new UUID every time this is called."
-  [x]
+  [x :- some?]
   (ref-method x))
diff --git a/src/metabase/lib/segment.cljc b/src/metabase/lib/segment.cljc
index f799a95e2bf..3f3f908ba96 100644
--- a/src/metabase/lib/segment.cljc
+++ b/src/metabase/lib/segment.cljc
@@ -7,7 +7,7 @@
 
 (defmethod lib.metadata.calculation/display-name-method :metadata/segment
   [_query _stage-number segment-metadata _style]
-  (or ((some-fn :display_name :name) segment-metadata)
+  (or ((some-fn :display-name :name) segment-metadata)
       (i18n/tru "[Unknown Segment]")))
 
 (defmethod lib.metadata.calculation/display-name-method :segment
diff --git a/src/metabase/lib/stage.cljc b/src/metabase/lib/stage.cljc
index d422148af5e..e0ce4031361 100644
--- a/src/metabase/lib/stage.cljc
+++ b/src/metabase/lib/stage.cljc
@@ -258,7 +258,7 @@
 
 (defn- implicitly-joinable-columns
   "Columns that are implicitly joinable from some other columns in `column-metadatas`. To be joinable, the column has to
-  have appropriate FK metadata, i.e. have an `:fk_target_field_id` pointing to another Field. (I think we only include
+  have appropriate FK metadata, i.e. have an `:fk-target-field-id` pointing to another Field. (I think we only include
   this information for Databases that support FKs and joins, so I don't think we need to do an additional DB feature
   check here.)
 
@@ -269,20 +269,20 @@
 
   Does not include columns that would be implicitly joinable via multiple hops."
   [query stage-number column-metadatas unique-name-fn]
-  (let [existing-table-ids (into #{} (map :table_id) column-metadatas)]
+  (let [existing-table-ids (into #{} (map :table-id) column-metadatas)]
     (into []
-          (comp (filter :fk_target_field_id)
-                (m/distinct-by :fk_target_field_id)
-                (map (fn [{source-field-id :id, target-field-id :fk_target_field_id}]
-                       (-> (lib.metadata/field query target-field-id)
+          (comp (filter :fk-target-field-id)
+                (m/distinct-by :fk-target-field-id)
+                (map (fn [{source-field-id :id, :keys [fk-target-field-id]}]
+                       (-> (lib.metadata/field query fk-target-field-id)
                            (assoc ::source-field-id source-field-id))))
-                (remove #(contains? existing-table-ids (:table_id %)))
-                (m/distinct-by :table_id)
-                (mapcat (fn [{table-id :table_id, ::keys [source-field-id]}]
+                (remove #(contains? existing-table-ids (:table-id %)))
+                (m/distinct-by :table-id)
+                (mapcat (fn [{:keys [table-id], ::keys [source-field-id]}]
                           (let [table-metadata (lib.metadata/table query table-id)]
                             (for [field (lib.metadata.calculation/default-columns query stage-number table-metadata unique-name-fn)
                                   :let  [field (assoc field
-                                                      :fk_field_id              source-field-id
+                                                      :fk-field-id              source-field-id
                                                       :lib/source               :source/implicitly-joinable
                                                       :lib/source-column-alias  (:name field))]]
                               (assoc field :lib/desired-column-alias (unique-name-fn
diff --git a/src/metabase/lib/table.cljc b/src/metabase/lib/table.cljc
index b9f166057db..e953d8eed31 100644
--- a/src/metabase/lib/table.cljc
+++ b/src/metabase/lib/table.cljc
@@ -11,7 +11,7 @@
 
 (defmethod lib.metadata.calculation/display-name-method :metadata/table
   [_query _stage-number table-metadata _style]
-  (or (:display_name table-metadata)
+  (or (:display-name table-metadata)
       (some->> (:name table-metadata)
                (u.humanization/name->human-readable-name :simple))))
 
@@ -45,7 +45,7 @@
   "Remove Fields that shouldn't be visible from the default Fields for a source Table.
   See [[metabase.query-processor.middleware.add-implicit-clauses/table->sorted-fields*]]."
   [field-metadatas]
-  (remove (fn [{visibility-type :visibility_type, active? :active, :as _field-metadata}]
+  (remove (fn [{:keys [visibility-type], active? :active, :as _field-metadata}]
             (or (false? active?)
                 (#{:sensitive :retired} (some-> visibility-type keyword))))
           field-metadatas))
diff --git a/src/metabase/lib/temporal_bucket.cljc b/src/metabase/lib/temporal_bucket.cljc
index 0dc45576963..b39147302e6 100644
--- a/src/metabase/lib/temporal_bucket.cljc
+++ b/src/metabase/lib/temporal_bucket.cljc
@@ -22,28 +22,29 @@
     unit :- [:maybe :keyword]]
    (if-not unit
      ""
-     (case (keyword unit)
-       :default         (i18n/trun "Default period"  "Default periods"  n)
-       :millisecond     (i18n/trun "Millisecond"     "Milliseconds"     n)
-       :second          (i18n/trun "Second"          "Seconds"          n)
-       :minute          (i18n/trun "Minute"          "Minutes"          n)
-       :hour            (i18n/trun "Hour"            "Hours"            n)
-       :day             (i18n/trun "Day"             "Days"             n)
-       :week            (i18n/trun "Week"            "Weeks"            n)
-       :month           (i18n/trun "Month"           "Months"           n)
-       :quarter         (i18n/trun "Quarter"         "Quarters"         n)
-       :year            (i18n/trun "Year"            "Years"            n)
-       :minute-of-hour  (i18n/trun "Minute of hour"  "Minutes of hour"  n)
-       :hour-of-day     (i18n/trun "Hour of day"     "Hours of day"     n)
-       :day-of-week     (i18n/trun "Day of week"     "Days of week"     n)
-       :day-of-month    (i18n/trun "Day of month"    "Days of month"    n)
-       :day-of-year     (i18n/trun "Day of year"     "Days of year"     n)
-       :week-of-year    (i18n/trun "Week of year"    "Weeks of year"    n)
-       :month-of-year   (i18n/trun "Month of year"   "Months of year"   n)
-       :quarter-of-year (i18n/trun "Quarter of year" "Quarters of year" n)
-       ;; e.g. :unknown-unit => "Unknown unit"
-       (let [[unit & more] (str/split (name unit) #"-")]
-         (str/join \space (cons (str/capitalize unit) more)))))))
+     (let [n (abs n)]
+       (case (keyword unit)
+         :default         (i18n/trun "Default period"  "Default periods"  n)
+         :millisecond     (i18n/trun "Millisecond"     "Milliseconds"     n)
+         :second          (i18n/trun "Second"          "Seconds"          n)
+         :minute          (i18n/trun "Minute"          "Minutes"          n)
+         :hour            (i18n/trun "Hour"            "Hours"            n)
+         :day             (i18n/trun "Day"             "Days"             n)
+         :week            (i18n/trun "Week"            "Weeks"            n)
+         :month           (i18n/trun "Month"           "Months"           n)
+         :quarter         (i18n/trun "Quarter"         "Quarters"         n)
+         :year            (i18n/trun "Year"            "Years"            n)
+         :minute-of-hour  (i18n/trun "Minute of hour"  "Minutes of hour"  n)
+         :hour-of-day     (i18n/trun "Hour of day"     "Hours of day"     n)
+         :day-of-week     (i18n/trun "Day of week"     "Days of week"     n)
+         :day-of-month    (i18n/trun "Day of month"    "Days of month"    n)
+         :day-of-year     (i18n/trun "Day of year"     "Days of year"     n)
+         :week-of-year    (i18n/trun "Week of year"    "Weeks of year"    n)
+         :month-of-year   (i18n/trun "Month of year"   "Months of year"   n)
+         :quarter-of-year (i18n/trun "Quarter of year" "Quarters of year" n)
+         ;; e.g. :unknown-unit => "Unknown unit"
+         (let [[unit & more] (str/split (name unit) #"-")]
+           (str/join \space (cons (str/capitalize unit) more))))))))
 
 (def ^:private TemporalIntervalAmount
   [:or [:enum :current :last :next] :int])
diff --git a/src/metabase/lib/types/constants.cljc b/src/metabase/lib/types/constants.cljc
index 0f78e121b09..ac4e0ce822a 100644
--- a/src/metabase/lib/types/constants.cljc
+++ b/src/metabase/lib/types/constants.cljc
@@ -34,25 +34,25 @@
 (def type-hierarchies
   "A front-end specific type hierarchy used by [[metabase.lib.types.isa/field-type?]].
   It is not meant to be used directly."
-  {::temporal    {:effective_type [:type/Temporal]
-                  :semantic_type  [:type/Temporal]}
-   ::number      {:effective_type [:type/Number]
-                  :semantic_type  [:type/Number]}
-   ::string      {:effective_type [:type/Text]
-                  :semantic_type  [:type/Text :type/Category]}
-   ::string_like {:effective_type [:type/TextLike]}
-   ::boolean     {:effective_type [:type/Boolean]}
-   ::coordinate  {:semantic_type [:type/Coordinate]}
-   ::location    {:semantic_type [:type/Address]}
-   ::entity      {:semantic_type [:type/FK :type/PK :type/Name]}
-   ::foreign_key {:semantic_type [:type/FK]}
-   ::primary_key {:semantic_type [:type/PK]}
+  {::temporal    {:effective-type [:type/Temporal]
+                  :semantic-type  [:type/Temporal]}
+   ::number      {:effective-type [:type/Number]
+                  :semantic-type  [:type/Number]}
+   ::string      {:effective-type [:type/Text]
+                  :semantic-type  [:type/Text :type/Category]}
+   ::string_like {:effective-type [:type/TextLike]}
+   ::boolean     {:effective-type [:type/Boolean]}
+   ::coordinate  {:semantic-type [:type/Coordinate]}
+   ::location    {:semantic-type [:type/Address]}
+   ::entity      {:semantic-type [:type/FK :type/PK :type/Name]}
+   ::foreign_key {:semantic-type [:type/FK]}
+   ::primary_key {:semantic-type [:type/PK]}
    ::summable    {:include [::number]
                   :exclude [::entity ::location ::temporal]}
    ::scope       {:include [::number ::temporal ::category ::entity ::string]
                   :exclude [::location]}
-   ::category    {:effective_type [:type/Boolean]
-                  :semantic_type  [:type/Category]
+   ::category    {:effective-type [:type/Boolean]
+                  :semantic-type  [:type/Category]
                   :include        [::location]}
    ;; NOTE: this is defunct right now.  see definition of metabase.lib.types.isa/dimension?.
    ::dimension   {:include [::temporal ::category ::entity]}})
diff --git a/src/metabase/lib/types/isa.cljc b/src/metabase/lib/types/isa.cljc
index cb4daf689ee..65482c7b235 100644
--- a/src/metabase/lib/types/isa.cljc
+++ b/src/metabase/lib/types/isa.cljc
@@ -3,15 +3,18 @@
   (:require
    [medley.core :as m]
    [metabase.lib.types.constants :as lib.types.constants]
-   [metabase.lib.util :as lib.u])
+   [metabase.lib.util :as lib.u]
+   [metabase.types])
   (:refer-clojure :exclude [isa? any? boolean? number? string?]))
 
+(comment metabase.types/keep-me)
+
 (defn ^:export isa?
   "Decide if `_column` is a subtype of the type denoted by the keyword `type-kw`.
   Both effective and semantic types are taken into account."
-  [{:keys [effective_type semantic_type] :as _column} type-kw]
-  (or (clojure.core/isa? effective_type type-kw)
-      (clojure.core/isa? semantic_type type-kw)))
+  [{:keys [effective-type semantic-type] :as _column} type-kw]
+  (or (clojure.core/isa? effective-type type-kw)
+      (clojure.core/isa? semantic-type type-kw)))
 
 (defn ^:export field-type?
   "Returns if `column` is of category `category`.
@@ -23,7 +26,7 @@
 
       ;; check field types
       (some (fn [[type-type types]]
-              (and (#{:effective_type :semantic_type} type-type)
+              (and (#{:effective-type :semantic-type} type-type)
                    (some #(clojure.core/isa? (type-type column) %) types)))
             type-definition)
       true
@@ -96,7 +99,7 @@
 (defn ^:export description?
   "Is `column` a description?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Description))
+  (clojure.core/isa? (:semantic-type column) :type/Description))
 
 (defn ^:export dimension?
   "Is `column` a dimension?"
@@ -114,17 +117,17 @@
 (defn ^:export foreign-key?
   "Is `column` a foreign-key?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/FK))
+  (clojure.core/isa? (:semantic-type column) :type/FK))
 
 (defn ^:export primary-key?
   "Is `column` a primary-key?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/PK))
+  (clojure.core/isa? (:semantic-type column) :type/PK))
 
 (defn ^:export entity-name?
   "Is `column` an entity name?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Name))
+  (clojure.core/isa? (:semantic-type column) :type/Name))
 
 (defn ^:export any?
   "Is this `_column` whatever (including nil)?"
@@ -134,19 +137,19 @@
 (defn ^:export numeric-base-type?
   "Is `column` a numneric base type?"
   [column]
-  (clojure.core/isa? (:effective_type column) :type/Number))
+  (clojure.core/isa? (:effective-type column) :type/Number))
 
 (defn ^:export date-without-time?
   "Is `column` a date without time?"
   [column]
-  (clojure.core/isa? (:effective_type column) :type/Date))
+  (clojure.core/isa? (:effective-type column) :type/Date))
 
 ;; ZipCode, ID, etc derive from Number but should not be formatted as numbers
 (defn ^:export number?
   "Is `column` a number without some other semantic type (like ZIP code)?"
   [column]
   (and (numeric-base-type? column)
-       (let [semantic-type (:semantic_type column)]
+       (let [semantic-type (:semantic-type column)]
          (or (nil? semantic-type)
              ;; this is a precaution, :type/Number is not a semantic type
              (clojure.core/isa? semantic-type :type/Number)))))
@@ -154,83 +157,83 @@
 (defn ^:export time?
   "Is `column` a time?"
   [column]
-  (clojure.core/isa? (:effective_type column) :type/Time))
+  (clojure.core/isa? (:effective-type column) :type/Time))
 
 (defn ^:export address?
   "Is `column` an address?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Address))
+  (clojure.core/isa? (:semantic-type column) :type/Address))
 
 (defn ^:export city?
   "Is `column` a city?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/City))
+  (clojure.core/isa? (:semantic-type column) :type/City))
 
 (defn ^:export state?
   "Is `column` a state?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/State))
+  (clojure.core/isa? (:semantic-type column) :type/State))
 
 (defn ^:export zip-code?
   "Is `column` a zip-code?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/ZipCode))
+  (clojure.core/isa? (:semantic-type column) :type/ZipCode))
 
 (defn ^:export country?
   "Is `column` a country?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Country))
+  (clojure.core/isa? (:semantic-type column) :type/Country))
 
 (defn ^:export coordinate?
   "Is `column` a coordinate?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Coordinate))
+  (clojure.core/isa? (:semantic-type column) :type/Coordinate))
 
 (defn ^:export latitude?
   "Is `column` a latitude?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Latitude))
+  (clojure.core/isa? (:semantic-type column) :type/Latitude))
 
 (defn ^:export longitude?
   "Is `column` a longitude?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Longitude))
+  (clojure.core/isa? (:semantic-type column) :type/Longitude))
 
 (defn ^:export currency?
   "Is `column` a currency?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Currency))
+  (clojure.core/isa? (:semantic-type column) :type/Currency))
 
 (defn ^:export comment?
   "Is `column` a comment?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Comment))
+  (clojure.core/isa? (:semantic-type column) :type/Comment))
 
 (defn ^:export id?
   "Is `column` an ID?"
   [column]
-  (or (clojure.core/isa? (:semantic_type column) :type/FK)
-      (clojure.core/isa? (:semantic_type column) :type/PK)))
+  (or (clojure.core/isa? (:semantic-type column) :type/FK)
+      (clojure.core/isa? (:semantic-type column) :type/PK)))
 
 (defn ^:export URL?
   "Is `column` a URL?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/URL))
+  (clojure.core/isa? (:semantic-type column) :type/URL))
 
 (defn ^:export email?
   "Is `column` an email?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/Email))
+  (clojure.core/isa? (:semantic-type column) :type/Email))
 
 (defn ^:export avatar-URL?
   "Is `column` an avatar URL?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/AvatarURL))
+  (clojure.core/isa? (:semantic-type column) :type/AvatarURL))
 
 (defn ^:export image-URL?
   "Is `column` an image URL?"
   [column]
-  (clojure.core/isa? (:semantic_type column) :type/ImageURL))
+  (clojure.core/isa? (:semantic-type column) :type/ImageURL))
 
 (defn ^:export has-latitude-and-longitude?
   "Does the collection `columns` contain both a latitude and a longitude column?"
diff --git a/src/metabase/lib/util.cljc b/src/metabase/lib/util.cljc
index d96b3030ba5..c17dd74833b 100644
--- a/src/metabase/lib/util.cljc
+++ b/src/metabase/lib/util.cljc
@@ -116,18 +116,26 @@
 (defn- joins->pipeline [joins]
   (mapv join->pipeline joins))
 
+(defn ->stage-metadata
+  "Convert legacy `:source-metadata` to [[metabase.lib.metadata/StageMetadata]]."
+  [source-metadata]
+  (when source-metadata
+    (-> (if (vector? source-metadata)
+          {:columns source-metadata}
+          source-metadata)
+        (update :columns (fn [columns]
+                           (mapv (fn [column]
+                                   (-> column
+                                       (update-keys u/->kebab-case-en)
+                                       (assoc :lib/type :metadata/field)))
+                                 columns)))
+        (assoc :lib/type :metadata/results))))
+
 (defn- inner-query->stages [{:keys [source-query source-metadata], :as inner-query}]
   (let [previous-stages (if source-query
                           (inner-query->stages source-query)
                           [])
-        source-metadata (when source-metadata
-                          (-> (if (vector? source-metadata)
-                                {:columns source-metadata}
-                                source-metadata)
-                              (update :columns (fn [columns]
-                                                 (for [column columns]
-                                                   (assoc column :lib/type :metadata/field))))
-                              (assoc :lib/type :metadata/results)))
+        source-metadata (->stage-metadata source-metadata)
         previous-stage  (dec (count previous-stages))
         previous-stages (cond-> previous-stages
                           (and source-metadata
@@ -157,13 +165,14 @@
           :stages   (inner-query->stages (:query query))}
          (dissoc query :type :query)))
 
-(def ^:private AnyQuery
+(def LegacyOrPMBQLQuery
+  "Schema for a map that is either a legacy query OR a pMBQL query."
   [:or
    [:map
-    {:error/fn "legacy query"}
+    {:error/message "legacy query"}
     [:type [:enum :native :query]]]
    [:map
-    {:error/fn "pMBQL query"}
+    {:error/message "pMBQL query"}
     [:lib/type [:= :mbql/query]]]])
 
 (mu/defn pipeline
@@ -171,7 +180,7 @@
   goal here is just to make sure we have `:stages` in the correct place and the like. See [[metabase.lib.convert]] for
   functions that actually ensure all parts of the query match the pMBQL schema (they use this function as part of that
   process.)"
-  [query :- AnyQuery]
+  [query :- LegacyOrPMBQLQuery]
   (if (= (:lib/type query) :mbql/query)
     query
     (case (:type query)
@@ -212,7 +221,7 @@
 (mu/defn query-stage :- ::lib.schema/stage
   "Fetch a specific `stage` of a query. This handles negative indices as well, e.g. `-1` will return the last stage of
   the query."
-  [query        :- AnyQuery
+  [query        :- LegacyOrPMBQLQuery
    stage-number :- :int]
   (let [{:keys [stages]} (pipeline query)]
     (get (vec stages) (non-negative-stage-index stages stage-number))))
@@ -229,7 +238,7 @@
     (apply f stage args)
 
   `stage-number` can be a negative index, e.g. `-1` will update the last stage of the query."
-  [query        :- AnyQuery
+  [query        :- LegacyOrPMBQLQuery
    stage-number :- :int
    f & args]
   (let [{:keys [stages], :as query} (pipeline query)
diff --git a/src/metabase/models/interface.clj b/src/metabase/models/interface.clj
index 332ca9a7b66..3d89980e03b 100644
--- a/src/metabase/models/interface.clj
+++ b/src/metabase/models/interface.clj
@@ -1,8 +1,6 @@
 (ns metabase.models.interface
   (:require
    [buddy.core.codecs :as codecs]
-   [camel-snake-kebab.core :as csk]
-   [camel-snake-kebab.internals.macros :as csk.macros]
    [cheshire.core :as json]
    [cheshire.generate :as json.generate]
    [clojure.core.memoize :as memoize]
@@ -447,10 +445,6 @@
 
 (methodical/prefer-method! #'t2.before-insert/before-insert :hook/timestamped? :hook/entity-id)
 
-;;; define a custom CSK conversion function so we don't run into problems if the system locale is Turkish
-(declare ^:private ->kebab-case-en) ; so Kondo doesn't complain
-(csk.macros/defconversion "kebab-case-en" u/lower-case-en u/lower-case-en "-")
-
 (methodical/defmethod t2.model/resolve-model :before :default
   "Ensure the namespace for given model is loaded.
   This is a safety mechanism as we moving to toucan2 and we don't need to require the model namespaces in order to use it."
@@ -460,7 +454,7 @@
              ;; don't try to require if it's already registered as a :metabase/model; this way ones defined in EE
              ;; namespaces won't break if they are loaded in some other way.
              (not (isa? x :metabase/model)))
-    (let [model-namespace (str "metabase.models." (->kebab-case-en (name x)))]
+    (let [model-namespace (str "metabase.models." (u/->kebab-case-en (name x)))]
       ;; use `classloader/require` which is thread-safe and plays nice with our plugins system
       (classloader/require model-namespace)))
   x)
@@ -693,4 +687,4 @@
 (methodical/defmethod t2.hydrate/fk-keys-for-automagic-hydration :default
   "In Metabase the FK key used for automagic hydration should use underscores (work around upstream Toucan 2 issue)."
   [_original-model dest-key _hydrated-key]
-  [(csk/->snake_case (keyword (str (name dest-key) "_id")))])
+  [(u/->snake_case_en (keyword (str (name dest-key) "_id")))])
diff --git a/src/metabase/models/metric.clj b/src/metabase/models/metric.clj
index 3100253640f..b5b6f6b07af 100644
--- a/src/metabase/models/metric.clj
+++ b/src/metabase/models/metric.clj
@@ -56,7 +56,7 @@
   [metadata-provider :- lib.metadata/MetadataProvider
    {:keys [definition], table-id :table_id, :as _metric}]
   (when (seq definition)
-    (when-let [{database-id :db_id} (when table-id
+    (when-let [{database-id :db-id} (when table-id
                                       (lib.metadata.protocols/table metadata-provider table-id))]
       (try
         (let [definition (merge {:source-table table-id}
diff --git a/src/metabase/models/segment.clj b/src/metabase/models/segment.clj
index 0e20b265f88..e96d3b2052e 100644
--- a/src/metabase/models/segment.clj
+++ b/src/metabase/models/segment.clj
@@ -56,7 +56,7 @@
   [metadata-provider :- lib.metadata/MetadataProvider
    {table-id :table_id, :keys [definition], :as _segment}]
   (when (seq definition)
-    (when-let [{database-id :db_id} (when table-id (lib.metadata.protocols/table metadata-provider table-id))]
+    (when-let [{database-id :db-id} (when table-id (lib.metadata.protocols/table metadata-provider table-id))]
       (try
         (let [definition (merge {:source-table table-id}
                                 definition)
diff --git a/src/metabase/util.cljc b/src/metabase/util.cljc
index 38bee573e7e..255f1b555e9 100644
--- a/src/metabase/util.cljc
+++ b/src/metabase/util.cljc
@@ -1,7 +1,7 @@
 (ns metabase.util
   "Common utility functions useful throughout the codebase."
   (:require
-   [camel-snake-kebab.core :as csk]
+   [camel-snake-kebab.internals.macros :as csk.macros]
    [clojure.pprint :as pprint]
    [clojure.set :as set]
    [clojure.string :as str]
@@ -24,7 +24,8 @@
            (java.text Normalizer Normalizer$Form)
            (java.util Locale)
            (org.apache.commons.validator.routines RegexValidator UrlValidator)))
-  #?(:cljs (:require-macros [metabase.util])))
+  #?(:cljs (:require-macros [camel-snake-kebab.internals.macros :as csk.macros]
+                            [metabase.util])))
 
 (u.ns/import-fns
   [u.format colorize format-bytes format-color format-milliseconds format-nanoseconds format-seconds])
@@ -125,30 +126,6 @@
   [m]
   (m/filter-vals some? m))
 
-(defn normalize-map
-  "Given any map-like object, return it as a Clojure map with :kebab-case keyword keys.
-  The input map can be a:
-  - Clojure map with string or keyword keys,
-  - JS object (with string keys)
-  The keys are converted to `kebab-case` from `camelCase` or `snake_case` as necessary, and turned into keywords.
-  Namespaces keywords are rejected with an exception.
-
-  Returns an empty map if nil is input (like [[update-keys]])."
-  [m]
-  (let [base #?(:clj  m
-                ;; If we're running in CLJS, convert to a ClojureScript map as needed.
-                :cljs (if (object? m)
-                        (js->clj m)
-                        m))]
-    (update-keys base csk/->kebab-case-keyword)))
-
-(defn snake-key
-  "Convert a keyword or string `k` from `lisp-case` to `snake-case`."
-  [k]
-  (if (keyword? k)
-    (keyword (snake-key (name k)))
-    (str/replace k #"-" "_")))
-
 (defn recursive-map-keys
   "Recursively replace the keys in a map with the value of `(f key)`."
   [f m]
@@ -158,11 +135,6 @@
       %)
    m))
 
-(defn snake-keys
-  "Convert the keys in a map from `lisp-case` to `snake_case`."
-  [m]
-  (recursive-map-keys snake-key m))
-
 (defn add-period
   "Fixes strings that don't terminate in a period; also accounts for strings
   that end in `:`. Used for formatting docs."
@@ -176,11 +148,9 @@
         (str text ".")))))
 
 (defn lower-case-en
-  "Locale-agnostic version of `clojure.string/lower-case`.
-  `clojure.string/lower-case` uses the default locale in conversions, turning
-  `ID` into `ıd`, in the Turkish locale. This function always uses the
-  `en-US` locale."
-  [^CharSequence s]
+  "Locale-agnostic version of [[clojure.string/lower-case]]. [[clojure.string/lower-case]] uses the default locale in
+  conversions, turning `ID` into `ıd`, in the Turkish locale. This function always uses the `en-US` locale."
+  ^String [^CharSequence s]
   #?(:clj  (.. s toString (toLowerCase (Locale/US)))
      :cljs (.toLowerCase s)))
 
@@ -189,14 +159,61 @@
   `clojure.string/upper-case` uses the default locale in conversions, turning
   `id` into `Ä°D`, in the Turkish locale. This function always uses the
   `en-US` locale."
-  [^CharSequence s]
+  ^String [^CharSequence s]
   #?(:clj  (.. s toString (toUpperCase (Locale/US)))
      :cljs (.toUpperCase s)))
 
-(defn screaming-snake-case
-  "Turns `strings-that-look-like-deafening-vipers` into `STRINGS_THAT_LOOK_LIKE_DEAFENING_VIPERS`."
-  [s]
-  (upper-case-en (str/replace s "-" "_")))
+(defn capitalize-en
+  "Locale-agnostic version of [[clojure.string/capitalize]]."
+  ^String [^CharSequence s]
+  (when-let [s (some-> s str)]
+    (if (< (count s) 2)
+      (upper-case-en s)
+      (str (upper-case-en (subs s 0 1))
+           (lower-case-en (subs s 1))))))
+
+;;; define custom CSK conversion functions so we don't run into problems if the system locale is Turkish
+
+;; so Kondo doesn't complain
+(declare ^:private ->kebab-case-en*)
+(declare ^:private ->camelCaseEn*)
+(declare ^:private ->snake_case_en*)
+(declare ^:private ->SCREAMING_SNAKE_CASE_EN*)
+
+(csk.macros/defconversion "kebab-case-en*"           lower-case-en lower-case-en "-")
+(csk.macros/defconversion "camelCaseEn*"             lower-case-en capitalize-en "")
+(csk.macros/defconversion "snake_case_en*"           lower-case-en lower-case-en "_")
+(csk.macros/defconversion "SCREAMING_SNAKE_CASE_EN*" upper-case-en upper-case-en "_")
+
+(defn- wrap-csk-conversion-fn-to-handle-nil-and-namespaced-keywords
+  "Wrap a CSK defconversion function so that it handles nil and namespaced keywords, which it doesn't support out of the
+  box for whatever reason."
+  [f]
+  (fn [x]
+    (when x
+      (if (qualified-keyword? x)
+        (keyword (f (namespace x)) (f (name x)))
+        (f x)))))
+
+(def ^{:arglists '([x])} ->kebab-case-en
+  "Like [[camel-snake-kebab.core/->kebab-case]], but always uses English for lower-casing, supports keywords with
+  namespaces, and returns `nil` when passed `nil` (rather than throwing an exception)."
+  (wrap-csk-conversion-fn-to-handle-nil-and-namespaced-keywords ->kebab-case-en*))
+
+(def ^{:arglists '([x])} ->snake_case_en
+  "Like [[camel-snake-kebab.core/->snake_case]], but always uses English for lower-casing, supports keywords with
+  namespaces, and returns `nil` when passed `nil` (rather than throwing an exception)."
+  (wrap-csk-conversion-fn-to-handle-nil-and-namespaced-keywords ->snake_case_en*))
+
+(def ^{:arglists '([x])} ->camelCaseEn
+  "Like [[camel-snake-kebab.core/->camelCase]], but always uses English for upper- and lower-casing, supports keywords
+  with namespaces, and returns `nil` when passed `nil` (rather than throwing an exception)."
+  (wrap-csk-conversion-fn-to-handle-nil-and-namespaced-keywords ->camelCaseEn*))
+
+(def ^{:arglists '([x])} ->SCREAMING_SNAKE_CASE_EN
+  "Like [[camel-snake-kebab.core/->SCREAMING_SNAKE_CASE]], but always uses English for upper- and lower-casing, supports
+  keywords with namespaces, and returns `nil` when passed `nil` (rather than throwing an exception)."
+  (wrap-csk-conversion-fn-to-handle-nil-and-namespaced-keywords ->SCREAMING_SNAKE_CASE_EN*))
 
 (defn capitalize-first-char
   "Like string/capitalize, only it ignores the rest of the string
@@ -207,6 +224,27 @@
     (str (upper-case-en (subs s 0 1))
          (subs s 1))))
 
+(defn snake-keys
+  "Convert the keys in a map from `kebab-case` to `snake_case`."
+  [m]
+  (recursive-map-keys ->snake_case_en m))
+
+(defn normalize-map
+  "Given any map-like object, return it as a Clojure map with :kebab-case keyword keys.
+  The input map can be a:
+  - Clojure map with string or keyword keys,
+  - JS object (with string keys)
+  The keys are converted to `kebab-case` from `camelCase` or `snake_case` as necessary, and turned into keywords.
+
+  Returns an empty map if nil is input (like [[update-keys]])."
+  [m]
+  (let [base #?(:clj  m
+                ;; If we're running in CLJS, convert to a ClojureScript map as needed.
+                :cljs (if (object? m)
+                        (js->clj m)
+                        m))]
+    (update-keys base (comp keyword ->kebab-case-en))))
+
 ;; Log the maximum memory available to the JVM at launch time as well since it is very handy for debugging things
 #?(:clj
    (when-not *compile-files*
@@ -550,8 +588,7 @@
 (defn lower-case-map-keys
   "Changes the keys of a given map to lower case."
   [m]
-  (into {} (for [[k v] m]
-             [(-> k name lower-case-en keyword) v])))
+  (update-keys m #(-> % name lower-case-en keyword)))
 
 (defn pprint-to-str
   "Returns the output of pretty-printing `x` as a string.
diff --git a/test/metabase/lib/aggregation_test.cljc b/test/metabase/lib/aggregation_test.cljc
index 1cdba752651..33835861b12 100644
--- a/test/metabase/lib/aggregation_test.cljc
+++ b/test/metabase/lib/aggregation_test.cljc
@@ -142,29 +142,29 @@
                              (col-info-for-aggregation-clause clause))
     ;; :count, no field
     [:/ {} [:count {}] 2]
-    {:base_type    :type/Float
+    {:base-type    :type/Float
      :name         "count_divided_by_2"
-     :display_name "Count ÷ 2"}
+     :display-name "Count ÷ 2"}
 
     ;; :sum
     [:sum {} [:+ {} (lib.tu/field-clause :venues :price) 1]]
-    {:base_type    :type/Integer
+    {:base-type    :type/Integer
      :name         "sum_PRICE_plus_1"
-     :display_name "Sum of Price + 1"}
+     :display-name "Sum of Price + 1"}
 
     ;; options map
     [:sum
      {:name "sum_2", :display-name "My custom name", :base-type :type/BigInteger}
      (lib.tu/field-clause :venues :price)]
-    {:base_type    :type/BigInteger
+    {:base-type    :type/BigInteger
      :name         "sum_2"
-     :display_name "My custom name"}))
+     :display-name "My custom name"}))
 
 (deftest ^:parallel col-info-named-aggregation-test
   (testing "col info for an `expression` aggregation w/ a named expression should work as expected"
-    (is (=? {:base_type    :type/Integer
+    (is (=? {:base-type    :type/Integer
              :name         "sum_double-price"
-             :display_name "Sum of double-price"}
+             :display-name "Sum of double-price"}
             (col-info-for-aggregation-clause
              (lib.tu/venues-query-with-last-stage
               {:expressions {"double-price" [:*
@@ -182,7 +182,6 @@
          :database (meta/id)
          :stages [{:lib/type :mbql.stage/mbql
                    :source-table (meta/id :venues)
-                   :lib/options {:lib/uuid string?}
                    :aggregation [[:sum {:lib/uuid string?}
                                   [:field
                                    {:base-type :type/Integer, :lib/uuid string?}
@@ -238,9 +237,9 @@
                   (lib/expression "double-price" (lib/* (lib/field (meta/id :venues :price)) 2))
                   (lib/aggregate (lib/sum [:expression {:lib/uuid (str (random-uuid))} "double-price"])))]
     (is (=? [{:lib/type     :metadata/field
-              :base_type    :type/Integer
+              :base-type    :type/Integer
               :name         "sum_double-price"
-              :display_name "Sum of double-price"}]
+              :display-name "Sum of double-price"}]
             (lib/aggregations query)))
     (is (= :type/Integer
            (lib/type-of query (first (lib/aggregations query)))))))
@@ -251,9 +250,9 @@
                     (lib/aggregate (lib/sum (lib/field (meta/id :venues :price)))))]
       (is (=? {:settings     {:is_priceless true}
                :lib/type     :metadata/field
-               :base_type    :type/Integer
+               :base-type    :type/Integer
                :name         "sum_PRICE"
-               :display_name "Sum of Price"
+               :display-name "Sum of Price"
                :lib/source   :source/aggregations}
               (lib.metadata.calculation/metadata query (first (lib/aggregations query -1))))))))
 
@@ -275,12 +274,12 @@
            (lib.metadata.calculation/display-name query ag-ref)))
     (is (=? {:lib/type                                   :metadata/field
              :lib/source                                 :source/aggregations
-             :display_name                               "Average of Price + 1"
-             :effective_type                             :type/Float
+             :display-name                               "Average of Price + 1"
+             :effective-type                             :type/Float
              :metabase.lib.aggregation/aggregation-index 0}
             (lib.metadata.calculation/metadata query ag-ref)))
-    (is (=? {:display_name   "Average of Price + 1"
-             :effective_type :type/Float}
+    (is (=? {:display-name   "Average of Price + 1"
+             :effective-type :type/Float}
             (lib.metadata.calculation/display-info query ag-ref)))))
 
 (deftest ^:parallel aggregate-should-drop-invalid-parts
diff --git a/test/metabase/lib/breakout_test.cljc b/test/metabase/lib/breakout_test.cljc
index e104c1122b2..7d9d42e68cf 100644
--- a/test/metabase/lib/breakout_test.cljc
+++ b/test/metabase/lib/breakout_test.cljc
@@ -70,65 +70,65 @@
     (testing (lib.util/format "Query =\n%s" (u/pprint-to-str query))
       (is (=? [{:lib/type                 :metadata/field
                 :name                     "ID"
-                :display_name             "ID"
+                :display-name             "ID"
                 :id                       (meta/id :venues :id)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/BigInteger
+                :table-id                 (meta/id :venues)
+                :base-type                :type/BigInteger
                 :lib/source-column-alias  "ID"
                 :lib/desired-column-alias "ID"}
                {:lib/type                 :metadata/field
                 :name                     "NAME"
-                :display_name             "Name"
+                :display-name             "Name"
                 :id                       (meta/id :venues :name)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Text
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Text
                 :lib/source-column-alias  "NAME"
                 :lib/desired-column-alias "NAME"}
                {:lib/type                 :metadata/field
                 :name                     "CATEGORY_ID"
-                :display_name             "Category ID"
+                :display-name             "Category ID"
                 :id                       (meta/id :venues :category-id)
-                :table_id                 (meta/id :venues)
+                :table-id                 (meta/id :venues)
                 :lib/source-column-alias  "CATEGORY_ID"
                 :lib/desired-column-alias "CATEGORY_ID"}
                {:lib/type                 :metadata/field
                 :name                     "LATITUDE"
-                :display_name             "Latitude"
+                :display-name             "Latitude"
                 :id                       (meta/id :venues :latitude)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Float
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Float
                 :lib/source-column-alias  "LATITUDE"
                 :lib/desired-column-alias "LATITUDE"}
                {:lib/type                 :metadata/field
                 :name                     "LONGITUDE"
-                :display_name             "Longitude"
+                :display-name             "Longitude"
                 :id                       (meta/id :venues :longitude)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Float
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Float
                 :lib/source-column-alias  "LONGITUDE"
                 :lib/desired-column-alias "LONGITUDE"}
                {:lib/type                 :metadata/field
                 :name                     "PRICE"
-                :display_name             "Price"
+                :display-name             "Price"
                 :id                       (meta/id :venues :price)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Integer
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Integer
                 :lib/source-column-alias  "PRICE"
                 :lib/desired-column-alias "PRICE"}
                {:lib/type                 :metadata/field
                 :name                     "ID"
-                :display_name             "ID"
+                :display-name             "ID"
                 :id                       (meta/id :categories :id)
-                :table_id                 (meta/id :categories)
-                :base_type                :type/BigInteger
+                :table-id                 (meta/id :categories)
+                :base-type                :type/BigInteger
                 :lib/source-column-alias  "ID"
                 :lib/desired-column-alias "CATEGORIES__via__CATEGORY_ID__ID"}
                {:lib/type                 :metadata/field
                 :name                     "NAME"
-                :display_name             "Name"
+                :display-name             "Name"
                 :id                       (meta/id :categories :name)
-                :table_id                 (meta/id :categories)
-                :base_type                :type/Text
+                :table-id                 (meta/id :categories)
+                :base-type                :type/Text
                 :lib/source-column-alias  "NAME"
                 :lib/desired-column-alias "CATEGORIES__via__CATEGORY_ID__NAME"}]
               (lib/breakoutable-columns query))))))
@@ -145,9 +145,9 @@
                  {:id (meta/id :venues :longitude) :name "LONGITUDE"}
                  {:id (meta/id :venues :price) :name "PRICE"}
                  {:lib/type     :metadata/field
-                  :base_type    :type/Integer
+                  :base-type    :type/Integer
                   :name         "Category ID + 1"
-                  :display_name "Category ID + 1"
+                  :display-name "Category ID + 1"
                   :lib/source   :source/expressions}
                  {:id (meta/id :categories :id) :name "ID"}
                  {:id (meta/id :categories :name) :name "NAME"}]
@@ -172,18 +172,18 @@
                  {:id (meta/id :venues :price) :name "PRICE"}
                  {:lib/type     :metadata/field
                   :name         "ID"
-                  :display_name "ID"
+                  :display-name "ID"
                   :source_alias "Cat"
                   :id           (meta/id :categories :id)
-                  :table_id     (meta/id :categories)
-                  :base_type    :type/BigInteger}
+                  :table-id     (meta/id :categories)
+                  :base-type    :type/BigInteger}
                  {:lib/type     :metadata/field
                   :name         "NAME"
-                  :display_name "Name"
+                  :display-name "Name"
                   :source_alias "Cat"
                   :id           (meta/id :categories :name)
-                  :table_id     (meta/id :categories)
-                  :base_type    :type/Text}]
+                  :table-id     (meta/id :categories)
+                  :base-type    :type/Text}]
                 (lib/breakoutable-columns query)))))))
 
 (deftest ^:parallel breakoutable-columns-source-card-test
@@ -193,57 +193,57 @@
     (testing (str (pr-str varr) \newline (lib.util/format "Query =\n%s" (u/pprint-to-str query)))
       (let [columns (lib/breakoutable-columns query)]
         (is (=? [{:name                     "USER_ID"
-                  :display_name             "User ID"
-                  :base_type                :type/Integer
+                  :display-name             "User ID"
+                  :base-type                :type/Integer
                   :lib/source               :source/card
                   :lib/desired-column-alias "USER_ID"}
                  {:name                     "count"
-                  :display_name             "Count"
-                  :base_type                :type/Integer
+                  :display-name             "Count"
+                  :base-type                :type/Integer
                   :lib/source               :source/card
                   :lib/desired-column-alias "count"}
                  {:name                     "ID"
-                  :display_name             "ID"
-                  :base_type                :type/BigInteger
+                  :display-name             "ID"
+                  :base-type                :type/BigInteger
                   :lib/source               :source/implicitly-joinable
                   :lib/desired-column-alias "USERS__via__USER_ID__ID"}
                  {:name                     "NAME"
-                  :display_name             "Name"
-                  :base_type                :type/Text
+                  :display-name             "Name"
+                  :base-type                :type/Text
                   :lib/source               :source/implicitly-joinable
                   :lib/desired-column-alias "USERS__via__USER_ID__NAME"}
                  {:name                     "LAST_LOGIN"
-                  :display_name             "Last Login"
-                  :base_type                :type/DateTime
+                  :display-name             "Last Login"
+                  :base-type                :type/DateTime
                   :lib/source               :source/implicitly-joinable
                   :lib/desired-column-alias "USERS__via__USER_ID__LAST_LOGIN"}]
                 columns))
         (testing `lib/display-info
           (is (=? [{:name                   "USER_ID"
-                    :display_name           "User ID"
-                    :table                  {:name "My Card", :display_name "My Card"}
-                    :is_from_previous_stage false
-                    :is_implicitly_joinable false}
+                    :display-name           "User ID"
+                    :table                  {:name "My Card", :display-name "My Card"}
+                    :is-from-previous-stage false
+                    :is-implicitly-joinable false}
                    {:name                   "count"
-                    :display_name           "Count"
-                    :table                  {:name "My Card", :display_name "My Card"}
-                    :is_from_previous_stage false
-                    :is_implicitly_joinable false}
+                    :display-name           "Count"
+                    :table                  {:name "My Card", :display-name "My Card"}
+                    :is-from-previous-stage false
+                    :is-implicitly-joinable false}
                    {:name                   "ID"
-                    :display_name           "ID"
-                    :table                  {:name "USERS", :display_name "Users"}
-                    :is_from_previous_stage false
-                    :is_implicitly_joinable true}
+                    :display-name           "ID"
+                    :table                  {:name "USERS", :display-name "Users"}
+                    :is-from-previous-stage false
+                    :is-implicitly-joinable true}
                    {:name                   "NAME"
-                    :display_name           "Name"
-                    :table                  {:name "USERS", :display_name "Users"}
-                    :is_from_previous_stage false
-                    :is_implicitly_joinable true}
+                    :display-name           "Name"
+                    :table                  {:name "USERS", :display-name "Users"}
+                    :is-from-previous-stage false
+                    :is-implicitly-joinable true}
                    {:name                   "LAST_LOGIN"
-                    :display_name           "Last Login"
-                    :table                  {:name "USERS", :display_name "Users"}
-                    :is_from_previous_stage false
-                    :is_implicitly_joinable true}]
+                    :display-name           "Last Login"
+                    :table                  {:name "USERS", :display-name "Users"}
+                    :is-from-previous-stage false
+                    :is-implicitly-joinable true}]
                   (for [col columns]
                     (lib/display-info query col)))))))))
 
@@ -258,8 +258,7 @@
       (is (=? {:lib/type :mbql/query
                :database (meta/id)
                :stages   [{:lib/type     :mbql.stage/mbql
-                           :source-table (meta/id :venues)
-                           :lib/options  {:lib/uuid string?}}]}
+                           :source-table (meta/id :venues)}]}
               query))
       (testing (lib.util/format "Query =\n%s" (u/pprint-to-str query))
         (let [breakoutable-columns (lib/breakoutable-columns query)
@@ -269,7 +268,6 @@
                    :database (meta/id)
                    :stages   [{:lib/type     :mbql.stage/mbql
                                :source-table (meta/id :venues)
-                               :lib/options  {:lib/uuid string?}
                                :breakout     [[:field {:lib/uuid string? :base-type :type/Text} (meta/id :venues :name)]]}]}
                   query'))
           (is (=? [[:field {:lib/uuid string? :base-type :type/Text} (meta/id :venues :name)]]
@@ -295,12 +293,12 @@
               query'))
       (is (= "Venues, Grouped by Categories → Name and Price"
              (lib/describe-query query')))
-      (is (=? [{:display_name "ID",          :lib/source :source/table-defaults}
-               {:display_name "Name",        :lib/source :source/table-defaults}
-               {:display_name "Category ID", :lib/source :source/table-defaults}
-               {:display_name "Latitude",    :lib/source :source/table-defaults}
-               {:display_name "Longitude",   :lib/source :source/table-defaults}
-               {:display_name "ID",          :lib/source :source/implicitly-joinable}]
+      (is (=? [{:display-name "ID",          :lib/source :source/table-defaults}
+               {:display-name "Name",        :lib/source :source/table-defaults}
+               {:display-name "Category ID", :lib/source :source/table-defaults}
+               {:display-name "Latitude",    :lib/source :source/table-defaults}
+               {:display-name "Longitude",   :lib/source :source/table-defaults}
+               {:display-name "ID",          :lib/source :source/implicitly-joinable}]
               (lib/breakoutable-columns query'))))))
 
 (deftest ^:parallel breakoutable-columns-with-source-card-e2e-test
@@ -310,7 +308,7 @@
         (let [name-col (m/find-first #(= (:name %) "USER_ID")
                                      (lib/breakoutable-columns query))]
           (is (=? {:name      "USER_ID"
-                   :base_type :type/Integer}
+                   :base-type :type/Integer}
                   name-col))
           (let [query' (lib/breakout query name-col)]
             (is (=? {:stages
@@ -328,15 +326,15 @@
   (let [query (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
                   (lib/expression "expr" (lib/absolute-datetime "2020" :month))
                   (lib/with-fields [(lib/field "VENUES" "ID")]))]
-    (is (=? [{:id (meta/id :venues :id),          :name "ID",          :display_name "ID",          :lib/source :source/table-defaults}
-             {:id (meta/id :venues :name),        :name "NAME",        :display_name "Name",        :lib/source :source/table-defaults}
-             {:id (meta/id :venues :category-id), :name "CATEGORY_ID", :display_name "Category ID", :lib/source :source/table-defaults}
-             {:id (meta/id :venues :latitude),    :name "LATITUDE",    :display_name "Latitude",    :lib/source :source/table-defaults}
-             {:id (meta/id :venues :longitude),   :name "LONGITUDE",   :display_name "Longitude",   :lib/source :source/table-defaults}
-             {:id (meta/id :venues :price),       :name "PRICE",       :display_name "Price",       :lib/source :source/table-defaults}
-             {:name "expr", :display_name "expr", :lib/source :source/expressions}
-             {:id (meta/id :categories :id),   :name "ID",   :display_name "ID",   :lib/source :source/implicitly-joinable}
-             {:id (meta/id :categories :name), :name "NAME", :display_name "Name", :lib/source :source/implicitly-joinable}]
+    (is (=? [{:id (meta/id :venues :id),          :name "ID",          :display-name "ID",          :lib/source :source/table-defaults}
+             {:id (meta/id :venues :name),        :name "NAME",        :display-name "Name",        :lib/source :source/table-defaults}
+             {:id (meta/id :venues :category-id), :name "CATEGORY_ID", :display-name "Category ID", :lib/source :source/table-defaults}
+             {:id (meta/id :venues :latitude),    :name "LATITUDE",    :display-name "Latitude",    :lib/source :source/table-defaults}
+             {:id (meta/id :venues :longitude),   :name "LONGITUDE",   :display-name "Longitude",   :lib/source :source/table-defaults}
+             {:id (meta/id :venues :price),       :name "PRICE",       :display-name "Price",       :lib/source :source/table-defaults}
+             {:name "expr", :display-name "expr", :lib/source :source/expressions}
+             {:id (meta/id :categories :id),   :name "ID",   :display-name "ID",   :lib/source :source/implicitly-joinable}
+             {:id (meta/id :categories :name), :name "NAME", :display-name "Name", :lib/source :source/implicitly-joinable}]
             (lib/breakoutable-columns query)))
     (let [expr (m/find-first #(= (:name %) "expr") (lib/breakoutable-columns query))]
       (is (=? {:lib/type   :metadata/field
@@ -357,8 +355,8 @@
                   (lib/with-fields [(lib/field "VENUES" "ID")
                                     (lib.dev/expression-ref "expr")])
                   (lib/append-stage))]
-    (is (=? [{:id (meta/id :venues :id), :name "ID", :display_name "ID", :lib/source :source/previous-stage}
-             {:name "expr", :display_name "expr", :lib/source :source/previous-stage}]
+    (is (=? [{:id (meta/id :venues :id), :name "ID", :display-name "ID", :lib/source :source/previous-stage}
+             {:name "expr", :display-name "expr", :lib/source :source/previous-stage}]
             (lib/breakoutable-columns query)))
     (let [expr (m/find-first #(= (:name %) "expr") (lib/breakoutable-columns query))]
       (is (=? {:lib/type   :metadata/field
diff --git a/test/metabase/lib/card_test.cljc b/test/metabase/lib/card_test.cljc
index 40860f71122..a581388a293 100644
--- a/test/metabase/lib/card_test.cljc
+++ b/test/metabase/lib/card_test.cljc
@@ -27,36 +27,38 @@
               (lib.metadata.calculation/metadata query)))
       (testing `lib/display-info
         (is (=? [{:name                   "USER_ID"
-                  :display_name           "User ID"
+                  :display-name           "User ID"
                   :table                  {:name         "My Card"
-                                           :display_name "My Card"}
-                  :effective_type         :type/Integer
-                  :semantic_type          :type/FK
-                  :is_calculated          false
-                  :is_from_previous_stage false
-                  :is_implicitly_joinable false
-                  :is_from_join           false}
+                                           :display-name "My Card"}
+                  :effective-type         :type/Integer
+                  :semantic-type          :type/FK
+                  :is-calculated          false
+                  :is-from-previous-stage false
+                  :is-implicitly-joinable false
+                  :is-from-join           false}
                  {:name                   "count"
-                  :display_name           "Count"
+                  :display-name           "Count"
                   :table                  {:name         "My Card"
-                                           :display_name "My Card"}
-                  :effective_type         :type/Integer
-                  :is_from_previous_stage false
-                  :is_from_join           false
-                  :is_calculated          false
-                  :is_implicitly_joinable false}]
+                                           :display-name "My Card"}
+                  :effective-type         :type/Integer
+                  :is-from-previous-stage false
+                  :is-from-join           false
+                  :is-calculated          false
+                  :is-implicitly-joinable false}]
                 (for [col (lib.metadata.calculation/metadata query)]
                   (lib/display-info query col))))))))
 
 (deftest ^:parallel card-source-query-metadata-test
   (doseq [metadata [{:id              1
                      :name            "My Card"
-                     :result_metadata meta/results-metadata}
-                    ;; in some cases the FE is transforming the metadata like this, not sure why but handle it anyway
+                     :result-metadata meta/card-results-metadata
+                     :dataset-query   {}}
+                    ;; in some cases [the FE unit tests are broken] the FE is transforming the metadata like this, not sure why but handle it anyway
                     ;; (#29739)
-                    {:id     1
-                     :name   "My Card"
-                     :fields (:columns meta/results-metadata)}]]
+                    {:id            1
+                     :name          "My Card"
+                     :fields        meta/card-results-metadata
+                     :dataset-query {}}]]
     (testing (str "metadata = \n" (u/pprint-to-str metadata))
       (let [query {:lib/type     :mbql/query
                    :lib/metadata (lib.tu/mock-metadata-provider
@@ -65,19 +67,19 @@
                    :stages       [{:lib/type     :mbql.stage/mbql
                                    :lib/options  {:lib/uuid (str (random-uuid))}
                                    :source-table "card__1"}]}]
-        (is (=? (for [col (:columns meta/results-metadata)]
+        (is (=? (for [col meta/card-results-metadata]
                   (assoc col :lib/source :source/card))
                 (lib.metadata.calculation/metadata query)))))))
 
 (deftest ^:parallel card-results-metadata-merge-metadata-provider-metadata-test
-  (testing "Merge metadata from the metadata provider into result_metadata (#30046)"
+  (testing "Merge metadata from the metadata provider into result-metadata (#30046)"
     (let [query (lib.tu/query-with-card-source-table-with-result-metadata)]
       (is (=? [{:lib/type                 :metadata/field
                 :id                       (meta/id :checkins :user-id)
-                :table_id                 (meta/id :checkins)
-                :semantic_type            :type/FK
-                ;; this comes from the metadata provider, it's not present in `result_metadata`
-                :fk_target_field_id       (meta/id :users :id)
+                :table-id                 (meta/id :checkins)
+                :semantic-type            :type/FK
+                ;; this comes from the metadata provider, it's not present in `result-metadata`
+                :fk-target-field-id       (meta/id :users :id)
                 :lib/desired-column-alias "USER_ID"}
                {:lib/type :metadata/field
                 :name     "count"}]
diff --git a/test/metabase/lib/column_group_test.cljc b/test/metabase/lib/column_group_test.cljc
index ac667d23ed7..eb78f0e1455 100644
--- a/test/metabase/lib/column_group_test.cljc
+++ b/test/metabase/lib/column_group_test.cljc
@@ -17,27 +17,27 @@
     (is (not (mc/explain [:sequential @#'lib.column-group/ColumnGroup] groups)))
     (is (=? [{::lib.column-group/group-type :group-type/main
               :lib/type                     :metadata/column-group
-              ::lib.column-group/columns    [{:name "ID", :display_name "ID"}
-                                             {:name "NAME", :display_name "Name"}
-                                             {:name "CATEGORY_ID", :display_name "Category ID"}
-                                             {:name "LATITUDE", :display_name "Latitude"}
-                                             {:name "LONGITUDE", :display_name "Longitude"}
-                                             {:name "PRICE", :display_name "Price"}]}
+              ::lib.column-group/columns    [{:name "ID", :display-name "ID"}
+                                             {:name "NAME", :display-name "Name"}
+                                             {:name "CATEGORY_ID", :display-name "Category ID"}
+                                             {:name "LATITUDE", :display-name "Latitude"}
+                                             {:name "LONGITUDE", :display-name "Longitude"}
+                                             {:name "PRICE", :display-name "Price"}]}
              {::lib.column-group/group-type :group-type/join.implicit
               :lib/type                     :metadata/column-group
-              ::lib.column-group/columns    [{:name "ID", :display_name "ID"}
-                                             {:name "NAME", :display_name "Name"}]}]
+              ::lib.column-group/columns    [{:name "ID", :display-name "ID"}
+                                             {:name "NAME", :display-name "Name"}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:is_from_join           false
-                :is_implicitly_joinable false
+      (is (=? [{:is-from-join           false
+                :is-implicitly-joinable false
                 :name                   "VENUES"
-                :display_name           "Venues"}
-               {:is_from_join           false
-                :is_implicitly_joinable true
+                :display-name           "Venues"}
+               {:is-from-join           false
+                :is-implicitly-joinable true
                 :name                   "CATEGORY_ID"
-                :display_name           "Category ID"
-                :fk_reference_name      "Category"}]
+                :display-name           "Category ID"
+                :fk-reference-name      "Category"}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -51,14 +51,14 @@
         columns (lib/orderable-columns query)
         groups  (lib/group-columns columns)]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:display_name "Name", :lib/source :source/breakouts}
-                                             {:display_name "Sum of ID", :lib/source :source/aggregations}]}]
+              ::lib.column-group/columns    [{:display-name "Name", :lib/source :source/breakouts}
+                                             {:display-name "Sum of ID", :lib/source :source/aggregations}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:is_from_join           false
-                :is_implicitly_joinable false
+      (is (=? [{:is-from-join           false
+                :is-implicitly-joinable false
                 :name                   "VENUES"
-                :display_name           "Venues"}]
+                :display-name           "Venues"}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -73,13 +73,13 @@
         columns (lib/orderable-columns query)
         groups  (lib/group-columns columns)]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:display_name "Name", :lib/source :source/previous-stage}
-                                             {:display_name "Sum of ID", :lib/source :source/previous-stage}]}]
+              ::lib.column-group/columns    [{:display-name "Name", :lib/source :source/previous-stage}
+                                             {:display-name "Sum of ID", :lib/source :source/previous-stage}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:display_name ""
-                :is_from_join false
-                :is_implicitly_joinable false}]
+      (is (=? [{:display-name ""
+                :is-from-join false
+                :is-implicitly-joinable false}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -91,24 +91,24 @@
         columns (lib/orderable-columns query)
         groups  (lib/group-columns columns)]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:display_name "User ID", :lib/source :source/card}
-                                             {:display_name "Count", :lib/source :source/card}]}
+              ::lib.column-group/columns    [{:display-name "User ID", :lib/source :source/card}
+                                             {:display-name "Count", :lib/source :source/card}]}
              {::lib.column-group/group-type :group-type/join.implicit
               :fk-field-id                  (meta/id :checkins :user-id)
-              ::lib.column-group/columns    [{:display_name "ID", :lib/source :source/implicitly-joinable}
-                                             {:display_name "Name", :lib/source :source/implicitly-joinable}
-                                             {:display_name "Last Login", :lib/source :source/implicitly-joinable}]}]
+              ::lib.column-group/columns    [{:display-name "ID", :lib/source :source/implicitly-joinable}
+                                             {:display-name "Name", :lib/source :source/implicitly-joinable}
+                                             {:display-name "Last Login", :lib/source :source/implicitly-joinable}]}]
             groups))
     (testing `lib/display-info
       (is (=? [{:name                   "My Card"
-                :display_name           "My Card"
-                :is_from_join           false
-                :is_implicitly_joinable false}
+                :display-name           "My Card"
+                :is-from-join           false
+                :is-implicitly-joinable false}
                {:name                   "USER_ID"
-                :display_name           "User ID"
-                :fk_reference_name      "User"
-                :is_from_join           false
-                :is_implicitly_joinable true}]
+                :display-name           "User ID"
+                :fk-reference-name      "User"
+                :is-from-join           false
+                :is-implicitly-joinable true}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -120,26 +120,26 @@
         columns (lib/orderable-columns query)
         groups  (lib/group-columns columns)]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:name "ID", :display_name "ID"}
-                                             {:name "NAME", :display_name "Name"}
-                                             {:name "CATEGORY_ID", :display_name "Category ID"}
-                                             {:name "LATITUDE", :display_name "Latitude"}
-                                             {:name "LONGITUDE", :display_name "Longitude"}
-                                             {:name "PRICE", :display_name "Price"}]}
+              ::lib.column-group/columns    [{:name "ID", :display-name "ID"}
+                                             {:name "NAME", :display-name "Name"}
+                                             {:name "CATEGORY_ID", :display-name "Category ID"}
+                                             {:name "LATITUDE", :display-name "Latitude"}
+                                             {:name "LONGITUDE", :display-name "Longitude"}
+                                             {:name "PRICE", :display-name "Price"}]}
              {::lib.column-group/group-type :group-type/join.explicit
               :join-alias                   "Cat"
-              ::lib.column-group/columns    [{:display_name "ID", :lib/source :source/joins}
-                                             {:display_name "Name", :lib/source :source/joins}]}]
+              ::lib.column-group/columns    [{:display-name "ID", :lib/source :source/joins}
+                                             {:display-name "Name", :lib/source :source/joins}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:is_from_join           false
-                :is_implicitly_joinable false
+      (is (=? [{:is-from-join           false
+                :is-implicitly-joinable false
                 :name                   "VENUES"
-                :display_name           "Venues"}
-               {:is_from_join           true
-                :is_implicitly_joinable false
+                :display-name           "Venues"}
+               {:is-from-join           true
+                :is-implicitly-joinable false
                 :name                   "Cat"
-                :display_name           "Categories"}]
+                :display-name           "Categories"}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -151,28 +151,28 @@
         columns (lib/orderable-columns query)
         groups  (lib/group-columns columns)]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:name "ID", :display_name "ID"}
-                                             {:name "NAME", :display_name "Name"}
-                                             {:name "CATEGORY_ID", :display_name "Category ID"}
-                                             {:name "LATITUDE", :display_name "Latitude"}
-                                             {:name "LONGITUDE", :display_name "Longitude"}
-                                             {:name "PRICE", :display_name "Price"}
-                                             {:display_name "expr", :lib/source :source/expressions}]}
+              ::lib.column-group/columns    [{:name "ID", :display-name "ID"}
+                                             {:name "NAME", :display-name "Name"}
+                                             {:name "CATEGORY_ID", :display-name "Category ID"}
+                                             {:name "LATITUDE", :display-name "Latitude"}
+                                             {:name "LONGITUDE", :display-name "Longitude"}
+                                             {:name "PRICE", :display-name "Price"}
+                                             {:display-name "expr", :lib/source :source/expressions}]}
              {::lib.column-group/group-type :group-type/join.implicit
               :lib/type                     :metadata/column-group
-              ::lib.column-group/columns    [{:name "ID", :display_name "ID"}
-                                             {:name "NAME", :display_name "Name"}]}]
+              ::lib.column-group/columns    [{:name "ID", :display-name "ID"}
+                                             {:name "NAME", :display-name "Name"}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:is_from_join           false
-                :is_implicitly_joinable false
+      (is (=? [{:is-from-join           false
+                :is-implicitly-joinable false
                 :name                   "VENUES"
-                :display_name           "Venues"}
-               {:is_from_join           false
-                :is_implicitly_joinable true
+                :display-name           "Venues"}
+               {:is-from-join           false
+                :is-implicitly-joinable true
                 :name                   "CATEGORY_ID"
-                :display_name           "Category ID"
-                :fk_reference_name      "Category"}]
+                :display-name           "Category ID"
+                :fk-reference-name      "Category"}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -185,25 +185,25 @@
         columns (lib/orderable-columns query)
         groups  (lib/group-columns columns)]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:display_name "User ID", :lib/source :source/card}
-                                             {:display_name "Count", :lib/source :source/card}
-                                             {:display_name "expr", :lib/source :source/expressions}]}
+              ::lib.column-group/columns    [{:display-name "User ID", :lib/source :source/card}
+                                             {:display-name "Count", :lib/source :source/card}
+                                             {:display-name "expr", :lib/source :source/expressions}]}
              {::lib.column-group/group-type :group-type/join.implicit
               :fk-field-id                  (meta/id :checkins :user-id)
-              ::lib.column-group/columns    [{:display_name "ID", :lib/source :source/implicitly-joinable}
-                                             {:display_name "Name", :lib/source :source/implicitly-joinable}
-                                             {:display_name "Last Login", :lib/source :source/implicitly-joinable}] }]
+              ::lib.column-group/columns    [{:display-name "ID", :lib/source :source/implicitly-joinable}
+                                             {:display-name "Name", :lib/source :source/implicitly-joinable}
+                                             {:display-name "Last Login", :lib/source :source/implicitly-joinable}] }]
             groups))
     (testing `lib/display-info
       (is (=? [{:name                   "My Card"
-                :display_name           "My Card"
-                :is_from_join           false
-                :is_implicitly_joinable false}
+                :display-name           "My Card"
+                :is-from-join           false
+                :is-implicitly-joinable false}
                {:name                   "USER_ID"
-                :display_name           "User ID"
-                :fk_reference_name      "User"
-                :is_from_join           false
-                :is_implicitly_joinable true}]
+                :display-name           "User ID"
+                :fk-reference-name      "User"
+                :is-from-join           false
+                :is-implicitly-joinable true}]
               (for [group groups]
                 (lib/display-info query group)))))
     (testing `lib/columns-group-columns
@@ -214,13 +214,13 @@
   (let [query  (lib.tu/native-query)
         groups (lib/group-columns (lib/orderable-columns query))]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:display_name "another Field", :lib/source :source/native}
-                                             {:display_name "sum of User ID", :lib/source :source/native}]}]
+              ::lib.column-group/columns    [{:display-name "another Field", :lib/source :source/native}
+                                             {:display-name "sum of User ID", :lib/source :source/native}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:display_name           "Native query"
-                :is_from_join           false
-                :is_implicitly_joinable false}]
+      (is (=? [{:display-name           "Native query"
+                :is-from-join           false
+                :is-implicitly-joinable false}]
               (for [group groups]
                 (lib/display-info query group)))))))
 
@@ -229,12 +229,12 @@
                    lib/append-stage)
         groups (lib/group-columns (lib/orderable-columns query))]
     (is (=? [{::lib.column-group/group-type :group-type/main
-              ::lib.column-group/columns    [{:display_name "another Field", :lib/source :source/previous-stage}
-                                             {:display_name "sum of User ID", :lib/source :source/previous-stage}]}]
+              ::lib.column-group/columns    [{:display-name "another Field", :lib/source :source/previous-stage}
+                                             {:display-name "sum of User ID", :lib/source :source/previous-stage}]}]
             groups))
     (testing `lib/display-info
-      (is (=? [{:display_name           ""
-                :is_from_join           false
-                :is_implicitly_joinable false}]
+      (is (=? [{:display-name           ""
+                :is-from-join           false
+                :is-implicitly-joinable false}]
               (for [group groups]
                 (lib/display-info query group)))))))
diff --git a/test/metabase/lib/dev_test.cljc b/test/metabase/lib/dev_test.cljc
index 39d09dd34be..ec36b3be844 100644
--- a/test/metabase/lib/dev_test.cljc
+++ b/test/metabase/lib/dev_test.cljc
@@ -21,7 +21,6 @@
   (is (=? {:lib/type :mbql/query
            :database (meta/id)
            :stages   [{:lib/type     :mbql.stage/mbql
-                       :lib/options  {:lib/uuid string?}
                        :source-table (meta/id :venues)}]}
           (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
               (dissoc :lib/metadata)))))
diff --git a/test/metabase/lib/expression_test.cljc b/test/metabase/lib/expression_test.cljc
index 2724a0d8b93..c1751ca7bb8 100644
--- a/test/metabase/lib/expression_test.cljc
+++ b/test/metabase/lib/expression_test.cljc
@@ -20,7 +20,6 @@
            :database (meta/id)
            :stages [{:lib/type :mbql.stage/mbql
                      :source-table (meta/id :venues)
-                     :lib/options {:lib/uuid string?}
                      :expressions {"myadd" [:+ {:lib/uuid string?}
                                             1
                                             [:field {:base-type :type/Integer, :lib/uuid string?} (meta/id :venues :category-id)]]}}]}
@@ -85,9 +84,9 @@
             (is (= typ (lib.schema.expression/type-of resolved)))))))))
 
 (deftest ^:parallel col-info-expression-ref-test
-  (is (=? {:base_type    :type/Integer
+  (is (=? {:base-type    :type/Integer
            :name         "double-price"
-           :display_name "double-price"
+           :display-name "double-price"
            :lib/source   :source/expressions}
           (lib.metadata.calculation/metadata
            (lib.tu/venues-query-with-last-stage
@@ -106,8 +105,8 @@
                                             [:interval {:lib/uuid (str (random-uuid))} -1 :month]]}
                 :fields      [[:expression {:base-type :type/DateTime, :lib/uuid (str (random-uuid))} "prev_month"]]})]
     (is (=? [{:name         "prev_month"
-              :display_name "prev_month"
-              :base_type    :type/DateTime
+              :display-name "prev_month"
+              :base-type    :type/DateTime
               :lib/source   :source/expressions}]
             (lib.metadata.calculation/metadata query)))))
 
@@ -162,8 +161,8 @@
     (testing "Uses the first clause"
       (testing "Gets the type information from the field"
         (is (=? {:name         "expr"
-                 :display_name "expr"
-                 :base_type    :type/Text}
+                 :display-name "expr"
+                 :base-type    :type/Text}
                 (infer-first [:coalesce
                               {:lib/uuid (str (random-uuid))}
                               (lib.tu/field-clause :venues :name)
@@ -172,9 +171,9 @@
           (is (not (contains? (infer-first [:coalesce {:lib/uuid (str (random-uuid))} (lib.tu/field-clause :venues :name) "bar"])
                               :id)))))
       (testing "Gets the type information from the literal"
-        (is (=? {:base_type    :type/Text
+        (is (=? {:base-type    :type/Text
                  :name         "expr"
-                 :display_name "expr"}
+                 :display-name "expr"}
                 (infer-first [:coalesce {:lib/uuid (str (random-uuid))} "bar" (lib.tu/field-clause :venues :name)])))))))
 
 (deftest ^:parallel infer-case-test
@@ -182,8 +181,8 @@
     (testing "Uses first available type information"
       (testing "From a field"
         (is (=? {:name         "expr"
-                 :display_name "expr"
-                 :base_type    :type/Text}
+                 :display-name "expr"
+                 :base-type    :type/Text}
                 (infer-first [:coalesce
                               {:lib/uuid (str (random-uuid))}
                               (lib.tu/field-clause :venues :name)
@@ -194,9 +193,9 @@
                           :id))))))))
 
 (deftest ^:parallel col-info-for-temporal-expression-test
-  (is (=? {:base_type    :type/DateTime
+  (is (=? {:base-type    :type/DateTime
            :name         "last-login-plus-2"
-           :display_name "last-login-plus-2"
+           :display-name "last-login-plus-2"
            :lib/source   :source/expressions}
           (lib.metadata.calculation/metadata
            (lib.tu/venues-query-with-last-stage
@@ -245,7 +244,7 @@
 (deftest ^:parallel expressions-names-test
   (testing "expressions should include the original expression name"
     (is (=? [{:name         "expr"
-              :display_name "expr"}]
+              :display-name "expr"}]
             (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
                 (lib/expression "expr" (lib/absolute-datetime "2020" :month))
                 lib/expressions)))))
diff --git a/test/metabase/lib/field_test.cljc b/test/metabase/lib/field_test.cljc
index 322438748c9..93a2b69eeee 100644
--- a/test/metabase/lib/field_test.cljc
+++ b/test/metabase/lib/field_test.cljc
@@ -37,23 +37,23 @@
   (let [grandparent {:lib/type  :metadata/field
                      :name      "grandparent"
                      :id        (grandparent-parent-child-id :grandparent)
-                     :base_type :type/Text}
+                     :base-type :type/Text}
         parent      {:lib/type  :metadata/field
                      :name      "parent"
-                     :parent_id (grandparent-parent-child-id :grandparent)
+                     :parent-id (grandparent-parent-child-id :grandparent)
                      :id        (grandparent-parent-child-id :parent)
-                     :base_type :type/Text}
+                     :base-type :type/Text}
         child       {:lib/type  :metadata/field
                      :name      "child"
-                     :parent_id (grandparent-parent-child-id :parent)
+                     :parent-id (grandparent-parent-child-id :parent)
                      :id        (grandparent-parent-child-id :child)
-                     :base_type :type/Text}]
+                     :base-type :type/Text}]
     (lib.tu/mock-metadata-provider
      {:database meta/metadata
       :tables   [(meta/table-metadata :venues)]
       :fields   (mapv (fn [field-metadata]
-                        (merge {:visibility_type :normal
-                                :table_id        (meta/id :venues)}
+                        (merge {:visibility-type :normal
+                                :table-id        (meta/id :venues)}
                                field-metadata))
                       [grandparent parent child])})))
 
@@ -69,26 +69,26 @@
              -1
              a-field-clause))]
     (testing "For fields with parents we should return them with a combined name including parent's name"
-      (is (=? {:table_id          (meta/id :venues)
+      (is (=? {:table-id          (meta/id :venues)
                :name              "grandparent.parent"
-               :parent_id         (grandparent-parent-child-id :grandparent)
+               :parent-id         (grandparent-parent-child-id :grandparent)
                :id                (grandparent-parent-child-id :parent)
-               :visibility_type   :normal}
+               :visibility-type   :normal}
               (col-info [:field {:lib/uuid (str (random-uuid))} (grandparent-parent-child-id :parent)]))))
     (testing "nested-nested fields should include grandparent name (etc)"
-      (is (=? {:table_id          (meta/id :venues)
+      (is (=? {:table-id          (meta/id :venues)
                :name              "grandparent.parent.child"
-               :parent_id         (grandparent-parent-child-id :parent)
+               :parent-id         (grandparent-parent-child-id :parent)
                :id                (grandparent-parent-child-id :child)
-               :visibility_type   :normal}
+               :visibility-type   :normal}
               (col-info [:field {:lib/uuid (str (random-uuid))} (grandparent-parent-child-id :child)]))))))
 
 (deftest ^:parallel col-info-field-literals-test
   (testing "field literals should get the information from the matching `:lib/stage-metadata` if it was supplied"
     (is (=? {:name          "sum"
-             :display_name  "sum of User ID"
-             :base_type     :type/Integer
-             :semantic_type :type/FK}
+             :display-name  "sum of User ID"
+             :base-type     :type/Integer
+             :semantic-type :type/FK}
             (lib.metadata.calculation/metadata
              (lib.tu/native-query)
              -1
@@ -125,7 +125,7 @@
                              (lib/display-name query -1 field style))
       :default "Name"
       :long    "Categories → Name")
-    (is (=? {:display_name "Name"}
+    (is (=? {:display-name "Name"}
             (lib.metadata.calculation/metadata query -1 field)))))
 
 (deftest ^:parallel unresolved-lib-field-with-temporal-bucket-test
@@ -147,17 +147,17 @@
 (def ^:private temporal-bucketing-mock-metadata
   "Mock metadata for testing temporal bucketing stuff.
 
-  * Includes a date field where the `:base_type` is `:type/Text`, but `:effective_type` is `:type/Date` because of a
-    `:Coercion/ISO8601->Date`, so we can test that `:effective_type` is preserved properly
+  * Includes a date field where the `:base-type` is `:type/Text`, but `:effective-type` is `:type/Date` because of a
+    `:Coercion/ISO8601->Date`, so we can test that `:effective-type` is preserved properly
 
   * Includes a mocked Field with `:type/Time`"
   (let [date-field        (assoc (meta/field-metadata :people :birth-date)
-                                 :base_type         :type/Text
-                                 :effective_type    :type/Date
-                                 :coercion_strategy :Coercion/ISO8601->Date)
+                                 :base-type         :type/Text
+                                 :effective-type    :type/Date
+                                 :coercion-strategy :Coercion/ISO8601->Date)
         time-field        (assoc (meta/field-metadata :orders :created-at)
-                                 :base_type      :type/Time
-                                 :effective_type :type/Time)
+                                 :base-type      :type/Time
+                                 :effective-type :type/Time)
         metadata-provider (lib.tu/composed-metadata-provider
                            (lib.tu/mock-metadata-provider
                             {:fields [date-field
@@ -211,7 +211,7 @@
                                               :expected-units lib.schema.temporal-bucketing/datetime-bucketing-units}
                                              {:metadata       (get-in temporal-bucketing-mock-metadata [:fields :time])
                                               :expected-units lib.schema.temporal-bucketing/time-bucketing-units}]]
-    (testing (str (:base_type metadata) " Field")
+    (testing (str (:base-type metadata) " Field")
       (doseq [[what x] {"column metadata" metadata, "field ref" (lib/ref metadata)}]
         (testing (str what "\n\n" (u/pprint-to-str x))
           (is (= expected-units
@@ -222,7 +222,7 @@
                                                    (lib/with-temporal-bucket x :month-of-year))))))))))
 
 (deftest ^:parallel joined-field-column-name-test
-  (let [card  {:dataset_query {:database (meta/id)
+  (let [card  {:dataset-query {:database (meta/id)
                                :type     :query
                                :query    {:source-table (meta/id :venues)
                                           :joins        [{:fields       :all
@@ -273,19 +273,19 @@
 (deftest ^:parallel source-card-table-display-info-test
   (let [query (assoc lib.tu/venues-query :lib/metadata lib.tu/metadata-provider-with-card)
         field (lib.metadata.calculation/metadata query (assoc (lib.metadata/field query (meta/id :venues :name))
-                                                              :table_id "card__1"))]
+                                                              :table-id "card__1"))]
     (is (=? {:name           "NAME"
-             :display_name   "Name"
-             :semantic_type  :type/Name
-             :effective_type :type/Text
-             :table          {:name "My Card", :display_name "My Card"}}
+             :display-name   "Name"
+             :semantic-type  :type/Name
+             :effective-type :type/Text
+             :table          {:name "My Card", :display-name "My Card"}}
             (lib/display-info query field)))))
 
 (deftest ^:parallel resolve-column-name-in-join-test
   (testing ":field refs with string names should work if the Field comes from a :join"
     (let [card-1            {:name          "My Card"
                              :id            1
-                             :dataset_query {:database (meta/id)
+                             :dataset-query {:database (meta/id)
                                              :type     :query
                                              :query    {:source-table (meta/id :checkins)
                                                         :aggregation  [[:count]]
diff --git a/test/metabase/lib/filter_test.cljc b/test/metabase/lib/filter_test.cljc
index f9b9f2a04e0..c546fbe9584 100644
--- a/test/metabase/lib/filter_test.cljc
+++ b/test/metabase/lib/filter_test.cljc
@@ -119,7 +119,6 @@
          :database (meta/id)
          :stages [{:lib/type :mbql.stage/mbql
                    :source-table (meta/id :categories)
-                   :lib/options {:lib/uuid string?}
                    :filters [original-filter]}]}]
     (testing "no filter"
       (is (nil? (lib/filters q2))))
diff --git a/test/metabase/lib/join_test.cljc b/test/metabase/lib/join_test.cljc
index 264556a8e5c..0e346d98bac 100644
--- a/test/metabase/lib/join_test.cljc
+++ b/test/metabase/lib/join_test.cljc
@@ -30,12 +30,10 @@
   (is (=? {:lib/type :mbql/query
            :database (meta/id)
            :stages   [{:lib/type     :mbql.stage/mbql
-                       :lib/options  {:lib/uuid string?}
                        :source-table (meta/id :venues)
                        :joins        [{:lib/type    :mbql/join
                                        :lib/options {:lib/uuid string?}
                                        :stages      [{:lib/type     :mbql.stage/mbql
-                                                      :lib/options  {:lib/uuid string?}
                                                       :source-table (meta/id :categories)}]
                                        :conditions  [[:=
                                                       {:lib/uuid string?}
@@ -53,7 +51,6 @@
   (is (=? {:lib/type :mbql/query
            :database (meta/id)
            :stages   [{:lib/type     :mbql.stage/mbql
-                       :lib/options  {:lib/uuid string?}
                        :source-table (meta/id :categories)
                        :joins        [{:lib/type    :mbql/join
                                        :lib/options {:lib/uuid string?}
@@ -101,7 +98,7 @@
                   (dissoc :lib/metadata)))))))
 
 (deftest ^:parallel col-info-implicit-join-test
-  (testing (str "when a `:field` with `:source-field` (implicit join) is used, we should add in `:fk_field_id` "
+  (testing (str "when a `:field` with `:source-field` (implicit join) is used, we should add in `:fk-field-id` "
                 "info about the source Field")
     (let [query (lib/query
                  meta/metadata-provider
@@ -112,7 +109,7 @@
                               :fields       [[:field (meta/id :categories :name) {:source-field (meta/id :venues :category-id)}]]}}))]
       (is (=? [{:name        "NAME"
                 :id          (meta/id :categories :name)
-                :fk_field_id (meta/id :venues :category-id)
+                :fk-field-id (meta/id :venues :category-id)
                 :lib/source  :source/fields}]
               (lib.metadata.calculation/metadata query -1 query))))))
 
@@ -142,7 +139,7 @@
                  :lib/metadata meta/metadata-provider}]
       (let [metadata (lib.metadata.calculation/metadata query)]
         (is (=? [(merge (meta/field-metadata :categories :name)
-                        {:display_name                  "Name"
+                        {:display-name                  "Name"
                          :lib/source                    :source/fields
                          :metabase.lib.field/join-alias "CATEGORIES__via__CATEGORY_ID"})]
                 metadata))
@@ -156,7 +153,7 @@
 (deftest ^:parallel join-against-source-card-metadata-test
   (let [card-1            {:name          "My Card"
                            :id            1
-                           :dataset_query {:database (meta/id)
+                           :dataset-query {:database (meta/id)
                                            :type     :query
                                            :query    {:source-table (meta/id :checkins)
                                                       :aggregation  [[:count]]
@@ -257,15 +254,15 @@
                                                                    :lib/options  {:lib/uuid "e8888108-22a7-4f97-8315-ff63503634d7"}
                                                                    :source-table (meta/id :categories)}]}]}]}]
     (is (=? [{:name                     "ID"
-              :display_name             "ID"
+              :display-name             "ID"
               :lib/source-column-alias  "ID"
               :lib/desired-column-alias "ID"}
              {:name                     "NAME"
-              :display_name             "Name"
+              :display-name             "Name"
               :lib/source-column-alias  "NAME"
               :lib/desired-column-alias "NAME"}
              {:name                     "ID"
-              :display_name             "ID"
+              :display-name             "ID"
               :lib/source-column-alias  "ID"
               :lib/desired-column-alias "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY_bfaf4e7b"}]
             (lib.metadata.calculation/metadata query)))))
diff --git a/test/metabase/lib/metadata/jvm_test.clj b/test/metabase/lib/metadata/jvm_test.clj
index fc73d59e228..ee0278363d7 100644
--- a/test/metabase/lib/metadata/jvm_test.clj
+++ b/test/metabase/lib/metadata/jvm_test.clj
@@ -1,13 +1,20 @@
 (ns metabase.lib.metadata.jvm-test
   (:require
    [clojure.test :refer :all]
+   [malli.core :as mc]
+   [malli.error :as me]
    [metabase.lib.core :as lib]
+   [metabase.lib.metadata :as lib.metadata]
    [metabase.lib.metadata.calculation :as lib.metadata.calculation]
-   [metabase.lib.metadata.jvm :as sut]
+   [metabase.lib.metadata.jvm :as lib.metadata.jvm]
    [metabase.test :as mt]))
 
+(deftest ^:parallel fetch-field-test
+  (let [field (#'lib.metadata.jvm/fetch-instance :metadata/field (mt/id :categories :id))]
+    (is (not (me/humanize (mc/validate lib.metadata/ColumnMetadata field))))))
+
 (deftest ^:parallel saved-question-metadata-test
-  (let [card  {:dataset_query {:database (mt/id)
+  (let [card  {:dataset-query {:database (mt/id)
                                :type     :query
                                :query    {:source-table (mt/id :venues)
                                           :joins        [{:fields       :all
@@ -17,7 +24,7 @@
                                                                          [:field (mt/id :categories :id) {:join-alias "Cat"}]]
                                                           :alias        "Cat"}]}}}
         query (lib/saved-question-query
-               (metabase.lib.metadata.jvm/application-database-metadata-provider (mt/id))
+               (lib.metadata.jvm/application-database-metadata-provider (mt/id))
                card)]
     (is (=? [{:lib/desired-column-alias "ID"}
              {:lib/desired-column-alias "NAME"}
diff --git a/test/metabase/lib/metadata_test.cljc b/test/metabase/lib/metadata_test.cljc
index 5655f62e601..63c3f824847 100644
--- a/test/metabase/lib/metadata_test.cljc
+++ b/test/metabase/lib/metadata_test.cljc
@@ -33,11 +33,11 @@
 (deftest ^:parallel stage-column-metadata-test
   (let [query (lib/saved-question-query meta/metadata-provider meta/saved-question)]
     (are [x] (=? {:lib/type       :metadata/field
-                  :display_name   "CATEGORY_ID"
+                  :display-name   "CATEGORY_ID"
                   :name           "CATEGORY_ID"
-                  :base_type      :type/Integer
-                  :effective_type :type/Integer
-                  :semantic_type  nil}
+                  :base-type      :type/Integer
+                  :effective-type :type/Integer
+                  :semantic-type  nil}
                  x)
       (lib.metadata/stage-column query "CATEGORY_ID")
       (lib.metadata/stage-column query -1 "CATEGORY_ID"))))
diff --git a/test/metabase/lib/metric_test.cljc b/test/metabase/lib/metric_test.cljc
index b71f66dcbe5..b2612f25eb9 100644
--- a/test/metabase/lib/metric_test.cljc
+++ b/test/metabase/lib/metric_test.cljc
@@ -40,6 +40,6 @@
                     (lib/aggregate [:metric {:lib/uuid (str (random-uuid))} "ga:totalEvents"]))]
       (is (=? [{:lib/type     :metadata/field
                 :name         "metric"
-                :display_name "[Unknown Metric]"
-                :base_type    :type/*}]
+                :display-name "[Unknown Metric]"
+                :base-type    :type/*}]
               (lib.metadata.calculation/metadata query -1 query))))))
diff --git a/test/metabase/lib/order_by_test.cljc b/test/metabase/lib/order_by_test.cljc
index bb83ca3d827..49027dcee67 100644
--- a/test/metabase/lib/order_by_test.cljc
+++ b/test/metabase/lib/order_by_test.cljc
@@ -51,15 +51,12 @@
   (is (=? {:lib/type :mbql/query
            :database (meta/id)
            :stages   [{:lib/type     :mbql.stage/mbql
-                       :lib/options  {:lib/uuid string?}
                        :source-table (meta/id :venues)}
-                      {:lib/type    :mbql.stage/mbql
-                       :lib/options {:lib/uuid string?}
-                       :order-by    [[:asc
-                                      {:lib/uuid string?}
-                                      [:field {:lib/uuid string?} (meta/id :venues :id)]]]}
-                      {:lib/type    :mbql.stage/mbql
-                       :lib/options {:lib/uuid string?}}]}
+                      {:lib/type :mbql.stage/mbql
+                       :order-by [[:asc
+                                   {:lib/uuid string?}
+                                   [:field {:lib/uuid string?} (meta/id :venues :id)]]]}
+                      {:lib/type :mbql.stage/mbql}]}
           (-> (lib/query meta/metadata-provider {:database (meta/id)
                                                  :type     :query
                                                  :query    {:source-query {:source-query {:source-table (meta/id :venues)}}}})
@@ -130,27 +127,27 @@
                     (lib/aggregate (lib/avg (lib/+ (lib/field "VENUES" "PRICE") 1)))
                     (lib/breakout (lib/field "VENUES" "CATEGORY_ID")))]
       (testing (lib.util/format "Query =\n%s" (u/pprint-to-str query))
-        (is (=? [{:database_type      "INTEGER"
-                  :semantic_type      :type/FK
+        (is (=? [{:database-type      "INTEGER"
+                  :semantic-type      :type/FK
                   :lib/type           :metadata/field
-                  :table_id           (meta/id :venues)
+                  :table-id           (meta/id :venues)
                   :name               "CATEGORY_ID"
-                  :has_field_values   :none
+                  :has-field-values   :none
                   :lib/source         :source/breakouts
-                  :fk_target_field_id (meta/id :categories :id)
-                  :effective_type     :type/Integer
+                  :fk-target-field-id (meta/id :categories :id)
+                  :effective-type     :type/Integer
                   :id                 (meta/id :venues :category-id)
-                  :display_name       "Category ID"
-                  :base_type          :type/Integer}
+                  :display-name       "Category ID"
+                  :base-type          :type/Integer}
                  {:lib/type     :metadata/field
-                  :base_type    :type/Integer
+                  :base-type    :type/Integer
                   :name         "sum_PRICE"
-                  :display_name "Sum of Price"
+                  :display-name "Sum of Price"
                   :lib/source   :source/aggregations}
                  {:lib/type     :metadata/field
-                  :base_type    :type/Float
+                  :base-type    :type/Float
                   :name         "avg_PRICE_plus_1"
-                  :display_name "Average of Price + 1"
+                  :display-name "Average of Price + 1"
                   :lib/source   :source/aggregations}]
                 (lib/orderable-columns query)))))))
 
@@ -162,8 +159,8 @@
       (testing (lib.util/format "Query =\n%s" (u/pprint-to-str query))
         (is (=? [{:lib/type     :metadata/field
                   :name         "Category ID + 1"
-                  :display_name "Category ID + 1"
-                  :base_type    :type/Integer
+                  :display-name "Category ID + 1"
+                  :base-type    :type/Integer
                   :lib/source   :source/breakouts}]
                 (lib/orderable-columns query)))))))
 
@@ -172,65 +169,65 @@
     (testing (lib.util/format "Query =\n%s" (u/pprint-to-str query))
       (is (=? [{:lib/type                 :metadata/field
                 :name                     "ID"
-                :display_name             "ID"
+                :display-name             "ID"
                 :id                       (meta/id :venues :id)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/BigInteger
+                :table-id                 (meta/id :venues)
+                :base-type                :type/BigInteger
                 :lib/source-column-alias  "ID"
                 :lib/desired-column-alias "ID"}
                {:lib/type                 :metadata/field
                 :name                     "NAME"
-                :display_name             "Name"
+                :display-name             "Name"
                 :id                       (meta/id :venues :name)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Text
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Text
                 :lib/source-column-alias  "NAME"
                 :lib/desired-column-alias "NAME"}
                {:lib/type                 :metadata/field
                 :name                     "CATEGORY_ID"
-                :display_name             "Category ID"
+                :display-name             "Category ID"
                 :id                       (meta/id :venues :category-id)
-                :table_id                 (meta/id :venues)
+                :table-id                 (meta/id :venues)
                 :lib/source-column-alias  "CATEGORY_ID"
                 :lib/desired-column-alias "CATEGORY_ID"}
                {:lib/type                 :metadata/field
                 :name                     "LATITUDE"
-                :display_name             "Latitude"
+                :display-name             "Latitude"
                 :id                       (meta/id :venues :latitude)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Float
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Float
                 :lib/source-column-alias  "LATITUDE"
                 :lib/desired-column-alias "LATITUDE"}
                {:lib/type                 :metadata/field
                 :name                     "LONGITUDE"
-                :display_name             "Longitude"
+                :display-name             "Longitude"
                 :id                       (meta/id :venues :longitude)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Float
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Float
                 :lib/source-column-alias  "LONGITUDE"
                 :lib/desired-column-alias "LONGITUDE"}
                {:lib/type                 :metadata/field
                 :name                     "PRICE"
-                :display_name             "Price"
+                :display-name             "Price"
                 :id                       (meta/id :venues :price)
-                :table_id                 (meta/id :venues)
-                :base_type                :type/Integer
+                :table-id                 (meta/id :venues)
+                :base-type                :type/Integer
                 :lib/source-column-alias  "PRICE"
                 :lib/desired-column-alias "PRICE"}
                {:lib/type                 :metadata/field
                 :name                     "ID"
-                :display_name             "ID"
+                :display-name             "ID"
                 :id                       (meta/id :categories :id)
-                :table_id                 (meta/id :categories)
-                :base_type                :type/BigInteger
+                :table-id                 (meta/id :categories)
+                :base-type                :type/BigInteger
                 :lib/source-column-alias  "ID"
                 :lib/desired-column-alias "CATEGORIES__via__CATEGORY_ID__ID"}
                {:lib/type                 :metadata/field
                 :name                     "NAME"
-                :display_name             "Name"
+                :display-name             "Name"
                 :id                       (meta/id :categories :name)
-                :table_id                 (meta/id :categories)
-                :base_type                :type/Text
+                :table-id                 (meta/id :categories)
+                :base-type                :type/Text
                 :lib/source-column-alias  "NAME"
                 :lib/desired-column-alias "CATEGORIES__via__CATEGORY_ID__NAME"}]
               (lib/orderable-columns query))))))
@@ -247,9 +244,9 @@
                  {:id (meta/id :venues :longitude) :name "LONGITUDE"}
                  {:id (meta/id :venues :price) :name "PRICE"}
                  {:lib/type     :metadata/field
-                  :base_type    :type/Integer
+                  :base-type    :type/Integer
                   :name         "Category ID + 1"
-                  :display_name "Category ID + 1"
+                  :display-name "Category ID + 1"
                   :lib/source   :source/expressions}
                  {:id (meta/id :categories :id) :name "ID"}
                  {:id (meta/id :categories :name) :name "NAME"}]
@@ -289,18 +286,18 @@
                  {:id (meta/id :venues :price) :name "PRICE"}
                  {:lib/type     :metadata/field
                   :name         "ID"
-                  :display_name "ID"
+                  :display-name "ID"
                   :source_alias "Cat"
                   :id           (meta/id :categories :id)
-                  :table_id     (meta/id :categories)
-                  :base_type    :type/BigInteger}
+                  :table-id     (meta/id :categories)
+                  :base-type    :type/BigInteger}
                  {:lib/type     :metadata/field
                   :name         "NAME"
-                  :display_name "Name"
+                  :display-name "Name"
                   :source_alias "Cat"
                   :id           (meta/id :categories :name)
-                  :table_id     (meta/id :categories)
-                  :base_type    :type/Text}]
+                  :table-id     (meta/id :categories)
+                  :base-type    :type/Text}]
                 (lib/orderable-columns query)))))))
 
 (deftest ^:parallel orderable-columns-source-card-test
@@ -309,57 +306,57 @@
           :let [query (varr)]]
     (testing (str (pr-str varr) \newline (lib.util/format "Query =\n%s" (u/pprint-to-str query)))
       (is (=? [{:name                     "USER_ID"
-                :display_name             "User ID"
-                :base_type                :type/Integer
+                :display-name             "User ID"
+                :base-type                :type/Integer
                 :lib/source               :source/card
                 :lib/desired-column-alias "USER_ID"}
                {:name                     "count"
-                :display_name             "Count"
-                :base_type                :type/Integer
+                :display-name             "Count"
+                :base-type                :type/Integer
                 :lib/source               :source/card
                 :lib/desired-column-alias "count"}
                {:name                     "ID"
-                :display_name             "ID"
-                :base_type                :type/BigInteger
+                :display-name             "ID"
+                :base-type                :type/BigInteger
                 :lib/source               :source/implicitly-joinable
                 :lib/desired-column-alias "USERS__via__USER_ID__ID"}
                {:name                     "NAME"
-                :display_name             "Name"
-                :base_type                :type/Text
+                :display-name             "Name"
+                :base-type                :type/Text
                 :lib/source               :source/implicitly-joinable
                 :lib/desired-column-alias "USERS__via__USER_ID__NAME"}
                {:name                     "LAST_LOGIN"
-                :display_name             "Last Login"
-                :base_type                :type/DateTime
+                :display-name             "Last Login"
+                :base-type                :type/DateTime
                 :lib/source               :source/implicitly-joinable
                 :lib/desired-column-alias "USERS__via__USER_ID__LAST_LOGIN"}]
               (lib/orderable-columns query)))
       (testing `lib/display-info
         (is (=? [{:name                   "USER_ID"
-                  :display_name           "User ID"
-                  :table                  {:name "My Card", :display_name "My Card"}
-                  :is_from_previous_stage false
-                  :is_implicitly_joinable false}
+                  :display-name           "User ID"
+                  :table                  {:name "My Card", :display-name "My Card"}
+                  :is-from-previous-stage false
+                  :is-implicitly-joinable false}
                  {:name                   "count"
-                  :display_name           "Count"
-                  :table                  {:name "My Card", :display_name "My Card"}
-                  :is_from_previous_stage false
-                  :is_implicitly_joinable false}
+                  :display-name           "Count"
+                  :table                  {:name "My Card", :display-name "My Card"}
+                  :is-from-previous-stage false
+                  :is-implicitly-joinable false}
                  {:name                   "ID"
-                  :display_name           "ID"
-                  :table                  {:name "USERS", :display_name "Users"}
-                  :is_from_previous_stage false
-                  :is_implicitly_joinable true}
+                  :display-name           "ID"
+                  :table                  {:name "USERS", :display-name "Users"}
+                  :is-from-previous-stage false
+                  :is-implicitly-joinable true}
                  {:name                   "NAME"
-                  :display_name           "Name"
-                  :table                  {:name "USERS", :display_name "Users"}
-                  :is_from_previous_stage false
-                  :is_implicitly_joinable true}
+                  :display-name           "Name"
+                  :table                  {:name "USERS", :display-name "Users"}
+                  :is-from-previous-stage false
+                  :is-implicitly-joinable true}
                  {:name                   "LAST_LOGIN"
-                  :display_name           "Last Login"
-                  :table                  {:name "USERS", :display_name "Users"}
-                  :is_from_previous_stage false
-                  :is_implicitly_joinable true}]
+                  :display-name           "Last Login"
+                  :table                  {:name "USERS", :display-name "Users"}
+                  :is-from-previous-stage false
+                  :is-implicitly-joinable true}]
                 (for [col (lib/orderable-columns query)]
                   (lib/display-info query col))))))))
 
@@ -369,8 +366,7 @@
       (is (=? {:lib/type :mbql/query
                :database (meta/id)
                :stages   [{:lib/type     :mbql.stage/mbql
-                           :source-table (meta/id :venues)
-                           :lib/options  {:lib/uuid string?}}]}
+                           :source-table (meta/id :venues)}]}
               query))
       (testing (lib.util/format "Query =\n%s" (u/pprint-to-str query))
         (let [orderable-columns (lib/orderable-columns query)
@@ -380,7 +376,6 @@
                    :database (meta/id)
                    :stages   [{:lib/type     :mbql.stage/mbql
                                :source-table (meta/id :venues)
-                               :lib/options  {:lib/uuid string?}
                                :order-by     [[:asc
                                                {:lib/uuid string?}
                                                [:field {:lib/uuid string? :base-type :type/Text} (meta/id :venues :name)]]]}]}
@@ -397,7 +392,7 @@
         (let [name-col (m/find-first #(= (:name %) "USER_ID")
                                      (lib/orderable-columns query))]
           (is (=? {:name      "USER_ID"
-                   :base_type :type/Integer}
+                   :base-type :type/Integer}
                   name-col))
           (let [query' (lib/order-by query name-col)]
             (is (=? {:stages
@@ -463,20 +458,20 @@
               :name                     "ID"
               :lib/source               :source/previous-stage
               :lib/type                 :metadata/field
-              :base_type                :type/BigInteger
-              :effective_type           :type/BigInteger
-              :display_name             "ID"
-              :table_id                 (meta/id :venues)
+              :base-type                :type/BigInteger
+              :effective-type           :type/BigInteger
+              :display-name             "ID"
+              :table-id                 (meta/id :venues)
               :lib/source-column-alias  "ID"
               :lib/desired-column-alias "ID"}
              {:id                       (meta/id :categories :id)
               :name                     "ID"
               :lib/source               :source/previous-stage
               :lib/type                 :metadata/field
-              :base_type                :type/BigInteger
-              :effective_type           :type/BigInteger
-              :display_name             "ID"
-              :table_id                 (meta/id :categories)
+              :base-type                :type/BigInteger
+              :effective-type           :type/BigInteger
+              :display-name             "ID"
+              :table-id                 (meta/id :categories)
               :lib/source-column-alias  "Cat__ID"
               :lib/desired-column-alias "Cat__ID"}]
             (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
@@ -495,38 +490,38 @@
 (deftest ^:parallel orderable-columns-exclude-already-sorted-columns-test
   (testing "orderable-columns should not return normal Fields already included in :order-by (#29807)"
     (let [query (lib/query-for-table-name meta/metadata-provider "VENUES")]
-      (is (=? [{:display_name "ID",          :lib/source :source/table-defaults}
-               {:display_name "Name",        :lib/source :source/table-defaults}
-               {:display_name "Category ID", :lib/source :source/table-defaults}
-               {:display_name "Latitude",    :lib/source :source/table-defaults}
-               {:display_name "Longitude",   :lib/source :source/table-defaults}
-               {:display_name "Price",       :lib/source :source/table-defaults}
-               {:display_name "ID",          :lib/source :source/implicitly-joinable}
-               {:display_name "Name",        :lib/source :source/implicitly-joinable}]
+      (is (=? [{:display-name "ID",          :lib/source :source/table-defaults}
+               {:display-name "Name",        :lib/source :source/table-defaults}
+               {:display-name "Category ID", :lib/source :source/table-defaults}
+               {:display-name "Latitude",    :lib/source :source/table-defaults}
+               {:display-name "Longitude",   :lib/source :source/table-defaults}
+               {:display-name "Price",       :lib/source :source/table-defaults}
+               {:display-name "ID",          :lib/source :source/implicitly-joinable}
+               {:display-name "Name",        :lib/source :source/implicitly-joinable}]
               (lib/orderable-columns query)))
       (let [query' (lib/order-by query (second (lib/orderable-columns query)))]
         (is (=? {:stages [{:order-by [[:asc {} [:field {} (meta/id :venues :name)]]]}]}
                 query'))
         (is (=? [[:asc {} [:field {} (meta/id :venues :name)]]]
                 (lib/order-bys query')))
-        (is (=? [{:display_name "ID",          :lib/source :source/table-defaults}
-                 {:display_name "Category ID", :lib/source :source/table-defaults}
-                 {:display_name "Latitude",    :lib/source :source/table-defaults}
-                 {:display_name "Longitude",   :lib/source :source/table-defaults}
-                 {:display_name "Price",       :lib/source :source/table-defaults}
-                 {:display_name "ID",          :lib/source :source/implicitly-joinable}
-                 {:display_name "Name",        :lib/source :source/implicitly-joinable}]
+        (is (=? [{:display-name "ID",          :lib/source :source/table-defaults}
+                 {:display-name "Category ID", :lib/source :source/table-defaults}
+                 {:display-name "Latitude",    :lib/source :source/table-defaults}
+                 {:display-name "Longitude",   :lib/source :source/table-defaults}
+                 {:display-name "Price",       :lib/source :source/table-defaults}
+                 {:display-name "ID",          :lib/source :source/implicitly-joinable}
+                 {:display-name "Name",        :lib/source :source/implicitly-joinable}]
                 (lib/orderable-columns query')))
         (testing "Introduce a new stage"
           (let [query'' (lib/append-stage query')]
-            (is (=? [{:display_name "ID",          :lib/source :source/previous-stage}
-                     {:display_name "Name",        :lib/source :source/previous-stage}
-                     {:display_name "Category ID", :lib/source :source/previous-stage}
-                     {:display_name "Latitude",    :lib/source :source/previous-stage}
-                     {:display_name "Longitude",   :lib/source :source/previous-stage}
-                     {:display_name "Price",       :lib/source :source/previous-stage}
-                     {:display_name "ID",          :lib/source :source/implicitly-joinable}
-                     {:display_name "Name",        :lib/source :source/implicitly-joinable}]
+            (is (=? [{:display-name "ID",          :lib/source :source/previous-stage}
+                     {:display-name "Name",        :lib/source :source/previous-stage}
+                     {:display-name "Category ID", :lib/source :source/previous-stage}
+                     {:display-name "Latitude",    :lib/source :source/previous-stage}
+                     {:display-name "Longitude",   :lib/source :source/previous-stage}
+                     {:display-name "Price",       :lib/source :source/previous-stage}
+                     {:display-name "ID",          :lib/source :source/implicitly-joinable}
+                     {:display-name "Name",        :lib/source :source/implicitly-joinable}]
                     (lib/orderable-columns query'')))))))))
 
 (deftest ^:parallel orderable-columns-exclude-already-sorted-aggregation-test
@@ -534,11 +529,11 @@
     (let [query (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
                     (lib/aggregate (lib/sum (lib/field (meta/id :venues :price))))
                     (lib/aggregate (lib/sum (lib/field (meta/id :venues :id)))))]
-      (is (=? [{:display_name "Sum of Price", :lib/source :source/aggregations}
-               {:display_name "Sum of ID",    :lib/source :source/aggregations}]
+      (is (=? [{:display-name "Sum of Price", :lib/source :source/aggregations}
+               {:display-name "Sum of ID",    :lib/source :source/aggregations}]
               (lib/orderable-columns query)))
       (let [query' (lib/order-by query (first (lib/orderable-columns query)))]
-        (is (=? [{:display_name "Sum of ID", :lib/source :source/aggregations}]
+        (is (=? [{:display-name "Sum of ID", :lib/source :source/aggregations}]
                 (lib/orderable-columns query')))))))
 
 (deftest ^:parallel orderable-columns-exclude-already-sorted-joined-columns-test
@@ -559,26 +554,26 @@
                                          [:field {} (meta/id :venues :category-id)]
                                          [:field {:join-alias "Cat"} (meta/id :categories :id)]]]}]}]}
               query))
-      (is (=? [{:display_name "ID",          :lib/source :source/table-defaults}
-               {:display_name "Name",        :lib/source :source/table-defaults}
-               {:display_name "Category ID", :lib/source :source/table-defaults}
-               {:display_name "Latitude",    :lib/source :source/table-defaults}
-               {:display_name "Longitude",   :lib/source :source/table-defaults}
-               {:display_name "Price",       :lib/source :source/table-defaults}
+      (is (=? [{:display-name "ID",          :lib/source :source/table-defaults}
+               {:display-name "Name",        :lib/source :source/table-defaults}
+               {:display-name "Category ID", :lib/source :source/table-defaults}
+               {:display-name "Latitude",    :lib/source :source/table-defaults}
+               {:display-name "Longitude",   :lib/source :source/table-defaults}
+               {:display-name "Price",       :lib/source :source/table-defaults}
                ;; implicitly joinable versions shouldn't be returned either, since we have an explicit join.
-               {:display_name "ID",   :lib/source :source/joins}
-               {:display_name "Name", :lib/source :source/joins}]
+               {:display-name "ID",   :lib/source :source/joins}
+               {:display-name "Name", :lib/source :source/joins}]
               (lib/orderable-columns query)))
       (let [query' (lib/order-by query (m/find-first #(and (= (:source_alias %) "Cat")
-                                                           (= (:display_name %) "Name"))
+                                                           (= (:display-name %) "Name"))
                                                      (lib/orderable-columns query)))]
-        (is (=? [{:display_name "ID",          :lib/source :source/table-defaults}
-                 {:display_name "Name",        :lib/source :source/table-defaults}
-                 {:display_name "Category ID", :lib/source :source/table-defaults}
-                 {:display_name "Latitude",    :lib/source :source/table-defaults}
-                 {:display_name "Longitude",   :lib/source :source/table-defaults}
-                 {:display_name "Price",       :lib/source :source/table-defaults}
-                 {:display_name "ID",          :lib/source :source/joins}]
+        (is (=? [{:display-name "ID",          :lib/source :source/table-defaults}
+                 {:display-name "Name",        :lib/source :source/table-defaults}
+                 {:display-name "Category ID", :lib/source :source/table-defaults}
+                 {:display-name "Latitude",    :lib/source :source/table-defaults}
+                 {:display-name "Longitude",   :lib/source :source/table-defaults}
+                 {:display-name "Price",       :lib/source :source/table-defaults}
+                 {:display-name "ID",          :lib/source :source/joins}]
                 (lib/orderable-columns query')))))))
 
 (deftest ^:parallel orderable-columns-exclude-already-sorted-implicitly-joinable-columns-test
@@ -593,39 +588,39 @@
               query))
       (is (= "Venues, Sorted by Categories → Name ascending"
              (lib/describe-query query)))
-      (is (=? [{:display_name "ID",          :lib/source :source/table-defaults}
-               {:display_name "Name",        :lib/source :source/table-defaults}
-               {:display_name "Category ID", :lib/source :source/table-defaults}
-               {:display_name "Latitude",    :lib/source :source/table-defaults}
-               {:display_name "Longitude",   :lib/source :source/table-defaults}
-               {:display_name "Price",       :lib/source :source/table-defaults}
-               {:display_name "ID",          :lib/source :source/implicitly-joinable}]
+      (is (=? [{:display-name "ID",          :lib/source :source/table-defaults}
+               {:display-name "Name",        :lib/source :source/table-defaults}
+               {:display-name "Category ID", :lib/source :source/table-defaults}
+               {:display-name "Latitude",    :lib/source :source/table-defaults}
+               {:display-name "Longitude",   :lib/source :source/table-defaults}
+               {:display-name "Price",       :lib/source :source/table-defaults}
+               {:display-name "ID",          :lib/source :source/implicitly-joinable}]
               (lib/orderable-columns query))))))
 
 (deftest ^:parallel orderable-columns-exclude-already-sorted-expression-test
   (testing "orderable-columns should not return expressions that are already in :order-by (#29807)"
     (let [query (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
                     (lib/expression "My Expression" (lib/+ 2 3)))]
-      (is (=? [{:display_name "ID",            :lib/source :source/table-defaults}
-               {:display_name "Name",          :lib/source :source/table-defaults}
-               {:display_name "Category ID",   :lib/source :source/table-defaults}
-               {:display_name "Latitude",      :lib/source :source/table-defaults}
-               {:display_name "Longitude",     :lib/source :source/table-defaults}
-               {:display_name "Price",         :lib/source :source/table-defaults}
-               {:display_name "My Expression", :lib/source :source/expressions}
-               {:display_name "ID",            :lib/source :source/implicitly-joinable}
-               {:display_name "Name",          :lib/source :source/implicitly-joinable}]
+      (is (=? [{:display-name "ID",            :lib/source :source/table-defaults}
+               {:display-name "Name",          :lib/source :source/table-defaults}
+               {:display-name "Category ID",   :lib/source :source/table-defaults}
+               {:display-name "Latitude",      :lib/source :source/table-defaults}
+               {:display-name "Longitude",     :lib/source :source/table-defaults}
+               {:display-name "Price",         :lib/source :source/table-defaults}
+               {:display-name "My Expression", :lib/source :source/expressions}
+               {:display-name "ID",            :lib/source :source/implicitly-joinable}
+               {:display-name "Name",          :lib/source :source/implicitly-joinable}]
               (lib/orderable-columns query)))
-      (let [query' (lib/order-by query (m/find-first #(= (:display_name %) "My Expression")
+      (let [query' (lib/order-by query (m/find-first #(= (:display-name %) "My Expression")
                                                      (lib/orderable-columns query)))]
-        (is (=? [{:display_name "ID",            :lib/source :source/table-defaults}
-                 {:display_name "Name",          :lib/source :source/table-defaults}
-                 {:display_name "Category ID",   :lib/source :source/table-defaults}
-                 {:display_name "Latitude",      :lib/source :source/table-defaults}
-                 {:display_name "Longitude",     :lib/source :source/table-defaults}
-                 {:display_name "Price",         :lib/source :source/table-defaults}
-                 {:display_name "ID",            :lib/source :source/implicitly-joinable}
-                 {:display_name "Name",          :lib/source :source/implicitly-joinable}]
+        (is (=? [{:display-name "ID",            :lib/source :source/table-defaults}
+                 {:display-name "Name",          :lib/source :source/table-defaults}
+                 {:display-name "Category ID",   :lib/source :source/table-defaults}
+                 {:display-name "Latitude",      :lib/source :source/table-defaults}
+                 {:display-name "Longitude",     :lib/source :source/table-defaults}
+                 {:display-name "Price",         :lib/source :source/table-defaults}
+                 {:display-name "ID",            :lib/source :source/implicitly-joinable}
+                 {:display-name "Name",          :lib/source :source/implicitly-joinable}]
                 (lib/orderable-columns query')))))))
 
 (deftest ^:parallel order-by-aggregation-test
@@ -634,8 +629,8 @@
                                 (lib/aggregate (lib/avg (lib/+ (lib/field "VENUES" "PRICE") 1))))
           orderable-columns (lib/orderable-columns query)]
       (is (=? [{:lib/type                                   :metadata/field
-                :base_type                                  :type/Float
-                :display_name                               "Average of Price + 1"
+                :base-type                                  :type/Float
+                :display-name                               "Average of Price + 1"
                 :lib/source                                 :source/aggregations
                 :metabase.lib.aggregation/aggregation-index 0}]
               orderable-columns))
@@ -647,7 +642,7 @@
                 query'))
         (is (=? [[:asc {} [:aggregation {:effective-type :type/Float} 0]]]
                (lib/order-bys query')))
-        (is (=? [{:display_name "Average of Price + 1"
+        (is (=? [{:display-name "Average of Price + 1"
                   :direction    :asc}]
                 (map (partial lib/display-info query') (lib/order-bys query'))))
         (is (= "Venues, Average of Price + 1, Sorted by Average of Price + 1 ascending"
@@ -668,15 +663,15 @@
   (let [query (-> (lib/query-for-table-name meta/metadata-provider "VENUES")
                   (lib/expression "expr" (lib/absolute-datetime "2020" :month))
                   (lib/with-fields [(lib/field "VENUES" "ID")]))]
-    (is (=? [{:id (meta/id :venues :id),          :name "ID",          :display_name "ID",          :lib/source :source/table-defaults}
-             {:id (meta/id :venues :name),        :name "NAME",        :display_name "Name",        :lib/source :source/table-defaults}
-             {:id (meta/id :venues :category-id), :name "CATEGORY_ID", :display_name "Category ID", :lib/source :source/table-defaults}
-             {:id (meta/id :venues :latitude),    :name "LATITUDE",    :display_name "Latitude",    :lib/source :source/table-defaults}
-             {:id (meta/id :venues :longitude),   :name "LONGITUDE",   :display_name "Longitude",   :lib/source :source/table-defaults}
-             {:id (meta/id :venues :price),       :name "PRICE",       :display_name "Price",       :lib/source :source/table-defaults}
-             {:name "expr", :display_name "expr", :lib/source :source/expressions}
-             {:id (meta/id :categories :id),   :name "ID",   :display_name "ID",   :lib/source :source/implicitly-joinable}
-             {:id (meta/id :categories :name), :name "NAME", :display_name "Name", :lib/source :source/implicitly-joinable}]
+    (is (=? [{:id (meta/id :venues :id),          :name "ID",          :display-name "ID",          :lib/source :source/table-defaults}
+             {:id (meta/id :venues :name),        :name "NAME",        :display-name "Name",        :lib/source :source/table-defaults}
+             {:id (meta/id :venues :category-id), :name "CATEGORY_ID", :display-name "Category ID", :lib/source :source/table-defaults}
+             {:id (meta/id :venues :latitude),    :name "LATITUDE",    :display-name "Latitude",    :lib/source :source/table-defaults}
+             {:id (meta/id :venues :longitude),   :name "LONGITUDE",   :display-name "Longitude",   :lib/source :source/table-defaults}
+             {:id (meta/id :venues :price),       :name "PRICE",       :display-name "Price",       :lib/source :source/table-defaults}
+             {:name "expr", :display-name "expr", :lib/source :source/expressions}
+             {:id (meta/id :categories :id),   :name "ID",   :display-name "ID",   :lib/source :source/implicitly-joinable}
+             {:id (meta/id :categories :name), :name "NAME", :display-name "Name", :lib/source :source/implicitly-joinable}]
             (lib/orderable-columns query)))
     (let [expr (m/find-first #(= (:name %) "expr") (lib/orderable-columns query))]
       (is (=? {:lib/type   :metadata/field
@@ -692,29 +687,29 @@
 
 (deftest ^:parallel orderable-columns-display-info-test
   (let [query (lib/query-for-table-name meta/metadata-provider "VENUES")]
-    (is (=? [{:semantic_type          :type/PK
-              :is_calculated          false
-              :table                  {:name "VENUES", :display_name "Venues" :is_source_table true}
+    (is (=? [{:semantic-type          :type/PK
+              :is-calculated          false
+              :table                  {:name "VENUES", :display-name "Venues" :is-source-table true}
               :name                   "ID"
-              :is_from_previous_stage false
-              :is_implicitly_joinable false
-              :effective_type         :type/BigInteger
-              :is_from_join           false
-              :display_name           "ID"}
-             {:display_name "Name"
-              :table {:is_source_table true}}
-             {:display_name "Category ID"
-              :table {:is_source_table true}}
-             {:display_name "Latitude"
-              :table {:is_source_table true}}
-             {:display_name "Longitude"
-              :table {:is_source_table true}}
-             {:display_name "Price"
-              :table {:is_source_table true}}
-             {:display_name "ID"
-              :table {:name "CATEGORIES" :display_name "Categories" :is_source_table false}}
-             {:display_name "Name"
-              :table {:name "CATEGORIES" :display_name "Categories" :is_source_table false}}]
+              :is-from-previous-stage false
+              :is-implicitly-joinable false
+              :effective-type         :type/BigInteger
+              :is-from-join false
+              :display-name           "ID"}
+             {:display-name "Name"
+              :table {:is-source-table true}}
+             {:display-name "Category ID"
+              :table {:is-source-table true}}
+             {:display-name "Latitude"
+              :table {:is-source-table true}}
+             {:display-name "Longitude"
+              :table {:is-source-table true}}
+             {:display-name "Price"
+              :table {:is-source-table true}}
+             {:display-name "ID"
+              :table {:name "CATEGORIES" :display-name "Categories" :is-source-table false}}
+             {:display-name "Name"
+              :table {:name "CATEGORIES" :display-name "Categories" :is-source-table false}}]
             (for [col (lib/orderable-columns query)]
               (lib/display-info query col))))))
 
@@ -725,10 +720,10 @@
         _                 (is (some? col))
         query'            (lib/order-by query col)]
     (is (=? [{:name           "NAME"
-              :display_name   "Name"
-              :semantic_type  :type/Name
-              :effective_type :type/Text
-              :table          {:name "VENUES", :display_name "Venues"}
+              :display-name   "Name"
+              :semantic-type  :type/Name
+              :effective-type :type/Text
+              :table          {:name "VENUES", :display-name "Venues"}
               :direction      :asc}]
             (for [order-by (lib/order-bys query')]
               (lib/display-info query' order-by))))))
diff --git a/test/metabase/lib/query_test.cljc b/test/metabase/lib/query_test.cljc
index 0c2f9e13307..c04be756985 100644
--- a/test/metabase/lib/query_test.cljc
+++ b/test/metabase/lib/query_test.cljc
@@ -35,10 +35,10 @@
            :stages   [{:lib/type    :mbql.stage/native
                        :lib/options {:lib/uuid string?}
                        :native      "SELECT * FROM VENUES;"}]}
-          (lib/native-query meta/metadata-provider meta/results-metadata "SELECT * FROM VENUES;"))))
+          (lib/native-query meta/metadata-provider meta/qp-results-metadata "SELECT * FROM VENUES;"))))
 
 (deftest ^:parallel native-query-suggested-name-test
-  (let [query (lib/native-query meta/metadata-provider meta/results-metadata "SELECT * FROM VENUES;")]
+  (let [query (lib/native-query meta/metadata-provider meta/qp-results-metadata "SELECT * FROM VENUES;")]
     (is (= "Native query"
            (lib.metadata.calculation/describe-query query)))
     (is (nil? (lib.metadata.calculation/suggested-name query)))))
@@ -49,21 +49,18 @@
            :stages   [{:lib/type    :mbql.stage/native
                        :native      "SELECT * FROM VENUES;"}]}
           (lib/saved-question-query meta/metadata-provider
-                                    {:dataset_query   {:database (meta/id)
+                                    {:dataset-query   {:database (meta/id)
                                                        :type     :native
                                                        :native   {:query "SELECT * FROM VENUES;"}}
-                                     :result_metadata meta/results-metadata}))))
+                                     :result-metadata meta/card-results-metadata}))))
 
 (deftest ^:parallel notebook-query-test
   (is (=? {:lib/type :mbql/query
            :database (meta/id)
            :stages   [{:lib/type     :mbql.stage/mbql
-                       :lib/options  {:lib/uuid string?}
                        :source-table (meta/id :venues)}
-                      {:lib/type    :mbql.stage/mbql
-                       :lib/options {:lib/uuid string?}}
-                      {:lib/type    :mbql.stage/mbql
-                       :lib/options {:lib/uuid string?}}]}
+                      {:lib/type :mbql.stage/mbql}
+                      {:lib/type :mbql.stage/mbql}]}
           (lib/query meta/metadata-provider {:database (meta/id)
                                              :type     :query
                                              :query    {:source-query {:source-query {:source-table (meta/id :venues)}}}}))))
diff --git a/test/metabase/lib/stage_test.cljc b/test/metabase/lib/stage_test.cljc
index 3fb527c3020..c60ad86bfdb 100644
--- a/test/metabase/lib/stage_test.cljc
+++ b/test/metabase/lib/stage_test.cljc
@@ -40,14 +40,14 @@
                                    {}
                                    0.8
                                    [:avg {} (lib.tu/field-clause :venues :price)]]]})]
-        (is (=? [{:base_type                :type/Float
+        (is (=? [{:base-type                :type/Float
                   :name                     "0_8_times_avg_PRICE"
-                  :display_name             "0.8 × Average of Price"
+                  :display-name             "0.8 × Average of Price"
                   :lib/source-column-alias  "0_8_times_avg_PRICE"
                   :lib/desired-column-alias "0_8_times_avg_PRICE"}
-                 {:base_type                :type/Float
+                 {:base-type                :type/Float
                   :name                     "0_8_times_avg_PRICE"
-                  :display_name             "0.8 × Average of Price"
+                  :display-name             "0.8 × Average of Price"
                   :lib/source-column-alias  "0_8_times_avg_PRICE"
                   :lib/desired-column-alias "0_8_times_avg_PRICE_2"}]
                 (lib.metadata.calculation/metadata query -1 query)))))))
@@ -124,14 +124,14 @@
                   :name                     "ID"
                   :lib/source               :source/joins
                   :source_alias             "Cat"
-                  :display_name             "ID"
+                  :display-name             "ID"
                   :lib/source-column-alias  "ID"
                   :lib/desired-column-alias "Cat__ID"}
                  {:id                       (meta/id :categories :name)
                   :name                     "NAME"
                   :lib/source               :source/joins
                   :source_alias             "Cat"
-                  :display_name             "Name"
+                  :display-name             "Name"
                   :lib/source-column-alias  "NAME"
                   :lib/desired-column-alias "Cat__NAME"}]
                 metadata))
@@ -153,9 +153,9 @@
     (let [query     (query-with-expressions)
           id-plus-1 (first (lib/expressions query))]
       (is (=? {:lib/type     :metadata/field
-               :base_type    :type/Integer
+               :base-type    :type/Integer
                :name         "ID + 1"
-               :display_name "ID + 1"
+               :display-name "ID + 1"
                :lib/source   :source/expressions}
               id-plus-1))
       (let [query' (-> query
@@ -182,28 +182,28 @@
             :let [query (varr)]]
       (testing (pr-str varr)
         (is (=? [{:name                     "USER_ID"
-                  :display_name             "User ID"
-                  :base_type                :type/Integer
+                  :display-name             "User ID"
+                  :base-type                :type/Integer
                   :lib/source               :source/card
                   :lib/desired-column-alias "USER_ID"}
                  {:name                     "count"
-                  :display_name             "Count"
-                  :base_type                :type/Integer
+                  :display-name             "Count"
+                  :base-type                :type/Integer
                   :lib/source               :source/card
                   :lib/desired-column-alias "count"}
                  {:name                     "ID"
-                  :display_name             "ID"
-                  :base_type                :type/BigInteger
+                  :display-name             "ID"
+                  :base-type                :type/BigInteger
                   :lib/source               :source/implicitly-joinable
                   :lib/desired-column-alias "USERS__via__USER_ID__ID"}
                  {:name                     "NAME"
-                  :display_name             "Name"
-                  :base_type                :type/Text
+                  :display-name             "Name"
+                  :base-type                :type/Text
                   :lib/source               :source/implicitly-joinable
                   :lib/desired-column-alias "USERS__via__USER_ID__NAME"}
                  {:name                     "LAST_LOGIN"
-                  :display_name             "Last Login"
-                  :base_type                :type/DateTime
+                  :display-name             "Last Login"
+                  :base-type                :type/DateTime
                   :lib/source               :source/implicitly-joinable
                   :lib/desired-column-alias "USERS__via__USER_ID__LAST_LOGIN"}]
                 (lib.metadata.calculation/visible-columns query)))))))
diff --git a/test/metabase/lib/temporal_bucket_test.cljc b/test/metabase/lib/temporal_bucket_test.cljc
index 2f311201c26..4219ec1396f 100644
--- a/test/metabase/lib/temporal_bucket_test.cljc
+++ b/test/metabase/lib/temporal_bucket_test.cljc
@@ -54,7 +54,8 @@
          (lib.temporal-bucket/describe-temporal-unit nil)))
   (is (= "Day"
          (lib.temporal-bucket/describe-temporal-unit :day)
-         (lib.temporal-bucket/describe-temporal-unit 1 :day)))
+         (lib.temporal-bucket/describe-temporal-unit 1 :day)
+         (lib.temporal-bucket/describe-temporal-unit -1 :day)))
   (is (= "Days"
          (lib.temporal-bucket/describe-temporal-unit 2 :day)))
   (is (= "Unknown unit"
diff --git a/test/metabase/lib/test_metadata.cljc b/test/metabase/lib/test_metadata.cljc
index cc4cff48ae7..6a9b950d1fc 100644
--- a/test/metabase/lib/test_metadata.cljc
+++ b/test/metabase/lib/test_metadata.cljc
@@ -137,60 +137,60 @@
 (defmethod field-metadata [:categories :id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "BIGINT"
-   :semantic_type       :type/PK
-   :table_id            (id :categories)
-   :coercion_strategy   nil
+   :database-type       "BIGINT"
+   :semantic-type       :type/PK
+   :table-id            (id :categories)
+   :coercion-strategy   nil
    :name                "ID"
-   :fingerprint_version 0
-   :has_field_values    :none
+   :fingerprint-version 0
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/BigInteger
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/BigInteger
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :categories :id)
    :position            0
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "ID"
-   :database_position   0
-   :database_required   false
+   :preview-display     true
+   :display-name        "ID"
+   :database-position   0
+   :database-required   false
    :fingerprint         nil
-   :base_type           :type/BigInteger
-   :points_of_interest  nil
+   :base-type           :type/BigInteger
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:categories :name]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "CHARACTER VARYING"
-   :semantic_type       :type/Name
-   :table_id            (id :categories)
-   :coercion_strategy   nil
+   :database-type       "CHARACTER VARYING"
+   :semantic-type       :type/Name
+   :table-id            (id :categories)
+   :coercion-strategy   nil
    :name                "NAME"
-   :fingerprint_version 5
-   :has_field_values    :list
+   :fingerprint-version 5
+   :has-field-values    :list
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Text
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Text
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :categories :name)
    :position            1
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Name"
-   :database_position   1
-   :database_required   true
+   :preview-display     true
+   :display-name        "Name"
+   :database-position   1
+   :database-required   true
    :fingerprint
    {:global {:distinct-count 75, :nil% 0.0}
     :type   {:type/Text {:percent-json   0.0
@@ -198,16 +198,16 @@
                          :percent-email  0.0
                          :percent-state  0.0
                          :average-length 8.333333333333334}}}
-   :base_type           :type/Text
-   :points_of_interest  nil
+   :base-type           :type/Text
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod table-metadata :categories
   [_table-name]
   {:description             nil
-   :entity_type             :entity/GenericTable
+   :entity-type             :entity/GenericTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "CATEGORIES"
    :fields                  [(field-metadata :categories :id)
                              (field-metadata :categories :name)]
@@ -215,146 +215,146 @@
    :segments                []
    :active                  true
    :id                      (id :categories)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Categories"
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Categories"
    :metrics                 []
-   :points_of_interest      nil
+   :points-of-interest      nil
    :lib/type                :metadata/table})
 
 (defmethod field-metadata [:checkins :id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "BIGINT"
-   :semantic_type       :type/PK
-   :table_id            (id :checkins)
-   :coercion_strategy   nil
+   :database-type       "BIGINT"
+   :semantic-type       :type/PK
+   :table-id            (id :checkins)
+   :coercion-strategy   nil
    :name                "ID"
-   :fingerprint_version 0
-   :has_field_values    :none
+   :fingerprint-version 0
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/BigInteger
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/BigInteger
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :checkins :id)
    :position            0
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "ID"
-   :database_position   0
-   :database_required   false
+   :preview-display     true
+   :display-name        "ID"
+   :database-position   0
+   :database-required   false
    :fingerprint         nil
-   :base_type           :type/BigInteger
-   :points_of_interest  nil
+   :base-type           :type/BigInteger
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:checkins :date]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "DATE"
-   :semantic_type       nil
-   :table_id            (id :checkins)
-   :coercion_strategy   nil
+   :database-type       "DATE"
+   :semantic-type       nil
+   :table-id            (id :checkins)
+   :coercion-strategy   nil
    :name                "DATE"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Date
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Date
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :checkins :date)
    :position            1
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Date"
-   :database_position   1
-   :database_required   false
+   :preview-display     true
+   :display-name        "Date"
+   :database-position   1
+   :database-required   false
    :fingerprint         {:global {:distinct-count 618, :nil% 0.0}
                          :type   #:type{:DateTime {:earliest "2013-01-03", :latest "2015-12-29"}}}
-   :base_type           :type/Date
-   :points_of_interest  nil
+   :base-type           :type/Date
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:checkins :user-id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "INTEGER"
-   :semantic_type       :type/FK
-   :table_id            (id :checkins)
-   :coercion_strategy   nil
+   :database-type       "INTEGER"
+   :semantic-type       :type/FK
+   :table-id            (id :checkins)
+   :coercion-strategy   nil
    :name                "USER_ID"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  (id :users :id)
-   :custom_position     0
-   :effective_type      :type/Integer
+   :fk-target-field-id  (id :users :id)
+   :custom-position     0
+   :effective-type      :type/Integer
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :checkins :user-id)
    :position            2
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "User ID"
-   :database_position   2
-   :database_required   false
+   :preview-display     true
+   :display-name        "User ID"
+   :database-position   2
+   :database-required   false
    :fingerprint         {:global {:distinct-count 15, :nil% 0.0}}
-   :base_type           :type/Integer
-   :points_of_interest  nil
+   :base-type           :type/Integer
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:checkins :venue-id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "INTEGER"
-   :semantic_type       :type/FK
-   :table_id            (id :checkins)
-   :coercion_strategy   nil
+   :database-type       "INTEGER"
+   :semantic-type       :type/FK
+   :table-id            (id :checkins)
+   :coercion-strategy   nil
    :name                "VENUE_ID"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  (id :venues :id)
-   :custom_position     0
-   :effective_type      :type/Integer
+   :fk-target-field-id  (id :venues :id)
+   :custom-position     0
+   :effective-type      :type/Integer
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :checkins :venue-id)
    :position            3
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Venue ID"
-   :database_position   3
-   :database_required   false
+   :preview-display     true
+   :display-name        "Venue ID"
+   :database-position   3
+   :database-required   false
    :fingerprint         {:global {:distinct-count 100, :nil% 0.0}}
-   :base_type           :type/Integer
-   :points_of_interest  nil
+   :base-type           :type/Integer
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod table-metadata :checkins
   [_table-name]
   {:description             nil
-   :entity_type             :entity/EventTable
+   :entity-type             :entity/EventTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "CHECKINS"
    :fields                  [(field-metadata :checkins :id)
                              (field-metadata :checkins :date)
@@ -364,72 +364,72 @@
    :segments                []
    :active                  true
    :id                      (id :checkins)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Checkins"
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Checkins"
    :metrics                 []
-   :points_of_interest      nil
+   :points-of-interest      nil
    :lib/type                :metadata/table})
 
 (defmethod field-metadata [:users :id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "BIGINT"
-   :semantic_type       :type/PK
-   :table_id            (id :users)
-   :coercion_strategy   nil
+   :database-type       "BIGINT"
+   :semantic-type       :type/PK
+   :table-id            (id :users)
+   :coercion-strategy   nil
    :name                "ID"
-   :fingerprint_version 0
-   :has_field_values    :none
+   :fingerprint-version 0
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/BigInteger
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/BigInteger
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :users :id)
    :position            0
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "ID"
-   :database_position   0
-   :database_required   false
+   :preview-display     true
+   :display-name        "ID"
+   :database-position   0
+   :database-required   false
    :fingerprint         nil
-   :base_type           :type/BigInteger
-   :points_of_interest  nil
+   :base-type           :type/BigInteger
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:users :name]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "CHARACTER VARYING"
-   :semantic_type       :type/Name
-   :table_id            (id :users)
-   :coercion_strategy   nil
+   :database-type       "CHARACTER VARYING"
+   :semantic-type       :type/Name
+   :table-id            (id :users)
+   :coercion-strategy   nil
    :name                "NAME"
-   :fingerprint_version 5
-   :has_field_values    :list
+   :fingerprint-version 5
+   :has-field-values    :list
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Text
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Text
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :users :name)
    :position            1
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Name"
-   :database_position   1
-   :database_required   false
+   :preview-display     true
+   :display-name        "Name"
+   :database-position   1
+   :database-required   false
    :fingerprint         {:global {:distinct-count 15, :nil% 0.0}
                          :type   #:type{:Text
                                         {:percent-json   0.0
@@ -437,68 +437,68 @@
                                          :percent-email  0.0
                                          :percent-state  0.0
                                          :average-length 13.266666666666667}}}
-   :base_type           :type/Text
-   :points_of_interest  nil
+   :base-type           :type/Text
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:users :last-login]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "TIMESTAMP"
-   :semantic_type       nil
-   :table_id            (id :users)
-   :coercion_strategy   nil
+   :database-type       "TIMESTAMP"
+   :semantic-type       nil
+   :table-id            (id :users)
+   :coercion-strategy   nil
    :name                "LAST_LOGIN"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/DateTime
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/DateTime
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :users :last-login)
    :position            2
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Last Login"
-   :database_position   2
-   :database_required   false
+   :preview-display     true
+   :display-name        "Last Login"
+   :database-position   2
+   :database-required   false
    :fingerprint         {:global {:distinct-count 15, :nil% 0.0}
                          :type   #:type{:DateTime {:earliest "2014-01-01T08:30:00Z", :latest "2014-12-05T15:15:00Z"}}}
-   :base_type           :type/DateTime
-   :points_of_interest  nil
+   :base-type           :type/DateTime
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:users :password]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "CHARACTER VARYING"
-   :semantic_type       :type/Category
-   :table_id            (id :users)
-   :coercion_strategy   nil
+   :database-type       "CHARACTER VARYING"
+   :semantic-type       :type/Category
+   :table-id            (id :users)
+   :coercion-strategy   nil
    :name                "PASSWORD"
-   :fingerprint_version 5
-   :has_field_values    :list
+   :fingerprint-version 5
+   :has-field-values    :list
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Text
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Text
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :users :password)
    :position            3
-   :visibility_type     :sensitive
+   :visibility-type     :sensitive
    :target              nil
-   :preview_display     true
-   :display_name        "Password"
-   :database_position   3
-   :database_required   false
+   :preview-display     true
+   :display-name        "Password"
+   :database-position   3
+   :database-required   false
    :fingerprint         {:global {:distinct-count 15, :nil% 0.0}
                          :type   #:type{:Text
                                         {:percent-json   0.0
@@ -506,16 +506,16 @@
                                          :percent-email  0.0
                                          :percent-state  0.0
                                          :average-length 36.0}}}
-   :base_type           :type/Text
-   :points_of_interest  nil
+   :base-type           :type/Text
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod table-metadata :users
   [_table-name]
   {:description             nil
-   :entity_type             :entity/UserTable
+   :entity-type             :entity/UserTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "USERS"
    :fields                  [(field-metadata :users :id)
                              (field-metadata :users :name)
@@ -525,72 +525,72 @@
    :segments                []
    :active                  true
    :id                      (id :users)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Users"
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Users"
    :metrics                 []
-   :points_of_interest      nil
+   :points-of-interest      nil
    :lib/type                :metadata/table})
 
 (defmethod field-metadata [:venues :id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "BIGINT"
-   :semantic_type       :type/PK
-   :table_id            (id :venues)
-   :coercion_strategy   nil
+   :database-type       "BIGINT"
+   :semantic-type       :type/PK
+   :table-id            (id :venues)
+   :coercion-strategy   nil
    :name                "ID"
-   :fingerprint_version 0
-   :has_field_values    :none
+   :fingerprint-version 0
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/BigInteger
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/BigInteger
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :venues :id)
    :position            0
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "ID"
-   :database_position   0
-   :database_required   false
+   :preview-display     true
+   :display-name        "ID"
+   :database-position   0
+   :database-required   false
    :fingerprint         nil
-   :base_type           :type/BigInteger
-   :points_of_interest  nil
+   :base-type           :type/BigInteger
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:venues :name]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "CHARACTER VARYING"
-   :semantic_type       :type/Name
-   :table_id            (id :venues)
-   :coercion_strategy   nil
+   :database-type       "CHARACTER VARYING"
+   :semantic-type       :type/Name
+   :table-id            (id :venues)
+   :coercion-strategy   nil
    :name                "NAME"
-   :fingerprint_version 5
-   :has_field_values    :list
+   :fingerprint-version 5
+   :has-field-values    :list
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Text
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Text
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :venues :name)
    :position            1
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Name"
-   :database_position   1
-   :database_required   false
+   :preview-display     true
+   :display-name        "Name"
+   :database-position   1
+   :database-required   false
    :fingerprint         {:global {:distinct-count 100, :nil% 0.0}
                          :type   #:type{:Text
                                         {:percent-json   0.0
@@ -598,67 +598,67 @@
                                          :percent-email  0.0
                                          :percent-state  0.0
                                          :average-length 15.63}}}
-   :base_type           :type/Text
-   :points_of_interest  nil
+   :base-type           :type/Text
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:venues :category-id]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "INTEGER"
-   :semantic_type       :type/FK
-   :table_id            (id :venues)
-   :coercion_strategy   nil
+   :database-type       "INTEGER"
+   :semantic-type       :type/FK
+   :table-id            (id :venues)
+   :coercion-strategy   nil
    :name                "CATEGORY_ID"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  (id :categories :id)
-   :custom_position     0
-   :effective_type      :type/Integer
+   :fk-target-field-id  (id :categories :id)
+   :custom-position     0
+   :effective-type      :type/Integer
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :venues :category-id)
    :position            2
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Category ID"
-   :database_position   2
-   :database_required   false
+   :preview-display     true
+   :display-name        "Category ID"
+   :database-position   2
+   :database-required   false
    :fingerprint         {:global {:distinct-count 28, :nil% 0.0}}
-   :base_type           :type/Integer
-   :points_of_interest  nil
+   :base-type           :type/Integer
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:venues :latitude]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "DOUBLE PRECISION"
-   :semantic_type       :type/Latitude
-   :table_id            (id :venues)
-   :coercion_strategy   nil
+   :database-type       "DOUBLE PRECISION"
+   :semantic-type       :type/Latitude
+   :table-id            (id :venues)
+   :coercion-strategy   nil
    :name                "LATITUDE"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Float
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Float
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :venues :latitude)
    :position            3
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Latitude"
-   :database_position   3
-   :database_required   false
+   :preview-display     true
+   :display-name        "Latitude"
+   :database-position   3
+   :database-required   false
    :fingerprint         {:global {:distinct-count 94, :nil% 0.0}
                          :type   #:type{:Number
                                         {:min 10.0646
@@ -667,36 +667,36 @@
                                          :max 40.7794
                                          :sd  3.4346725397190827
                                          :avg 35.505891999999996}}}
-   :base_type           :type/Float
-   :points_of_interest  nil
+   :base-type           :type/Float
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:venues :longitude]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "DOUBLE PRECISION"
-   :semantic_type       :type/Longitude
-   :table_id            (id :venues)
-   :coercion_strategy   nil
+   :database-type       "DOUBLE PRECISION"
+   :semantic-type       :type/Longitude
+   :table-id            (id :venues)
+   :coercion-strategy   nil
    :name                "LONGITUDE"
-   :fingerprint_version 5
-   :has_field_values    :none
+   :fingerprint-version 5
+   :has-field-values    :none
    :settings            nil
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Float
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Float
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :venues :longitude)
    :position            4
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Longitude"
-   :database_position   4
-   :database_required   false
+   :preview-display     true
+   :display-name        "Longitude"
+   :database-position   4
+   :database-required   false
    :fingerprint
    {:global {:distinct-count 84, :nil% 0.0}
     :type
@@ -707,36 +707,36 @@
             :max -73.9533
             :sd  14.162810671348238
             :avg -115.99848699999998}}}
-   :base_type           :type/Float
-   :points_of_interest  nil
+   :base-type           :type/Float
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod field-metadata [:venues :price]
   [_table-name _field-name]
   {:description         nil
-   :database_type       "INTEGER"
-   :semantic_type       :type/Category
-   :table_id            (id :venues)
-   :coercion_strategy   nil
+   :database-type       "INTEGER"
+   :semantic-type       :type/Category
+   :table-id            (id :venues)
+   :coercion-strategy   nil
    :name                "PRICE"
-   :fingerprint_version 5
-   :has_field_values    :list
+   :fingerprint-version 5
+   :has-field-values    :list
    :settings            {:is_priceless true}
    :caveats             nil
-   :fk_target_field_id  nil
-   :custom_position     0
-   :effective_type      :type/Integer
+   :fk-target-field-id  nil
+   :custom-position     0
+   :effective-type      :type/Integer
    :active              true
-   :nfc_path            nil
-   :parent_id           nil
+   :nfc-path            nil
+   :parent-id           nil
    :id                  (id :venues :price)
    :position            5
-   :visibility_type     :normal
+   :visibility-type     :normal
    :target              nil
-   :preview_display     true
-   :display_name        "Price"
-   :database_position   5
-   :database_required   false
+   :preview-display     true
+   :display-name        "Price"
+   :database-position   5
+   :database-required   false
    :fingerprint         {:global {:distinct-count 4, :nil% 0.0}
                          :type   #:type{:Number
                                         {:min 1.0
@@ -745,16 +745,16 @@
                                          :max 4.0
                                          :sd  0.7713951678941896
                                          :avg 2.03}}}
-   :base_type           :type/Integer
-   :points_of_interest  nil
+   :base-type           :type/Integer
+   :points-of-interest  nil
    :lib/type            :metadata/field})
 
 (defmethod table-metadata :venues
   [_table-name]
   {:description             nil
-   :entity_type             :entity/GenericTable
+   :entity-type             :entity/GenericTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "VENUES"
    :fields                  [(field-metadata :venues :id)
                              (field-metadata :venues :name)
@@ -766,72 +766,72 @@
    :segments                []
    :active                  true
    :id                      (id :venues)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Venues"
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Venues"
    :metrics                 []
-   :points_of_interest      nil
+   :points-of-interest      nil
    :lib/type                :metadata/table})
 
  (defmethod field-metadata [:products :id]
   [_table-name _field-name]
    {:description                nil
-    :database_type              "BIGINT"
-    :semantic_type              :type/PK
-    :table_id                   (id :products)
-    :coercion_strategy          nil
+    :database-type              "BIGINT"
+    :semantic-type              :type/PK
+    :table-id                   (id :products)
+    :coercion-strategy          nil
     :name                       "ID"
-    :fingerprint_version        0
-    :has_field_values           nil
+    :fingerprint-version        0
+    :has-field-values           nil
     :settings                   nil
     :caveats                    nil
-    :fk_target_field_id         nil
-    :custom_position            0
-    :effective_type             :type/BigInteger
+    :fk-target-field-id         nil
+    :custom-position            0
+    :effective-type             :type/BigInteger
     :active                     true
-    :nfc_path                   nil
-    :parent_id                  nil
+    :nfc-path                   nil
+    :parent-id                  nil
     :id                         (id :products :id)
-    :database_is_auto_increment true
+    :database-is-auto-increment true
     :position                   0
-    :visibility_type            :normal
-    :preview_display            true
-    :display_name               "ID"
-    :database_position          0
-    :database_required          false
+    :visibility-type            :normal
+    :preview-display            true
+    :display-name               "ID"
+    :database-position          0
+    :database-required          false
     :fingerprint                nil
-    :base_type                  :type/BigInteger
-    :points_of_interest         nil
+    :base-type                  :type/BigInteger
+    :points-of-interest         nil
     :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:products :rating]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              :type/Score
-   :table_id                   (id :products)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              :type/Score
+   :table-id                   (id :products)
+   :coercion-strategy          nil
    :name                       "RATING"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :products :rating)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   6
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Rating"
-   :database_position          6
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Rating"
+   :database-position          6
+   :database-required          false
    :fingerprint                {:global {:distinct-count 23, :nil% 0.0}
                                 :type   {:type/Number {:min 0.0
                                                        :q1  3.5120465053408525
@@ -839,72 +839,72 @@
                                                        :max 5.0
                                                        :sd  1.3605488657451452
                                                        :avg 3.4715}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
  (defmethod field-metadata [:products :category]
    [_table-name _field-name]
    {:description                nil
-    :database_type              "CHARACTER VARYING"
-    :semantic_type              :type/Category
-    :table_id                   (id :products)
-    :coercion_strategy          nil
+    :database-type              "CHARACTER VARYING"
+    :semantic-type              :type/Category
+    :table-id                   (id :products)
+    :coercion-strategy          nil
     :name                       "CATEGORY"
-    :fingerprint_version        5
-    :has_field_values           :auto-list
+    :fingerprint-version        5
+    :has-field-values           :auto-list
     :settings                   nil
     :caveats                    nil
-    :fk_target_field_id         nil
-    :custom_position            0
-    :effective_type             :type/Text
+    :fk-target-field-id         nil
+    :custom-position            0
+    :effective-type             :type/Text
     :active                     true
-    :nfc_path                   nil
-    :parent_id                  nil
+    :nfc-path                   nil
+    :parent-id                  nil
     :id                         (id :products :category)
-    :database_is_auto_increment false
+    :database-is-auto-increment false
     :position                   3
-    :visibility_type            :normal
-    :preview_display            true
-    :display_name               "Category"
-    :database_position          3
-    :database_required          false
+    :visibility-type            :normal
+    :preview-display            true
+    :display-name               "Category"
+    :database-position          3
+    :database-required          false
     :fingerprint                {:global {:distinct-count 4, :nil% 0.0}
                                  :type   {:type/Text {:percent-json   0.0
                                                       :percent-url    0.0
                                                       :percent-email  0.0
                                                       :percent-state  0.0
                                                       :average-length 6.375}}}
-    :base_type                  :type/Text
-    :points_of_interest         nil
+    :base-type                  :type/Text
+    :points-of-interest         nil
     :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:products :price]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              nil
-   :table_id                   (id :products)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              nil
+   :table-id                   (id :products)
+   :coercion-strategy          nil
    :name                       "PRICE"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :products :price)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   5
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Price"
-   :database_position          5
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Price"
+   :database-position          5
+   :database-required          false
    :fingerprint                {:global {:distinct-count 168, :nil% 0.0}
                                 :type   {:type/Number {:min 15.69
                                                        :q1  37.139492751669884
@@ -912,167 +912,167 @@
                                                        :max 98.82
                                                        :sd  21.711152906916283
                                                        :avg 55.746399999999994}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
  (defmethod field-metadata [:products :title]
    [_table-name _field-name]
    {:description                nil
-    :database_type              "CHARACTER VARYING"
-    :semantic_type              :type/Title
-    :table_id                   (id :products)
-    :coercion_strategy          nil
+    :database-type              "CHARACTER VARYING"
+    :semantic-type              :type/Title
+    :table-id                   (id :products)
+    :coercion-strategy          nil
     :name                       "TITLE"
-    :fingerprint_version        5
-    :has_field_values           :auto-list
+    :fingerprint-version        5
+    :has-field-values           :auto-list
     :settings                   nil
     :caveats                    nil
-    :fk_target_field_id         nil
-    :custom_position            0
-    :effective_type             :type/Text
+    :fk-target-field-id         nil
+    :custom-position            0
+    :effective-type             :type/Text
     :active                     true
-    :nfc_path                   nil
-    :parent_id                  nil
+    :nfc-path                   nil
+    :parent-id                  nil
     :id                         (id :products :title)
-    :database_is_auto_increment false
+    :database-is-auto-increment false
     :position                   2
-    :visibility_type            :normal
-    :preview_display            true
-    :display_name               "Title"
-    :database_position          2
-    :database_required          false
+    :visibility-type            :normal
+    :preview-display            true
+    :display-name               "Title"
+    :database-position          2
+    :database-required          false
     :fingerprint                {:global {:distinct-count 199, :nil% 0.0}
                                  :type   {:type/Text {:percent-json   0.0
                                                       :percent-url    0.0
                                                       :percent-email  0.0
                                                       :percent-state  0.0
                                                       :average-length 21.495}}}
-    :base_type                  :type/Text
-    :points_of_interest         nil
+    :base-type                  :type/Text
+    :points-of-interest         nil
     :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:products :created-at]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "TIMESTAMP WITH TIME ZONE"
-   :semantic_type              :type/CreationTimestamp
-   :table_id                   (id :products)
-   :coercion_strategy          nil
+   :database-type              "TIMESTAMP WITH TIME ZONE"
+   :semantic-type              :type/CreationTimestamp
+   :table-id                   (id :products)
+   :coercion-strategy          nil
    :name                       "CREATED_AT"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/DateTimeWithLocalTZ
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/DateTimeWithLocalTZ
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :products :created-at)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   7
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Created At"
-   :database_position          7
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Created At"
+   :database-position          7
+   :database-required          false
    :fingerprint                {:global {:distinct-count 200, :nil% 0.0}
                                 :type   {:type/DateTime {:earliest "2016-04-26T19:29:55.147Z"
                                                          :latest   "2019-04-15T13:34:19.931Z"}}}
-   :base_type                  :type/DateTimeWithLocalTZ
-   :points_of_interest         nil
+   :base-type                  :type/DateTimeWithLocalTZ
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:products :vendor]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              :type/Company
-   :table_id                   (id :products)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              :type/Company
+   :table-id                   (id :products)
+   :coercion-strategy          nil
    :name                       "VENDOR"
-   :fingerprint_version        5
-   :has_field_values           :auto-list
+   :fingerprint-version        5
+   :has-field-values           :auto-list
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :products :vendor)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   4
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Vendor"
-   :database_position          4
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Vendor"
+   :database-position          4
+   :database-required          false
    :fingerprint                {:global {:distinct-count 200, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 20.6}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:products :ean]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              nil
-   :table_id                   (id :products)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              nil
+   :table-id                   (id :products)
+   :coercion-strategy          nil
    :name                       "EAN"
-   :fingerprint_version        5
-   :has_field_values           :auto-list
+   :fingerprint-version        5
+   :has-field-values           :auto-list
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :products :ean)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   1
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Ean"
-   :database_position          1
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Ean"
+   :database-position          1
+   :database-required          false
    :fingerprint                {:global {:distinct-count 200, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 13.0}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod table-metadata :products
   [_table-name]
   {:description             nil
-   :entity_type             :entity/ProductTable
+   :entity-type             :entity/ProductTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "PRODUCTS"
    :caveats                 nil
    :active                  true
    :id                      (id :products)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Products"
-   :points_of_interest      nil
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Products"
+   :points-of-interest      nil
    :lib/type                :metadata/table
    :fields                  [(field-metadata :products :id)
                              (field-metadata :products :rating)
@@ -1086,60 +1086,60 @@
 (defmethod field-metadata [:orders :id]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "BIGINT"
-   :semantic_type              :type/PK
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "BIGINT"
+   :semantic-type              :type/PK
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "ID"
-   :fingerprint_version        0
-   :has_field_values           nil
+   :fingerprint-version        0
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/BigInteger
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/BigInteger
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :id)
-   :database_is_auto_increment true
+   :database-is-auto-increment true
    :position                   0
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "ID"
-   :database_position          0
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "ID"
+   :database-position          0
+   :database-required          false
    :fingerprint                nil
-   :base_type                  :type/BigInteger
-   :points_of_interest         nil
+   :base-type                  :type/BigInteger
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :subtotal]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              nil
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              nil
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "SUBTOTAL"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :subtotal)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   3
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Subtotal"
-   :database_position          3
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Subtotal"
+   :database-position          3
+   :database-required          false
    :fingerprint                {:global {:distinct-count 334, :nil% 0.0}
                                 :type   {:type/Number
                                          {:min 15.69
@@ -1148,36 +1148,36 @@
                                           :max 148.23
                                           :sd  32.536819823931104
                                           :avg 77.012717}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :total]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              nil
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              nil
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "TOTAL"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :total)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   5
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Total"
-   :database_position          5
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Total"
+   :database-position          5
+   :database-required          false
    :fingerprint                {:global {:distinct-count 3710, :nil% 0.0}
                                 :type   {:type/Number
                                          {:min 8.94
@@ -1186,36 +1186,36 @@
                                           :max 159.35
                                           :sd  34.264752087910324
                                           :avg 80.35850400000001}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :tax]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              nil
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              nil
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "TAX"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :tax)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   4
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Tax"
-   :database_position          4
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Tax"
+   :database-position          4
+   :database-required          false
    :fingerprint                {:global {:distinct-count 797, :nil% 0.0}
                                 :type   {:type/Number
                                          {:min 0.0
@@ -1224,36 +1224,36 @@
                                           :max 11.12
                                           :sd  2.3206651358900316
                                           :avg 3.8722100000000004}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :discount]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              :type/Discount
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              :type/Discount
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "DISCOUNT"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :discount)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   6
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Discount"
-   :database_position          6
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Discount"
+   :database-position          6
+   :database-required          false
    :fingerprint                {:global {:distinct-count 479, :nil% 0.898}
                                 :type   {:type/Number {:min 0.17
                                                        :q1  2.978591571097236
@@ -1261,36 +1261,36 @@
                                                        :max 61.7
                                                        :sd  3.053736975739119
                                                        :avg 5.161009803921569}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :quantity]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "INTEGER"
-   :semantic_type              :type/Quantity
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "INTEGER"
+   :semantic-type              :type/Quantity
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "QUANTITY"
-   :fingerprint_version        5
-   :has_field_values           :auto-list
+   :fingerprint-version        5
+   :has-field-values           :auto-list
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Integer
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Integer
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :quantity)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   8
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Quantity"
-   :database_position          8
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Quantity"
+   :database-position          8
+   :database-required          false
    :fingerprint                {:global {:distinct-count 62, :nil% 0.0}
                                 :type   {:type/Number {:min 0.0
                                                        :q1  1.755882607764982
@@ -1298,121 +1298,121 @@
                                                        :max 100.0
                                                        :sd  4.214258386403798
                                                        :avg 3.7015}}}
-   :base_type                  :type/Integer
-   :points_of_interest         nil
+   :base-type                  :type/Integer
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :created-at]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "TIMESTAMP WITH TIME ZONE"
-   :semantic_type              :type/CreationTimestamp
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "TIMESTAMP WITH TIME ZONE"
+   :semantic-type              :type/CreationTimestamp
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "CREATED_AT"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/DateTimeWithLocalTZ
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/DateTimeWithLocalTZ
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :created-at)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   7
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Created At"
-   :database_position          7
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Created At"
+   :database-position          7
+   :database-required          false
    :fingerprint                {:global {:distinct-count 10000, :nil% 0.0}
                                 :type   {:type/DateTime {:earliest "2016-04-30T18:56:13.352Z"
                                                          :latest   "2020-04-19T14:07:15.657Z"}}}
-   :base_type                  :type/DateTimeWithLocalTZ
-   :points_of_interest         nil
+   :base-type                  :type/DateTimeWithLocalTZ
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :product-id]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "INTEGER"
-   :semantic_type              :type/FK
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "INTEGER"
+   :semantic-type              :type/FK
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "PRODUCT_ID"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         (id :products :id)
-   :custom_position            0
-   :effective_type             :type/Integer
+   :fk-target-field-id         (id :products :id)
+   :custom-position            0
+   :effective-type             :type/Integer
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :product-id)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   2
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Product ID"
-   :database_position          2
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Product ID"
+   :database-position          2
+   :database-required          false
    :fingerprint                {:global {:distinct-count 200, :nil% 0.0}}
-   :base_type                  :type/Integer
-   :points_of_interest         nil
+   :base-type                  :type/Integer
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:orders :user-id]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "INTEGER"
-   :semantic_type              :type/FK
-   :table_id                   (id :orders)
-   :coercion_strategy          nil
+   :database-type              "INTEGER"
+   :semantic-type              :type/FK
+   :table-id                   (id :orders)
+   :coercion-strategy          nil
    :name                       "USER_ID"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         (id :people :id)
-   :custom_position            0
-   :effective_type             :type/Integer
+   :fk-target-field-id         (id :people :id)
+   :custom-position            0
+   :effective-type             :type/Integer
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :orders :user-id)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   1
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "User ID"
-   :database_position          1
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "User ID"
+   :database-position          1
+   :database-required          false
    :fingerprint                {:global {:distinct-count 929, :nil% 0.0}}
-   :base_type                  :type/Integer
-   :points_of_interest         nil
+   :base-type                  :type/Integer
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod table-metadata :orders
   [_table-name]
   {:description             nil
-   :entity_type             :entity/TransactionTable
+   :entity-type             :entity/TransactionTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "ORDERS"
    :caveats                 nil
    :active                  true
    :id                      (id :orders)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Orders"
-   :points_of_interest      nil
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Orders"
+   :points-of-interest      nil
    :lib/type                :metadata/table
    :fields                  [(field-metadata :orders :id)
                              (field-metadata :orders :subtotal)
@@ -1427,276 +1427,276 @@
 (defmethod field-metadata [:people :id]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "BIGINT"
-   :semantic_type              :type/PK
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "BIGINT"
+   :semantic-type              :type/PK
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "ID"
-   :fingerprint_version        0
-   :has_field_values           nil
+   :fingerprint-version        0
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/BigInteger
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/BigInteger
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :id)
-   :database_is_auto_increment true
+   :database-is-auto-increment true
    :position                   0
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "ID"
-   :database_position          0
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "ID"
+   :database-position          0
+   :database-required          false
    :fingerprint                nil
-   :base_type                  :type/BigInteger
-   :points_of_interest         nil
+   :base-type                  :type/BigInteger
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :state]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              :type/State
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              :type/State
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "STATE"
-   :fingerprint_version        5
-   :has_field_values           :auto-list
+   :fingerprint-version        5
+   :has-field-values           :auto-list
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :state)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   7
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "State"
-   :database_position          7
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "State"
+   :database-position          7
+   :database-required          false
    :fingerprint                {:global {:distinct-count 49, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  1.0
                                                      :average-length 2.0}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :city]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              :type/City
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              :type/City
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "CITY"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :city)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   5
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "City"
-   :database_position          5
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "City"
+   :database-position          5
+   :database-required          false
    :fingerprint                {:global {:distinct-count 1966, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.002
                                                      :average-length 8.284}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :address]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              nil
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              nil
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "ADDRESS"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :address)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   1
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Address"
-   :database_position          1
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Address"
+   :database-position          1
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2490, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 20.85}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :name]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              :type/Name
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              :type/Name
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "NAME"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :name)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   4
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Name"
-   :database_position          4
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Name"
+   :database-position          4
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2499, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 13.532}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :source]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              :type/Source
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              :type/Source
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "SOURCE"
-   :fingerprint_version        5
-   :has_field_values           :auto-list
+   :fingerprint-version        5
+   :has-field-values           :auto-list
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :source)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   8
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Source"
-   :database_position          8
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Source"
+   :database-position          8
+   :database-required          false
    :fingerprint                {:global {:distinct-count 5, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 7.4084}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :zip]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              nil
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              nil
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "ZIP"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :zip)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   10
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Zip"
-   :database_position          10
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Zip"
+   :database-position          10
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2234, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 5.0}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :latitude]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              :type/Latitude
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              :type/Latitude
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "LATITUDE"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :latitude)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   11
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Latitude"
-   :database_position          11
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Latitude"
+   :database-position          11
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2491, :nil% 0.0}
                                 :type   {:type/Number {:min 25.775827
                                                        :q1  35.302705923023126
@@ -1704,105 +1704,105 @@
                                                        :max 70.6355001
                                                        :sd  6.390832341883712
                                                        :avg 39.87934670484002}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :password]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              nil
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              nil
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "PASSWORD"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :password)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   3
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Password"
-   :database_position          3
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Password"
+   :database-position          3
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2500, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 36.0}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :birth-date]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DATE"
-   :semantic_type              nil
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "DATE"
+   :semantic-type              nil
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "BIRTH_DATE"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Date
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Date
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :birth-date)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   9
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Birth Date"
-   :database_position          9
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Birth Date"
+   :database-position          9
+   :database-required          false
    :fingerprint
    {:global {:distinct-count 2308, :nil% 0.0}
     :type   {:type/DateTime {:earliest "1958-04-26", :latest "2000-04-03"}}}
-   :base_type                  :type/Date
-   :points_of_interest         nil
+   :base-type                  :type/Date
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :longitude]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "DOUBLE PRECISION"
-   :semantic_type              :type/Longitude
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "DOUBLE PRECISION"
+   :semantic-type              :type/Longitude
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "LONGITUDE"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Float
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Float
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :longitude)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   6
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Longitude"
-   :database_position          6
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Longitude"
+   :database-position          6
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2491, :nil% 0.0}
                                 :type   {:type/Number {:min -166.5425726
                                                        :q1  -101.58350792373135
@@ -1810,95 +1810,95 @@
                                                        :max -67.96735199999999
                                                        :sd  15.399698968175663
                                                        :avg -95.18741780363999}}}
-   :base_type                  :type/Float
-   :points_of_interest         nil
+   :base-type                  :type/Float
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :email]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              :type/Email
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              :type/Email
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "EMAIL"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :email)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   2
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Email"
-   :database_position          2
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Email"
+   :database-position          2
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2500, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  1.0
                                                      :percent-state  0.0
                                                      :average-length 24.1824}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:people :created-at]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "TIMESTAMP WITH TIME ZONE"
-   :semantic_type              :type/CreationTimestamp
-   :table_id                   (id :people)
-   :coercion_strategy          nil
+   :database-type              "TIMESTAMP WITH TIME ZONE"
+   :semantic-type              :type/CreationTimestamp
+   :table-id                   (id :people)
+   :coercion-strategy          nil
    :name                       "CREATED_AT"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/DateTimeWithLocalTZ
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/DateTimeWithLocalTZ
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :people :created-at)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   12
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Created At"
-   :database_position          12
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Created At"
+   :database-position          12
+   :database-required          false
    :fingerprint                {:global {:distinct-count 2499, :nil% 0.0}
                                 :type   {:type/DateTime {:earliest "2016-04-19T21:35:18.752Z"
                                                          :latest   "2019-04-19T14:06:27.3Z"}}}
-   :base_type                  :type/DateTimeWithLocalTZ
-   :points_of_interest         nil
+   :base-type                  :type/DateTimeWithLocalTZ
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod table-metadata :people
   [_table-name]
   {:description             nil
-   :entity_type             :entity/UserTable
+   :entity-type             :entity/UserTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "PEOPLE"
    :caveats                 nil
    :active                  true
    :id                      (id :people)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "People"
-   :points_of_interest      nil
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "People"
+   :points-of-interest      nil
    :lib/type                :metadata/table
    :fields                  [(field-metadata :people :id)
                              (field-metadata :people :state)
@@ -1917,93 +1917,93 @@
 (defmethod field-metadata [:reviews :id]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "BIGINT"
-   :semantic_type              :type/PK
-   :table_id                   (id :reviews)
-   :coercion_strategy          nil
+   :database-type              "BIGINT"
+   :semantic-type              :type/PK
+   :table-id                   (id :reviews)
+   :coercion-strategy          nil
    :name                       "ID"
-   :fingerprint_version        0
-   :has_field_values           nil
+   :fingerprint-version        0
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/BigInteger
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/BigInteger
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :reviews :id)
-   :database_is_auto_increment true
+   :database-is-auto-increment true
    :position                   0
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "ID"
-   :database_position          0
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "ID"
+   :database-position          0
+   :database-required          false
    :fingerprint                nil
-   :base_type                  :type/BigInteger
-   :points_of_interest         nil
+   :base-type                  :type/BigInteger
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:reviews :created-at]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "TIMESTAMP WITH TIME ZONE"
-   :semantic_type              :type/CreationTimestamp
-   :table_id                   (id :reviews)
-   :coercion_strategy          nil
+   :database-type              "TIMESTAMP WITH TIME ZONE"
+   :semantic-type              :type/CreationTimestamp
+   :table-id                   (id :reviews)
+   :coercion-strategy          nil
    :name                       "CREATED_AT"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/DateTimeWithLocalTZ
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/DateTimeWithLocalTZ
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :reviews :created-at)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   5
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Created At"
-   :database_position          5
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Created At"
+   :database-position          5
+   :database-required          false
    :fingerprint                {:global {:distinct-count 1112, :nil% 0.0}
                                 :type   {:type/DateTime {:earliest "2016-06-03T00:37:05.818Z"
                                                          :latest   "2020-04-19T14:15:25.677Z"}}}
-   :base_type                  :type/DateTimeWithLocalTZ
-   :points_of_interest         nil
+   :base-type                  :type/DateTimeWithLocalTZ
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:reviews :rating]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "INTEGER"
-   :semantic_type              :type/Score
-   :table_id                   (id :reviews)
-   :coercion_strategy          nil
+   :database-type              "INTEGER"
+   :semantic-type              :type/Score
+   :table-id                   (id :reviews)
+   :coercion-strategy          nil
    :name                       "RATING"
-   :fingerprint_version        5
-   :has_field_values           :auto-list
+   :fingerprint-version        5
+   :has-field-values           :auto-list
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Integer
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Integer
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :reviews :rating)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   3
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Rating"
-   :database_position          3
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Rating"
+   :database-position          3
+   :database-required          false
    :fingerprint                {:global {:distinct-count 5, :nil% 0.0}
                                 :type   {:type/Number {:min 1.0
                                                        :q1  3.54744353181696
@@ -2011,129 +2011,129 @@
                                                        :max 5.0
                                                        :sd  1.0443899855660577
                                                        :avg 3.987410071942446}}}
-   :base_type                  :type/Integer
-   :points_of_interest         nil
+   :base-type                  :type/Integer
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:reviews :reviewer]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              nil
-   :table_id                   (id :reviews)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              nil
+   :table-id                   (id :reviews)
+   :coercion-strategy          nil
    :name                       "REVIEWER"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :reviews :reviewer)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   2
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Reviewer"
-   :database_position          2
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Reviewer"
+   :database-position          2
+   :database-required          false
    :fingerprint                {:global {:distinct-count 1076, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.001798561151079137
                                                      :average-length 9.972122302158274}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:reviews :body]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "CHARACTER VARYING"
-   :semantic_type              nil
-   :table_id                   (id :reviews)
-   :coercion_strategy          nil
+   :database-type              "CHARACTER VARYING"
+   :semantic-type              nil
+   :table-id                   (id :reviews)
+   :coercion-strategy          nil
    :name                       "BODY"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         nil
-   :custom_position            0
-   :effective_type             :type/Text
+   :fk-target-field-id         nil
+   :custom-position            0
+   :effective-type             :type/Text
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :reviews :body)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   4
-   :visibility_type            :normal
-   :preview_display            false
-   :display_name               "Body"
-   :database_position          4
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            false
+   :display-name               "Body"
+   :database-position          4
+   :database-required          false
    :fingerprint                {:global {:distinct-count 1112, :nil% 0.0}
                                 :type   {:type/Text {:percent-json   0.0
                                                      :percent-url    0.0
                                                      :percent-email  0.0
                                                      :percent-state  0.0
                                                      :average-length 177.41996402877697}}}
-   :base_type                  :type/Text
-   :points_of_interest         nil
+   :base-type                  :type/Text
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod field-metadata [:reviews :product-id]
   [_table-name _field-name]
   {:description                nil
-   :database_type              "INTEGER"
-   :semantic_type              :type/FK
-   :table_id                   (id :reviews)
-   :coercion_strategy          nil
+   :database-type              "INTEGER"
+   :semantic-type              :type/FK
+   :table-id                   (id :reviews)
+   :coercion-strategy          nil
    :name                       "PRODUCT_ID"
-   :fingerprint_version        5
-   :has_field_values           nil
+   :fingerprint-version        5
+   :has-field-values           nil
    :settings                   nil
    :caveats                    nil
-   :fk_target_field_id         (id :products :id)
-   :custom_position            0
-   :effective_type             :type/Integer
+   :fk-target-field-id         (id :products :id)
+   :custom-position            0
+   :effective-type             :type/Integer
    :active                     true
-   :nfc_path                   nil
-   :parent_id                  nil
+   :nfc-path                   nil
+   :parent-id                  nil
    :id                         (id :reviews :product-id)
-   :database_is_auto_increment false
+   :database-is-auto-increment false
    :position                   1
-   :visibility_type            :normal
-   :preview_display            true
-   :display_name               "Product ID"
-   :database_position          1
-   :database_required          false
+   :visibility-type            :normal
+   :preview-display            true
+   :display-name               "Product ID"
+   :database-position          1
+   :database-required          false
    :fingerprint                {:global {:distinct-count 176, :nil% 0.0}}
-   :base_type                  :type/Integer
-   :points_of_interest         nil
+   :base-type                  :type/Integer
+   :points-of-interest         nil
    :lib/type                   :metadata/field})
 
 (defmethod table-metadata :reviews
   [_table-name]
   {:description             nil
-   :entity_type             :entity/GenericTable
+   :entity-type             :entity/GenericTable
    :schema                  "PUBLIC"
-   :show_in_getting_started false
+   :show-in-getting-started false
    :name                    "REVIEWS"
    :caveats                 nil
    :active                  true
    :id                      (id :reviews)
-   :db_id                   (id)
-   :visibility_type         nil
-   :field_order             :database
-   :initial_sync_status     "complete"
-   :display_name            "Reviews"
-   :points_of_interest      nil
+   :db-id                   (id)
+   :visibility-type         nil
+   :field-order             :database
+   :initial-sync-status     "complete"
+   :display-name            "Reviews"
+   :points-of-interest      nil
    :lib/type                :metadata/table
    :fields                  [(field-metadata :reviews :id)
                              (field-metadata :reviews :created-at)
@@ -2170,10 +2170,10 @@
                                   :right-join
                                   :standard-deviation-aggregations
                                   :temporal-extract}
-   :cache_field_values_schedule "0 50 0 * * ? *"
+   :cache-field-values-schedule "0 50 0 * * ? *"
    :timezone                    "UTC"
-   :auto_run_queries            true
-   :metadata_sync_schedule      "0 50 * * * ? *"
+   :auto-run-queries            true
+   :metadata-sync-schedule      "0 50 * * * ? *"
    :name                        "test-data"
    :settings                    nil
    :caveats                     nil
@@ -2185,27 +2185,108 @@
                                  (table-metadata :orders)
                                  (table-metadata :people)
                                  (table-metadata :reviews)]
-   :creator_id                  nil
-   :is_full_sync                true
-   :cache_ttl                   nil
-   :is_sample                   false
+   :creator-id                  nil
+   :is-full-sync                true
+   :cache-ttl                   nil
+   :is-sample                   false
    :id                          (id)
-   :is_on_demand                false
+   :is-on-demand                false
    :options                     nil
    :engine                      :h2
-   :initial_sync_status         "complete"
-   :dbms_version                {:flavor "H2", :version "2.1.212 (2022-04-09)", :semantic-version [2 1]}
+   :initial-sync-status         "complete"
+   :dbms-version                {:flavor "H2", :version "2.1.212 (2022-04-09)", :semantic-version [2 1]}
    :refingerprint               nil
-   :points_of_interest          nil
+   :points-of-interest          nil
    :lib/type                    :metadata/database})
 
 (def metadata-provider
   "[[metabase.lib.metadata.protocols/MetadataProvider]] using the test [[metadata]]."
   (meta.graph-provider/->SimpleGraphMetadataProvider metadata))
 
-(def results-metadata
+(def card-results-metadata
+  "Capture of the `result_metadata` saved with a Card with a `SELECT * FROM VENUES;` query. Actually this is a little
+  different because this is pre-massaged into the MLv2 shape (it has `:lib/type` and uses `kebab-case` keys), to make
+  it easier to use in tests. It should not make a difference because transformation to the MLv2 shape is idempotent...
+  and at some point we'll probably update the backend to store stuff in this shape anyway."
+  [{:lib/type       :metadata/field
+    :display-name   "ID"
+    :name           "ID"
+    :base-type      :type/BigInteger
+    :effective-type :type/BigInteger
+    :semantic-type  :type/PK
+    :fingerprint    nil}
+   {:lib/type       :metadata/field
+    :display-name   "NAME"              ; TODO -- these display names are icky
+    :name           "NAME"
+    :base-type      :type/Text
+    :effective-type :type/Text
+    :semantic-type  :type/Name
+    :fingerprint    {:global {:distinct-count 100, :nil% 0.0}
+                     :type   {:type/Text {:percent-json   0.0
+                                          :percent-url    0.0
+                                          :percent-email  0.0
+                                          :percent-state  0.0
+                                          :average-length 15.63}}}}
+   {:lib/type       :metadata/field
+    :display-name   "CATEGORY_ID"
+    :name           "CATEGORY_ID"
+    :base-type      :type/Integer
+    :effective-type :type/Integer
+    :semantic-type  nil
+    :fingerprint    {:global {:distinct-count 28, :nil% 0.0}
+                     :type   {:type/Number
+                              {:min 2.0
+                               :q1  6.89564392373896
+                               :q3  49.240253073352044
+                               :max 74.0
+                               :sd  23.058108414099443
+                               :avg 29.98}}}}
+   {:lib/type       :metadata/field
+    :display-name   "LATITUDE"
+    :name           "LATITUDE"
+    :base-type      :type/Float
+    :effective-type :type/Float
+    :semantic-type  :type/Latitude
+    :fingerprint
+    {:global {:distinct-count 94, :nil% 0.0}
+     :type   {:type/Number {:min 10.0646
+                            :q1  34.06098873016278
+                            :q3  37.77185
+                            :max 40.7794
+                            :sd  3.4346725397190827
+                            :avg 35.505891999999996}}}}
+   {:lib/type       :metadata/field
+    :display-name   "LONGITUDE"
+    :name           "LONGITUDE"
+    :base-type      :type/Float
+    :effective-type :type/Float
+    :semantic-type  :type/Longitude
+    :fingerprint    {:global {:distinct-count 84, :nil% 0.0}
+                     :type   {:type/Number
+                              {:min -165.374
+                               :q1  -122.40857106781186
+                               :q3  -118.2635
+                               :max -73.9533
+                               :sd  14.162810671348238
+                               :avg -115.99848699999998}}}}
+   {:lib/type       :metadata/field
+    :display-name   "PRICE"
+    :name           "PRICE"
+    :base-type      :type/Integer
+    :effective-type :type/Integer
+    :semantic-type  nil
+    :fingerprint    {:global {:distinct-count 4, :nil% 0.0}
+                     :type   {:type/Number
+                              {:min 1.0
+                               :q1  1.4591129021415095
+                               :q3  2.493086095768049
+                               :max 4.0
+                               :sd  0.7713951678941896
+                               :avg 2.03}}}}])
+
+(def qp-results-metadata
   "Capture of the `data.results_metadata` that would come back when running `SELECT * FROM VENUES;` with the Query
-  Processor, or saved as `Card.result_metadata` for a Saved Question.
+  Processor.
 
   IRL queries actually come back with both `data.cols` and `data.results_metadata.columns`, which are slightly
   different from one another; the frontend merges these together into one unified metadata map. This is both icky and
@@ -2214,86 +2295,13 @@
   add it to `data.results_metadata.columns` in QP results, and add it here as well, so we can start moving toward a
   world where we don't have two versions of the metadata in query responses."
   {:lib/type :metadata/results
-   :columns  [{:lib/type       :metadata/field
-               :display_name   "ID"
-               :name           "ID"
-               :base_type      :type/BigInteger
-               :effective_type :type/BigInteger
-               :semantic_type  :type/PK
-               :fingerprint    nil}
-              {:lib/type       :metadata/field
-               :display_name   "NAME" ; TODO -- these display names are icky
-               :name           "NAME"
-               :base_type      :type/Text
-               :effective_type :type/Text
-               :semantic_type  :type/Name
-               :fingerprint    {:global {:distinct-count 100, :nil% 0.0}
-                                :type   {:type/Text {:percent-json   0.0
-                                                     :percent-url    0.0
-                                                     :percent-email  0.0
-                                                     :percent-state  0.0
-                                                     :average-length 15.63}}}}
-              {:lib/type       :metadata/field
-               :display_name   "CATEGORY_ID"
-               :name           "CATEGORY_ID"
-               :base_type      :type/Integer
-               :effective_type :type/Integer
-               :semantic_type  nil
-               :fingerprint    {:global {:distinct-count 28, :nil% 0.0}
-                                :type   {:type/Number
-                                         {:min 2.0
-                                          :q1  6.89564392373896
-                                          :q3  49.240253073352044
-                                          :max 74.0
-                                          :sd  23.058108414099443
-                                          :avg 29.98}}}}
-              {:lib/type       :metadata/field
-               :display_name   "LATITUDE"
-               :name           "LATITUDE"
-               :base_type      :type/Float
-               :effective_type :type/Float
-               :semantic_type  :type/Latitude
-               :fingerprint
-               {:global {:distinct-count 94, :nil% 0.0}
-                :type   {:type/Number {:min 10.0646
-                                       :q1  34.06098873016278
-                                       :q3  37.77185
-                                       :max 40.7794
-                                       :sd  3.4346725397190827
-                                       :avg 35.505891999999996}}}}
-              {:lib/type       :metadata/field
-               :display_name   "LONGITUDE"
-               :name           "LONGITUDE"
-               :base_type      :type/Float
-               :effective_type :type/Float
-               :semantic_type  :type/Longitude
-               :fingerprint    {:global {:distinct-count 84, :nil% 0.0}
-                                :type   {:type/Number
-                                         {:min -165.374
-                                          :q1  -122.40857106781186
-                                          :q3  -118.2635
-                                          :max -73.9533
-                                          :sd  14.162810671348238
-                                          :avg -115.99848699999998}}}}
-              {:lib/type       :metadata/field
-               :display_name   "PRICE"
-               :name           "PRICE"
-               :base_type      :type/Integer
-               :effective_type :type/Integer
-               :semantic_type  nil
-               :fingerprint    {:global {:distinct-count 4, :nil% 0.0}
-                                :type   {:type/Number
-                                         {:min 1.0
-                                          :q1  1.4591129021415095
-                                          :q3  2.493086095768049
-                                          :max 4.0
-                                          :sd  0.7713951678941896
-                                          :avg 2.03}}}}]})
+   :columns  card-results-metadata})
 
 (def saved-question
   "An representative Saved Question, with [[results-metadata]]. For testing queries that use a Saved Question as their
-  source."
-  {:dataset_query   {:database (id)
+  source. If you added `:lib/type`, `:id`, and `:name`, you could also use this as
+  a [[metabase.lib.metadata/CardMetadata]]."
+  {:dataset-query   {:database (id)
                      :type     :query
                      :query    {:source-table (id :venues)}}
-   :result_metadata results-metadata})
+   :result-metadata card-results-metadata})
diff --git a/test/metabase/lib/test_util.cljc b/test/metabase/lib/test_util.cljc
index e4950e87f21..6d284f5a570 100644
--- a/test/metabase/lib/test_util.cljc
+++ b/test/metabase/lib/test_util.cljc
@@ -33,7 +33,7 @@
    (field-clause table field nil))
   ([table field options]
    [:field
-    (merge {:base-type (:base_type (meta/field-metadata table field))
+    (merge {:base-type (:base-type (meta/field-metadata table field))
             :lib/uuid  (str (random-uuid))}
            options)
     (meta/id table field)]))
@@ -97,15 +97,15 @@
 (deftest ^:parallel composed-metadata-provider-test
   (testing "Return things preferentially from earlier metadata providers"
     (let [time-field        (assoc (meta/field-metadata :people :birth-date)
-                                   :base_type      :type/Time
-                                   :effective_type :type/Time)
+                                   :base-type      :type/Time
+                                   :effective-type :type/Time)
           metadata-provider (composed-metadata-provider
                              (mock-metadata-provider
                               {:fields [time-field]})
                              meta/metadata-provider)]
       (is (=? {:name           "BIRTH_DATE"
-               :base_type      :type/Time
-               :effective_type :type/Time}
+               :base-type      :type/Time
+               :effective-type :type/Time}
               (lib.metadata/field
                metadata-provider
                (meta/id :people :birth-date)))))))
@@ -117,7 +117,7 @@
    (mock-metadata-provider
     {:cards [{:name          "My Card"
               :id            1
-              :dataset_query {:database (meta/id)
+              :dataset-query {:database (meta/id)
                               :type     :query
                               :query    {:source-table (meta/id :checkins)
                                          :aggregation  [[:count]]
@@ -140,13 +140,15 @@
    (mock-metadata-provider
     {:cards [{:name            "My Card"
               :id              1
-              :dataset_query   {:database (meta/id)
+              ;; THIS IS A LEGACY STYLE QUERY!
+              :dataset-query   {:database (meta/id)
                                 :type     :query
                                 :query    {:source-table (meta/id :checkins)
                                            :aggregation  [[:count]]
                                            :breakout     [[:field (meta/id :checkins :user-id) nil]]}}
-              ;; this is copied directly from a QP response
-              :result_metadata [{:description       nil
+              ;; this is copied directly from a QP response. NOT CONVERTED TO KEBAB-CASE YET, BECAUSE THIS IS HOW IT
+              ;; LOOKS IN LEGACY QUERIES!
+              :result-metadata [{:description       nil
                                  :semantic_type     :type/FK
                                  :table_id          (meta/id :checkins)
                                  :coercion_strategy nil
@@ -208,12 +210,12 @@
                    :lib/stage-metadata {:lib/type :metadata/results
                                         :columns  [{:lib/type      :metadata/field
                                                     :name          "abc"
-                                                    :display_name  "another Field"
-                                                    :base_type     :type/Integer
-                                                    :semantic_type :type/FK}
+                                                    :display-name  "another Field"
+                                                    :base-type     :type/Integer
+                                                    :semantic-type :type/FK}
                                                    {:lib/type      :metadata/field
                                                     :name          "sum"
-                                                    :display_name  "sum of User ID"
-                                                    :base_type     :type/Integer
-                                                    :semantic_type :type/FK}]}
+                                                    :display-name  "sum of User ID"
+                                                    :base-type     :type/Integer
+                                                    :semantic-type :type/FK}]}
                    :native             "SELECT whatever"}]})
diff --git a/test/metabase/lib/types/isa_test.cljc b/test/metabase/lib/types/isa_test.cljc
index 8d464a52cff..46170e71487 100644
--- a/test/metabase/lib/types/isa_test.cljc
+++ b/test/metabase/lib/types/isa_test.cljc
@@ -12,19 +12,19 @@
       :type/* :Relation/* :Semantic/* :type/Text :type/Address))
   (testing "effective type passes"
     (is (lib.types.isa/isa?
-         {:effective_type :type/Text, :semantic_type :type/Address}
+         {:effective-type :type/Text, :semantic-type :type/Address}
          :type/Text)))
   (testing "semantic type passes"
     (is (lib.types.isa/isa?
-         {:effective_type :type/Number, :semantic_type :type/ZipCode}
+         {:effective-type :type/Number, :semantic-type :type/ZipCode}
          :type/Text)))
   (testing "both effective type and semantic type pass"
     (is (lib.types.isa/isa?
-         {:effective_type :type/Text, :semantic_type :type/City}
+         {:effective-type :type/Text, :semantic-type :type/City}
          :type/Text)))
   (testing "none of effective type and semantic type passes"
     (is (not (lib.types.isa/isa?
-              {:effective_type :type/Number, :semantic_type :type/IPAddress}
+              {:effective-type :type/Number, :semantic-type :type/IPAddress}
               :type/Text)))))
 
 (deftest ^:parallel column-isa-test
@@ -35,71 +35,71 @@
       (testing "effective type"
         (is (=? [{:name "NAME"
                   :lib/desired-column-alias "NAME"
-                  :semantic_type :type/Name
-                  :effective_type :type/Text}
+                  :semantic-type :type/Name
+                  :effective-type :type/Text}
                  {:name "NAME"
                   :lib/desired-column-alias "CATEGORIES__via__CATEGORY_ID__NAME"
-                  :semantic_type :type/Name
-                  :effective_type :type/Text}]
+                  :semantic-type :type/Name
+                  :effective-type :type/Text}]
                 (columns-of-type :type/Text))))
       (testing "semantic type"
         (is (=? [{:name "ID"
                   :lib/desired-column-alias "ID"
-                  :semantic_type :type/PK
-                  :effective_type :type/BigInteger}
+                  :semantic-type :type/PK
+                  :effective-type :type/BigInteger}
                  {:name "CATEGORY_ID"
                   :lib/desired-column-alias "CATEGORY_ID"
-                  :semantic_type :type/FK
-                  :effective_type :type/Integer}
+                  :semantic-type :type/FK
+                  :effective-type :type/Integer}
                  {:name "ID"
                   :lib/desired-column-alias "CATEGORIES__via__CATEGORY_ID__ID"
-                  :semantic_type :type/PK
-                  :effective_type :type/BigInteger}]
+                  :semantic-type :type/PK
+                  :effective-type :type/BigInteger}]
                 (columns-of-type :Relation/*))))))
 
 (deftest ^:parallel field-type-test
   (testing "temporal"
-    (are [typ] (= ::lib.types.constants/temporal (lib.types.isa/field-type {:effective_type typ}))
+    (are [typ] (= ::lib.types.constants/temporal (lib.types.isa/field-type {:effective-type typ}))
       :type/Date :type/DateTime :type/Time))
   (testing "numeric"
-    (are [typ] (= ::lib.types.constants/number (lib.types.isa/field-type {:effective_type typ}))
+    (are [typ] (= ::lib.types.constants/number (lib.types.isa/field-type {:effective-type typ}))
       :type/BigInteger :type/Integer :type/Float :type/Decimal))
   (testing "string"
-    (is (= ::lib.types.constants/string (lib.types.isa/field-type {:effective_type :type/Text}))))
+    (is (= ::lib.types.constants/string (lib.types.isa/field-type {:effective-type :type/Text}))))
   (testing "types of string"
-    (are [typ] (= ::lib.types.constants/string (lib.types.isa/field-type {:effective_type :type/Text
-                                                                          :semantic_type typ}))
+    (are [typ] (= ::lib.types.constants/string (lib.types.isa/field-type {:effective-type :type/Text
+                                                                          :semantic-type typ}))
       :type/Name :type/Description :type/UUID :type/URL))
   (testing "primary key"
-    (is (= ::lib.types.constants/primary_key (lib.types.isa/field-type {:effective_type :type/Integer
-                                                                        :semantic_type :type/PK}))))
+    (is (= ::lib.types.constants/primary_key (lib.types.isa/field-type {:effective-type :type/Integer
+                                                                        :semantic-type :type/PK}))))
   (testing "foreign key"
-    (is (= ::lib.types.constants/foreign_key (lib.types.isa/field-type {:effective_type :type/Integer
-                                                                        :semantic_type :type/FK}))))
+    (is (= ::lib.types.constants/foreign_key (lib.types.isa/field-type {:effective-type :type/Integer
+                                                                        :semantic-type :type/FK}))))
   (testing "boolean"
-    (is (= ::lib.types.constants/boolean (lib.types.isa/field-type {:effective_type :type/Boolean}))))
+    (is (= ::lib.types.constants/boolean (lib.types.isa/field-type {:effective-type :type/Boolean}))))
   (testing "location"
-    (are [typ] (= ::lib.types.constants/location (lib.types.isa/field-type {:semantic_type typ}))
+    (are [typ] (= ::lib.types.constants/location (lib.types.isa/field-type {:semantic-type typ}))
       :type/City :type/Country))
   (testing "coordinate"
-    (are [typ] (= ::lib.types.constants/coordinate (lib.types.isa/field-type {:semantic_type typ}))
+    (are [typ] (= ::lib.types.constants/coordinate (lib.types.isa/field-type {:semantic-type typ}))
       :type/Latitude :type/Longitude))
   (testing "string like"
-    (are [typ] (= ::lib.types.constants/string_like (lib.types.isa/field-type {:effective_type typ}))
+    (are [typ] (= ::lib.types.constants/string_like (lib.types.isa/field-type {:effective-type typ}))
       :type/TextLike :type/IPAddress))
   (testing "strings, regardless of the effective type is"
-    (are [typ] (= ::lib.types.constants/string (lib.types.isa/field-type {:effective_type :type/Float
-                                                                          :semantic_type typ}))
+    (are [typ] (= ::lib.types.constants/string (lib.types.isa/field-type {:effective-type :type/Float
+                                                                          :semantic-type typ}))
       :type/Name :type/Category)))
   (testing "boolean, regardless of the semantic type"
-    (is (= ::lib.types.constants/boolean (lib.types.isa/field-type {:effective_type :type/Boolean
-                                                  :semantic_type :type/Category}))))
+    (is (= ::lib.types.constants/boolean (lib.types.isa/field-type {:effective-type :type/Boolean
+                                                  :semantic-type :type/Category}))))
   (testing "unexpected things"
     (are [column] (nil? (lib.types.isa/field-type column))
-      {:effective_type "DERP DERP DERP"}
-      {:semantic_type "DERP DERP DERP"}
-      {:effective_type nil}
-      {:semantic_type nil}
+      {:effective-type "DERP DERP DERP"}
+      {:semantic-type "DERP DERP DERP"}
+      {:effective-type nil}
+      {:semantic-type nil}
       "DERP DERP DERP"
       :type/Category
       nil))
@@ -108,9 +108,9 @@
   (letfn [(column [x]
             (cond
               (map? x)             x
-              (isa? x :Semantic/*) {:semantic_type x}
-              (isa? x :Relation/*) {:semantic_type x}
-              :else                {:effective_type x}))]
+              (isa? x :Semantic/*) {:semantic-type x}
+              (isa? x :Relation/*) {:semantic-type x}
+              :else                {:effective-type x}))]
     (doseq [{:keys [nom pred positive negative]}
             [{:nom "date?", :pred lib.types.isa/date?
               :positive :type/DateTime, :negative :type/City}
@@ -190,21 +190,21 @@
 
 (deftest ^:parallel has-latitude-and-longitude?-test
   (is (true? (lib.types.isa/has-latitude-and-longitude?
-              [{:semantic_type :type/Latitude} {:semantic_type :type/Longitude}])))
+              [{:semantic-type :type/Latitude} {:semantic-type :type/Longitude}])))
   (are [columns] (false? (lib.types.isa/has-latitude-and-longitude?
                           columns))
-    [{:semantic_type :type/Latitude}]
-    [{:semantic_type :type/Longitude}]
-    [{:semantic_type :type/Longitude} {:semantic_type :type/Address}]
+    [{:semantic-type :type/Latitude}]
+    [{:semantic-type :type/Longitude}]
+    [{:semantic-type :type/Longitude} {:semantic-type :type/Address}]
     []
     nil))
 
 (deftest ^:parallel primary-key-pred-test
   (let [integer-table-id 1
-        columns [{:semantic_type :type/PK, :table-id (inc integer-table-id), :name "column0"}
-                 {:semantic_type :type/PK, :name "column1"}
-                 {:semantic_type :type/PK, :table-id integer-table-id, :name "column2"}
-                 {:semantic_type :type/Address, :name "column3"}]]
+        columns [{:semantic-type :type/PK, :table-id (inc integer-table-id), :name "column0"}
+                 {:semantic-type :type/PK, :name "column1"}
+                 {:semantic-type :type/PK, :table-id integer-table-id, :name "column2"}
+                 {:semantic-type :type/Address, :name "column3"}]]
     (testing "with integer table-id :table-id has to match"
       (let [primary-key? (lib.types.isa/primary-key-pred integer-table-id)]
         (is (= ["column2"]
diff --git a/test/metabase/util_test.cljc b/test/metabase/util_test.cljc
index 074c97dacd2..a782ada2dc1 100644
--- a/test/metabase/util_test.cljc
+++ b/test/metabase/util_test.cljc
@@ -227,19 +227,44 @@
     {}  nil
     nil nil))
 
-;; TODO Can we achieve something like with-locale in CLJS?
+(deftest ^:parallel lower-case-en-test
+  (is (= "id"
+         (u/lower-case-en "ID"))))
+
 #?(:clj
-   (deftest lower-case-en-test
+   (deftest lower-case-en-turkish-test
+     ;; TODO Can we achieve something like with-locale in CLJS?
      (mt/with-locale "tr"
        (is (= "id"
               (u/lower-case-en "ID"))))))
 
+(deftest ^:parallel upper-case-en-test
+  (is (= "ID"
+         (u/upper-case-en "id"))))
+
 #?(:clj
-   (deftest upper-case-en-test
+   (deftest upper-case-en-turkish-test
      (mt/with-locale "tr"
        (is (= "ID"
               (u/upper-case-en "id"))))))
 
+(deftest ^:parallel capitalize-en-test
+  (are [s expected] (= expected
+                       (u/capitalize-en s))
+    nil    nil
+    ""     ""
+    "ibis" "Ibis"
+    "IBIS" "Ibis"
+    "Ibis" "Ibis"))
+
+#?(:clj
+   (deftest capitalize-en-turkish-test
+     (mt/with-locale "tr"
+       (is (= "Ibis"
+              (u/capitalize-en "ibis")
+              (u/capitalize-en "IBIS")
+              (u/capitalize-en "Ibis"))))))
+
 (deftest ^:parallel parse-currency-test
   (are [s expected] (= expected
                        (u/parse-currency s))
@@ -290,7 +315,7 @@
                              (= x m)
                              (= ys (concat non-pos rest))))))))
 
-(deftest normalize-map-test
+(deftest ^:parallel normalize-map-test
   (testing "nil and empty maps return empty maps"
     (is (= {} (u/normalize-map nil)))
     (is (= {} (u/normalize-map {}))))
@@ -306,6 +331,12 @@
        (testing "JS objects get turned into Clojure maps"
          (is (= exp (u/normalize-map #js {"kebab-key" 1 "snake_key" 2 "camelKey" 3})))))))
 
+#?(:clj
+   (deftest normalize-map-turkish-test
+     (mt/with-locale "tr"
+       (is (= {:bird "Toucan"}
+              (u/normalize-map {:BIRD "Toucan"}))))))
+
 (deftest ^:parallel or-with-test
   (testing "empty case"
     (is (= nil (u/or-with identity))))
-- 
GitLab