First version

This commit is contained in:
Yves
2025-02-17 13:07:01 +01:00
parent 4228845a08
commit 75f2880fab
12 changed files with 869 additions and 37 deletions

60
src/utils/encoding.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include "utils/encoding.hpp"
#include <vector>
namespace duckdb {
// Copied from https://www.mycplus.com/source-code/c-source-code/base64-encode-decode/
constexpr char k_encoding_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_";
std::vector<char> BuildDecodingTable() {
std::vector<char> decoding_table;
decoding_table.resize(256);
for (int i = 0; i < 64; ++i) {
decoding_table[static_cast<unsigned char>(k_encoding_table[i])] = i;
}
return decoding_table;
}
const static std::vector<char> k_decoding_table = BuildDecodingTable();
std::string DecodeBase64(const std::string &data) {
size_t input_length = data.size();
if (input_length < 4 || input_length % 4 != 0) {
// Handle this exception
return "";
}
size_t output_length = input_length / 4 * 3;
if (data[input_length - 1] == '=') {
output_length--;
}
if (data[input_length - 2] == '=') {
output_length--;
}
std::string decoded_data;
decoded_data.resize(output_length);
for (size_t i = 0, j = 0; i < input_length;) {
uint32_t sextet_a = data[i] == '=' ? 0 & i++ : k_decoding_table[data[i++]];
uint32_t sextet_b = data[i] == '=' ? 0 & i++ : k_decoding_table[data[i++]];
uint32_t sextet_c = data[i] == '=' ? 0 & i++ : k_decoding_table[data[i++]];
uint32_t sextet_d = data[i] == '=' ? 0 & i++ : k_decoding_table[data[i++]];
uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
if (j < output_length) {
decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
}
if (j < output_length) {
decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
}
if (j < output_length) {
decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
}
}
return decoded_data;
}
} // namespace duckdb

34
src/utils/env.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include "utils/env.hpp"
#include <cstdlib>
#include <duckdb.hpp>
namespace duckdb {
const char *TryGetEnv(const char *name) {
const char *res = std::getenv(name);
if (res) {
return res;
}
return std::getenv(StringUtil::Upper(name).c_str());
}
std::string GetEnvOrDefault(const char *name, const char *default_value) {
const char *res = TryGetEnv(name);
if (res) {
return res;
}
return default_value;
}
bool IsEnvEnabled(const char *name) {
const char *res = TryGetEnv(name);
if (!res) {
return false;
}
auto lc_res = StringUtil::Lower(res);
return lc_res == "1" || lc_res == "true";
}
} // namespace duckdb

30
src/utils/helpers.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "utils/helpers.hpp"
#include <duckdb/main/extension_util.hpp>
namespace duckdb {
bool ShouldRun(TableFunctionInput &input) {
auto state = dynamic_cast<RunOnceTableFunctionState *>(input.global_state.get());
D_ASSERT(state != nullptr);
if (state->run) {
return false;
}
state->run = true;
return true;
}
unique_ptr<FunctionData> ResultBind(ClientContext &, TableFunctionBindInput &,
vector<LogicalType> &out_types,
vector<std::string> &out_names) {
out_names.emplace_back("result");
out_types.emplace_back(LogicalType::VARCHAR);
return nullptr;
}
void RegisterTF(DatabaseInstance &instance, const char* name, table_function_t func) {
TableFunction tf(name, {}, func, ResultBind, RunOnceTableFunctionState::Init);
ExtensionUtil::RegisterFunction(instance, tf);
}
} // namespace duckdb

View File

@@ -0,0 +1,49 @@
#include "utils/serialization.hpp"
#include "duckdb/common/serializer/deserializer.hpp"
#include "duckdb/common/serializer/serializer.hpp"
namespace duckdb {
namespace ui {
void EmptyResult::Serialize(Serializer &) const {
}
void TokenizeResult::Serialize(Serializer &serializer) const {
serializer.WriteProperty(100, "offsets", offsets);
serializer.WriteProperty(101, "types", types);
}
// Adapted from parts of DataChunk::Serialize
void ColumnNamesAndTypes::Serialize(Serializer &serializer) const {
serializer.WriteProperty(100, "names", names);
serializer.WriteProperty(101, "types", types);
}
// Adapted from parts of DataChunk::Serialize
void Chunk::Serialize(Serializer &serializer) const {
serializer.WriteProperty(100, "row_count", row_count);
serializer.WriteList(101, "vectors", vectors.size(), [&](Serializer::List &list, idx_t i) {
list.WriteObject([&](Serializer &object) {
// Reference the vector to avoid potentially mutating it during serialization
Vector serialized_vector(vectors[i].GetType());
serialized_vector.Reference(vectors[i]);
serialized_vector.Serialize(object, row_count);
});
});
}
void SuccessResult::Serialize(Serializer &serializer) const {
serializer.WriteProperty(100, "success", true);
serializer.WriteProperty(101, "column_names_and_types", column_names_and_types);
serializer.WriteList(102, "chunks", chunks.size(),
[&](Serializer::List &list, idx_t i) { list.WriteElement(chunks[i]); });
}
void ErrorResult::Serialize(Serializer &serializer) const {
serializer.WriteProperty(100, "success", false);
serializer.WriteProperty(101, "error", error);
}
} // namespace ui
} // namespace duckdb