Skip to content
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

Wrong datetime formating when building the query #185

Closed
gbrian opened this issue Mar 17, 2016 · 16 comments
Closed

Wrong datetime formating when building the query #185

gbrian opened this issue Mar 17, 2016 · 16 comments
Labels
!deprecated-label:bug Deprecated label - Use #bug instead inactive Inactive for >= 30 days

Comments

@gbrian
Copy link
Contributor

gbrian commented Mar 17, 2016

HI,

image

I've found that datetime is being custom formatted before sending to SQLAlchemy that causes incompatibility between Datetime and Datetime2 in SQLServer.

I'll check to use the SQLAlchemy dialect of the datasource to format instead.

@mistercrunch
Copy link
Member

that would really help! I knew this was going to hit on some db with different autocast...

@gbrian
Copy link
Contributor Author

gbrian commented Apr 5, 2016

HI,

Haven't found a nice way to let SQLAlchemy dialect to convert the date time yet.
BTW I'm managing with this patch/workaround at models.py line 542*


            # UGLY: I guess correct way is to delegate on SQLAlchemy dialect
            # UPDATE: Datetime depends on each dialect and I haven't found an easy way to manage
            #         Maybe we can allow user to define its custome format at Database definition
            def get_dtformat(type):
                if type == 'SMALLDATETIME' or type == 'DATETIME':
                    return '%Y-%m-%d %H:%M:%S'
                if type == 'DATE':
                    return '%Y-%m-%d'
                if type == 'TIME':
                    return '%H:%M:%S'
                return '%Y-%m-%d %H:%M:%S.%f'

            tf = get_dtformat(cols[granularity].type or 'DATE')

*Sorry for posting code, I'm facing some issues managing new branches and PR.

@rmnguleria
Copy link

Thanks for the workaround .

@pablolemosassis
Copy link

I am still finding problem with this issue. I just updated to latest caravel.
Should I do anything to make this #283 fix to work?

screenshot 2016-04-27 17 47 39

@mistercrunch
Copy link
Member

#283 was not the right approach. we have yet to find a solution to this.

@mistercrunch
Copy link
Member

This should help #446, please test and report whether it fixes your issues.

@xrmx
Copy link
Contributor

xrmx commented Aug 8, 2016

@gbrian is this fixed for you?

@gbrian
Copy link
Contributor Author

gbrian commented Aug 9, 2016

Hi @xrmx,

Sorry not working due to precision:
image

Don't know the best fix, I'll suggest trim precision.
http://stackoverflow.com/questions/19025192/convert-varchar-to-datetime-in-sql-which-is-having-millisec/38843397#38843397

@xrmx xrmx added !deprecated-label:bug Deprecated label - Use #bug instead help wanted labels Aug 9, 2016
@gbrian
Copy link
Contributor Author

gbrian commented Aug 10, 2016

@xrmx : If you agree we can use column data type to decide if we can use DateTime2 or trim milliseconds. I mean in case column has been defined as DateTime2 cast to DateTime2, if not just trim (but not TSQL version).
Will this work for you?

image

@xrmx
Copy link
Contributor

xrmx commented Aug 10, 2016

@gbrian adding a proper python_date_format wouldn't fix that? I know it's manual and not working out of the box is lame.

@gbrian
Copy link
Contributor Author

gbrian commented Aug 10, 2016

@xrmx proper way (IMO)

-- Using default and 126 format for Datetime2
SELECT CONVERT(DATETIME2, '2015-08-10 11:58:47.123456', 126) as MSSQLDateTime2
-- Using default[:-3] and 121 format for Datetime 
SELECT CONVERT(DATETIME, '2015-08-10 11:58:47.123', 121) as MSSQLDateTime2

so
some changes in the code like:

