diff --git a/Cargo.toml b/Cargo.toml index 19bd592f..0a98e48c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ databend-driver-core = { path = "sql", version = "0.26.1" } databend-driver-macros = { path = "macros", version = "0.26.1" } tokio-stream = "0.1" -chrono = { version = "0.4.35", default-features = false, features = ["clock"] } +chrono = { version = "=0.4.39", default-features = false, features = ["clock"] } arrow = { version = "53.0" } arrow-array = { version = "53.0" } arrow-schema = { version = "53.0" } diff --git a/bindings/python/src/blocking.rs b/bindings/python/src/blocking.rs index 4865f5eb..71f25217 100644 --- a/bindings/python/src/blocking.rs +++ b/bindings/python/src/blocking.rs @@ -16,6 +16,7 @@ use std::collections::BTreeMap; use std::path::Path; use std::sync::Arc; +use databend_driver::SchemaRef; use pyo3::exceptions::{PyAttributeError, PyException, PyStopIteration}; use pyo3::types::{PyList, PyTuple}; use pyo3::{prelude::*, IntoPyObjectExt}; @@ -200,6 +201,7 @@ pub struct BlockingDatabendCursor { rows: Option>>, // buffer is used to store only the first row after execute buffer: Vec, + schema: Option, } impl BlockingDatabendCursor { @@ -208,6 +210,7 @@ impl BlockingDatabendCursor { conn: Arc::new(conn), rows: None, buffer: Vec::new(), + schema: None, } } } @@ -216,6 +219,7 @@ impl BlockingDatabendCursor { fn reset(&mut self) { self.rows = None; self.buffer.clear(); + self.schema = None; } } @@ -223,28 +227,33 @@ impl BlockingDatabendCursor { impl BlockingDatabendCursor { #[getter] pub fn description<'p>(&'p self, py: Python<'p>) -> PyResult { - match self.rows { - None => Ok(py.None()), - Some(ref rows) => { - let schema = wait_for_future(py, async move { - let rows = rows.lock().await; - rows.schema() - }); - let mut fields = vec![]; - for field in schema.fields() { - let field = ( - field.name.clone(), // name - field.data_type.to_string(), // type_code - None::, // display_size - None::, // internal_size - None::, // precision - None::, // scale - None::, // null_ok - ); - fields.push(field.into_pyobject(py)?); - } - PyList::new(py, fields)?.into_py_any(py) + if let Some(ref schema) = self.schema { + let mut fields = vec![]; + for field in schema.fields() { + let field = ( + field.name.clone(), // name + field.data_type.to_string(), // type_code + None::, // display_size + None::, // internal_size + None::, // precision + None::, // scale + None::, // null_ok + ); + fields.push(field.into_pyobject(py)?); } + PyList::new(py, fields)?.into_py_any(py) + } else { + Ok(py.None()) + } + } + + fn set_schema(&mut self, py: Python) { + if let Some(ref rows) = self.rows { + let schema = wait_for_future(py, async move { + let rows = rows.lock().await; + rows.schema() + }); + self.schema = Some(schema) } } @@ -291,6 +300,7 @@ impl BlockingDatabendCursor { self.buffer.push(Row::new(first)); } self.rows = Some(Arc::new(Mutex::new(rows))); + self.set_schema(py); Ok(py.None()) } diff --git a/bindings/python/tests/cursor/steps/binding.py b/bindings/python/tests/cursor/steps/binding.py index bebc0083..e021d4ab 100644 --- a/bindings/python/tests/cursor/steps/binding.py +++ b/bindings/python/tests/cursor/steps/binding.py @@ -170,6 +170,9 @@ def _(context): ret.append(row.values()) assert ret == expected, f"ret: {ret}" + desc = context.cursor.description + assert desc != None + # fetchmany context.cursor.execute("SELECT * FROM test") rows = context.cursor.fetchmany(3) diff --git a/driver/Cargo.toml b/driver/Cargo.toml index ab15336b..0dfdab75 100644 --- a/driver/Cargo.toml +++ b/driver/Cargo.toml @@ -38,7 +38,7 @@ databend-common-ast = "0.2.1" derive-visitor = { version = "0.4.0", features = ["std-types-drive"] } async-trait = "0.1" -chrono = { version = "0.4.35", default-features = false, features = ["clock"] } +chrono = { version = "=0.4.39", default-features = false, features = ["clock"] } csv = "1.3" glob = "0.3" log = "0.4" diff --git a/sql/Cargo.toml b/sql/Cargo.toml index 34b938b2..4351a931 100644 --- a/sql/Cargo.toml +++ b/sql/Cargo.toml @@ -21,7 +21,7 @@ databend-client = { workspace = true } tokio-stream = { workspace = true } tonic = { workspace = true, optional = true } -chrono = { version = "0.4.35", default-features = false } +chrono = { version = "=0.4.39", default-features = false } geozero = { version = "0.14.0", features = ["with-wkb"] } glob = "0.3" hex = "0.4.3"