use std::ptr::{self, NonNull};
use super::*;
use crate::core::{error, native_teardown::drop_device_owned_handle};
pub struct DataFrameMixedLeftJoinState {
handle: NonNull<cudf_sys::cudf_mixed_left_join_state_handle_state>,
domain: Arc<ExecutionDomain>,
left: DataFrame,
predicate: AstExpression,
options: DataFrameMixedJoinOptions,
}
impl std::fmt::Debug for DataFrameMixedLeftJoinState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DataFrameMixedLeftJoinState")
.field("left_rows", &self.left.num_rows())
.field("options", &self.options)
.finish_non_exhaustive()
}
}
unsafe impl Send for DataFrameMixedLeftJoinState {}
impl Drop for DataFrameMixedLeftJoinState {
fn drop(&mut self) {
drop_device_owned_handle(
self.handle.as_ptr(),
self.domain.device_id(),
"MixedLeftJoinState::drop",
|owned| unsafe { cudf_sys::cudf_mixed_left_join_state_destroy(owned) },
);
}
}
#[derive(Debug)]
pub struct DataFrameMixedLeftJoinFinalized {
state: DataFrameMixedLeftJoinState,
output_size: usize,
}
impl DataFrameMixedLeftJoinState {
pub fn new(
left: &DataFrame,
predicate: AstExpression,
options: DataFrameMixedJoinOptions,
exec: Exec<'_>,
) -> Result<Self> {
let operation = "dataframe::mixed_left_join_state::new";
let (left_keys, _, _) =
resolve_join_keys(options.on_keys(), options.left_on_keys(), options.right_on_keys(), operation)?;
if options.left_predicate_column_names().is_empty() || options.right_predicate_column_names().is_empty() {
return Err(Error::new_with(
ErrorCode::ForeignInvalidArgument,
operation,
"mixed join requires predicate columns",
));
}
let keys = resolve_column_names(left.columns_map(), &string_refs(&left_keys), operation)?;
let conditional =
resolve_column_names(left.columns_map(), &string_refs(options.left_predicate_column_names()), operation)?;
let keys = build_borrowed_table_view_from_columns(left.columns_map(), &keys)?;
let conditional = build_borrowed_table_view_from_columns(left.columns_map(), &conditional)?;
let mut domains = vec![conditional.execution_domain()];
predicate.literal_domains(&mut domains);
let execution = ResolvedExecution::many(keys.execution_domain(), domains, exec, operation)?;
let mut handle = ptr::null_mut();
error::check_status_in(
unsafe {
cudf_sys::cudf_mixed_left_join_state_create_ex(
keys.raw_handle(),
conditional.raw_handle(),
predicate.raw_handle(),
options.null_eq().to_join_raw(),
&mut handle,
execution.exec_options(),
)
},
operation,
)?;
Ok(Self {
handle: error::require_non_null(handle, operation, "mixed left join state")?,
domain: Arc::clone(execution.output_domain()),
left: left.clone(),
predicate,
options,
})
}
pub fn consume(&mut self, right: &DataFrame) -> Result<()> {
let operation = "dataframe::mixed_left_join_state::consume";
let tables = mixed_join_tables(&self.left, right, &self.options, operation)?;
let mut domains = vec![
tables.left_equality.execution_domain(),
tables.left_conditional.execution_domain(),
tables.right_equality.execution_domain(),
tables.right_conditional.execution_domain(),
];
self.predicate.literal_domains(&mut domains);
let execution = ResolvedExecution::many(&self.domain, domains, Exec::RETAINED, operation)?;
error::check_status_in(
unsafe {
cudf_sys::cudf_mixed_left_join_state_consume_ex(
self.handle.as_ptr(),
tables.right_equality.raw_handle(),
tables.right_conditional.raw_handle(),
execution.exec_options(),
)
},
operation,
)
}
pub fn device_allocated_size_bytes(&self) -> Result<usize> {
let mut bytes = 0;
error::check_status_in(
unsafe { cudf_sys::cudf_mixed_left_join_state_device_allocated_size(self.handle.as_ptr(), &mut bytes) },
"dataframe::mixed_left_join_state::device_allocated_size_bytes",
)?;
Ok(bytes)
}
pub fn seal(self, anti: bool) -> Result<DataFrameMixedLeftJoinFinalized> {
let operation = "dataframe::mixed_left_join_state::seal";
let execution = ResolvedExecution::unary(&self.domain, Exec::RETAINED, operation)?;
error::check_status_in(
unsafe {
cudf_sys::cudf_mixed_left_join_state_seal_ex(
self.handle.as_ptr(),
if anti {
cudf_sys::CUDF_JOIN_KIND_LEFT_ANTI_JOIN
} else {
cudf_sys::CUDF_JOIN_KIND_LEFT_SEMI_JOIN
},
execution.exec_options(),
)
},
operation,
)?;
let mut output_size = 0;
error::check_status_in(
unsafe { cudf_sys::cudf_mixed_left_join_state_output_size(self.handle.as_ptr(), &mut output_size) },
operation,
)?;
Ok(DataFrameMixedLeftJoinFinalized { state: self, output_size })
}
}
impl DataFrameMixedLeftJoinFinalized {
pub fn output_size(&self) -> usize {
self.output_size
}
pub fn device_allocated_size_bytes(&self) -> Result<usize> {
self.state.device_allocated_size_bytes()
}
pub fn gather_map_reservation_size_bytes(&self) -> Result<usize> {
self.output_size.checked_mul(std::mem::size_of::<i32>()).ok_or_else(|| {
Error::new_with(
ErrorCode::SizeOverflow,
"dataframe::mixed_left_join_finalized::gather_map_reservation_size_bytes",
"gather-map bytes overflow usize",
)
})
}
pub fn materialize_indices(&self) -> Result<DataFrameJoinIndices> {
let operation = "dataframe::mixed_left_join_finalized::materialize_indices";
let execution = ResolvedExecution::unary(&self.state.domain, Exec::RETAINED, operation)?;
let mut out = ptr::null_mut();
error::check_status_in(
unsafe {
cudf_sys::cudf_mixed_left_join_state_materialize_indices_ex(
self.state.handle.as_ptr(),
&mut out,
execution.exec_options(),
)
},
operation,
)?;
let indices = unsafe { Column::from_raw_with_domain(out, Arc::clone(execution.output_domain())) }?;
single_side_indices_from_raw(join::SingleSideJoinIndices { indices }, operation)
}
}