]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
String compiler can now literal compile datetime objects
authorFederico Caselli <cfederico87@gmail.com>
Tue, 24 Mar 2020 21:55:46 +0000 (22:55 +0100)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 30 Mar 2020 01:57:53 +0000 (21:57 -0400)
Add ability to literal compile a :class:`DateTime`, :class:`Date`
or :class:"Time" when using the string dialect for debugging purposes.
This change does not impact real dialect implementation that retain
their current behavior.

Fixes: #5052
Change-Id: Ia3fad2be905c6d35b0106b9a2388c7508f067e90
(cherry picked from commit 83eb1b23cbe5a7ee0f2534256cf16f0f865bdbbb)

doc/build/changelog/unreleased_13/5052.rst [new file with mode: 0644]
lib/sqlalchemy/engine/default.py
test/sql/test_compiler.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_13/5052.rst b/doc/build/changelog/unreleased_13/5052.rst
new file mode 100644 (file)
index 0000000..9680ba5
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: sql, types
+    :tickets: 5052
+
+    Add ability to literal compile a :class:`DateTime`, :class:`Date`
+    or :class:"Time" when using the string dialect for debugging purposes.
+    This change does not impact real dialect implementation that retain
+    their current behavior.
index 6760dd0f40fcf6833005af3ea4b0577969b5694f..62ceb5ccc8fa8122de8c9b9c91821bff8096d115 100644 (file)
@@ -651,6 +651,26 @@ class DefaultDialect(interfaces.Dialect):
         return name
 
 
+class _RendersLiteral(object):
+    def literal_processor(self, dialect):
+        def process(value):
+            return "'%s'" % value
+
+        return process
+
+
+class _StrDateTime(_RendersLiteral, sqltypes.DateTime):
+    pass
+
+
+class _StrDate(_RendersLiteral, sqltypes.Date):
+    pass
+
+
+class _StrTime(_RendersLiteral, sqltypes.Time):
+    pass
+
+
 class StrCompileDialect(DefaultDialect):
 
     statement_compiler = compiler.StrSQLCompiler
@@ -667,6 +687,12 @@ class StrCompileDialect(DefaultDialect):
 
     supports_simple_order_by_label = True
 
+    colspecs = {
+        sqltypes.DateTime: _StrDateTime,
+        sqltypes.Date: _StrDate,
+        sqltypes.Time: _StrTime,
+    }
+
 
 class DefaultExecutionContext(interfaces.ExecutionContext):
     isinsert = False
index e406a6423a149d5c8abdf49ed33a9e8fd3e6366e..35d8de5720173e625aac804a69e515d129708a0e 100644 (file)
@@ -10,6 +10,7 @@ styling and coherent test organization.
 
 """
 
+import datetime
 import decimal
 
 from sqlalchemy import alias
@@ -48,6 +49,7 @@ from sqlalchemy import sql
 from sqlalchemy import String
 from sqlalchemy import subquery
 from sqlalchemy import Table
+from sqlalchemy import testing
 from sqlalchemy import Text
 from sqlalchemy import text
 from sqlalchemy import TIMESTAMP
@@ -3376,6 +3378,21 @@ class StringifySpecialTest(fixtures.TestBase):
             "WITHIN GROUP (ORDER BY mytable.name DESC) AS anon_1 FROM mytable",
         )
 
+    @testing.combinations(
+        ("datetime", datetime.datetime.now()),
+        ("date", datetime.date.today()),
+        ("time", datetime.time()),
+        argnames="value",
+        id_="ia",
+    )
+    def test_render_datetime(self, value):
+        lit = literal(value)
+
+        eq_ignore_whitespace(
+            str(lit.compile(compile_kwargs={"literal_binds": True})),
+            "'%s'" % value,
+        )
+
 
 class KwargPropagationTest(fixtures.TestBase):
     @classmethod
index 34247e9c3e7b5ef87282221324607fd4e8b2afec..8e2a4372a0958725e91288e9a9d59923050a25ee 100644 (file)
@@ -3199,3 +3199,26 @@ class CallableTest(fixtures.TestBase):
         )
         assert isinstance(thang_table.c.name.type, Unicode)
         thang_table.create()
+
+
+class LiteralTest(fixtures.TestBase):
+    __backend__ = True
+
+    @testing.combinations(
+        ("datetime", datetime.datetime.now()),
+        ("date", datetime.date.today()),
+        ("time", datetime.time()),
+        argnames="value",
+        id_="ia",
+    )
+    @testing.skip_if(lambda: testing.requires.datetime_literals)
+    def test_render_datetime(self, value):
+        lit = literal(value)
+
+        assert_raises_message(
+            NotImplementedError,
+            "Don't know how to literal-quote value.*",
+            lit.compile,
+            dialect=testing.db.dialect,
+            compile_kwargs={"literal_binds": True},
+        )