diff --git a/bindings/python/README.md b/bindings/python/README.md index abbd23ad..4c065fc1 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -97,20 +97,21 @@ asyncio.run(main()) ### General Data Types -| Databend | Python | -| ----------- | ------------------- | -| `BOOLEAN` | `bool` | -| `TINYINT` | `int` | -| `SMALLINT` | `int` | -| `INT` | `int` | -| `BIGINT` | `int` | -| `FLOAT` | `float` | -| `DOUBLE` | `float` | -| `DECIMAL` | `decimal.Decimal` | -| `DATE` | `datetime.date` | -| `TIMESTAMP` | `datetime.datetime` | -| `VARCHAR` | `str` | -| `BINARY` | `bytes` | +| Databend | Python | +|-------------|----------------------| +| `BOOLEAN` | `bool` | +| `TINYINT` | `int` | +| `SMALLINT` | `int` | +| `INT` | `int` | +| `BIGINT` | `int` | +| `FLOAT` | `float` | +| `DOUBLE` | `float` | +| `DECIMAL` | `decimal.Decimal` | +| `DATE` | `datetime.date` | +| `TIMESTAMP` | `datetime.datetime` | +| `INTERVAL` | `datetime.timedelta` | +| `VARCHAR` | `str` | +| `BINARY` | `bytes` | ### Semi-Structured Data Types diff --git a/bindings/python/src/types.rs b/bindings/python/src/types.rs index 1afde17f..097b3ad1 100644 --- a/bindings/python/src/types.rs +++ b/bindings/python/src/types.rs @@ -14,7 +14,7 @@ use std::sync::Arc; -use chrono::{NaiveDate, NaiveDateTime}; +use chrono::{Duration, NaiveDate, NaiveDateTime}; use once_cell::sync::Lazy; use pyo3::exceptions::{PyAttributeError, PyException, PyStopAsyncIteration, PyStopIteration}; use pyo3::sync::GILOnceCell; @@ -102,7 +102,14 @@ impl<'py> IntoPyObject<'py> for Value { databend_driver::Value::Variant(s) => s.into_bound_py_any(py)?, databend_driver::Value::Geometry(s) => s.into_bound_py_any(py)?, databend_driver::Value::Geography(s) => s.into_bound_py_any(py)?, - databend_driver::Value::Interval(s) => s.into_bound_py_any(py)?, + databend_driver::Value::Interval(s) => { + let value = databend_driver::Interval::from_string(&s).unwrap(); + let total_micros = (value.months as i64) * 30 * 86400000000 + + (value.days as i64) * 86400000000 + + value.micros; + let s = Duration::microseconds(total_micros); + s.into_bound_py_any(py)? + } }; Ok(val) } diff --git a/bindings/python/tests/asyncio/steps/binding.py b/bindings/python/tests/asyncio/steps/binding.py index a2336812..0144d41e 100644 --- a/bindings/python/tests/asyncio/steps/binding.py +++ b/bindings/python/tests/asyncio/steps/binding.py @@ -13,7 +13,7 @@ # limitations under the License. import os -from datetime import datetime, date +from datetime import datetime, date, timedelta from decimal import Decimal from behave import given, when, then @@ -66,6 +66,10 @@ async def _(context): row = await context.conn.query_row("select to_binary('xyz')") assert row.values() == (b"xyz",), f"Binary: {row.values()}" + # Interval + row = await context.conn.query_row("select to_interval('1 hours')") + assert row.values() == (timedelta(hours=1),), f"Interval: {row.values()}" + # Decimal row = await context.conn.query_row("SELECT 15.7563::Decimal(8,4), 2.0+3.0") assert row.values() == ( diff --git a/bindings/python/tests/blocking/steps/binding.py b/bindings/python/tests/blocking/steps/binding.py index 6ff9e734..15248c90 100644 --- a/bindings/python/tests/blocking/steps/binding.py +++ b/bindings/python/tests/blocking/steps/binding.py @@ -13,7 +13,7 @@ # limitations under the License. import os -from datetime import datetime, date +from datetime import datetime, date, timedelta from decimal import Decimal from behave import given, when, then @@ -61,6 +61,10 @@ async def _(context): row = context.conn.query_row("select to_binary('xyz')") assert row.values() == (b"xyz",), f"Binary: {row.values()}" + # Interval + row = context.conn.query_row("select to_interval('1 microseconds')") + assert row.values() == (timedelta(microseconds=1),), f"Interval: {row.values()}" + # Decimal row = context.conn.query_row("SELECT 15.7563::Decimal(8,4), 2.0+3.0") assert row.values() == ( diff --git a/bindings/python/tests/cursor/steps/binding.py b/bindings/python/tests/cursor/steps/binding.py index 21f48173..5900abf0 100644 --- a/bindings/python/tests/cursor/steps/binding.py +++ b/bindings/python/tests/cursor/steps/binding.py @@ -13,7 +13,7 @@ # limitations under the License. import os -from datetime import datetime, date +from datetime import datetime, date, timedelta from decimal import Decimal from behave import given, when, then @@ -62,6 +62,11 @@ async def _(context): row = context.cursor.fetchone() assert row[0] == b"xyz", f"Binary: {row.values()}" + # Interval + context.cursor.execute("select to_interval('1 days')") + row = context.cursor.fetchone() + assert row.values() == (timedelta(1),), f"Interval: {row.values()}" + # Decimal context.cursor.execute("SELECT 15.7563::Decimal(8,4), 2.0+3.0") row = context.cursor.fetchone()