| 69 | } |
| 70 | |
| 71 | std::shared_ptr<VectorFunction> getVectorFunction( |
| 72 | const std::string& name, |
| 73 | const std::vector<TypePtr>& inputTypes, |
| 74 | const std::vector<VectorPtr>& constantInputs, |
| 75 | const core::QueryConfig& config, |
| 76 | const TypePtr& resultType) { |
| 77 | auto sanitizedName = sanitizeName(name); |
| 78 | |
| 79 | if (!constantInputs.empty()) { |
| 80 | BOLT_CHECK_EQ(inputTypes.size(), constantInputs.size()); |
| 81 | } |
| 82 | |
| 83 | // Zip `inputTypes` and `constantInputs` vectors into a single vector of |
| 84 | // `VectorFunctionArg`. |
| 85 | std::vector<VectorFunctionArg> inputArgs; |
| 86 | inputArgs.reserve(inputTypes.size()); |
| 87 | |
| 88 | for (vector_size_t i = 0; i < inputTypes.size(); ++i) { |
| 89 | inputArgs.push_back({ |
| 90 | inputTypes[i], |
| 91 | constantInputs.size() > i ? constantInputs[i] : nullptr, |
| 92 | }); |
| 93 | } |
| 94 | |
| 95 | return vectorFunctionFactories().withRLock( |
| 96 | [&sanitizedName, &inputArgs, &config, &inputTypes, &resultType, &name]( |
| 97 | auto& functionMap) -> std::shared_ptr<VectorFunction> { |
| 98 | if (auto destType = resolveVectorFunction(sanitizedName, inputTypes)) { |
| 99 | BOLT_USER_CHECK( |
| 100 | (resultType == nullptr || |
| 101 | (destType != nullptr && destType->equivalent(*resultType))), |
| 102 | "Found incompatible return types for vector function '{}' ({} vs. {}) with input types ({}).", |
| 103 | name, |
| 104 | destType, |
| 105 | resultType, |
| 106 | folly::join(", ", inputTypes)); |
| 107 | auto functionIterator = functionMap.find(sanitizedName); |
| 108 | return functionIterator->second.factory( |
| 109 | sanitizedName, inputArgs, config); |
| 110 | } |
| 111 | return nullptr; |
| 112 | }); |
| 113 | } |
| 114 | |
| 115 | /// Registers a new vector function. When overwrite = true, previous functions |
| 116 | /// with the given name will be replaced. |