#include "storage/storage_utils.h"
#include <filesystem>
#if defined(_WIN32) || defined(__EMSCRIPTEN__)
#include <cctype>
#include <string_view>
#endif
#include "common/null_buffer.h"
#include "common/types/list_t.h"
#include "common/types/string_t.h"
#include "common/types/types.h"
#include "main/client_context.h"
#include "main/db_config.h"
#include "main/settings.h"
#include <format>
using namespace lbug::common;
namespace lbug {
namespace storage {
namespace {
#if defined(_WIN32) || defined(__EMSCRIPTEN__)
static bool isWindowsDrivePath(std::string_view path) {
return path.length() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) &&
path[1] == ':';
}
static bool isWindowsUNCPath(std::string_view path) {
return path.length() >= 2 &&
((path[0] == '\\' && path[1] == '\\') || (path[0] == '/' && path[1] == '/'));
}
#endif
}
std::string StorageUtils::getColumnName(const std::string& propertyName, ColumnType type,
const std::string& prefix) {
switch (type) {
case ColumnType::DATA: {
return std::format("{}_data", propertyName);
}
case ColumnType::NULL_MASK: {
return std::format("{}_null", propertyName);
}
case ColumnType::INDEX: {
return std::format("{}_index", propertyName);
}
case ColumnType::OFFSET: {
return std::format("{}_offset", propertyName);
}
case ColumnType::CSR_OFFSET: {
return std::format("{}_csr_offset", prefix);
}
case ColumnType::CSR_LENGTH: {
return std::format("{}_csr_length", prefix);
}
case ColumnType::STRUCT_CHILD: {
return std::format("{}_{}_child", propertyName, prefix);
}
default: {
if (prefix.empty()) {
return propertyName;
}
return std::format("{}_{}", prefix, propertyName);
}
}
}
std::string StorageUtils::expandPath(const main::ClientContext* context, const std::string& path) {
if (main::DBConfig::isDBPathInMemory(path)) {
return path;
}
auto fullPath = path;
if (path.starts_with('~')) {
fullPath =
context->getCurrentSetting(main::HomeDirectorySetting::name).getValue<std::string>() +
fullPath.substr(1);
}
#ifdef __EMSCRIPTEN__
if (isWindowsDrivePath(fullPath) || isWindowsUNCPath(fullPath)) {
for (auto& ch : fullPath) {
if (ch == '\\') {
ch = '/';
}
}
}
#endif
std::filesystem::path normalizedPath;
std::filesystem::path filePath{fullPath};
auto shouldAvoidAbsolute = filePath.is_absolute();
#if defined(_WIN32) || defined(__EMSCRIPTEN__)
shouldAvoidAbsolute =
shouldAvoidAbsolute || isWindowsDrivePath(fullPath) || isWindowsUNCPath(fullPath);
#endif
if (shouldAvoidAbsolute) {
normalizedPath = filePath.lexically_normal();
} else {
normalizedPath = std::filesystem::absolute(filePath).lexically_normal();
}
return normalizedPath.string();
}
uint32_t StorageUtils::getDataTypeSize(const LogicalType& type) {
switch (type.getPhysicalType()) {
case PhysicalTypeID::STRING:
case PhysicalTypeID::JSON: {
return sizeof(string_t);
}
case PhysicalTypeID::ARRAY:
case PhysicalTypeID::LIST: {
return sizeof(list_t);
}
case PhysicalTypeID::STRUCT: {
uint32_t size = 0;
const auto fieldsTypes = StructType::getFieldTypes(type);
for (const auto& fieldType : fieldsTypes) {
size += getDataTypeSize(*fieldType);
}
size += NullBuffer::getNumBytesForNullValues(fieldsTypes.size());
return size;
}
default: {
return PhysicalTypeUtils::getFixedTypeSize(type.getPhysicalType());
}
}
}
} }