def dttm_sql_literal(self, dttm, type):
        """Convert datetime object to string

        If database_expression is empty, the internal dttm
        will be parsed as the string with the pattern that
        the user inputted (python_date_format)
        If database_expression is not empty, the internal dttm
        will be parsed as the sql sentence for the database to convert
        """
        tf = self.python_date_format or '%Y-%m-%d %H:%M:%S.%f'
        if self.database_expression:
            return self.database_expression.format(dttm.strftime('%Y-%m-%d %H:%M:%S'))
        elif tf == 'epoch_s':
            return str((dttm - datetime(1970, 1, 1)).total_seconds())
        elif tf == 'epoch_ms':
            return str((dttm - datetime(1970, 1, 1)).total_seconds() * 1000.0)
        else:
            default = "'{}'".format(dttm.strftime(tf))
            iso = dttm.isoformat()
            d = {
                'mssql': "CONVERT({}, '{}', {})".
                            format("DATETIME2" if type.lower() == "datetime2" else "DATETIME",
                            default if type.lower() == "datetime2" else default[:- 3],
                            126 if type.lower() == "datetime2" else 121),  # untested
                'mysql': default,
                'oracle':
                    """TO_TIMESTAMP('{}', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')""".format(iso),
                'presto': default,
                'sqlite': default,
            }
            for k, v in d.items():
                if self.table.database.sqlalchemy_uri.startswith(k):
                    return v
            return default

I think is this way I keep as much precision as possible with the definition the user has done.

@xrmx
Copy link
Contributor

xrmx commented Aug 10, 2016

@gbrian a diff is easier to review :) Anyway the chain of ifs insinde the format is a no-go imho :) Also we can remove the for loop and the dict if we need to patch only mssql and oracle. Also in mssql case do we really need the CONVERT, can't we just return a slice of default instead?

uri = self.table.database.sqlachemy_uri
if uri.startswith('oracle'):
    iso = dttm.isoformat()
   return """TO_TIMESTAMP('{}', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')""".format(iso)
elif uri.startswith('mssql'):
    field_type = type.upper()
    if field_type == 'DATETIME':
        return default[:-3]
    return default
else:
    return default

@gbrian
Copy link
Contributor Author

gbrian commented Aug 10, 2016

Yeah! totally agree with the "ifs" ;) was just playing around, sorry. Sadly I don't have an older SQL Server version to test the "default" behavior so I though CONVERT will be more backward compatible: http://www.techonthenet.com/sql_server/functions/convert.php (basically will cover SQL Server 2005)

Let me try again:

image

@xrmx
Copy link
Contributor

xrmx commented Aug 10, 2016

@gbrian do we really need the convert for the DATETIME2? it looks like it can handle our default just fine.
Anyway open a pull request, looks pretty good anyway and an improvement over current code :)
BTW please reorder the ifs to check for mssql first, i moved there just for c&p convenience :)

@gbrian
Copy link
Contributor Author

gbrian commented Aug 10, 2016

Ah, ok! yep you are right, for DATETIME2, CONVERT is not needed. Creating PR, talk later

@AndreiPashkin
Copy link

What is the point of formatting dates within Superset, why don't let SQLAlchemy do that?

@kristw kristw added the inactive Inactive for >= 30 days label Mar 20, 2019
@stale stale bot closed this as completed Apr 11, 2019
graceguo-supercat pushed a commit to graceguo-supercat/superset that referenced this issue Oct 4, 2021
zhaoyongjie pushed a commit to zhaoyongjie/incubator-superset that referenced this issue Nov 17, 2021
zhaoyongjie pushed a commit to zhaoyongjie/incubator-superset that referenced this issue Nov 24, 2021
zhaoyongjie pushed a commit to zhaoyongjie/incubator-superset that referenced this issue Nov 25, 2021
zhaoyongjie pushed a commit to zhaoyongjie/incubator-superset that referenced this issue Nov 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
!deprecated-label:bug Deprecated label - Use #bug instead inactive Inactive for >= 30 days
Projects
None yet
Development

No branches or pull requests

7 participants