// ----------------- inline void incompatible_join_visitor(SEXP left, SEXP right, const std::string& name_left, const std::string& name_right) { std::stringstream s ; s << "Can't join on '" << name_left << "' x '" << name_right << "' because of incompatible types (" << get_single_class(left) << "/" << get_single_class(right) << ")" ; stop( s.str() ) ; }
JoinVisitor* join_visitor(SEXP left, SEXP right, const SymbolString& name_left, const SymbolString& name_right, bool warn_) { // handle Date separately bool lhs_date = Rf_inherits(left, "Date"); bool rhs_date = Rf_inherits(right, "Date"); switch (lhs_date + rhs_date) { case 2: return date_join_visitor<ACCEPT_NA_MATCH>(left, right); case 1: stop("cannot join a Date object with an object that is not a Date object"); case 0: break; default: break; } bool lhs_time = Rf_inherits(left, "POSIXct"); bool rhs_time = Rf_inherits(right, "POSIXct"); switch (lhs_time + rhs_time) { case 2: return new POSIXctJoinVisitor<ACCEPT_NA_MATCH>(left, right); case 1: stop("cannot join a POSIXct object with an object that is not a POSIXct object"); case 0: break; default: break; } switch (TYPEOF(left)) { case CPLXSXP: { switch (TYPEOF(right)) { case CPLXSXP: return new JoinVisitorImpl<CPLXSXP, CPLXSXP, ACCEPT_NA_MATCH>(left, right); default: break; } break; } case INTSXP: { bool lhs_factor = Rf_inherits(left, "factor"); switch (TYPEOF(right)) { case INTSXP: { bool rhs_factor = Rf_inherits(right, "factor"); if (lhs_factor && rhs_factor) { if (same_levels(left, right)) { return new JoinVisitorImpl<INTSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); } else { if (warn_) Rf_warning("joining factors with different levels, coercing to character vector"); return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } } else if (!lhs_factor && !rhs_factor) { return new JoinVisitorImpl<INTSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); } break; } case REALSXP: { if (!lhs_factor && is_bare_vector(right)) { return new JoinVisitorImpl<INTSXP, REALSXP, ACCEPT_NA_MATCH>(left, right); } break; // what else: perhaps we can have INTSXP which is a Date and REALSXP which is a Date too ? } case LGLSXP: { if (!lhs_factor) { return new JoinVisitorImpl<INTSXP, LGLSXP, ACCEPT_NA_MATCH>(left, right); } break; } case STRSXP: { if (lhs_factor) { if (warn_) Rf_warning("joining factor and character vector, coercing into character vector"); return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } } default: break; } break; } case REALSXP: { switch (TYPEOF(right)) { case REALSXP: return new JoinVisitorImpl<REALSXP, REALSXP, ACCEPT_NA_MATCH>(left, right); case INTSXP: return new JoinVisitorImpl<REALSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); default: break; } } case LGLSXP: { switch (TYPEOF(right)) { case LGLSXP: return new JoinVisitorImpl<LGLSXP, LGLSXP, ACCEPT_NA_MATCH> (left, right); case INTSXP: return new JoinVisitorImpl<LGLSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); case REALSXP: return new JoinVisitorImpl<LGLSXP, REALSXP, ACCEPT_NA_MATCH>(left, right); default: break; } break; } case STRSXP: { switch (TYPEOF(right)) { case INTSXP: { if (Rf_inherits(right, "factor")) { if (warn_) Rf_warning("joining character vector and factor, coercing into character vector"); return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } break; } case STRSXP: { return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } default: break; } break; } default: break; } stop("Can't join on '%s' x '%s' because of incompatible types (%s / %s)", name_left.get_utf8_cstring(), name_right.get_utf8_cstring(), get_single_class(left), get_single_class(right) ); return 0; }
// ----------------- inline void incompatible_join_visitor(SEXP left, SEXP right, const std::string& name_left, const std::string& name_right) { stop( "Can't join on '%s' x '%s' because of incompatible types (%s / %s)", name_left, name_right, get_single_class(left), get_single_class(right) ) ; }