From c0fac6daea51ead6d99b8d798b3e03f554246de4 Mon Sep 17 00:00:00 2001
From: Robert Roland <rob@metabase.com>
Date: Mon, 13 Jul 2020 11:13:06 -0700
Subject: [PATCH] Add support for TIMESTAMP columns in SQLite (#12886)

TIMESTAMP columns will now map to :type/DateTime instead of attempted
parsing them as times.

Resolves #12045

[ci sqlite]
---
 .../sqlite/src/metabase/driver/sqlite.clj     | 33 ++++++------
 .../test/metabase/driver/sqlite_test.clj      | 52 ++++++++++++++++---
 2 files changed, 63 insertions(+), 22 deletions(-)

diff --git a/modules/drivers/sqlite/src/metabase/driver/sqlite.clj b/modules/drivers/sqlite/src/metabase/driver/sqlite.clj
index 4461b594edc..dd32d9edf23 100644
--- a/modules/drivers/sqlite/src/metabase/driver/sqlite.clj
+++ b/modules/drivers/sqlite/src/metabase/driver/sqlite.clj
@@ -56,22 +56,23 @@
 ;; e.g. NVARCHAR(100) or NUMERIC(10,5) See also http://www.sqlite.org/datatype3.html
 (def ^:private database-type->base-type
   (sql-jdbc.sync/pattern-based-database-type->base-type
-   [[#"BIGINT"   :type/BigInteger]
-    [#"BIG INT"  :type/BigInteger]
-    [#"INT"      :type/Integer]
-    [#"CHAR"     :type/Text]
-    [#"TEXT"     :type/Text]
-    [#"CLOB"     :type/Text]
-    [#"BLOB"     :type/*]
-    [#"REAL"     :type/Float]
-    [#"DOUB"     :type/Float]
-    [#"FLOA"     :type/Float]
-    [#"NUMERIC"  :type/Float]
-    [#"DECIMAL"  :type/Decimal]
-    [#"BOOLEAN"  :type/Boolean]
-    [#"DATETIME" :type/DateTime]
-    [#"DATE"     :type/Date]
-    [#"TIME"     :type/Time]]))
+   [[#"BIGINT"    :type/BigInteger]
+    [#"BIG INT"   :type/BigInteger]
+    [#"INT"       :type/Integer]
+    [#"CHAR"      :type/Text]
+    [#"TEXT"      :type/Text]
+    [#"CLOB"      :type/Text]
+    [#"BLOB"      :type/*]
+    [#"REAL"      :type/Float]
+    [#"DOUB"      :type/Float]
+    [#"FLOA"      :type/Float]
+    [#"NUMERIC"   :type/Float]
+    [#"DECIMAL"   :type/Decimal]
+    [#"BOOLEAN"   :type/Boolean]
+    [#"TIMESTAMP" :type/DateTime]
+    [#"DATETIME"  :type/DateTime]
+    [#"DATE"      :type/Date]
+    [#"TIME"      :type/Time]]))
 
 (defmethod sql-jdbc.sync/database-type->base-type :sqlite
   [_ database-type]
diff --git a/modules/drivers/sqlite/test/metabase/driver/sqlite_test.clj b/modules/drivers/sqlite/test/metabase/driver/sqlite_test.clj
index 33284517ea4..d5873c3e6be 100644
--- a/modules/drivers/sqlite/test/metabase/driver/sqlite_test.clj
+++ b/modules/drivers/sqlite/test/metabase/driver/sqlite_test.clj
@@ -1,19 +1,27 @@
 (ns metabase.driver.sqlite-test
-  (:require [clojure.test :refer :all]
-            [metabase.query-processor-test :as qp.test]
+  (:require [clojure.java.jdbc :as jdbc]
+            [clojure.test :refer :all]
+            [metabase
+             [driver :as driver]
+             [query-processor-test :as qp.test]
+             [sync :as sync]
+             [test :as mt]]
+            [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn]
+            [metabase.models
+             [database :refer [Database]]
+             [table :refer [Table]]]
             [metabase.test
              [data :as data]
-             [util :as tu]]
-            [metabase.test.data.datasets :as datasets]))
+             [util :as tu]]))
 
 (deftest timezone-id-test
-  (datasets/test-driver :sqlite
+  (mt/test-driver :sqlite
     (is (= "UTC"
            (tu/db-timezone-id)))))
 
 (deftest filter-by-date-test
   "Make sure filtering against a LocalDate works correctly in SQLite"
-  (datasets/test-driver :sqlite
+  (mt/test-driver :sqlite
     (is (= [[225 "2014-03-04T00:00:00Z"]
             [409 "2014-03-05T00:00:00Z"]
             [917 "2014-03-05T00:00:00Z"]
@@ -32,3 +40,35 @@
                {:fields   [$id $date]
                 :filter   [:between $date "2014-03-04" "2014-03-07"]
                 :order-by [[:asc $date]]}))))))
+
+(defn- default-table-result [table-name]
+  {:name table-name
+   :schema nil
+   :description nil})
+
+(deftest timestamp-test-db
+  (let [driver :sqlite]
+    (mt/test-driver driver
+      (let [db-name "timestamp_test"
+            details (mt/dbdef->connection-details :sqlite :db {:database-name db-name})]
+        (doseq [stmt ["DROP TABLE IF EXISTS timestamp_table;"
+                      "CREATE TABLE timestamp_table (created_at timestamp);"
+                      "INSERT INTO timestamp_table (created_at) VALUES (datetime('now'));"]]
+          (jdbc/execute! (sql-jdbc.conn/connection-details->spec driver details)
+                         [stmt]))
+        (mt/with-temp Database [db {:engine driver :details (assoc details :dbname db-name)}]
+          (sync/sync-database! db)
+          (mt/with-db db
+            (testing "timestamp columns"
+              (testing "database should be synced"
+                (is (= {:tables (set (map default-table-result ["timestamp_table"]))}
+                       (driver/describe-database driver db))))
+
+              (testing "timestamp column should exist"
+                (is (= {:name "timestamp_table"
+                        :schema nil
+                        :fields #{{:name "created_at"
+                                   :database-type "TIMESTAMP"
+                                   :base-type :type/DateTime
+                                   :database-position 0}}}
+                       (driver/describe-table driver db (Table (mt/id :timestamp_table)))))))))))))
-- 
GitLab