| 200 | } |
| 201 | |
| 202 | Status HashJoinSchema::ValidateSchemas(JoinType join_type, const Schema& left_schema, |
| 203 | const std::vector<FieldRef>& left_keys, |
| 204 | const std::vector<FieldRef>& left_output, |
| 205 | const Schema& right_schema, |
| 206 | const std::vector<FieldRef>& right_keys, |
| 207 | const std::vector<FieldRef>& right_output, |
| 208 | const std::string& left_field_name_suffix, |
| 209 | const std::string& right_field_name_suffix) { |
| 210 | // Checks for key fields: |
| 211 | // 1. Key field refs must match exactly one input field |
| 212 | // 2. Same number of key fields on left and right |
| 213 | // 3. At least one key field |
| 214 | // 4. Equal data types for corresponding key fields |
| 215 | // 5. Some data types may not be allowed in a key field or non-key field |
| 216 | // |
| 217 | if (left_keys.size() != right_keys.size()) { |
| 218 | return Status::Invalid("Different number of key fields on left (", left_keys.size(), |
| 219 | ") and right (", right_keys.size(), ") side of the join"); |
| 220 | } |
| 221 | if (left_keys.empty()) { |
| 222 | return Status::Invalid("Join key cannot be empty"); |
| 223 | } |
| 224 | for (size_t i = 0; i < left_keys.size() + right_keys.size(); ++i) { |
| 225 | bool left_side = i < left_keys.size(); |
| 226 | const FieldRef& field_ref = |
| 227 | left_side ? left_keys[i] : right_keys[i - left_keys.size()]; |
| 228 | Result<FieldPath> result = field_ref.FindOne(left_side ? left_schema : right_schema); |
| 229 | if (!result.ok()) { |
| 230 | return Status::Invalid("No match or multiple matches for key field reference ", |
| 231 | field_ref.ToString(), left_side ? " on left " : " on right ", |
| 232 | "side of the join"); |
| 233 | } |
| 234 | const FieldPath& match = result.ValueUnsafe(); |
| 235 | const std::shared_ptr<DataType>& type = |
| 236 | (left_side ? left_schema.fields() : right_schema.fields())[match[0]]->type(); |
| 237 | if (!IsTypeSupported(*type)) { |
| 238 | return Status::Invalid("Data type ", *type, " is not supported in join key field"); |
| 239 | } |
| 240 | } |
| 241 | for (size_t i = 0; i < left_keys.size(); ++i) { |
| 242 | const FieldRef& left_ref = left_keys[i]; |
| 243 | const FieldRef& right_ref = right_keys[i]; |
| 244 | int left_id = left_ref.FindOne(left_schema).ValueUnsafe()[0]; |
| 245 | int right_id = right_ref.FindOne(right_schema).ValueUnsafe()[0]; |
| 246 | const std::shared_ptr<DataType>& left_type = left_schema.fields()[left_id]->type(); |
| 247 | const std::shared_ptr<DataType>& right_type = right_schema.fields()[right_id]->type(); |
| 248 | if (!HashJoinDictUtil::KeyDataTypesValid(left_type, right_type)) { |
| 249 | return Status::Invalid( |
| 250 | "Incompatible data types for corresponding join field keys: ", |
| 251 | left_ref.ToString(), " of type ", left_type->ToString(), " and ", |
| 252 | right_ref.ToString(), " of type ", right_type->ToString()); |
| 253 | } |
| 254 | } |
| 255 | for (const auto& field : left_schema.fields()) { |
| 256 | const auto& type = *field->type(); |
| 257 | if (!IsTypeSupported(type)) { |
| 258 | return Status::Invalid("Data type ", type, |
| 259 | " is not supported in join non-key field ", field->name()); |