From c0b85ad6ad1df2497a95c87d837c32d87f17291f Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 13 Apr 2017 10:11:41 -0400 Subject: [PATCH] Remove MySQL UTC_TIMESTAMP rule Removed an ancient and unnecessary intercept of the UTC_TIMESTAMP MySQL function, which was getting in the way of using it with a parameter. Change-Id: I6e6b52c051418bcb9d31987e78299310810cb78d Fixes: #3966 --- doc/build/changelog/changelog_11.rst | 8 +++ lib/sqlalchemy/dialects/mysql/base.py | 3 - test/dialect/mysql/test_compiler.py | 7 ++- test/dialect/mysql/test_dialect.py | 81 +++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 423a7342aa..169c763602 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,14 @@ .. changelog:: :version: 1.1.10 + .. change:: 3966 + :tags: bug, mysql + :tickets: 3966 + + Removed an ancient and unnecessary intercept of the UTC_TIMESTAMP + MySQL function, which was getting in the way of using it with a + parameter. + .. change:: 3961 :tags: bug, mysql :tickets: 3961 diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index c6c1eb8bbd..dc7e3b369b 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -799,9 +799,6 @@ class MySQLCompiler(compiler.SQLCompiler): def visit_random_func(self, fn, **kw): return "rand%s" % self.function_argspec(fn) - def visit_utc_timestamp_func(self, fn, **kw): - return "UTC_TIMESTAMP" - def visit_sysdate_func(self, fn, **kw): return "SYSDATE()" diff --git a/test/dialect/mysql/test_compiler.py b/test/dialect/mysql/test_compiler.py index be5f002e3a..3c33f540c0 100644 --- a/test/dialect/mysql/test_compiler.py +++ b/test/dialect/mysql/test_compiler.py @@ -336,7 +336,12 @@ class SQLTest(fixtures.TestBase, AssertsCompiledSQL): ) def test_utc_timestamp(self): - self.assert_compile(func.utc_timestamp(), "UTC_TIMESTAMP") + self.assert_compile(func.utc_timestamp(), "utc_timestamp()") + + def test_utc_timestamp_fsp(self): + self.assert_compile( + func.utc_timestamp(5), "utc_timestamp(%s)", + checkparams={"utc_timestamp_1": 5}) def test_sysdate(self): self.assert_compile(func.sysdate(), "SYSDATE()") diff --git a/test/dialect/mysql/test_dialect.py b/test/dialect/mysql/test_dialect.py index cf8712e04c..e6bff35530 100644 --- a/test/dialect/mysql/test_dialect.py +++ b/test/dialect/mysql/test_dialect.py @@ -126,6 +126,87 @@ class DialectTest(fixtures.TestBase): assert c.execute('SELECT @@tx_isolation;').scalar() == mysql_value +class RemoveUTCTimestampTest(fixtures.TablesTest): + """This test exists because we removed the MySQL dialect's + override of the UTC_TIMESTAMP() function, where the commit message + for this feature stated that "it caused problems with executemany()". + Since no example was provided, we are trying lots of combinations + here. + + [ticket:3966] + + """ + __only_on__ = 'mysql' + __backend__ = True + + @classmethod + def define_tables(cls, metadata): + Table( + 't', metadata, + Column('id', Integer, primary_key=True), + Column('x', Integer), + Column('data', DateTime) + ) + + Table( + 't_default', metadata, + Column('id', Integer, primary_key=True), + Column('x', Integer), + Column('idata', DateTime, default=func.utc_timestamp()), + Column('udata', DateTime, onupdate=func.utc_timestamp()) + ) + + def test_insert_executemany(self): + with testing.db.connect() as conn: + conn.execute( + self.tables.t.insert().values(data=func.utc_timestamp()), + [{"x": 5}, {"x": 6}, {"x": 7}] + ) + + def test_update_executemany(self): + with testing.db.connect() as conn: + timestamp = datetime.datetime(2015, 4, 17, 18, 5, 2) + conn.execute( + self.tables.t.insert(), + [ + {"x": 5, "data": timestamp}, + {"x": 6, "data": timestamp}, + {"x": 7, "data": timestamp}] + ) + + conn.execute( + self.tables.t.update(). + values(data=func.utc_timestamp()). + where(self.tables.t.c.x == bindparam('xval')), + [{"xval": 5}, {"xval": 6}, {"xval": 7}] + ) + + def test_insert_executemany_w_default(self): + with testing.db.connect() as conn: + conn.execute( + self.tables.t_default.insert(), + [{"x": 5}, {"x": 6}, {"x": 7}] + ) + + def test_update_executemany_w_default(self): + with testing.db.connect() as conn: + timestamp = datetime.datetime(2015, 4, 17, 18, 5, 2) + conn.execute( + self.tables.t_default.insert(), + [ + {"x": 5, "idata": timestamp}, + {"x": 6, "idata": timestamp}, + {"x": 7, "idata": timestamp}] + ) + + conn.execute( + self.tables.t_default.update(). + values(idata=func.utc_timestamp()). + where(self.tables.t_default.c.x == bindparam('xval')), + [{"xval": 5}, {"xval": 6}, {"xval": 7}] + ) + + class SQLModeDetectionTest(fixtures.TestBase): __only_on__ = 'mysql' __backend__ = True -- 2.47.2