| 121 | } |
| 122 | |
| 123 | std::unique_ptr<BoundBaseScanSource> Binder::bindFileScanSource(const BaseScanSource& scanSource, |
| 124 | const options_t& options, const std::vector<std::string>& columnNames, |
| 125 | const std::vector<LogicalType>& columnTypes) { |
| 126 | auto fileSource = scanSource.constPtrCast<FileScanSource>(); |
| 127 | auto filePaths = bindFilePaths(fileSource->filePaths); |
| 128 | auto boundOptions = bindParsingOptions(options); |
| 129 | FileTypeInfo fileTypeInfo; |
| 130 | |
| 131 | if (boundOptions.contains(FileScanInfo::FILE_FORMAT_OPTION_NAME)) { |
| 132 | auto fileFormat = boundOptions.at(FileScanInfo::FILE_FORMAT_OPTION_NAME).toString(); |
| 133 | fileTypeInfo = FileTypeInfo{FileTypeUtils::fromString(fileFormat), fileFormat}; |
| 134 | } else { |
| 135 | fileTypeInfo = bindFileTypeInfo(filePaths); |
| 136 | } |
| 137 | // If we defined a certain FileType, we have to ensure the path is a file, not something else |
| 138 | // (e.g. an existed directory) |
| 139 | if (fileTypeInfo.fileType != FileType::UNKNOWN) { |
| 140 | for (const auto& filePath : filePaths) { |
| 141 | if (!LocalFileSystem::fileExists(filePath) && LocalFileSystem::isLocalPath(filePath)) { |
| 142 | throw BinderException{std::format("Provided path is not a file: {}.", filePath)}; |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | boundOptions.erase(FileScanInfo::FILE_FORMAT_OPTION_NAME); |
| 147 | // Bind file configuration |
| 148 | auto fileScanInfo = std::make_unique<FileScanInfo>(std::move(fileTypeInfo), filePaths); |
| 149 | fileScanInfo->options = std::move(boundOptions); |
| 150 | TableFunction func; |
| 151 | if (handleFileViaFunction(clientContext, filePaths)) { |
| 152 | func = VirtualFileSystem::GetUnsafe(*clientContext)->getHandleFunction(filePaths[0]); |
| 153 | } else { |
| 154 | func = getScanFunction(fileScanInfo->fileTypeInfo, *fileScanInfo); |
| 155 | } |
| 156 | // Bind table function |
| 157 | auto bindInput = TableFuncBindInput(); |
| 158 | bindInput.addLiteralParam(Value::createValue(filePaths[0])); |
| 159 | auto extraInput = std::make_unique<ExtraScanTableFuncBindInput>(); |
| 160 | extraInput->fileScanInfo = fileScanInfo->copy(); |
| 161 | extraInput->expectedColumnNames = columnNames; |
| 162 | extraInput->expectedColumnTypes = LogicalType::copy(columnTypes); |
| 163 | extraInput->tableFunction = &func; |
| 164 | bindInput.extraInput = std::move(extraInput); |
| 165 | bindInput.binder = this; |
| 166 | auto bindData = func.bindFunc(clientContext, &bindInput); |
| 167 | auto info = BoundTableScanInfo(func, std::move(bindData)); |
| 168 | return std::make_unique<BoundTableScanSource>(ScanSourceType::FILE, std::move(info)); |
| 169 | } |
| 170 | |
| 171 | std::unique_ptr<BoundBaseScanSource> Binder::bindQueryScanSource(const BaseScanSource& scanSource, |
| 172 | const options_t& options, const std::vector<std::string>& columnNames, |
nothing calls this directly
no test coverage detected