diff --git a/project.clj b/project.clj
index 081323525e42a5f63a4214cd420743ca5136c830..890036e7ce1db63406caa74476e69293c882a488 100644
--- a/project.clj
+++ b/project.clj
@@ -59,7 +59,8 @@
          :init metabase.core/init}
   :eastwood {:exclude-namespaces [:test-paths]
              :add-linters [:unused-private-vars]
-             :exclude-linters [:constant-test]}                       ; korma macros generate some formats with if statements that are always logically true or false
+             :exclude-linters [:constant-test                         ; korma macros generate some forms with if statements that are always logically true or false
+                               :suspicious-expression]}               ; core.match macros generate some forms like (and expr) which is "suspicious"
   :profiles {:dev {:dependencies [[org.clojure/tools.nrepl "0.2.10"]  ; REPL <3
                                   [expectations "2.1.1"]              ; unit tests
                                   [marginalia "0.8.0"]                ; for documentation
diff --git a/src/metabase/db.clj b/src/metabase/db.clj
index ae11a585774a130afad090ceead26aef30c05521..399d83338af19c1d15d376a98d4aa9378f04abb3 100644
--- a/src/metabase/db.clj
+++ b/src/metabase/db.clj
@@ -186,7 +186,8 @@
     (sel :one User :id 1)          -> returns the User (or nil) whose id is 1
     (sel :many OrgPerm :user_id 1) -> returns sequence of OrgPerms whose user_id is 1
 
-  OPTION, if specified, is one of `:field`, `:fields`, `:id`, `:id->field`, `:field->id`, `:field->obj`, or `:id->fields`.
+  OPTION, if specified, is one of `:field`, `:fields`, `:id`, `:id->field`, `:field->id`, `:field->obj`, `:id->fields`,
+  `:field->field`, or `:field->fields`.
 
     ;; Only return IDs of objects.
     (sel :one :id User :email \"cam@metabase.com\") -> 120
@@ -215,6 +216,11 @@
       -> {\"venues\" {:id 1, :name \"venues\", ...}
           \"users\"  {:id 2, :name \"users\", ...}}
 
+    ;; Return a map of field value -> other fields.
+    (sel :many :field->fields [Table :name :id :db_id])
+      -> {\"venues\" {:id 1, :db_id 1}
+          \"users\"  {:id 2, :db_id 1}}
+
     ;; Return a map of ID -> specified fields
     (sel :many :id->fields [User :first_name :last_name])
       -> {1 {:first_name \"Cam\", :last_name \"Saul\"},
diff --git a/src/metabase/db/internal.clj b/src/metabase/db/internal.clj
index fb7c7fc0c9eaab058a55e69f9336624f0bf3255b..8f8cfe6e1f4331f2d4203561244b83b70f39f05c 100644
--- a/src/metabase/db/internal.clj
+++ b/src/metabase/db/internal.clj
@@ -137,6 +137,17 @@
          f2# ~f2]
      (sel:field->field* f1# f2# (sel* [~entity f1# f2#] ~@forms))))
 
+;;; :field->fields
+
+(defn sel:field->fields* [key-field other-fields results]
+  (into {} (for [result results]
+             {(key-field result) (select-keys result other-fields)})))
+
+(defmacro sel:field->fields [[entity key-field & other-fields] & forms]
+  `(let [key-field# ~key-field
+         other-fields# ~(vec other-fields)]
+     (sel:field->fields* key-field# other-fields# (sel* `[~~entity ~key-field# ~@other-fields#] ~@forms))))
+
 ;;; : id->field
 
 (defmacro sel:id->field [[entity field] & forms]
diff --git a/src/metabase/driver.clj b/src/metabase/driver.clj
index 9f8e32701a5f62b31b3163284c863fa12e08b7b5..b00dc02355638ae0d3c06384581e38f3e52ab4bb 100644
--- a/src/metabase/driver.clj
+++ b/src/metabase/driver.clj
@@ -32,22 +32,26 @@
               :name    "MongoDB"
               :example "mongodb://password:username@127.0.0.1:27017/db-name"}})
 
-(def ^:const class->base-type
-  "Map of classes returned from DB call to metabase.models.field/base-types"
-  {clojure.lang.PersistentArrayMap :DictionaryField ; are there other map types we need to account for ?
-   Boolean                         :BooleanField
-   Double                          :FloatField
-   Float                           :FloatField
-   Integer                         :IntegerField
-   Long                            :IntegerField
-   String                          :TextField
-   java.math.BigDecimal            :DecimalField
-   java.math.BigInteger            :BigIntegerField
-   java.sql.Date                   :DateField
-   java.sql.Timestamp              :DateTimeField
-   java.util.Date                  :DateField
-   java.util.UUID                  :TextField
-   org.postgresql.util.PGobject    :UnknownField}) ; this mapping included here since Native QP uses class->base-type directly. TODO - perhaps make *class-base->type* driver specific?
+(defn class->base-type
+  "Return the `Field.base_type` that corresponds to a given class returned by the DB."
+  [klass]
+  (or ({Boolean                         :BooleanField
+        Double                          :FloatField
+        Float                           :FloatField
+        Integer                         :IntegerField
+        Long                            :IntegerField
+        String                          :TextField
+        java.math.BigDecimal            :DecimalField
+        java.math.BigInteger            :BigIntegerField
+        java.sql.Date                   :DateField
+        java.sql.Timestamp              :DateTimeField
+        java.util.Date                  :DateField
+        java.util.UUID                  :TextField
+        org.postgresql.util.PGobject    :UnknownField} klass)
+      (cond
+        (isa? klass clojure.lang.IPersistentMap) :DictionaryField)
+      (do (log/warn (format "Don't know how to map class '%s' to a Field base_type, falling back to :UnknownField." klass))
+          :UnknownField)))
 
 ;; ## Driver Lookup
 
diff --git a/src/metabase/driver/generic_sql/native.clj b/src/metabase/driver/generic_sql/native.clj
index cd36f36f5b5609b8b9d9e17cb73f1a77c898a8d5..146fcb203b1f2852ef0dc49fb0c28495285e94c8 100644
--- a/src/metabase/driver/generic_sql/native.clj
+++ b/src/metabase/driver/generic_sql/native.clj
@@ -13,11 +13,7 @@
 (defn- value->base-type
   "Attempt to match a value we get back from the DB with the corresponding base-type`."
   [v]
-  (if-not v :UnknownField
-          (or (driver/class->base-type (type v))
-              (do (log/warn (format "Missing base type mapping for %s in driver/class->base-type. Please add an entry."
-                                    (str (type v))))
-                  :UnknownField))))
+  (driver/class->base-type (type v)))
 
 (defn process-and-run
   "Process and run a native (raw SQL) QUERY."
diff --git a/src/metabase/driver/mongo.clj b/src/metabase/driver/mongo.clj
index 52c4421a158b16d62457ccca63870e97685ebd58..826c97fe99ff016f4c6ca9f25000d027be3980e1 100644
--- a/src/metabase/driver/mongo.clj
+++ b/src/metabase/driver/mongo.clj
@@ -132,8 +132,7 @@
                               (sort-by second)                  ; source by count
                               last                              ; take last item (highest count)
                               first                             ; keep just the type
-                              (#(or (driver/class->base-type %) ; convert to corresponding Field base_type if possible
-                                    :UnknownField)))))))))      ; fall back to :UnknownField for things like clojure.lang.PersistentVector
+                              driver/class->base-type)))))))    ; get corresponding Field base_type
 
 (def driver
   "Concrete instance of the MongoDB driver."
diff --git a/src/metabase/driver/mongo/query_processor.clj b/src/metabase/driver/mongo/query_processor.clj
index 76b42e2694bf0288177e2b0a3b44f06b75050115..e663381ffc262be87ae4746029644b7b7edc9643 100644
--- a/src/metabase/driver/mongo/query_processor.clj
+++ b/src/metabase/driver/mongo/query_processor.clj
@@ -213,9 +213,9 @@
    is present, this is essentialy a separate implementation :/"
   [{aggregation :aggregation, breakout-fields :breakout, order-by :order-by, limit :limit, :as query}]
   (let [;; Shadow the top-level definition of field->name with one that will use "___" as the separator instead of "."
-        field->name          (u/rpartial field->name "___")
+        field->escaped-name  (u/rpartial field->name "___")
         [ag-field ag-clause] (breakout-aggregation->field-name+expression aggregation)
-        fields               (map field->name breakout-fields)
+        fields               (map field->escaped-name breakout-fields)
         $fields              (map field->$str breakout-fields)
         fields->$fields      (zipmap fields $fields)]
     `(ag-unescape-nested-field-names
@@ -228,7 +228,7 @@
                                                {field {$first $field}}))))}
                   {$sort    (->> order-by
                                  (mapcat (fn [{:keys [field direction]}]
-                                           [(field->name field) (case direction
+                                           [(field->escaped-name field) (case direction
                                                                   :ascending   1
                                                                   :descending -1)]))
                                  (apply sorted-map))}
diff --git a/src/metabase/driver/mongo/util.clj b/src/metabase/driver/mongo/util.clj
index 1c3ef7ce9f7e2ed7358d8a5085eff5317eb48b80..595d7ed94bd8db733d2e68bf4641152ae5257eeb 100644
--- a/src/metabase/driver/mongo/util.clj
+++ b/src/metabase/driver/mongo/util.clj
@@ -90,12 +90,11 @@
            ;; nil)
            (take 1000)
            (group-by type)
-           ;; create tuples like [Integer -count]. Make count negative so when we call (sort-by second) in the next step the rows
-           ;; with the highest count will be returned first (e.g. [Integer -100] will be sorted ahead of [Float -20])
+           ;; create tuples like [Integer count].
            (map (fn [[klass valus]]
-                  [klass (- 0 (count valus))]))
+                  [klass (count valus)]))
            (sort-by second)
-           first
-           first
-           driver/class->base-type)
+           last                     ; last result will be tuple with highest count
+           first                    ; keep just the type
+           driver/class->base-type) ; convert to Field base_type
       :UnknownField))
diff --git a/src/metabase/driver/sync.clj b/src/metabase/driver/sync.clj
index 8b142b48f3d711625317af142aa63970902e5e79..311a4f0c4b45efe9996630d795b42a45bc618894 100644
--- a/src/metabase/driver/sync.clj
+++ b/src/metabase/driver/sync.clj
@@ -151,8 +151,8 @@
   (let [database @(:db table)]
     ;; Now do the syncing for Table's Fields
     (log/debug (format "Determining active Fields for Table '%s'..." (:name table)))
-    (let [active-column-names->type (active-column-names->type driver table)
-          existing-field-name->id   (sel :many :field->id [Field :name], :table_id (:id table), :active true, :parent_id nil)]
+    (let [active-column-names->type  (active-column-names->type driver table)
+          existing-field-name->field (sel :many :field->fields [Field :name :base_type :id], :table_id (:id table), :active true, :parent_id nil)]
 
       (assert (map? active-column-names->type) "active-column-names->type should return a map.")
       (assert (every? string? (keys active-column-names->type)) "The keys of active-column-names->type should be strings.")
@@ -160,20 +160,27 @@
 
       ;; As above, first mark inactive Fields
       (let [active-column-names (set (keys active-column-names->type))]
-        (doseq [[field-name field-id] existing-field-name->id]
+        (doseq [[field-name {field-id :id}] existing-field-name->field]
           (when-not (contains? active-column-names field-name)
             (upd Field field-id :active false)
             (log/info (u/format-color 'cyan "Marked field '%s.%s' as inactive." (:name table) field-name)))))
 
-      ;; Next, create new Fields as needed
-      (let [existing-field-names (set (keys existing-field-name->id))]
+      ;; Create new Fields, update existing types if needed
+      (let [existing-field-names (set (keys existing-field-name->field))]
         (doseq [[active-field-name active-field-type] active-column-names->type]
-          (when-not (contains? existing-field-names active-field-name)
-            (log/info (u/format-color 'blue "Found new field: '%s.%s'" (:name table) active-field-name))
-            (ins Field
-              :table_id  (:id table)
-              :name      active-field-name
-              :base_type active-field-type))))
+          ;; If Field doesn't exist create it
+          (if-not (contains? existing-field-names active-field-name)
+            (do (log/info (u/format-color 'blue "Found new field: '%s.%s'" (:name table) active-field-name))
+                (ins Field
+                  :table_id  (:id table)
+                  :name      active-field-name
+                  :base_type active-field-type))
+            ;; Otherwise update the Field type if needed
+            (let [{existing-base-type :base_type, existing-field-id :id} (existing-field-name->field active-field-name)]
+              (when-not (= active-field-type existing-base-type)
+                (log/info (u/format-color 'blue "Field '%s.%s' has changed from a %s to a %s." (:name table) active-field-name existing-base-type active-field-type))
+                (upd Field existing-field-id :base_type active-field-type))))))
+      ;; TODO - we need to add functionality to update nested Field base types as well!
 
       ;; Now mark PK fields as such if needed
       (let [pk-fields (table-pks driver table)]