Skip to content

Time grain creates invalid DB2 SQL statements #35792

Closed

Description

@phlppnhllngr

Bug description

Description:
After updating from 4.1.1 to 5.0.0, time grain can no longer be selected in charts when using DB2, as doing so creates invalid SQL statements.

Steps to reproduce:

  1. Create chart, e. g. "Big Number with trendline"
  2. Select a column of DB2-type TIMESTAMP as "Temporal X-Axis"
  3. Select Time Grain = Day
  4. Run "Update chart"

Result:
Error "Unable to parse SQL: Error parsing near "-" at line ...

Screenshot of Bug:
Image

Stacktrace:
2025-10-22 09:55:32,981:WARNING:superset.views.error_handling:SupersetErrorException
Traceback (most recent call last):
File "/app/superset/sql/parse.py", line 267, in _parse
return sqlglot.parse(script, dialect=dialect)
File "/app/.venv/lib/python3.10/site-packages/sqlglot/init.py", line 102, in parse
return Dialect.get_or_raise(read or dialect).parse(sql, **opts)
File "/app/.venv/lib/python3.10/site-packages/sqlglot/dialects/dialect.py", line 991, in parse
return self.parser(**opts).parse(self.tokenize(sql), sql)
File "/app/.venv/lib/python3.10/site-packages/sqlglot/parser.py", line 1507, in parse
return self._parse(
File "/app/.venv/lib/python3.10/site-packages/sqlglot/parser.py", line 1579, in _parse
self.raise_error("Invalid expression / Unexpected token")
File "/app/.venv/lib/python3.10/site-packages/sqlglot/parser.py", line 1620, in raise_error
raise error
sqlglot.errors.ParseError: Invalid expression / Unexpected token. Line 1, Col: 69.
SELECT CAST(kw_split_time as TIMESTAMP) - HOUR(kw_split_time) HOURS - MINUTE(kw_split_time) MINUTES - SECOND(kw_split_time) SECONDS - MICROSECOND(kw_split_time) MICROSEC
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/app/.venv/lib/python3.10/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
File "/app/.venv/lib/python3.10/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/app/.venv/lib/python3.10/site-packages/flask_appbuilder/security/decorators.py", line 109, in wraps
return f(self, *args, **kwargs)
File "/app/superset/views/base_api.py", line 120, in wraps
duration, response = time_function(f, self, *args, **kwargs)
File "/app/superset/utils/core.py", line 1369, in time_function
response = func(*args, **kwargs)
File "/app/superset/utils/log.py", line 304, in wrapper
value = f(*args, **kwargs)
File "/app/superset/charts/data/api.py", line 260, in data
return self._get_data_response(
File "/app/superset/utils/log.py", line 304, in wrapper
value = f(*args, **kwargs)
File "/app/superset/charts/data/api.py", line 423, in _get_data_response
result = command.run(force_cached=force_cached)
File "/app/superset/commands/chart/data/get_data_command.py", line 45, in run
payload = self._query_context.get_payload(
File "/app/superset/common/query_context.py", line 102, in get_payload
return self._processor.get_payload(cache_query_context, force_cached)
File "/app/superset/common/query_context_processor.py", line 752, in get_payload
query_results = [
File "/app/superset/common/query_context_processor.py", line 753, in
get_query_results(
File "/app/superset/common/query_actions.py", line 227, in get_query_results
return result_func(query_context, query_obj, force_cached)
File "/app/superset/common/query_actions.py", line 189, in _get_results
payload = _get_full(query_context, query_obj, force_cached)
File "/app/superset/common/query_actions.py", line 103, in _get_full
payload = query_context.get_df_payload(query_obj, force_cached=force_cached)
File "/app/superset/common/query_context.py", line 123, in get_df_payload
return self.processor.get_df_payload(
File "/app/superset/common/query_context_processor.py", line 162, in get_df_payload
query_result = self.get_query_result(query_obj)
File "/app/superset/common/query_context_processor.py", line 265, in get_query_result
result = query_context.datasource.query(query_object.to_dict())
File "/app/superset/connectors/sqla/models.py", line 1748, in query
df = self.database.get_df(
File "/app/superset/models/core.py", line 706, in get_df
self.db_engine_spec.execute(cursor, sql
, self)
File "/app/superset/db_engine_specs/base.py", line 1858, in execute
if sql_parse.check_sql_functions_exist(query, disallowed_functions, cls.engine):
File "/app/superset/sql_parse.py", line 183, in check_sql_functions_exist
return SQLScript(sql, engine=engine).check_functions_present(function_list)
File "/app/superset/sql/parse.py", line 670, in init
self.statements = statement_class.split_script(script, engine)
File "/app/superset/sql/parse.py", line 327, in split_script
ast = cls._parse(remainder, engine)[0]
File "/app/superset/sql/parse.py", line 270, in _parse
raise SupersetParseError(
superset.exceptions.SupersetParseError: Error parsing near '-' at line 1:69

Screenshots/recordings

No response

Superset version

5.0.0

Python version

3.9

Node version

16

Browser

Chrome

Additional context

Linux DB2 (LUW)

Checklist

  • I have searched Superset docs and Slack and didn't find a solution to my problem.
  • I have searched the GitHub issue tracker and didn't find a similar bug report.
  • I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Activity

  1. dosubot commented on Oct 22, 2025

    @dosubot

    Hi @phlppnhllngr! I'm Dosu and I’m helping the superset team.

    This issue is caused by the way Superset's DB2 engine spec generates SQL for time grains: it uses expressions like CAST({col} as TIMESTAMP) - HOUR({col}) HOURS - MINUTE({col}) MINUTES ..., which is not valid DB2 syntax and leads to SQL parse errors when selecting a time grain such as "Day" in charts. This logic has not changed between 4.1.1 and 5.0.0, so it's not a new regression but a pre-existing bug that may be more visible in 5.0.0 due to stricter error handling. There is currently no official fix or workaround documented, and resolving this would require updating the DB2 time grain expressions in the engine spec to produce valid DB2 SQL. For now, avoiding time grain selection or customizing the engine spec code are the only options if you need this functionality to work correctly.
    Reference: DB2 engine spec code

    To reply, just mention @dosu.


    How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

  2. rusackas commented on Oct 27, 2025

    @rusackas
    Member

    Is this still the case in 6.0 or on master? We've been moving more toward SQL Glot, which may or may not affect things. If this is still the case with the db engine spec (likely the case) then we're open to contributions here... none of us (that I'm aware of) at Preset or working on Superset actively use DB2, so we could use some help on this one.

  3. phlppnhllngr commented on Oct 28, 2025

    @phlppnhllngr
    Author

    @rusackas I just downloaded and ran the most recent docker image from Dockerhub:
    https://hub.docker.com/layers/apache/superset/GHA-dev-18856474396/images/sha256-93f46124d410394985d8c96656a6e56f17eff7bbf5cfe394366d79f70880426f
    I assume it is created from the master branch...? superset version outputs "0.0.0-dev".
    The bug exists in this version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions