-
Notifications
You must be signed in to change notification settings - Fork 13.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(elasticsearch): time_zone setting does not work for cast datetime expressions #17048
Changes from 6 commits
1c21505
a97af18
356dbe3
2e36740
71ed931
82ed2cd
e2d6109
a54147f
5e43a5c
d96aec6
cca6a6f
6441f4d
aa600a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,8 @@ | |
# specific language governing permissions and limitations | ||
# under the License. | ||
from datetime import datetime | ||
from typing import Dict, Optional, Type | ||
from distutils.version import StrictVersion | ||
from typing import Any, Dict, Optional, Type | ||
|
||
from superset.db_engine_specs.base import BaseEngineSpec | ||
from superset.db_engine_specs.exceptions import ( | ||
|
@@ -59,9 +60,23 @@ def get_dbapi_exception_mapping(cls) -> Dict[Type[Exception], Type[Exception]]: | |
} | ||
|
||
@classmethod | ||
def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: | ||
def convert_dttm( | ||
cls, target_type: str, dttm: datetime, **kwargs: Any | ||
) -> Optional[str]: | ||
|
||
if target_type.upper() == utils.TemporalType.DATETIME: | ||
es_version = kwargs.get("version") | ||
# The elasticsearch CAST function does not take effect for the time zone | ||
# setting. In elasticsearch7.8 and above, we can use the DATETIME_PARSE | ||
# function to solve this problem. | ||
if es_version and StrictVersion(es_version) >= StrictVersion("7.8"): | ||
datetime_formatted = dttm.isoformat(sep=" ", timespec="seconds") | ||
return ( | ||
f"""DATETIME_PARSE('{datetime_formatted}', 'yyyy-MM-dd HH:mm:ss')""" | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should have a fallback/more clear error message if the version isn't parseable by >>> from distutils.version import StrictVersion
>>> StrictVersion("7.8.0.0")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/ville/.pyenv/versions/3.8-dev/lib/python3.8/distutils/version.py", line 40, in __init__
self.parse(vstring)
File "/Users/ville/.pyenv/versions/3.8-dev/lib/python3.8/distutils/version.py", line 137, in parse
raise ValueError("invalid version number '%s'" % vstring)
ValueError: invalid version number '7.8.0.0' Same for non-string values (I expect someone may try to enter it as a number, not string): >>> StrictVersion(7.8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/ville/.pyenv/versions/3.8-dev/lib/python3.8/distutils/version.py", line 40, in __init__
self.parse(vstring)
File "/Users/ville/.pyenv/versions/3.8-dev/lib/python3.8/distutils/version.py", line 135, in parse
match = self.version_re.match(vstring)
TypeError: expected string or bytes-like object Just in case, perhaps we could do something as simple as supports_dttm_parse = False
try:
if es_version:
supports_dttm_parse = StrictVersion(es_version) >= StrictVersion("7.8")
except ValueError:
... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @villebro I have updated it, you can review it when you have time |
||
|
||
return f"""CAST('{dttm.isoformat(timespec="seconds")}' AS DATETIME)""" | ||
|
||
return None | ||
|
||
|
||
|
@@ -87,7 +102,9 @@ class OpenDistroEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method | |
engine_name = "ElasticSearch (OpenDistro SQL)" | ||
|
||
@classmethod | ||
def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: | ||
def convert_dttm( | ||
cls, target_type: str, dttm: datetime, **kwargs: Any | ||
) -> Optional[str]: | ||
if target_type.upper() == utils.TemporalType.DATETIME: | ||
return f"""'{dttm.isoformat(timespec="seconds")}'""" | ||
return None | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this is
**kwargs: Any
and notdb_extra: Optional[Dict[str, Any]]
like has been done inget_column_spec
? Unpacking into kwargs will make more difficult to add new parameters to this method going forwardThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, the writing here is not strict enough, for
db_extra
, it is better to show the declaration type, I think, the method signature can be like this,def convert_dttm(cls, target_type: str, dttm: datetime, db_extra: Optional[Dict[str, Any]], **kwargs: Any)
also continue to retainkwargs
, so that later if a data source needs non-db_extra information, this way is also compatible, what do you thinkThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aniaan I'd prefer not to add
**kwargs
unless it's currently needed (it's easy enough to add later when the need comes up). And thinking more closely, I'd personally prefer to keep all arguments named so that all parameters in the method are explicit.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can, then we will not add it for now, and we will consider it later if we have this situation.
I'll correct the PR later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@villebro I have updated it, you can review it when you have time