in datafusion/proto/src/logical_plan/from_proto.rs [612:778]
fn try_from(scalar: &protobuf::ScalarValue) -> Result<Self, Self::Error> {
use protobuf::scalar_value::Value;
let value = scalar
.value
.as_ref()
.ok_or_else(|| Error::required("value"))?;
Ok(match value {
Value::BoolValue(v) => Self::Boolean(Some(*v)),
Value::Utf8Value(v) => Self::Utf8(Some(v.to_owned())),
Value::LargeUtf8Value(v) => Self::LargeUtf8(Some(v.to_owned())),
Value::Int8Value(v) => Self::Int8(Some(*v as i8)),
Value::Int16Value(v) => Self::Int16(Some(*v as i16)),
Value::Int32Value(v) => Self::Int32(Some(*v)),
Value::Int64Value(v) => Self::Int64(Some(*v)),
Value::Uint8Value(v) => Self::UInt8(Some(*v as u8)),
Value::Uint16Value(v) => Self::UInt16(Some(*v as u16)),
Value::Uint32Value(v) => Self::UInt32(Some(*v)),
Value::Uint64Value(v) => Self::UInt64(Some(*v)),
Value::Float32Value(v) => Self::Float32(Some(*v)),
Value::Float64Value(v) => Self::Float64(Some(*v)),
Value::Date32Value(v) => Self::Date32(Some(*v)),
Value::ListValue(scalar_list) => {
let protobuf::ScalarListValue {
is_null,
values,
field,
} = &scalar_list;
let field: Field = field.as_ref().required("field")?;
let field = Arc::new(field);
let values: Result<Vec<ScalarValue>, Error> =
values.iter().map(|val| val.try_into()).collect();
let values = values?;
validate_list_values(field.as_ref(), &values)?;
let values = if *is_null { None } else { Some(values) };
Self::List(values, field)
}
Value::NullValue(v) => {
let null_type: DataType = v.try_into()?;
null_type.try_into().map_err(Error::DataFusionError)?
}
Value::Decimal128Value(val) => {
let array = vec_to_array(val.value.clone());
Self::Decimal128(
Some(i128::from_be_bytes(array)),
val.p as u8,
val.s as i8,
)
}
Value::Decimal256Value(val) => {
let array = vec_to_array(val.value.clone());
Self::Decimal256(
Some(i256::from_be_bytes(array)),
val.p as u8,
val.s as i8,
)
}
Value::Date64Value(v) => Self::Date64(Some(*v)),
Value::Time32Value(v) => {
let time_value =
v.value.as_ref().ok_or_else(|| Error::required("value"))?;
match time_value {
protobuf::scalar_time32_value::Value::Time32SecondValue(t) => {
Self::Time32Second(Some(*t))
}
protobuf::scalar_time32_value::Value::Time32MillisecondValue(t) => {
Self::Time32Millisecond(Some(*t))
}
}
}
Value::Time64Value(v) => {
let time_value =
v.value.as_ref().ok_or_else(|| Error::required("value"))?;
match time_value {
protobuf::scalar_time64_value::Value::Time64MicrosecondValue(t) => {
Self::Time64Microsecond(Some(*t))
}
protobuf::scalar_time64_value::Value::Time64NanosecondValue(t) => {
Self::Time64Nanosecond(Some(*t))
}
}
}
Value::IntervalYearmonthValue(v) => Self::IntervalYearMonth(Some(*v)),
Value::IntervalDaytimeValue(v) => Self::IntervalDayTime(Some(*v)),
Value::DurationSecondValue(v) => Self::DurationSecond(Some(*v)),
Value::DurationMillisecondValue(v) => Self::DurationMillisecond(Some(*v)),
Value::DurationMicrosecondValue(v) => Self::DurationMicrosecond(Some(*v)),
Value::DurationNanosecondValue(v) => Self::DurationNanosecond(Some(*v)),
Value::TimestampValue(v) => {
let timezone = if v.timezone.is_empty() {
None
} else {
Some(v.timezone.as_str().into())
};
let ts_value =
v.value.as_ref().ok_or_else(|| Error::required("value"))?;
match ts_value {
protobuf::scalar_timestamp_value::Value::TimeMicrosecondValue(t) => {
Self::TimestampMicrosecond(Some(*t), timezone)
}
protobuf::scalar_timestamp_value::Value::TimeNanosecondValue(t) => {
Self::TimestampNanosecond(Some(*t), timezone)
}
protobuf::scalar_timestamp_value::Value::TimeSecondValue(t) => {
Self::TimestampSecond(Some(*t), timezone)
}
protobuf::scalar_timestamp_value::Value::TimeMillisecondValue(t) => {
Self::TimestampMillisecond(Some(*t), timezone)
}
}
}
Value::DictionaryValue(v) => {
let index_type: DataType = v
.index_type
.as_ref()
.ok_or_else(|| Error::required("index_type"))?
.try_into()?;
let value: Self = v
.value
.as_ref()
.ok_or_else(|| Error::required("value"))?
.as_ref()
.try_into()?;
Self::Dictionary(Box::new(index_type), Box::new(value))
}
Value::BinaryValue(v) => Self::Binary(Some(v.clone())),
Value::LargeBinaryValue(v) => Self::LargeBinary(Some(v.clone())),
Value::IntervalMonthDayNano(v) => Self::IntervalMonthDayNano(Some(
IntervalMonthDayNanoType::make_value(v.months, v.days, v.nanos),
)),
Value::StructValue(v) => {
// all structs must have at least 1 field, so we treat
// an empty values list as NULL
let values = if v.field_values.is_empty() {
None
} else {
Some(
v.field_values
.iter()
.map(|v| v.try_into())
.collect::<Result<Vec<ScalarValue>, _>>()?,
)
};
let fields = v
.fields
.iter()
.map(Field::try_from)
.collect::<Result<_, _>>()?;
Self::Struct(values, fields)
}
Value::FixedSizeBinaryValue(v) => {
Self::FixedSizeBinary(v.length, Some(v.clone().values))
}
})
}