Packages

An Elixir DuckDB library

Current section

Files

Jump to
exduckdb c_src duckdb src function scalar uuid gen_random.cpp
Raw

c_src/duckdb/src/function/scalar/uuid/gen_random.cpp

#include "duckdb/function/scalar/uuid_functions.hpp"
#include "duckdb/main/client_context.hpp"
#include "duckdb/planner/expression/bound_function_expression.hpp"
#include "duckdb/common/types/uuid.hpp"
namespace duckdb {
struct UUIDRandomBindData : public FunctionData {
ClientContext &context;
std::uniform_int_distribution<uint32_t> dist;
UUIDRandomBindData(ClientContext &context, std::uniform_int_distribution<uint32_t> dist)
: context(context), dist(dist) {
}
unique_ptr<FunctionData> Copy() override {
return make_unique<UUIDRandomBindData>(context, dist);
}
};
static unique_ptr<FunctionData> UUIDRandomBind(ClientContext &context, ScalarFunction &bound_function,
vector<unique_ptr<Expression>> &arguments) {
std::uniform_int_distribution<uint32_t> dist;
return make_unique<UUIDRandomBindData>(context, dist);
}
static void GenerateUUIDFunction(DataChunk &args, ExpressionState &state, Vector &result) {
D_ASSERT(args.ColumnCount() == 0);
auto &func_expr = (BoundFunctionExpression &)state.expr;
auto &info = (UUIDRandomBindData &)*func_expr.bind_info;
result.SetVectorType(VectorType::FLAT_VECTOR);
auto result_data = FlatVector::GetData<hugeint_t>(result);
for (idx_t i = 0; i < args.size(); i++) {
uint8_t bytes[16];
for (int i = 0; i < 16; i += 4) {
*reinterpret_cast<uint32_t *>(bytes + i) = info.dist(info.context.random_engine);
}
// variant must be 10xxxxxx
bytes[8] &= 0xBF;
bytes[8] |= 0x80;
// version must be 0100xxxx
bytes[6] &= 0x4F;
bytes[6] |= 0x40;
result_data[i].upper = 0;
result_data[i].upper |= ((int64_t)bytes[0] << 56);
result_data[i].upper |= ((int64_t)bytes[1] << 48);
result_data[i].upper |= ((int64_t)bytes[3] << 40);
result_data[i].upper |= ((int64_t)bytes[4] << 32);
result_data[i].upper |= ((int64_t)bytes[5] << 24);
result_data[i].upper |= ((int64_t)bytes[6] << 16);
result_data[i].upper |= ((int64_t)bytes[7] << 8);
result_data[i].upper |= bytes[8];
result_data[i].lower = 0;
result_data[i].lower |= ((uint64_t)bytes[8] << 56);
result_data[i].lower |= ((uint64_t)bytes[9] << 48);
result_data[i].lower |= ((uint64_t)bytes[10] << 40);
result_data[i].lower |= ((uint64_t)bytes[11] << 32);
result_data[i].lower |= ((uint64_t)bytes[12] << 24);
result_data[i].lower |= ((uint64_t)bytes[13] << 16);
result_data[i].lower |= ((uint64_t)bytes[14] << 8);
result_data[i].lower |= bytes[15];
}
}
void UUIDFun::RegisterFunction(BuiltinFunctions &set) {
// generate a random uuid
set.AddFunction(
ScalarFunction("gen_random_uuid", {}, LogicalType::UUID, GenerateUUIDFunction, true, UUIDRandomBind));
}
} // namespace duckdb