From fe00c07aea2bdefce57f0540cf38ba2265730a55 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Thu, 31 Jul 2025 06:25:42 -0400 Subject: [PATCH] Initial OSLog table function, without data --- CMakeLists.txt | 15 ++--- src/include/oslog_extension.hpp | 8 +-- src/oslog_extension.cpp | 52 ++++-------------- src/oslog_table.hpp | 9 +++ src/oslog_table.mm | 97 +++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 53 deletions(-) create mode 100644 src/oslog_table.hpp create mode 100644 src/oslog_table.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index a4dffe3..c3f6e4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,25 +3,22 @@ cmake_minimum_required(VERSION 3.5) # Set extension name here set(TARGET_NAME oslog) -# DuckDB's extension distribution supports vcpkg. As such, dependencies can be added in ./vcpkg.json and then -# used in cmake with find_package. Feel free to remove or replace with other dependencies. -# Note that it should also be removed from vcpkg.json to prevent needlessly installing it.. -find_package(OpenSSL REQUIRED) - set(EXTENSION_NAME ${TARGET_NAME}_extension) set(LOADABLE_EXTENSION_NAME ${TARGET_NAME}_loadable_extension) project(${TARGET_NAME}) include_directories(src/include) -set(EXTENSION_SOURCES src/oslog_extension.cpp) +set(EXTENSION_SOURCES src/oslog_extension.cpp src/oslog_table.mm) build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES}) build_loadable_extension(${TARGET_NAME} " " ${EXTENSION_SOURCES}) -# Link OpenSSL in both the static library as the loadable extension -target_link_libraries(${EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto) -target_link_libraries(${LOADABLE_EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(${EXTENSION_NAME} "-framework Foundation") +target_link_libraries(${EXTENSION_NAME} "-framework OSLog") + +target_link_libraries(${LOADABLE_EXTENSION_NAME} "-framework Foundation") +target_link_libraries(${LOADABLE_EXTENSION_NAME} "-framework OSLog") install( TARGETS ${EXTENSION_NAME} diff --git a/src/include/oslog_extension.hpp b/src/include/oslog_extension.hpp index 2ce3917..5e85adf 100644 --- a/src/include/oslog_extension.hpp +++ b/src/include/oslog_extension.hpp @@ -5,10 +5,10 @@ namespace duckdb { class OslogExtension : public Extension { -public: - void Load(DuckDB &db) override; - std::string Name() override; - std::string Version() const override; + public: + void Load(DuckDB& db) override; + std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/src/oslog_extension.cpp b/src/oslog_extension.cpp index 2928f79..d4d6aef 100644 --- a/src/oslog_extension.cpp +++ b/src/oslog_extension.cpp @@ -1,56 +1,28 @@ #define DUCKDB_EXTENSION_MAIN #include "oslog_extension.hpp" + #include "duckdb.hpp" #include "duckdb/common/exception.hpp" -#include "duckdb/common/string_util.hpp" -#include "duckdb/function/scalar_function.hpp" #include "duckdb/main/extension_util.hpp" -#include -// OpenSSL linked through vcpkg -#include +#include "oslog_table.hpp" namespace duckdb { -inline void OslogScalarFun(DataChunk &args, ExpressionState &state, Vector &result) { - auto &name_vector = args.data[0]; - UnaryExecutor::Execute(name_vector, result, args.size(), [&](string_t name) { - return StringVector::AddString(result, "Oslog " + name.GetString() + " 🐥"); - }); -} - -inline void OslogOpenSSLVersionScalarFun(DataChunk &args, ExpressionState &state, Vector &result) { - auto &name_vector = args.data[0]; - UnaryExecutor::Execute(name_vector, result, args.size(), [&](string_t name) { - return StringVector::AddString(result, "Oslog " + name.GetString() + ", my linked OpenSSL version is " + - OPENSSL_VERSION_TEXT); - }); +void OslogExtension::Load(DuckDB& db) { + ExtensionUtil::RegisterFunction(*db.instance, oslog::GetTableFunction()); } -static void LoadInternal(DatabaseInstance &instance) { - // Register a scalar function - auto oslog_scalar_function = ScalarFunction("oslog", {LogicalType::VARCHAR}, LogicalType::VARCHAR, OslogScalarFun); - ExtensionUtil::RegisterFunction(instance, oslog_scalar_function); - - // Register another scalar function - auto oslog_openssl_version_scalar_function = ScalarFunction("oslog_openssl_version", {LogicalType::VARCHAR}, - LogicalType::VARCHAR, OslogOpenSSLVersionScalarFun); - ExtensionUtil::RegisterFunction(instance, oslog_openssl_version_scalar_function); -} - -void OslogExtension::Load(DuckDB &db) { - LoadInternal(*db.instance); -} std::string OslogExtension::Name() { - return "oslog"; + return "oslog"; } std::string OslogExtension::Version() const { #ifdef EXT_VERSION_OSLOG - return EXT_VERSION_OSLOG; + return EXT_VERSION_OSLOG; #else - return ""; + return ""; #endif } @@ -58,13 +30,13 @@ std::string OslogExtension::Version() const { extern "C" { -DUCKDB_EXTENSION_API void oslog_init(duckdb::DatabaseInstance &db) { - duckdb::DuckDB db_wrapper(db); - db_wrapper.LoadExtension(); +DUCKDB_EXTENSION_API void oslog_init(duckdb::DatabaseInstance& db) { + duckdb::DuckDB db_wrapper(db); + db_wrapper.LoadExtension(); } -DUCKDB_EXTENSION_API const char *oslog_version() { - return duckdb::DuckDB::LibraryVersion(); +DUCKDB_EXTENSION_API const char* oslog_version() { + return duckdb::DuckDB::LibraryVersion(); } } diff --git a/src/oslog_table.hpp b/src/oslog_table.hpp new file mode 100644 index 0000000..0971bca --- /dev/null +++ b/src/oslog_table.hpp @@ -0,0 +1,9 @@ +#include + +namespace duckdb { +namespace oslog { + +duckdb::TableFunction GetTableFunction(); + +} // namespace oslog +} // namespace duckdb diff --git a/src/oslog_table.mm b/src/oslog_table.mm new file mode 100644 index 0000000..3a37e31 --- /dev/null +++ b/src/oslog_table.mm @@ -0,0 +1,97 @@ +#import +#import + +#include +#include + +#include + +namespace duckdb { +namespace oslog { + +namespace { + +struct OSLogLocalState : public LocalTableFunctionState { +}; + +struct OSLogTableFunction : public TableFunctionData { + OSLogStore* store = nil; +}; + +NSString* NSStringFromString(const string& str) { + return [[NSString alloc] initWithBytes:str.data() length:str.length() encoding:NSUTF8StringEncoding]; +} + +unique_ptr OSLogBind(ClientContext& context, + TableFunctionBindInput& input, + vector& return_types, + vector &names) { + const auto& archive = input.named_parameters["archive"]; + if (archive.IsNull()) { + throw InvalidInputException("Missing 'archive' parameter"); + } + + auto data = make_uniq(); + + NSError* error = nil; + NSURL* archive_url = [NSURL fileURLWithPath:NSStringFromString(StringValue::Get(archive))]; + data->store = [OSLogStore storeWithURL:archive_url error:&error]; + if (error) { + throw IOException(error.description.UTF8String); + } + + names = { + "date", + "eventType", + "level", + "subsystem", + "category", + "process", + "processId", + "sender", + "threadId", + "message", + "formatString", + }; + return_types = { + LogicalType::TIMESTAMP, // date + LogicalType::VARCHAR, // eventType + LogicalType::VARCHAR, // level + LogicalType::VARCHAR, // subsystem + LogicalType::VARCHAR, // category + LogicalType::VARCHAR, // process + LogicalType::BIGINT, // processId + LogicalType::VARCHAR, // sender + LogicalType::BIGINT, // threadId + LogicalType::VARCHAR, // message + LogicalType::VARCHAR, // formatString + }; + + return data; +} + +unique_ptr OSLogLocalInit( + ExecutionContext& context, + TableFunctionInitInput& input, + GlobalTableFunctionState* global_state) { + return make_uniq(); +} + +void OSLogTableFunction(ClientContext& context, + TableFunctionInput& data, + DataChunk& output) { + auto oslog = data->Cast(); +} + +} // namespace + +TableFunction GetTableFunction() { + TableFunction table_fn("oslog", /*args=*/ {}, &OSLogTableFunction, &OSLogBind, /*global_init=*/ nullptr, &OSLogLocalInit); + table_fn.named_parameters["archive"] = LogicalType::VARCHAR; + table_fn.named_parameters["start"] = LogicalType::TIMESTAMP; + table_fn.named_parameters["end"] = LogicalType::TIMESTAMP; + return table_fn; +} + +} // namespace oslog +} // namespace duckdb -- 2.43.5