如何强制polars-arrow使用arrow-array 46版本解决编译冲突?
我有两个依赖配置完全一致的Rust crate(一个为示例版本,一个为生产版本),示例代码可正常编译,但生产版本编译失败。
依赖配置
polars = {version="0.35.4", features=["lazy", "serde", "serde-lazy", "is_in", "diagonal_concat", "streaming", "object"]} polars-arrow = {version = "0.35.4", features=["arrow_rs"]} connectorx = {git="https://github.com/sfu-db/connector-x", features=["dst_arrow", "src_mysql"]} arrow-array = ">=46"
依赖版本说明
- polars 依赖
arrow-array = ">=41" - connectorx 依赖
arrow = "46"
编译报错
生产版本编译时出现以下错误:
the trait bound polars::prelude::ArrowField: std::convert::From<&arrow_schema::field::Field> is not satisfied
排查结果
示例版本中polars-arrow使用的是arrow-array 46版本,可正常编译;但生产版本中polars-arrow拉取了arrow-array 49版本,与connectorx依赖的46版本产生版本冲突,导致编译失败。
提问
如何强制polars-arrow使用arrow-array 46版本?
附无法编译的代码
use connectorx::{source_router::SourceConn, sql::CXQuery, get_arrow}; use polars::{prelude::{DataFrame, Field}, series::Series, functions::concat_df_diagonal}; use polars_arrow::{array::Array, datatypes::{Field as PolarsArrowField}}; use arrow_array::RecordBatch; pub fn conn() { let uri=format!("mysql://{0}:{1}@{2}:{3}/{4}?cxprotocol=binary", "username" , "password", "localhost", 3306, "dbname"); let mut source_conn = SourceConn::try_from(uri.as_str()).expect("parse conn str failed"); let queries = &[CXQuery::from("SELECT DISTINCT * FROM frtb")]; let destination = get_arrow::get_arrow(&source_conn, None, queries).expect("run failed"); let mut data = destination.arrow().unwrap(); let dt_cl = data.clone(); let res = record_batches_to_df(dt_cl); } pub fn record_batches_to_df<I>(batches: I) -> DataFrame where I: IntoIterator<Item=RecordBatch> { let mut batches_iter: <I as IntoIterator>::IntoIter = batches.into_iter(); let mut dfs = vec![]; for next_batch in batches_iter { dfs.push(batch_to_df(next_batch)); } let res = concat_df_diagonal(&dfs).unwrap(); res } pub fn batch_to_df(batch: RecordBatch) -> DataFrame { let mut columns = vec![]; batch.schema().all_fields().into_iter() .zip(batch.columns()) .for_each(|(f, c)|{ let polars_field = Field::from(&PolarsArrowField::from(f)); let chunk: Box<dyn Array> = From::from(c.as_ref()); let s = unsafe {Series::from_chunks_and_dtype_unchecked(polars_field.name.as_str(), vec![chunk], &polars_field.data_type())}; columns.push(s); }); DataFrame::from_iter(columns) }
要强制polars-arrow使用arrow-array 46版本,可通过以下几种方式实现:
1. 明确指定arrow生态依赖的精确版本
在Cargo.toml的[dependencies]块中,直接指定arrow-array和arrow-schema的精确版本,覆盖所有间接依赖的版本要求:
arrow-array = "46.0.0" arrow-schema = "46.0.0"
polars-arrow同时依赖arrow-array和arrow-schema,必须确保这两个依赖版本统一为46,才能避免跨版本的 trait 兼容问题。
2. 启用新版依赖解析器配合版本锁定
在Cargo.toml的[package]部分启用resolver = "2",新版解析器能更严格地处理依赖版本冲突:
[package] # 其他包配置项... resolver = "2"
再配合上述精确指定的arrow依赖版本,Cargo会严格遵循你设定的版本,不会自动升级到更高版本。
3. 复制示例项目的Cargo.lock文件
如果示例版本能正常编译,直接将示例项目中的Cargo.lock文件复制到生产版本项目中。Cargo会完全按照lock文件中的版本拉取依赖,确保polars-arrow使用arrow-array 46版本。
注意:复制后执行cargo build时不要添加--update参数,否则会重新解析依赖版本。
内容的提问来源于stack exchange,提问作者Anatoly Bugakov

