Completely forgot! Thank you, Mike. That works. On Tuesday, 17 May 2016 00:43:07 UTC+3, Mike Bayer wrote: > > > > On 05/16/2016 04:34 PM, Михаил Доронин wrote: > > I've opened issue here > > < > https://bitbucket.org/zzzeek/sqlalchemy/issues/3714/sqlalchemy-core-returns-string-instead-of>, > > > > please read it, it's very brief. > > > > Now Mike Bayer says that it's not a sqlalchemy bug, and says that I can > > use cast to hint to mysql to return datetime.date, but this won't work > > with sqlite which we're trying to use for tests. So it's doesn't solve > > my problem as I really want to use sqlite for tests. > > > > So I got a few questions > > > > Why ``` literal(d, Date)``` isn't working with mysql? > > the DBAPI turns it into a string, and on the MySQL side it is as though > you said: > > "SELECT '2016-01-01'" > > nothing about a date there. A string is sent back, the driver sees > string, you get a string. > > > > I've explicitly > > stated that this column is of type Date. > > your test case did not include any Column objects so there's nothing on > the database side that tells MySQL this is a date. If you are dealing > with regular tables and columns and selecting from those, rather from > free-standing literals which is always an awkward use case due to the > lack of typing information, both backends would work equally well. > > > But mysql still returns > > strings. What is the use of this type parameter in ```literal``` > function? > > that tells SQLAlchemy what datatype to treat this as on the python side > before passing it in. In the case of MySQL Date, this means, "do > nothing, the driver handles it". > > > > > Could someone point me to a sqlite bug report which says that cast isn't > > working correctly with casting string to date? Maybe I can fix this... > > There's no bug that I know of, only that if you go into the sqlite > console, CAST acts in a totally useless, non-SQL way: > > sqlite> select CAST ('2016-06-05' AS DATE); > 2016 > > There's probably some esoteric reason in SQLite's extremely weird typing > system that causes this. The reason you get a date back when you don't > use cast is because for SQLite, SQLAlchemy's Date type actually does a > string->date conversion. SQLite doesn't have a native "date" type > which is probably why the cast acts weird. > > > > > Are there any other workarounds that are actually portable? I mean > > besides changing my own functions logic to deal with corner cases like > > if result is string, than convert it to date etc. > > your test was extremely specific, and is attempting to do a round trip > of a date literal. > > To make that exact thing work you need to build a @compiles recipe using > a form such as that at > > http://docs.sqlalchemy.org/en/rel_1_0/core/compiler.html#utc-timestamp-function > > > from sqlalchemy.ext.compiler import compiles > from sqlalchemy.sql.elements import Cast > > > class MakeADate(Cast): > def __init__(self, elem): > super(MakeADate, self).__init__(elem, Date) > > > @compiles(MakeADate) > def _default_date(elem, compiler, **kw): > return compiler.visit_cast(elem, **kw) > > > @compiles(MakeADate, "sqlite") > def _sqlite_date(elem, compiler, **kw): > return compiler.process(elem.clause, **kw) > > > > full example: > > > from sqlalchemy import ( > create_engine, > Column, > String, > Integer, > Date > ) > from sqlalchemy.ext.declarative import declarative_base > from sqlalchemy.orm import Session > from sqlalchemy.sql import select, cast > from sqlalchemy.sql.expression import union, literal, alias > from itertools import chain > from datetime import date > > Base = declarative_base() > > e1 = create_engine("mysql://scott:tiger@localhost/test", echo=True) > > e2 = create_engine("sqlite://", echo='debug') > > > from sqlalchemy.ext.compiler import compiles > from sqlalchemy.sql.elements import Cast > > > class MakeADate(Cast): > def __init__(self, elem): > super(MakeADate, self).__init__(elem, Date) > > > @compiles(MakeADate) > def _default_date(elem, compiler, **kw): > return compiler.visit_cast(elem, **kw) > > > @compiles(MakeADate, "sqlite") > def _sqlite_date(elem, compiler, **kw): > return compiler.process(elem.clause, **kw) > > > dates = ( > date(2016, 1, 1), > date(2016, 1, 2), > ) > > > for engine in e1, e2: > session = Session(engine) > > selects = tuple(select([MakeADate(d)]) for d in dates) > > data = alias(union(*selects, use_labels=True), 'dates') > stmt = select((data,)) > result = session.execute(stmt).fetchall() > assert tuple(chain.from_iterable(result)) == dates > > > > > > > > > > -- > > You received this message because you are subscribed to the Google > > Groups "sqlalchemy" group. > > To unsubscribe from this group and stop receiving emails from it, send > > an email to sqlalchemy+...@googlegroups.com <javascript:> > > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:> > > <mailto:sqlal...@googlegroups.com <javascript:>>. > > Visit this group at https://groups.google.com/group/sqlalchemy. > > For more options, visit https://groups.google.com/d/optout. >
-- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.