From 7b62e4e7a61ca04760d5114110a6fa624114d575 Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Wed, 16 Mar 2022 10:34:15 +0800
Subject: [PATCH 1/7] fix: time filter should be [start, end)

---
 superset/connectors/sqla/models.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py
index 9cc2f8a78136b..4a68e666bdac8 100644
--- a/superset/connectors/sqla/models.py
+++ b/superset/connectors/sqla/models.py
@@ -308,7 +308,7 @@ def get_time_filter(
         if start_dttm:
             l.append(col >= self.table.text(self.dttm_sql_literal(start_dttm)))
         if end_dttm:
-            l.append(col <= self.table.text(self.dttm_sql_literal(end_dttm)))
+            l.append(col < self.table.text(self.dttm_sql_literal(end_dttm)))
         return and_(*l)
 
     def get_timestamp_expression(

From d023a7e3ac9e18442b7f1179140aa8c9e561c844 Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Wed, 16 Mar 2022 16:28:08 +0800
Subject: [PATCH 2/7] add ut

---
 tests/integration_tests/sqla_models_tests.py | 49 ++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/tests/integration_tests/sqla_models_tests.py b/tests/integration_tests/sqla_models_tests.py
index 14480f10bcc69..3570a22c6aa2f 100644
--- a/tests/integration_tests/sqla_models_tests.py
+++ b/tests/integration_tests/sqla_models_tests.py
@@ -41,6 +41,7 @@
     FilterOperator,
     GenericDataType,
     TemporalType,
+    backend,
 )
 from superset.utils.database import get_example_database
 from tests.integration_tests.fixtures.birth_names_dashboard import (
@@ -605,6 +606,54 @@ def test_filter_on_text_column(text_column_table):
     assert result_object.df["count"][0] == 1
 
 
+def test_should_generate_closed_and_open_time_filter_range():
+    with app.app_context():
+        if backend() in ["sqlite", "mysql"]:
+            pytest.skip(f"{backend()} has different dialect for datetime column")
+
+        table = SqlaTable(
+            table_name="temporal_column_table",
+            sql=("SELECT '2022-03-10'::timestamp as datetime_col"),
+            database=get_example_database(),
+        )
+        TableColumn(
+            column_name="datetime_col", type="TIMESTAMP", table=table, is_dttm=True,
+        )
+        SqlMetric(metric_name="count", expression="count(*)", table=table)
+        result_object = table.query(
+            {
+                "metrics": ["count"],
+                "is_timeseries": True,
+                "filter": [],
+                "from_dttm": datetime(2022, 1, 1),
+                "to_dttm": datetime(2023, 1, 1),
+                "granularity": "datetime_col",
+            }
+        )
+        """ >>> result_object.query
+            SELECT datetime_col AS __timestamp,
+                   count(*) AS count
+            FROM
+              (SELECT '2022-03-10' as datetime_col) AS virtual_table
+            WHERE datetime_col >= '2022-01-01 00:00:00.000000'
+              AND datetime_col < '2023-01-01 00:00:00.000000'
+            GROUP BY datetime_col
+        """
+        unformat_sql = result_object.query.replace("\n", " ")
+        unformat_sql = re.sub(r"(\s){2,}", " ", unformat_sql)
+        assert (
+            "WHERE "
+            "datetime_col "
+            ">= "
+            "TO_TIMESTAMP('2022-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US') "
+            "AND "
+            "datetime_col < "
+            "TO_TIMESTAMP('2023-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')"
+            in unformat_sql
+        )
+        assert result_object.df.iloc[0]["count"] == 1
+
+
 @pytest.mark.parametrize(
     "row,dimension,result",
     [

From 1c9224a5275f3329c3e13fc978fd4aaba9b7f85f Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Wed, 16 Mar 2022 16:31:32 +0800
Subject: [PATCH 3/7] minor fix

---
 tests/integration_tests/sqla_models_tests.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/integration_tests/sqla_models_tests.py b/tests/integration_tests/sqla_models_tests.py
index 3570a22c6aa2f..7f2f8d67ba26e 100644
--- a/tests/integration_tests/sqla_models_tests.py
+++ b/tests/integration_tests/sqla_models_tests.py
@@ -608,7 +608,7 @@ def test_filter_on_text_column(text_column_table):
 
 def test_should_generate_closed_and_open_time_filter_range():
     with app.app_context():
-        if backend() in ["sqlite", "mysql"]:
+        if backend() != "postgresql":
             pytest.skip(f"{backend()} has different dialect for datetime column")
 
         table = SqlaTable(

From aae7e270983e4bf24f8315ff0f0a10fce551d140 Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Wed, 16 Mar 2022 16:33:13 +0800
Subject: [PATCH 4/7] minor fix

---
 tests/integration_tests/sqla_models_tests.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/integration_tests/sqla_models_tests.py b/tests/integration_tests/sqla_models_tests.py
index 7f2f8d67ba26e..5d5b37a5d21ca 100644
--- a/tests/integration_tests/sqla_models_tests.py
+++ b/tests/integration_tests/sqla_models_tests.py
@@ -647,7 +647,8 @@ def test_should_generate_closed_and_open_time_filter_range():
             ">= "
             "TO_TIMESTAMP('2022-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US') "
             "AND "
-            "datetime_col < "
+            "datetime_col "
+            "< "
             "TO_TIMESTAMP('2023-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')"
             in unformat_sql
         )

From 5c97116dbebd3ed0efaaf17bd15ede34c06a39c7 Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Wed, 16 Mar 2022 16:36:40 +0800
Subject: [PATCH 5/7] minor fix

---
 tests/integration_tests/sqla_models_tests.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tests/integration_tests/sqla_models_tests.py b/tests/integration_tests/sqla_models_tests.py
index 5d5b37a5d21ca..94134b07dc90c 100644
--- a/tests/integration_tests/sqla_models_tests.py
+++ b/tests/integration_tests/sqla_models_tests.py
@@ -631,13 +631,13 @@ def test_should_generate_closed_and_open_time_filter_range():
             }
         )
         """ >>> result_object.query
-            SELECT datetime_col AS __timestamp,
-                   count(*) AS count
-            FROM
-              (SELECT '2022-03-10' as datetime_col) AS virtual_table
-            WHERE datetime_col >= '2022-01-01 00:00:00.000000'
-              AND datetime_col < '2023-01-01 00:00:00.000000'
-            GROUP BY datetime_col
+                SELECT datetime_col AS __timestamp,
+                       count(*) AS count
+                FROM
+                  (SELECT '2022-03-10'::timestamp as datetime_col) AS virtual_table
+                WHERE datetime_col >= TO_TIMESTAMP('2022-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')
+                  AND datetime_col < TO_TIMESTAMP('2023-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')
+                GROUP BY datetime_col
         """
         unformat_sql = result_object.query.replace("\n", " ")
         unformat_sql = re.sub(r"(\s){2,}", " ", unformat_sql)

From b74937b071ded2ef27b6c5fac931a324a059fa02 Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Wed, 16 Mar 2022 16:46:10 +0800
Subject: [PATCH 6/7] minor fix

---
 tests/integration_tests/sqla_models_tests.py | 27 ++++++--------------
 1 file changed, 8 insertions(+), 19 deletions(-)

diff --git a/tests/integration_tests/sqla_models_tests.py b/tests/integration_tests/sqla_models_tests.py
index 94134b07dc90c..995616bab676e 100644
--- a/tests/integration_tests/sqla_models_tests.py
+++ b/tests/integration_tests/sqla_models_tests.py
@@ -613,7 +613,10 @@ def test_should_generate_closed_and_open_time_filter_range():
 
         table = SqlaTable(
             table_name="temporal_column_table",
-            sql=("SELECT '2022-03-10'::timestamp as datetime_col"),
+            sql=(
+                "SELECT '2022-01-01'::timestamp as datetime_col"
+                " UNION SELECT '2023-01-01'::timestamp"
+            ),
             database=get_example_database(),
         )
         TableColumn(
@@ -623,7 +626,7 @@ def test_should_generate_closed_and_open_time_filter_range():
         result_object = table.query(
             {
                 "metrics": ["count"],
-                "is_timeseries": True,
+                "is_timeseries": False,
                 "filter": [],
                 "from_dttm": datetime(2022, 1, 1),
                 "to_dttm": datetime(2023, 1, 1),
@@ -631,27 +634,13 @@ def test_should_generate_closed_and_open_time_filter_range():
             }
         )
         """ >>> result_object.query
-                SELECT datetime_col AS __timestamp,
-                       count(*) AS count
+                SELECT count(*) AS count
                 FROM
-                  (SELECT '2022-03-10'::timestamp as datetime_col) AS virtual_table
+                  (SELECT '2022-01-01'::timestamp as datetime_col
+                   UNION SELECT '2023-01-01'::timestamp) AS virtual_table
                 WHERE datetime_col >= TO_TIMESTAMP('2022-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')
                   AND datetime_col < TO_TIMESTAMP('2023-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')
-                GROUP BY datetime_col
         """
-        unformat_sql = result_object.query.replace("\n", " ")
-        unformat_sql = re.sub(r"(\s){2,}", " ", unformat_sql)
-        assert (
-            "WHERE "
-            "datetime_col "
-            ">= "
-            "TO_TIMESTAMP('2022-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US') "
-            "AND "
-            "datetime_col "
-            "< "
-            "TO_TIMESTAMP('2023-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')"
-            in unformat_sql
-        )
         assert result_object.df.iloc[0]["count"] == 1
 
 

From 1d719be6d4e03f6d2ad9cb2959883e3b5627bac8 Mon Sep 17 00:00:00 2001
From: Yongjie Zhao <yongjie.zhao@gmail.com>
Date: Thu, 17 Mar 2022 09:32:23 +0800
Subject: [PATCH 7/7] more accurate ut

---
 tests/integration_tests/sqla_models_tests.py | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/tests/integration_tests/sqla_models_tests.py b/tests/integration_tests/sqla_models_tests.py
index 995616bab676e..54779fcbbff9b 100644
--- a/tests/integration_tests/sqla_models_tests.py
+++ b/tests/integration_tests/sqla_models_tests.py
@@ -614,8 +614,11 @@ def test_should_generate_closed_and_open_time_filter_range():
         table = SqlaTable(
             table_name="temporal_column_table",
             sql=(
-                "SELECT '2022-01-01'::timestamp as datetime_col"
-                " UNION SELECT '2023-01-01'::timestamp"
+                "SELECT '2021-12-31'::timestamp as datetime_col "
+                "UNION SELECT '2022-01-01'::timestamp "
+                "UNION SELECT '2022-03-10'::timestamp "
+                "UNION SELECT '2023-01-01'::timestamp "
+                "UNION SELECT '2023-03-10'::timestamp "
             ),
             database=get_example_database(),
         )
@@ -636,12 +639,15 @@ def test_should_generate_closed_and_open_time_filter_range():
         """ >>> result_object.query
                 SELECT count(*) AS count
                 FROM
-                  (SELECT '2022-01-01'::timestamp as datetime_col
-                   UNION SELECT '2023-01-01'::timestamp) AS virtual_table
+                  (SELECT '2021-12-31'::timestamp as datetime_col
+                   UNION SELECT '2022-01-01'::timestamp
+                   UNION SELECT '2022-03-10'::timestamp
+                   UNION SELECT '2023-01-01'::timestamp
+                   UNION SELECT '2023-03-10'::timestamp) AS virtual_table
                 WHERE datetime_col >= TO_TIMESTAMP('2022-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')
                   AND datetime_col < TO_TIMESTAMP('2023-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US')
         """
-        assert result_object.df.iloc[0]["count"] == 1
+        assert result_object.df.iloc[0]["count"] == 2
 
 
 @pytest.mark.parametrize(