use crate::input::proto::substrait;
use crate::output::diagnostic;
use crate::output::type_system::data;
use crate::parse::context;
fn parse_stats(
x: &substrait::rel_common::hint::Stats,
y: &mut context::Context,
) -> diagnostic::Result<()> {
proto_primitive_field!(x, y, row_count, |x, y| {
if *x < 0.0 {
diagnostic!(
y,
Error,
IllegalValueInHint,
"negative row counts are nonsensical"
);
}
Ok(())
});
proto_primitive_field!(x, y, record_size, |x, y| {
if *x < 0.0 {
diagnostic!(
y,
Error,
IllegalValueInHint,
"negative record sizes are nonsensical"
);
}
Ok(())
});
proto_field!(
x,
y,
advanced_extension,
crate::parse::extensions::advanced::parse_advanced_extension
);
Ok(())
}
fn parse_runtime_constraint(
x: &substrait::rel_common::hint::RuntimeConstraint,
y: &mut context::Context,
) -> diagnostic::Result<()> {
proto_field!(
x,
y,
advanced_extension,
crate::parse::extensions::advanced::parse_advanced_extension
);
Ok(())
}
fn parse_hint(x: &substrait::rel_common::Hint, y: &mut context::Context) -> diagnostic::Result<()> {
proto_field!(x, y, stats, parse_stats);
proto_field!(x, y, constraint, parse_runtime_constraint);
proto_primitive_field!(x, y, alias);
proto_field!(
x,
y,
advanced_extension,
crate::parse::extensions::advanced::parse_advanced_extension
);
Ok(())
}
fn parse_emit_mapping(
x: &i32,
_: &mut context::Context,
data_type: data::Type,
) -> diagnostic::Result<data::Type> {
let x: usize = (*x)
.try_into()
.map_err(|_| cause!(TypeInvalidSwizzle, "index cannot be negative"))?;
data_type
.index_struct(x)
.ok_or_else(|| cause!(TypeInvalidSwizzle, "index out of range"))
}
fn parse_emit_kind(
x: &substrait::rel_common::EmitKind,
y: &mut context::Context,
data_type: data::Type,
) -> diagnostic::Result<data::Type> {
match x {
substrait::rel_common::EmitKind::Direct(_) => Ok(data_type),
substrait::rel_common::EmitKind::Emit(x) => {
let fields = proto_repeated_field!(
x,
y,
output_mapping,
parse_emit_mapping,
|_, _, _, _, _| (),
data_type.clone()
)
.1
.into_iter()
.map(|x| x.unwrap_or_default())
.collect::<Vec<_>>();
Ok(data::new_struct(fields, false))
}
}
}
pub fn parse_rel_common(
x: &substrait::RelCommon,
y: &mut context::Context,
data_type: data::Type,
) -> diagnostic::Result<data::Type> {
proto_field!(x, y, hint, parse_hint);
let data_type = if proto_field!(
x,
y,
advanced_extension,
crate::parse::extensions::advanced::parse_advanced_extension
)
.1
.unwrap_or_default()
{
data::new_unresolved_type()
} else {
data_type
};
let data_type = proto_field!(x, y, emit_kind, parse_emit_kind, data_type.clone())
.1
.unwrap_or(data_type);
Ok(data_type)
}
macro_rules! handle_rel_common {
($input:expr, $context:expr) => {
let data_type = $context.data_type();
let result = proto_field!(
$input,
$context,
common,
crate::parse::relations::common::parse_rel_common,
data_type
)
.1;
if let Some(data_type) = result {
$context.set_schema(data_type);
}
};
}
macro_rules! handle_advanced_extension {
($input:expr, $context:expr) => {
if proto_field!(
$input,
$context,
advanced_extension,
crate::parse::extensions::advanced::parse_advanced_extension
)
.1
.unwrap_or_default()
{
$context.set_schema(std::sync::Arc::default());
}
};
}
macro_rules! handle_rel_input {
($input:expr, $context:expr) => {
handle_rel_input!($input, $context, input)
};
($input:expr, $context:expr, $field:ident) => {
proto_boxed_required_field!($input, $context, $field, crate::parse::relations::parse_rel)
.0
.data_type()
};
}
macro_rules! handle_rel_inputs {
($input:expr, $context:expr) => {
handle_rel_inputs!($input, $context, inputs)
};
($input:expr, $context:expr, $field:ident) => {
proto_repeated_field!($input, $context, $field, crate::parse::relations::parse_rel)
.0
.iter()
.map(|x| x.data_type())
};
}