rusackas commented on code in PR #43167:
URL: https://github.com/apache/superset/pull/43167#discussion_r3943101734


##########
superset/db_engine_specs/postgres.py:
##########
@@ -267,17 +267,32 @@ def get_timestamp_expr(
         time_grain: str | None,
     ) -> TimestampExpression:
         """
-        Construct a timestamp expression while preserving pure ``DATE`` 
semantics.
+        Construct a timestamp expression for Postgres temporal columns.
 
         Applying ``DATE_TRUNC`` to a ``DATE`` column implicitly casts the 
value to
         ``TIMESTAMP``, which can trigger unwanted timezone conversion on the 
client
         and shift the displayed date by a day. To avoid this, the truncated 
value is
         cast back to ``DATE`` when the source column is a pure ``DATE`` type.
 
+        String columns explicitly marked as temporal are cast to ``TIMESTAMP`` 
before
+        applying a time grain because Postgres does not implicitly cast 
strings for
+        ``DATE_TRUNC`` or ``EXTRACT``.
+
         See https://github.com/apache/superset/issues/42254.
+        See https://github.com/apache/superset/issues/42386.
         """
         expr = super().get_timestamp_expr(col, pdf, time_grain)
         col_type = getattr(col, "type", None)
+        if (
+            time_grain
+            and isinstance(col_type, String)
+            and pdf not in ("epoch_s", "epoch_ms")
+        ):

Review Comment:
   I think this one's pre-existing rather than something this PR introduces. 
The base spec already emits `event_timestamp * interval '1 second'` for a 
string epoch column, so the exclusion here just keeps it from getting wrapped 
in a second bad cast. Happy to see it handled in a follow-up, but I wouldn't 
block on it.



##########
tests/unit_tests/db_engine_specs/test_postgres.py:
##########
@@ -418,6 +418,40 @@ def test_get_timestamp_expr_datetime_column_not_cast() -> 
None:
     assert _compile(expr) == "DATE_TRUNC('day', event_ts)"
 
 
+def test_get_timestamp_expr_string_column_casts_to_timestamp() -> None:
+    """DB Eng Specs (postgres): temporal string columns are cast before 
truncation."""
+    col = column("event_timestamp", type_=types.String())
+    expr = spec.get_timestamp_expr(col, None, "P1D")
+    assert _compile(expr) == "DATE_TRUNC('day', CAST(event_timestamp AS 
TIMESTAMP))"
+
+
+def test_get_timestamp_expr_string_column_without_grain_not_cast() -> None:
+    """DB Eng Specs (postgres): strings without a time grain remain 
unchanged."""
+    col = column("event_timestamp", type_=types.String())
+    expr = spec.get_timestamp_expr(col, None, None)
+    assert _compile(expr) == "event_timestamp"
+
+
+def test_get_timestamp_expr_epoch_string_column_not_cast() -> None:
+    """DB Eng Specs (postgres): epoch conversion handles strings before 
truncation."""
+    col = column("event_timestamp", type_=types.String())

Review Comment:
   Agreed, the docstring oversells this a bit. The test is really just pinning 
that the new CAST wrapper stays out of the epoch path, so maybe say that 
instead.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to