| 1069 | } |
| 1070 | |
| 1071 | static QueryPlanNode buildPhysicalJoinImpl( |
| 1072 | std::vector<QueryPlanNode *> children, |
| 1073 | JoinOperator join_operator, |
| 1074 | JoinExpressionActions expression_actions, |
| 1075 | JoinSettings join_settings, |
| 1076 | JoinAlgorithmParams join_algorithm_params, |
| 1077 | SortingStep::Settings sorting_settings, |
| 1078 | const ActionsDAG::NodeRawConstPtrs & actions_after_join, |
| 1079 | const QueryPlanOptimizationSettings & optimization_settings, |
| 1080 | QueryPlan::Nodes & nodes, |
| 1081 | LogicalJoinInfo && logical_join_info) |
| 1082 | { |
| 1083 | auto * logical_lookup = typeid_cast<JoinStepLogicalLookup *>(children.back()->step.get()); |
| 1084 | |
| 1085 | auto table_join = std::make_shared<TableJoin>(join_settings, logical_lookup && logical_lookup->useNulls(), |
| 1086 | Context::getGlobalContextInstance()->getGlobalTemporaryVolume(), |
| 1087 | Context::getGlobalContextInstance()->getTempDataOnDisk()); |
| 1088 | |
| 1089 | PreparedJoinStorage prepared_join_storage; |
| 1090 | if (logical_lookup) |
| 1091 | { |
| 1092 | prepared_join_storage = std::move(logical_lookup->getPreparedJoinStorage()); |
| 1093 | prepared_join_storage.visit([&table_join](const auto & storage_) |
| 1094 | { |
| 1095 | table_join->setStorageJoin(storage_); |
| 1096 | }); |
| 1097 | } |
| 1098 | |
| 1099 | auto & join_expression = join_operator.expression; |
| 1100 | |
| 1101 | bool is_join_without_expression = isCrossOrComma(join_operator.kind) || isPaste(join_operator.kind); |
| 1102 | /// When we do JOIN ON NULL or JOIN ON 1 we create dummy columns and in fact joining on 1 = 0 or 1 = 1. |
| 1103 | /// For INNER JOIN we could just do CROSS, but for OUTER result depends on whether any table is empty or not. |
| 1104 | if ((!is_join_without_expression && join_expression.empty()) || |
| 1105 | (join_expression.size() == 1 |
| 1106 | && join_expression[0].getType()->onlyNull() |
| 1107 | && std::get<0>(join_expression[0].asBinaryPredicate()) == JoinConditionOperator::Unknown)) |
| 1108 | { |
| 1109 | UInt8 rhs_value = join_expression.empty() ? 1 : 0; |
| 1110 | join_expression.clear(); |
| 1111 | |
| 1112 | auto actions_dag = expression_actions.getActionsDAG(); |
| 1113 | |
| 1114 | auto dt = std::make_shared<DataTypeUInt8>(); |
| 1115 | |
| 1116 | auto lhs_column = dt->createColumnConst(0, 1); |
| 1117 | JoinActionRef lhs(&actions_dag->addColumn(std::move(lhs_column), dt, "__lhs_const"), expression_actions); |
| 1118 | lhs.setSourceRelations(BitSet().set(0)); |
| 1119 | |
| 1120 | auto rhs_column = dt->createColumnConst(0, rhs_value); |
| 1121 | JoinActionRef rhs(&actions_dag->addColumn(std::move(rhs_column), dt, "__rhs_const"), expression_actions); |
| 1122 | rhs.setSourceRelations(BitSet().set(1)); |
| 1123 | |
| 1124 | join_expression.push_back(JoinActionRef::transform({lhs, rhs}, JoinActionRef::AddFunction(JoinConditionOperator::Equals))); |
| 1125 | |
| 1126 | table_join->setIsJoinWithConstant(true); |
| 1127 | } |
| 1128 |
no test coverage detected