1#include "duckdb/execution/operator/helper/physical_set.hpp"
2
3#include "duckdb/common/string_util.hpp"
4#include "duckdb/main/database.hpp"
5#include "duckdb/main/client_context.hpp"
6
7namespace duckdb {
8
9void PhysicalSet::SetExtensionVariable(ClientContext &context, ExtensionOption &extension_option, const string &name,
10 SetScope scope, const Value &value) {
11 auto &config = DBConfig::GetConfig(context);
12 auto &target_type = extension_option.type;
13 Value target_value = value.CastAs(context, target_type);
14 if (extension_option.set_function) {
15 extension_option.set_function(context, scope, target_value);
16 }
17 if (scope == SetScope::GLOBAL) {
18 config.SetOption(name, value: std::move(target_value));
19 } else {
20 auto &client_config = ClientConfig::GetConfig(context);
21 client_config.set_variables[name] = std::move(target_value);
22 }
23}
24
25SourceResultType PhysicalSet::GetData(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const {
26 auto &config = DBConfig::GetConfig(context&: context.client);
27 if (config.options.lock_configuration) {
28 throw InvalidInputException("Cannot change configuration option \"%s\" - the configuration has been locked",
29 name);
30 }
31 auto option = DBConfig::GetOptionByName(name);
32 if (!option) {
33 // check if this is an extra extension variable
34 auto entry = config.extension_parameters.find(x: name);
35 if (entry == config.extension_parameters.end()) {
36 throw Catalog::UnrecognizedConfigurationError(context&: context.client, name);
37 }
38 SetExtensionVariable(context&: context.client, extension_option&: entry->second, name, scope, value);
39 return SourceResultType::FINISHED;
40 }
41 SetScope variable_scope = scope;
42 if (variable_scope == SetScope::AUTOMATIC) {
43 if (option->set_local) {
44 variable_scope = SetScope::SESSION;
45 } else {
46 D_ASSERT(option->set_global);
47 variable_scope = SetScope::GLOBAL;
48 }
49 }
50
51 Value input_val = value.CastAs(context&: context.client, target_type: option->parameter_type);
52 switch (variable_scope) {
53 case SetScope::GLOBAL: {
54 if (!option->set_global) {
55 throw CatalogException("option \"%s\" cannot be set globally", name);
56 }
57 auto &db = DatabaseInstance::GetDatabase(context&: context.client);
58 auto &config = DBConfig::GetConfig(context&: context.client);
59 config.SetOption(db: &db, option: *option, value: input_val);
60 break;
61 }
62 case SetScope::SESSION:
63 if (!option->set_local) {
64 throw CatalogException("option \"%s\" cannot be set locally", name);
65 }
66 option->set_local(context.client, input_val);
67 break;
68 default:
69 throw InternalException("Unsupported SetScope for variable");
70 }
71
72 return SourceResultType::FINISHED;
73}
74
75} // namespace duckdb
76