diff --git a/CHANGES.md b/CHANGES.md index 8ae5801..86a904c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ - Fixed SQL rendering of special DDL table options in `CrateDDLCompiler`. Before, configuring `crate_"translog.durability"` was not possible. - Unlocked supporting timezone-aware `DateTime` fields +- Added support for marshalling Python `datetime.date` values on `sa.DateTime` fields ## 2024/06/13 0.37.0 - Added support for CrateDB's [FLOAT_VECTOR] data type and its accompanying diff --git a/src/sqlalchemy_cratedb/dialect.py b/src/sqlalchemy_cratedb/dialect.py index 562ab0e..affe39b 100644 --- a/src/sqlalchemy_cratedb/dialect.py +++ b/src/sqlalchemy_cratedb/dialect.py @@ -115,10 +115,10 @@ class DateTime(sqltypes.DateTime): def bind_processor(self, dialect): def process(value): - if value is not None: - assert isinstance(value, datetime) + if isinstance(value, (datetime, date)): return value.strftime('%Y-%m-%dT%H:%M:%S.%f%z') - return value + else: + return value return process def result_processor(self, dialect, coltype): diff --git a/tests/datetime_test.py b/tests/datetime_test.py index 6aa782f..b4712cb 100644 --- a/tests/datetime_test.py +++ b/tests/datetime_test.py @@ -184,3 +184,33 @@ def test_datetime_tz(session): assert result["datetime_tz"].tzname() is None assert result["datetime_tz"].timetz() == OUTPUT_TIMETZ_TZ assert result["datetime_tz"].tzinfo is None + + +@pytest.mark.skipif(SA_VERSION < SA_1_4, reason="Test case not supported on SQLAlchemy 1.3") +def test_datetime_date(session): + """ + Validate assigning a `date` object to a `datetime` column works. + + It is needed by meltano-tap-cratedb. + + The test suite of `meltano-tap-cratedb`, derived from the corresponding + PostgreSQL adapter, will supply `dt.date` objects. Without this improvement, + those will otherwise fail. + """ + + # Insert record. + foo_item = FooBar( + name="foo", + datetime_notz=dt.date(2009, 5, 13), + datetime_tz=dt.date(2009, 5, 13), + ) + session.add(foo_item) + session.commit() + session.execute(sa.text("REFRESH TABLE foobar")) + + # Query record. + result = session.execute(sa.select(FooBar.name, FooBar.date, FooBar.datetime_notz, FooBar.datetime_tz)).mappings().first() + + # Compare outcome. + assert result["datetime_notz"] == dt.datetime(2009, 5, 13, 0, 0, 0) + assert result["datetime_tz"] == dt.datetime(2009, 5, 13, 0, 0, 0)