fix(sqlite): write midnight as a bare date for DATE columns in time filters - #44805
danielalyoshin wants to merge 3 commits into
Conversation
…ilters SqliteEngineSpec.convert_dttm returned None for DATE columns, so Superset fell back to a literal such as '2026-09-20 00:00:00.000000'. SQLite compares a DATE stored as 'YYYY-MM-DD' text as text, so a range from 09-20 to 09-22 returned 09-21 and 09-22. Midnight is now written as a bare date and other times keep their time part, the same as the D1 spec. Shillelagh and the Superset meta database inherit the change. The meta database used to drop such a DATE filter, because shillelagh cannot read a date with a time part, so whole-day ranges now apply there too.
|
The flagged issue is correct. The current implementation in To resolve this, you should ensure that non-midnight times for Regarding other comments on this PR, I have checked the available review comments and there are no additional comments to address at this time. superset/db_engine_specs/sqlite.py |
There was a problem hiding this comment.
Code Review Agent Run #63f777
Actionable Suggestions - 1
-
superset/db_engine_specs/sqlite.py - 1
- Midnight branch catches DateTime · Line 177-177
Review Details
-
Files reviewed - 4 · Commit Range:
a7d5a5c..a7d5a5c- superset/db_engine_specs/sqlite.py
- tests/unit_tests/db_engine_specs/test_shillelagh.py
- tests/unit_tests/db_engine_specs/test_sqlite.py
- tests/unit_tests/extensions/test_sqlalchemy.py
-
Files skipped - 0
-
Tools
- MyPy (Static Code Analysis) - ✔︎ Successful
- Astral Ruff (Static Code Analysis) - ✔︎ Successful
- Whispers (Secret Scanner) - ✔︎ Successful
- Detect-secrets (Secret Scanner) - ✔︎ Successful
Bito Usage Guide
Commands
Type the following command in the pull request comment and save the comment.
-
/review- Manually triggers an incremental AI Review. -
/review full- Manually triggers a full AI Review. -
/pause- Pauses automatic reviews on this pull request. -
/resume- Resumes automatic reviews. -
/resolve- Marks all Bito-posted review comments as resolved. -
/abort- Cancels all in-progress reviews.
Refer to the documentation for additional commands.
Configuration
This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.
Documentation & Help
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #44805 +/- ##
=======================================
Coverage 81.58% 81.59%
=======================================
Files 2977 2977
Lines 180845 180837 -8
Branches 41853 41852 -1
=======================================
- Hits 147550 147548 -2
+ Misses 30572 30568 -4
+ Partials 2723 2721 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Shillelagh drops a date filter with a time part without an error, so on the meta database a DATE bound other than midnight returned every row. ShillelaghEngineSpec now always writes a bare date for DATE columns, as the GSheets spec did, so the GSheets override is removed. The D1 override did the same as the SQLite one and is removed too. The SQLite range test builds its filter with get_time_filter, with and without a day grain, for SQLite and D1, and replaces the copy in test_d1.py. The meta database test covers a bound with a time part. UPDATING.md notes that DATE columns on SQLite no longer use the Datetime format.
# Conflicts: # UPDATING.md
Code Review Agent Run #db372eActionable Suggestions - 0Additional Suggestions - 1
Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
aminghadersohi
left a comment
There was a problem hiding this comment.
The gsheets.py conflict with #44695 is the datetime import line only: keeping master's line, the merged tree passes the engine-spec tests with unchanged convert_dttm output. I checked the python_date_format trade-off and agree with it; only the UPDATING note should say what breaks.
| one day late on `DATE` columns holding `YYYY-MM-DD` text. A `DATE` column that | ||
| holds values in another format, such as `20260920`, `09/20/2026` or epoch | ||
| seconds, is no longer filtered correctly. Columns declared as `INTEGER` are not | ||
| affected. |
There was a problem hiding this comment.
Measured on SQLite: with Datetime format %Y%m%d, %m/%d/%Y or epoch_s, a two-day range on a DATE column returns 2 rows on master and 0 here, which is what an operator can spot. The Shillelagh cut of non-midnight bounds isn't noted either.
| one day late on `DATE` columns holding `YYYY-MM-DD` text. A `DATE` column that | |
| holds values in another format, such as `20260920`, `09/20/2026` or epoch | |
| seconds, is no longer filtered correctly. Columns declared as `INTEGER` are not | |
| affected. | |
| one day late on `DATE` columns holding `YYYY-MM-DD` text. A `DATE` column that | |
| holds values in another format, such as `20260920`, `09/20/2026` or epoch | |
| seconds, now matches no rows, even with a Datetime format set. Columns declared | |
| as `INTEGER` are not affected. On Shillelagh and the meta database, a bound | |
| with a time of day is cut to its date. |
SUMMARY
SqliteEngineSpec.convert_dttmonly handlesStringandDateTimecolumns and returnsNoneforDate. Superset then falls back to a literal such as'2026-09-20 00:00:00.000000'. SQLite has no date type, so aDATEcolumn usually holds text such as2026-09-20, and that literal sorts after the day it starts. A time range on aDATEcolumn therefore starts and ends one day late: 2026-09-20 to 2026-09-22 returns 09-21 and 09-22 instead of 09-20 and 09-21.This PR writes midnight as a bare date for
DATEcolumns, the same fix #44505 made for D1, and close to what #43355 did for Google Sheets. A time other than midnight keeps its time part ('2026-09-20 12:00:00'), which sorts between two days, so each day counts as its midnight, as in a comparison of dates.DATETIME,TIMESTAMPand text columns are unchanged.Specs that inherit
convert_dttmfromSqliteEngineSpec:ShillelaghEngineSpecandSupersetEngineSpec(the meta database) always write a bare date for aDATEcolumn, asGSheetsEngineSpecdid. Shillelagh reads a date filter withdate.fromisoformat, which rejects a time part and drops the filter without an error, so on the meta database a filter on aDATEcolumn was dropped and every row came back. A bound with a time part is cut to its date there.GSheetsEngineSpecgets the same behavior fromShillelaghEngineSpec, andCloudflareD1EngineSpecdid the same as the new SQLite code, so both overrides are removed. Neither changes behavior.One behavior change to be aware of, also noted in
UPDATING.md: for aDATEcolumn the literal now comes from the engine spec, so the column's Datetime format (python_date_format) is no longer used in its time filters. SQLite already works this way forTEXTandDATETIMEcolumns, and #44505 and #43355 did the same for D1 and Google Sheets. ADATEcolumn that holds another format, such as20260920(%Y%m%d),09/20/2026(%m/%d/%Y) or epoch seconds (epoch_s), got the right rows before and gets none now. Columns declared asINTEGERare not affected. Letting a set Datetime format win over the engine spec would fix this for every database, so I plan to do that in a follow-up PR.Not in this PR: with a dataset timezone (
extra.timezone),get_time_filtermoves the bounds off midnight, so a range on aDATEcolumn is still one day off. That happens on master too, and on Postgres as well, so it will get its own PR.Tests:
test_sqlite.py:convert_dttmforDATEat midnight and at other times, and a range test on an in-memory SQLite. It builds the filter withget_time_filter, as a chart query does, with and without a day grain, for SQLite and D1. It replaces the copy intest_d1.py.test_shillelagh.py:convert_dttmforDATEonShillelaghEngineSpecandSupersetEngineSpec.extensions/test_sqlalchemy.py: a range test on aDATEcolumn through the meta database, at midnight and at noon.On master the midnight cases of the SQLite range test return 09-21 and 09-22, and both cases of the meta database test return all four days.
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Rows returned with the time filter a chart query builds, for a table holding 2026-09-19 to 2026-09-22:
DATE, 09-20 to 09-22DATE, 09-20 12:00 to 09-22 12:00DATETIME, 09-20 to 09-22DATEon the meta database, 09-20 to 09-22DATEon the meta database, 09-20 12:00 to 09-22 12:00DATEholding20260920, format%Y%m%d, 09-20 to 09-22DATEholding09/20/2026, format%m/%d/%Y, 09-20 to 09-22DATEholding epoch seconds, formatepoch_s, 09-20 to 09-22TESTING INSTRUCTIONS
Unit tests:
By hand:
CREATE TABLE t (day DATE); INSERT INTO t VALUES ('2026-09-19'), ('2026-09-20'), ('2026-09-21'), ('2026-09-22');and connect it to Superset (SQLite needsPREVENT_UNSAFE_DB_CONNECTIONS = False).tand a table chart ondaywith a custom time range from 2026-09-20 to 2026-09-22.ADDITIONAL INFORMATION