stac-rs
stac-rs copied to clipboard
Use DuckDB for in-memory server backend
Let's check out using arrow virtual tables: https://github.com/duckdb/duckdb-rs/issues/286,
Whelp, I tried, but it looks like it chokes on the spatial column:
Big ol' diff
diff --git a/crates/duckdb/src/client.rs b/crates/duckdb/src/client.rs
index 9c8b383..9042d0e 100644
--- a/crates/duckdb/src/client.rs
+++ b/crates/duckdb/src/client.rs
@@ -2,10 +2,17 @@ use crate::{Error, Extension, Result};
use arrow_array::{RecordBatch, RecordBatchIterator};
use chrono::DateTime;
use cql2::{Expr, ToDuckSQL};
-use duckdb::{Connection, types::Value};
+use duckdb::{
+ Connection,
+ types::Value,
+ vtab::{arrow::ArrowVTab, arrow_recordbatch_to_query_params},
+};
use geo::BoundingRect;
use geojson::Geometry;
-use stac::{Collection, SpatialExtent, TemporalExtent, geoarrow::DATETIME_COLUMNS};
+use stac::{
+ Collection, SpatialExtent, TemporalExtent,
+ geoarrow::{DATETIME_COLUMNS, Table},
+};
use stac_api::{Direction, Search};
use std::ops::{Deref, DerefMut};
@@ -18,6 +25,8 @@ pub const DEFAULT_CONVERT_WKB: bool = true;
const DEFAULT_COLLECTION_DESCRIPTION: &str =
"Auto-generated collection from stac-geoparquet extents";
+const ARROW_FROM: &str = "arrow(?, ?)";
+
/// A client for making DuckDB requests for STAC objects.
#[derive(Debug)]
pub struct Client {
@@ -169,7 +178,17 @@ impl Client {
/// let item_collection = client.search("data/100-sentinel-2-items.parquet", Default::default()).unwrap();
/// ```
pub fn search(&self, href: &str, search: Search) -> Result<stac_api::ItemCollection> {
- let record_batches = self.search_to_arrow(href, search)?;
+ let from = self.format_parquet_href(href);
+ self.search_from(&from, &[], search)
+ }
+
+ fn search_from(
+ &self,
+ from: &str,
+ params: &[Value],
+ search: Search,
+ ) -> Result<stac_api::ItemCollection> {
+ let record_batches = self.search_to_arrow_from(from, params, search)?;
if record_batches.is_empty() {
Ok(Default::default())
} else {
@@ -181,6 +200,32 @@ impl Client {
}
}
+ /// Searches an arrow table.
+ pub fn search_table(&self, table: Table, search: Search) -> Result<stac_api::ItemCollection> {
+ self.connection
+ .register_table_function::<ArrowVTab>("arrow")?;
+ let (record_batches, _) = table.into_inner();
+ if record_batches.len() > 1 {
+ unimplemented!("cannot limit/offset through multiple record batches (yet)")
+ }
+ let mut items = Vec::with_capacity(
+ record_batches
+ .iter()
+ .map(|record_batch| record_batch.num_rows())
+ .sum(),
+ );
+ for record_batch in record_batches {
+ let params = arrow_recordbatch_to_query_params(record_batch);
+ let item_collection = self.search_from(
+ ARROW_FROM,
+ &[params[0].into(), params[1].into()],
+ search.clone(),
+ )?;
+ items.extend(item_collection.items);
+ }
+ Ok(items.into())
+ }
+
/// Searches to an iterator of record batches.
///
/// # Examples
@@ -192,6 +237,16 @@ impl Client {
/// let record_batches = client.search_to_arrow("data/100-sentinel-2-items.parquet", Default::default()).unwrap();
/// ```
pub fn search_to_arrow(&self, href: &str, search: Search) -> Result<Vec<RecordBatch>> {
+ let from = self.format_parquet_href(href);
+ self.search_to_arrow_from(&from, &[], search)
+ }
+
+ fn search_to_arrow_from(
+ &self,
+ from: &str,
+ params: &[Value],
+ search: Search,
+ ) -> Result<Vec<RecordBatch>> {
// TODO can we return an iterator?
// Note that we pull out some fields early so we can avoid closing some search strings below.
@@ -203,13 +258,15 @@ impl Client {
// Check which columns we'll be selecting
let mut statement = self.prepare(&format!(
"SELECT column_name FROM (DESCRIBE SELECT * from {})",
- self.format_parquet_href(href)
+ from
))?;
let mut has_start_datetime = false;
let mut has_end_datetime = false;
let mut column_names = Vec::new();
let mut columns = Vec::new();
- for row in statement.query_map([], |row| row.get::<_, String>(0))? {
+ for row in statement.query_map(duckdb::params_from_iter(params), |row| {
+ row.get::<_, String>(0)
+ })? {
let column = row?;
if column == "start_datetime" {
has_start_datetime = true;
@@ -259,7 +316,7 @@ impl Client {
// Build wheres and params
let mut wheres = Vec::new();
- let mut params = Vec::new();
+ let mut additional_params = Vec::new();
if !search.ids.is_empty() {
wheres.push(format!(
"id IN ({})",
@@ -268,11 +325,11 @@ impl Client {
.collect::<Vec<_>>()
.join(",")
));
- params.extend(search.ids.into_iter().map(Value::Text));
+ additional_params.extend(search.ids.into_iter().map(Value::Text));
}
if let Some(intersects) = search.intersects {
wheres.push("ST_Intersects(geometry, ST_GeomFromGeoJSON(?))".to_string());
- params.push(Value::Text(intersects.to_string()));
+ additional_params.push(Value::Text(intersects.to_string()));
}
if !search.collections.is_empty() {
wheres.push(format!(
@@ -282,11 +339,11 @@ impl Client {
.collect::<Vec<_>>()
.join(",")
));
- params.extend(search.collections.into_iter().map(Value::Text));
+ additional_params.extend(search.collections.into_iter().map(Value::Text));
}
if let Some(bbox) = search.items.bbox {
wheres.push("ST_Intersects(geometry, ST_GeomFromGeoJSON(?))".to_string());
- params.push(Value::Text(bbox.to_geometry().to_string()));
+ additional_params.push(Value::Text(bbox.to_geometry().to_string()));
}
if let Some(datetime) = search.items.datetime {
let interval = stac::datetime::parse(&datetime)?;
@@ -299,7 +356,7 @@ impl Client {
"datetime"
}
));
- params.push(Value::Text(start.to_rfc3339()));
+ additional_params.push(Value::Text(start.to_rfc3339()));
}
if let Some(end) = interval.1 {
wheres.push(format!(
@@ -310,7 +367,7 @@ impl Client {
"datetime"
}
));
- params.push(Value::Text(end.to_rfc3339()));
+ additional_params.push(Value::Text(end.to_rfc3339()));
}
}
if let Some(filter) = search.items.filter {
@@ -337,16 +394,13 @@ impl Client {
suffix.push_str(&format!(" OFFSET {}", offset));
}
- let sql = format!(
- "SELECT {} FROM {}{}",
- columns.join(","),
- self.format_parquet_href(href),
- suffix,
- );
+ let sql = format!("SELECT {} FROM {}{}", columns.join(","), from, suffix,);
log::debug!("duckdb sql: {}", sql);
let mut statement = self.prepare(&sql)?;
statement
- .query_arrow(duckdb::params_from_iter(params))?
+ .query_arrow(duckdb::params_from_iter(
+ params.iter().chain(additional_params.iter()),
+ ))?
.map(|record_batch| {
let record_batch = if self.convert_wkb {
stac::geoarrow::with_native_geometry(record_batch, "geometry")?
@@ -423,7 +477,7 @@ mod tests {
use duckdb::Connection;
use geo::Geometry;
use rstest::{fixture, rstest};
- use stac::Bbox;
+ use stac::{Bbox, ItemCollection, geoarrow::TableBuilder};
use stac_api::{Search, Sortby};
use stac_validate::Validate;
@@ -672,4 +726,18 @@ mod tests {
.unwrap();
assert_eq!(item_collection.items.len(), 100);
}
+
+ #[rstest]
+ fn search_table(client: Client) {
+ let item_collection: ItemCollection =
+ stac_io::read("data/100-sentinel-2-items.parquet").unwrap();
+ let table = TableBuilder {
+ item_collection,
+ drop_invalid_attributes: false,
+ }
+ .build()
+ .unwrap();
+ let item_collection = client.search_table(table, Default::default()).unwrap();
+ assert_eq!(item_collection.items.len(), 100);
+ }
}
gives
Big ol' error
---- client::tests::search_table stdout ----
thread 'client::tests::search_table' panicked at crates/duckdb/src/client.rs:740:78:
called `Result::unwrap()` on an `Err` value: DuckDB(DuckDBFailure(Error { code: Unknown, extended_code: 1 }, Some("Binder Error: Unsupported data type: Union([(1, Field { name: \"Point\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (2, Field { name: \"LineString\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (3, Field { name: \"Polygon\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (4, Field { name: \"MultiPoint\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (5, Field { name: \"MultiLineString\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (6, Field { name: \"MultiPolygon\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (7, Field { name: \"GeometryCollection\", data_type: List(Field { name: \"geometries\", data_type: Union([(1, Field { name: \"Point\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (2, Field { name: \"LineString\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (3, Field { name: \"Polygon\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (4, Field { name: \"MultiPoint\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (5, Field { name: \"MultiLineString\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (6, Field { name: \"MultiPolygon\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} })], Dense), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (11, Field { name: \"Point Z\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (12, Field { name: \"LineString Z\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (13, Field { name: \"Polygon Z\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (14, Field { name: \"MultiPoint Z\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (15, Field { name: \"MultiLineString Z\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (16, Field { name: \"MultiPolygon Z\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (17, Field { name: \"GeometryCollection Z\", data_type: List(Field { name: \"geometries\", data_type: Union([(11, Field { name: \"Point Z\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (12, Field { name: \"LineString Z\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (13, Field { name: \"Polygon Z\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (14, Field { name: \"MultiPoint Z\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (15, Field { name: \"MultiLineString Z\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (16, Field { name: \"MultiPolygon Z\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} })], Dense), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (21, Field { name: \"Point M\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (22, Field { name: \"LineString M\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (23, Field { name: \"Polygon M\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (24, Field { name: \"MultiPoint M\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (25, Field { name: \"MultiLineString M\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (26, Field { name: \"MultiPolygon M\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (27, Field { name: \"GeometryCollection M\", data_type: List(Field { name: \"geometries\", data_type: Union([(21, Field { name: \"Point M\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (22, Field { name: \"LineString M\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (23, Field { name: \"Polygon M\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (24, Field { name: \"MultiPoint M\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (25, Field { name: \"MultiLineString M\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (26, Field { name: \"MultiPolygon M\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} })], Dense), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (31, Field { name: \"Point ZM\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (32, Field { name: \"LineString ZM\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (33, Field { name: \"Polygon ZM\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (34, Field { name: \"MultiPoint ZM\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (35, Field { name: \"MultiLineString ZM\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (36, Field { name: \"MultiPolygon ZM\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (37, Field { name: \"GeometryCollection ZM\", data_type: List(Field { name: \"geometries\", data_type: Union([(31, Field { name: \"Point ZM\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (32, Field { name: \"LineString ZM\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (33, Field { name: \"Polygon ZM\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (34, Field { name: \"MultiPoint ZM\", data_type: List(Field { name: \"points\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (35, Field { name: \"MultiLineString ZM\", data_type: List(Field { name: \"linestrings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} }), (36, Field { name: \"MultiPolygon ZM\", data_type: List(Field { name: \"polygons\", data_type: List(Field { name: \"rings\", data_type: List(Field { name: \"vertices\", data_type: Struct([Field { name: \"x\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"y\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"z\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"m\", data_type: Float64, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} })], Dense), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }), nullable: true, dict_id: 0, dict_is_ordered: false, metadata: {} })], Dense), please file an issue https://github.com/duckdb/duckdb-rs")))
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
client::tests::search_table
test result: FAILED. 19 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.41s