use std::{
fmt,
ptr::{self, NonNull},
sync::Arc,
};
mod dataframe;
pub use dataframe::{DataFrameMixedLeftJoinFinalized, DataFrameMixedLeftJoinState};
#[cfg(any(test, feature = "test-hooks"))]
pub(crate) use dataframe::{
trigger_merge_reassembly_key_count_error_for_test, trigger_projected_cross_join_input_row_limit_for_test,
trigger_projected_cross_join_output_row_overflow_for_test,
};
mod options;
use domain::{
compatible_conditional_join_domain, compatible_filter_join_indices_domain, compatible_join_indices_domain,
compatible_mixed_join_domain,
};
pub(crate) use options::{FilteredJoinOptions, HashJoinOptions};
pub use options::{JoinType, MergeOptions, NullEquality, NullableJoin};
use crate::{
core::{
column::{Column, ColumnView},
error::{
self, Error, ErrorCode, FACT_ACTUAL_ROWS, FACT_EXPECTED_ROWS, FACT_LEFT_TYPE_ID, FACT_RIGHT_TYPE_ID, Result,
},
native_teardown::drop_device_owned_handle,
table::{Table, TableView},
types::TypeId,
},
ops::ast::AstExpression,
runtime::{execution_context::Exec, execution_domain::ExecutionDomain, execution_resolver::ResolvedExecution},
};
#[derive(Debug)]
pub(crate) struct JoinIndices {
pub left: Column,
pub right: Column,
}
#[derive(Debug)]
pub(crate) struct SingleSideJoinIndices {
pub indices: Column,
}
#[derive(Debug)]
pub(crate) struct JoinSides {
pub left: Table,
pub right: Table,
}
#[derive(Clone, Copy)]
pub(crate) struct SplitJoinTables<'a, 'view> {
pub(crate) left_keys: &'a TableView<'view>,
pub(crate) right_keys: &'a TableView<'view>,
pub(crate) left_payload: &'a TableView<'view>,
pub(crate) right_payload: &'a TableView<'view>,
}
#[derive(Clone, Copy)]
struct FilterJoinInputs<'a, 'view> {
left: &'a TableView<'view>,
right: &'a TableView<'view>,
left_indices: &'a ColumnView<'view>,
right_indices: &'a ColumnView<'view>,
predicate: &'a AstExpression,
}
#[derive(Clone, Copy)]
struct MixedJoinTables<'a, 'view> {
left_equality: &'a TableView<'view>,
right_equality: &'a TableView<'view>,
left_conditional: &'a TableView<'view>,
right_conditional: &'a TableView<'view>,
}
#[derive(Clone, Copy)]
pub(crate) struct JoinCallContext<'a> {
output_domain: &'a Arc<ExecutionDomain>,
exec_options: &'a cudf_sys::cudf_exec_options_t,
operation: &'static str,
}
impl<'a> JoinCallContext<'a> {
pub(crate) fn new(
output_domain: &'a Arc<ExecutionDomain>,
exec_options: &'a cudf_sys::cudf_exec_options_t,
operation: &'static str,
) -> Self {
Self { output_domain, exec_options, operation }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum SizedConditionalPairJoinType {
Inner,
Left,
}
impl SizedConditionalPairJoinType {
fn as_str(self) -> &'static str {
match self {
Self::Inner => "inner",
Self::Left => "left",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum SizedMixedJoinType {
Inner,
Left,
Full,
}
impl SizedMixedJoinType {
fn as_str(self) -> &'static str {
match self {
Self::Inner => "inner",
Self::Left => "left",
Self::Full => "full",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum SizedMixedSingleSideJoinType {
LeftSemi,
LeftAnti,
}
impl SizedMixedSingleSideJoinType {
fn as_str(self) -> &'static str {
match self {
Self::LeftSemi => "left_semi",
Self::LeftAnti => "left_anti",
}
}
}
mod conditional;
mod domain;
mod filter;
mod hash;
mod mixed;
pub(crate) use conditional::*;
pub(crate) use filter::*;
pub(crate) use hash::*;
pub(crate) use mixed::*;
fn check_join_indices_status(
status: cudf_sys::cudf_status_t,
null_equality: NullEquality,
operation: &'static str,
) -> Result<()> {
error::check_status_in_with_details(
status,
operation,
[
("null_equality", format!("{:?}", null_equality).to_lowercase()),
("execution_authority", "resolved_domain".to_string()),
],
)
}
struct HashJoinHandle {
handle: NonNull<cudf_sys::cudf_hash_join_handle_state>,
_domain: Arc<ExecutionDomain>,
}
struct FilteredJoinHandle {
handle: NonNull<cudf_sys::cudf_filtered_join_handle_state>,
_domain: Arc<ExecutionDomain>,
}
struct FilteredJoinProbeHandle {
handle: NonNull<cudf_sys::cudf_filtered_join_probe_handle_state>,
_domain: Arc<ExecutionDomain>,
}
struct ConditionalFullJoinSizeDataHandle {
handle: NonNull<cudf_sys::cudf_conditional_full_join_size_data_handle_state>,
_domain: Arc<ExecutionDomain>,
}
struct MixedJoinSizeDataHandle {
handle: NonNull<cudf_sys::cudf_mixed_join_size_data_handle_state>,
_domain: Arc<ExecutionDomain>,
}
impl fmt::Debug for HashJoinHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HashJoinHandle").field("handle", &self.handle).finish()
}
}
impl fmt::Debug for FilteredJoinHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FilteredJoinHandle").field("handle", &self.handle).finish()
}
}
impl fmt::Debug for FilteredJoinProbeHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FilteredJoinProbeHandle").field("handle", &self.handle).finish()
}
}
impl fmt::Debug for ConditionalFullJoinSizeDataHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ConditionalFullJoinSizeDataHandle").field("handle", &self.handle).finish()
}
}
impl fmt::Debug for MixedJoinSizeDataHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MixedJoinSizeDataHandle").field("handle", &self.handle).finish()
}
}
unsafe impl Send for HashJoinHandle {}
unsafe impl Sync for HashJoinHandle {}
unsafe impl Send for FilteredJoinHandle {}
unsafe impl Sync for FilteredJoinHandle {}
unsafe impl Send for FilteredJoinProbeHandle {}
unsafe impl Sync for FilteredJoinProbeHandle {}
unsafe impl Send for ConditionalFullJoinSizeDataHandle {}
unsafe impl Sync for ConditionalFullJoinSizeDataHandle {}
unsafe impl Send for MixedJoinSizeDataHandle {}
unsafe impl Sync for MixedJoinSizeDataHandle {}
impl Drop for HashJoinHandle {
fn drop(&mut self) {
drop_device_owned_handle(
self.handle.as_ptr(),
self._domain.device_id(),
"HashJoinHandle::drop",
|owned| unsafe { cudf_sys::cudf_hash_join_destroy(owned) },
);
}
}
impl Drop for FilteredJoinHandle {
fn drop(&mut self) {
drop_device_owned_handle(
self.handle.as_ptr(),
self._domain.device_id(),
"FilteredJoinHandle::drop",
|owned| unsafe { cudf_sys::cudf_filtered_join_destroy(owned) },
);
}
}
impl Drop for FilteredJoinProbeHandle {
fn drop(&mut self) {
drop_device_owned_handle(
self.handle.as_ptr(),
self._domain.device_id(),
"FilteredJoinProbeHandle::drop",
|owned| unsafe { cudf_sys::cudf_filtered_join_probe_destroy(owned) },
);
}
}
impl Drop for ConditionalFullJoinSizeDataHandle {
fn drop(&mut self) {
drop_device_owned_handle(
self.handle.as_ptr(),
self._domain.device_id(),
"ConditionalFullJoinSizeDataHandle::drop",
|owned| unsafe { cudf_sys::cudf_conditional_full_join_size_data_destroy(owned) },
);
}
}
impl Drop for MixedJoinSizeDataHandle {
fn drop(&mut self) {
drop_device_owned_handle(
self.handle.as_ptr(),
self._domain.device_id(),
"MixedJoinSizeDataHandle::drop",
|owned| unsafe { cudf_sys::cudf_mixed_join_size_data_destroy(owned) },
);
}
}
#[derive(Clone)]
pub(crate) struct HashJoin {
handle: Arc<HashJoinHandle>,
build: Arc<Table>,
options: HashJoinOptions,
}
#[derive(Clone)]
pub(crate) struct FilteredJoin {
handle: Arc<FilteredJoinHandle>,
build: Arc<Table>,
options: FilteredJoinOptions,
}
pub(crate) struct FilteredJoinProbeState {
handle: FilteredJoinProbeHandle,
join: FilteredJoin,
output_domain: Arc<ExecutionDomain>,
output_size: usize,
semi_join: bool,
}
pub(crate) struct ConditionalFullJoinSizeData<'a> {
handle: ConditionalFullJoinSizeDataHandle,
output_domain: Arc<ExecutionDomain>,
output_size: usize,
_predicate: &'a AstExpression,
}
pub(crate) struct MixedJoinSizeData<'a> {
handle: MixedJoinSizeDataHandle,
output_domain: Arc<ExecutionDomain>,
output_size: usize,
join_type: SizedMixedJoinType,
_predicate: &'a AstExpression,
}
pub(crate) struct MixedSingleSideJoinSizeData<'a> {
handle: MixedJoinSizeDataHandle,
output_domain: Arc<ExecutionDomain>,
output_size: usize,
join_type: SizedMixedSingleSideJoinType,
_predicate: &'a AstExpression,
}
impl fmt::Debug for HashJoin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HashJoin")
.field("options", &self.options)
.field("placement", &self.build.execution_domain().placement())
.finish()
}
}
impl fmt::Debug for FilteredJoin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FilteredJoin")
.field("options", &self.options)
.field("placement", &self.build.execution_domain().placement())
.finish()
}
}
impl fmt::Debug for FilteredJoinProbeState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FilteredJoinProbeState")
.field("join_type", &if self.semi_join { "left_semi" } else { "left_anti" })
.field("output_size", &self.output_size)
.field("placement", &self.output_domain.placement())
.finish()
}
}
impl fmt::Debug for ConditionalFullJoinSizeData<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ConditionalFullJoinSizeData")
.field("join_type", &"full")
.field("output_size", &self.output_size)
.field("placement", &self.output_domain.placement())
.finish()
}
}
impl fmt::Debug for MixedJoinSizeData<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MixedJoinSizeData")
.field("join_type", &self.join_type.as_str())
.field("output_size", &self.output_size)
.field("placement", &self.output_domain.placement())
.finish()
}
}
impl fmt::Debug for MixedSingleSideJoinSizeData<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MixedSingleSideJoinSizeData")
.field("join_type", &self.join_type.as_str())
.field("output_size", &self.output_size)
.field("placement", &self.output_domain.placement())
.finish()
}
}