Current section
Files
Jump to
Current section
Files
c_src/duckdb/src/main/config.cpp
#include "duckdb/main/config.hpp"
#include "duckdb/common/string_util.hpp"
#include "duckdb/common/operator/cast_operators.hpp"
namespace duckdb {
static ConfigurationOption internal_options[] = {
{ConfigurationOptionType::ACCESS_MODE, "access_mode",
"Access mode of the database ([AUTOMATIC], READ_ONLY or READ_WRITE)", LogicalTypeId::VARCHAR},
{ConfigurationOptionType::DEFAULT_ORDER_TYPE, "default_order",
"The order type used when none is specified ([ASC] or DESC)", LogicalTypeId::VARCHAR},
{ConfigurationOptionType::DEFAULT_NULL_ORDER, "default_null_order",
"Null ordering used when none is specified ([NULLS_FIRST] or NULLS_LAST)", LogicalTypeId::VARCHAR},
{ConfigurationOptionType::ENABLE_EXTERNAL_ACCESS, "enable_external_access",
"Allow the database to access external state (through e.g. COPY TO/FROM, CSV readers, pandas replacement scans, "
"etc)",
LogicalTypeId::BOOLEAN},
{ConfigurationOptionType::ENABLE_OBJECT_CACHE, "enable_object_cache",
"Whether or not object cache is used to cache e.g. Parquet metadata", LogicalTypeId::BOOLEAN},
{ConfigurationOptionType::MAXIMUM_MEMORY, "max_memory", "The maximum memory of the system (e.g. 1GB)",
LogicalTypeId::VARCHAR},
{ConfigurationOptionType::THREADS, "threads", "The number of total threads used by the system",
LogicalTypeId::BIGINT},
{ConfigurationOptionType::INVALID, nullptr, nullptr, LogicalTypeId::INVALID}};
vector<ConfigurationOption> DBConfig::GetOptions() {
vector<ConfigurationOption> options;
for (idx_t index = 0; internal_options[index].name; index++) {
options.push_back(internal_options[index]);
}
return options;
}
idx_t DBConfig::GetOptionCount() {
idx_t count = 0;
for (idx_t index = 0; internal_options[index].name; index++) {
count++;
}
return count;
}
ConfigurationOption *DBConfig::GetOptionByIndex(idx_t target_index) {
for (idx_t index = 0; internal_options[index].name; index++) {
if (index == target_index) {
return internal_options + index;
}
}
return nullptr;
}
ConfigurationOption *DBConfig::GetOptionByName(const string &name) {
for (idx_t index = 0; internal_options[index].name; index++) {
if (internal_options[index].name == name) {
return internal_options + index;
}
}
return nullptr;
}
void DBConfig::SetOption(const ConfigurationOption &option, const Value &value) {
switch (option.type) {
case ConfigurationOptionType::ACCESS_MODE: {
auto parameter = StringUtil::Lower(value.ToString());
if (parameter == "automatic") {
access_mode = AccessMode::AUTOMATIC;
} else if (parameter == "read_only") {
access_mode = AccessMode::READ_ONLY;
} else if (parameter == "read_write") {
access_mode = AccessMode::READ_WRITE;
} else {
throw InvalidInputException(
"Unrecognized parameter for option ACCESS_MODE \"%s\". Expected READ_ONLY or READ_WRITE.", parameter);
}
break;
}
case ConfigurationOptionType::DEFAULT_ORDER_TYPE: {
auto parameter = StringUtil::Lower(value.ToString());
if (parameter == "asc") {
default_order_type = OrderType::ASCENDING;
} else if (parameter == "desc") {
default_order_type = OrderType::DESCENDING;
} else {
throw InvalidInputException("Unrecognized parameter for option DEFAULT_ORDER \"%s\". Expected ASC or DESC.",
parameter);
}
break;
}
case ConfigurationOptionType::DEFAULT_NULL_ORDER: {
auto parameter = StringUtil::Lower(value.ToString());
if (parameter == "nulls_first") {
default_null_order = OrderByNullType::NULLS_FIRST;
} else if (parameter == "nulls_last") {
default_null_order = OrderByNullType::NULLS_LAST;
} else {
throw InvalidInputException(
"Unrecognized parameter for option NULL_ORDER \"%s\". Expected NULLS_FIRST or NULLS_LAST.", parameter);
}
break;
}
case ConfigurationOptionType::ENABLE_EXTERNAL_ACCESS: {
enable_external_access = value.CastAs(LogicalType::BOOLEAN).GetValueUnsafe<int8_t>();
break;
}
case ConfigurationOptionType::ENABLE_OBJECT_CACHE: {
object_cache_enable = value.CastAs(LogicalType::BOOLEAN).GetValueUnsafe<int8_t>();
break;
}
case ConfigurationOptionType::MAXIMUM_MEMORY: {
maximum_memory = ParseMemoryLimit(value.ToString());
break;
}
case ConfigurationOptionType::THREADS: {
maximum_threads = value.GetValue<int64_t>();
break;
}
default: // LCOV_EXCL_START
break;
} // LCOV_EXCL_STOP
}
idx_t DBConfig::ParseMemoryLimit(const string &arg) {
if (arg[0] == '-' || arg == "null" || arg == "none") {
return INVALID_INDEX;
}
// split based on the number/non-number
idx_t idx = 0;
while (StringUtil::CharacterIsSpace(arg[idx])) {
idx++;
}
idx_t num_start = idx;
while ((arg[idx] >= '0' && arg[idx] <= '9') || arg[idx] == '.' || arg[idx] == 'e' || arg[idx] == 'E' ||
arg[idx] == '-') {
idx++;
}
if (idx == num_start) {
throw ParserException("Memory limit must have a number (e.g. PRAGMA memory_limit=1GB");
}
string number = arg.substr(num_start, idx - num_start);
// try to parse the number
double limit = Cast::Operation<string_t, double>(string_t(number));
// now parse the memory limit unit (e.g. bytes, gb, etc)
while (StringUtil::CharacterIsSpace(arg[idx])) {
idx++;
}
idx_t start = idx;
while (idx < arg.size() && !StringUtil::CharacterIsSpace(arg[idx])) {
idx++;
}
if (limit < 0) {
// limit < 0, set limit to infinite
return (idx_t)-1;
}
string unit = StringUtil::Lower(arg.substr(start, idx - start));
idx_t multiplier;
if (unit == "byte" || unit == "bytes" || unit == "b") {
multiplier = 1;
} else if (unit == "kilobyte" || unit == "kilobytes" || unit == "kb" || unit == "k") {
multiplier = 1000LL;
} else if (unit == "megabyte" || unit == "megabytes" || unit == "mb" || unit == "m") {
multiplier = 1000LL * 1000LL;
} else if (unit == "gigabyte" || unit == "gigabytes" || unit == "gb" || unit == "g") {
multiplier = 1000LL * 1000LL * 1000LL;
} else if (unit == "terabyte" || unit == "terabytes" || unit == "tb" || unit == "t") {
multiplier = 1000LL * 1000LL * 1000LL * 1000LL;
} else {
throw ParserException("Unknown unit for memory_limit: %s (expected: b, mb, gb or tb)", unit);
}
return (idx_t)multiplier * limit;
}
} // namespace duckdb