Current section
Files
Jump to
Current section
Files
c_src/duckdb/src/execution/operator/helper/physical_load.cpp
#include "duckdb/execution/operator/helper/physical_load.hpp"
#include "duckdb/common/file_system.hpp"
#include "duckdb/common/windows.hpp"
#include "duckdb/main/database.hpp"
#include "duckdb/main/client_context.hpp"
#ifndef _WIN32
#include <dlfcn.h>
#else
#define RTLD_LAZY 0
#define RTLD_LOCAL 0
#endif
namespace duckdb {
#ifdef _WIN32
void *dlopen(const char *file, int mode) {
D_ASSERT(file);
return (void *)LoadLibrary(file);
}
void *dlsym(void *handle, const char *name) {
D_ASSERT(handle);
return (void *)GetProcAddress((HINSTANCE)handle, name);
}
#endif
void PhysicalLoad::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p,
LocalSourceState &lstate) const {
auto &fs = FileSystem::GetFileSystem(context.client);
auto filename = fs.ConvertSeparators(info->filename);
if (!fs.FileExists(filename)) {
throw InvalidInputException("File %s not found", filename);
}
auto lib_hdl = dlopen(filename.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!lib_hdl) {
throw InvalidInputException("File %s could not be loaded", filename);
}
auto basename = fs.ExtractBaseName(filename);
auto init_fun_name = basename + "_init";
auto version_fun_name = basename + "_version";
void (*init_fun)(DatabaseInstance &);
const char *(*version_fun)(void);
*(void **)(&init_fun) = dlsym(lib_hdl, init_fun_name.c_str());
if (init_fun == nullptr) {
throw InvalidInputException("File %s did not contain initialization function %s", filename, init_fun_name);
}
*(void **)(&version_fun) = dlsym(lib_hdl, version_fun_name.c_str());
if (init_fun == nullptr) {
throw InvalidInputException("File %s did not contain version function %s", filename, version_fun_name);
}
auto extension_version = std::string((*version_fun)());
auto engine_version = DuckDB::LibraryVersion();
if (extension_version != engine_version) {
throw InvalidInputException("Extension %s version (%s) does not match DuckDB version (%s)", filename,
extension_version, engine_version);
}
try {
(*init_fun)(*context.client.db);
} catch (Exception &e) {
throw InvalidInputException("Initialization function %s from file %s threw an exception: %s", init_fun_name,
filename, e.what());
}
}
} // namespace duckdb