diff --git a/CHANGES.md b/CHANGES.md index 11f6f19..2727f64 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ ## Unreleased - Added/reactivated documentation as `sqlalchemy-cratedb` - 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 8c6fe23..77ba1c8 100644 --- a/src/sqlalchemy_cratedb/dialect.py +++ b/src/sqlalchemy_cratedb/dialect.py @@ -114,10 +114,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.%fZ') - 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 e52ca53..f6896be 100644 --- a/tests/datetime_test.py +++ b/tests/datetime_test.py @@ -167,3 +167,31 @@ def test_datetime_tz(session): assert result["datetime"].tzname() is None assert result["datetime"].timetz() == dt.time(19, 19, 30, 123000) assert result["datetime"].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=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)).mappings().first() + + # Compare outcome. + assert result["datetime"] == dt.datetime(2009, 5, 13, 0, 0, 0)