1#include "duckdb/main/settings.hpp"
2
3#include "duckdb/catalog/catalog_search_path.hpp"
4#include "duckdb/common/string_util.hpp"
5#include "duckdb/main/client_context.hpp"
6#include "duckdb/main/client_data.hpp"
7#include "duckdb/main/config.hpp"
8#include "duckdb/main/query_profiler.hpp"
9#include "duckdb/parallel/task_scheduler.hpp"
10#include "duckdb/parser/parser.hpp"
11#include "duckdb/planner/expression_binder.hpp"
12#include "duckdb/storage/buffer_manager.hpp"
13#include "duckdb/storage/storage_manager.hpp"
14#include "duckdb/main/database_manager.hpp"
15#include "duckdb/main/attached_database.hpp"
16#include "duckdb/main/database.hpp"
17
18namespace duckdb {
19
20//===--------------------------------------------------------------------===//
21// Access Mode
22//===--------------------------------------------------------------------===//
23void AccessModeSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
24 auto parameter = StringUtil::Lower(str: input.ToString());
25 if (parameter == "automatic") {
26 config.options.access_mode = AccessMode::AUTOMATIC;
27 } else if (parameter == "read_only") {
28 config.options.access_mode = AccessMode::READ_ONLY;
29 } else if (parameter == "read_write") {
30 config.options.access_mode = AccessMode::READ_WRITE;
31 } else {
32 throw InvalidInputException(
33 "Unrecognized parameter for option ACCESS_MODE \"%s\". Expected READ_ONLY or READ_WRITE.", parameter);
34 }
35}
36
37void AccessModeSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
38 config.options.access_mode = DBConfig().options.access_mode;
39}
40
41Value AccessModeSetting::GetSetting(ClientContext &context) {
42 auto &config = DBConfig::GetConfig(context);
43 switch (config.options.access_mode) {
44 case AccessMode::AUTOMATIC:
45 return "automatic";
46 case AccessMode::READ_ONLY:
47 return "read_only";
48 case AccessMode::READ_WRITE:
49 return "read_write";
50 default:
51 throw InternalException("Unknown access mode setting");
52 }
53}
54
55//===--------------------------------------------------------------------===//
56// Checkpoint Threshold
57//===--------------------------------------------------------------------===//
58void CheckpointThresholdSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
59 idx_t new_limit = DBConfig::ParseMemoryLimit(arg: input.ToString());
60 config.options.checkpoint_wal_size = new_limit;
61}
62
63void CheckpointThresholdSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
64 config.options.checkpoint_wal_size = DBConfig().options.checkpoint_wal_size;
65}
66
67Value CheckpointThresholdSetting::GetSetting(ClientContext &context) {
68 auto &config = DBConfig::GetConfig(context);
69 return Value(StringUtil::BytesToHumanReadableString(bytes: config.options.checkpoint_wal_size));
70}
71
72//===--------------------------------------------------------------------===//
73// Debug Checkpoint Abort
74//===--------------------------------------------------------------------===//
75void DebugCheckpointAbort::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
76 auto checkpoint_abort = StringUtil::Lower(str: input.ToString());
77 if (checkpoint_abort == "none") {
78 config.options.checkpoint_abort = CheckpointAbort::NO_ABORT;
79 } else if (checkpoint_abort == "before_truncate") {
80 config.options.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE;
81 } else if (checkpoint_abort == "before_header") {
82 config.options.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_BEFORE_HEADER;
83 } else if (checkpoint_abort == "after_free_list_write") {
84 config.options.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_AFTER_FREE_LIST_WRITE;
85 } else {
86 throw ParserException(
87 "Unrecognized option for PRAGMA debug_checkpoint_abort, expected none, before_truncate or before_header");
88 }
89}
90
91void DebugCheckpointAbort::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
92 config.options.checkpoint_abort = DBConfig().options.checkpoint_abort;
93}
94
95Value DebugCheckpointAbort::GetSetting(ClientContext &context) {
96 auto &config = DBConfig::GetConfig(db&: *context.db);
97 auto setting = config.options.checkpoint_abort;
98 switch (setting) {
99 case CheckpointAbort::NO_ABORT:
100 return "none";
101 case CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE:
102 return "before_truncate";
103 case CheckpointAbort::DEBUG_ABORT_BEFORE_HEADER:
104 return "before_header";
105 case CheckpointAbort::DEBUG_ABORT_AFTER_FREE_LIST_WRITE:
106 return "after_free_list_write";
107 default:
108 throw InternalException("Type not implemented for CheckpointAbort");
109 }
110}
111
112//===--------------------------------------------------------------------===//
113// Debug Force External
114//===--------------------------------------------------------------------===//
115
116void DebugForceExternal::ResetLocal(ClientContext &context) {
117 ClientConfig::GetConfig(context).force_external = ClientConfig().force_external;
118}
119
120void DebugForceExternal::SetLocal(ClientContext &context, const Value &input) {
121 ClientConfig::GetConfig(context).force_external = input.GetValue<bool>();
122}
123
124Value DebugForceExternal::GetSetting(ClientContext &context) {
125 return Value::BOOLEAN(value: ClientConfig::GetConfig(context).force_external);
126}
127
128//===--------------------------------------------------------------------===//
129// Debug Force NoCrossProduct
130//===--------------------------------------------------------------------===//
131
132void DebugForceNoCrossProduct::ResetLocal(ClientContext &context) {
133 ClientConfig::GetConfig(context).force_no_cross_product = ClientConfig().force_no_cross_product;
134}
135
136void DebugForceNoCrossProduct::SetLocal(ClientContext &context, const Value &input) {
137 ClientConfig::GetConfig(context).force_no_cross_product = input.GetValue<bool>();
138}
139
140Value DebugForceNoCrossProduct::GetSetting(ClientContext &context) {
141 return Value::BOOLEAN(value: ClientConfig::GetConfig(context).force_no_cross_product);
142}
143
144//===--------------------------------------------------------------------===//
145// Ordered Aggregate Threshold
146//===--------------------------------------------------------------------===//
147
148void OrderedAggregateThreshold::ResetLocal(ClientContext &context) {
149 ClientConfig::GetConfig(context).ordered_aggregate_threshold = ClientConfig().ordered_aggregate_threshold;
150}
151
152void OrderedAggregateThreshold::SetLocal(ClientContext &context, const Value &input) {
153 const auto param = input.GetValue<uint64_t>();
154 if (param <= 0) {
155 throw ParserException("Invalid option for PRAGMA ordered_aggregate_threshold, value must be positive");
156 }
157 ClientConfig::GetConfig(context).ordered_aggregate_threshold = param;
158}
159
160Value OrderedAggregateThreshold::GetSetting(ClientContext &context) {
161 return Value::UBIGINT(value: ClientConfig::GetConfig(context).ordered_aggregate_threshold);
162}
163
164//===--------------------------------------------------------------------===//
165// Debug Window Mode
166//===--------------------------------------------------------------------===//
167void DebugWindowMode::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
168 auto param = StringUtil::Lower(str: input.ToString());
169 if (param == "window") {
170 config.options.window_mode = WindowAggregationMode::WINDOW;
171 } else if (param == "combine") {
172 config.options.window_mode = WindowAggregationMode::COMBINE;
173 } else if (param == "separate") {
174 config.options.window_mode = WindowAggregationMode::SEPARATE;
175 } else {
176 throw ParserException("Unrecognized option for PRAGMA debug_window_mode, expected window, combine or separate");
177 }
178}
179
180void DebugWindowMode::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
181 config.options.window_mode = DBConfig().options.window_mode;
182}
183
184Value DebugWindowMode::GetSetting(ClientContext &context) {
185 return Value();
186}
187
188//===--------------------------------------------------------------------===//
189// Debug AsOf Join
190//===--------------------------------------------------------------------===//
191void DebugAsOfIEJoin::ResetLocal(ClientContext &context) {
192 ClientConfig::GetConfig(context).force_asof_iejoin = ClientConfig().force_asof_iejoin;
193}
194
195void DebugAsOfIEJoin::SetLocal(ClientContext &context, const Value &input) {
196 ClientConfig::GetConfig(context).force_asof_iejoin = input.GetValue<bool>();
197}
198
199Value DebugAsOfIEJoin::GetSetting(ClientContext &context) {
200 return Value::BOOLEAN(value: ClientConfig::GetConfig(context).force_asof_iejoin);
201}
202
203//===--------------------------------------------------------------------===//
204// Default Collation
205//===--------------------------------------------------------------------===//
206void DefaultCollationSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
207 auto parameter = StringUtil::Lower(str: input.ToString());
208 config.options.collation = parameter;
209}
210
211void DefaultCollationSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
212 config.options.collation = DBConfig().options.collation;
213}
214
215void DefaultCollationSetting::ResetLocal(ClientContext &context) {
216 auto &config = DBConfig::GetConfig(context);
217 config.options.collation = DBConfig().options.collation;
218}
219
220void DefaultCollationSetting::SetLocal(ClientContext &context, const Value &input) {
221 auto parameter = input.ToString();
222 // bind the collation to verify that it exists
223 ExpressionBinder::TestCollation(context, collation: parameter);
224 auto &config = DBConfig::GetConfig(context);
225 config.options.collation = parameter;
226}
227
228Value DefaultCollationSetting::GetSetting(ClientContext &context) {
229 auto &config = DBConfig::GetConfig(context);
230 return Value(config.options.collation);
231}
232
233//===--------------------------------------------------------------------===//
234// Default Order
235//===--------------------------------------------------------------------===//
236void DefaultOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
237 auto parameter = StringUtil::Lower(str: input.ToString());
238 if (parameter == "ascending" || parameter == "asc") {
239 config.options.default_order_type = OrderType::ASCENDING;
240 } else if (parameter == "descending" || parameter == "desc") {
241 config.options.default_order_type = OrderType::DESCENDING;
242 } else {
243 throw InvalidInputException("Unrecognized parameter for option DEFAULT_ORDER \"%s\". Expected ASC or DESC.",
244 parameter);
245 }
246}
247
248void DefaultOrderSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
249 config.options.default_order_type = DBConfig().options.default_order_type;
250}
251
252Value DefaultOrderSetting::GetSetting(ClientContext &context) {
253 auto &config = DBConfig::GetConfig(context);
254 switch (config.options.default_order_type) {
255 case OrderType::ASCENDING:
256 return "asc";
257 case OrderType::DESCENDING:
258 return "desc";
259 default:
260 throw InternalException("Unknown order type setting");
261 }
262}
263
264//===--------------------------------------------------------------------===//
265// Default Null Order
266//===--------------------------------------------------------------------===//
267void DefaultNullOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
268 auto parameter = StringUtil::Lower(str: input.ToString());
269
270 if (parameter == "nulls_first" || parameter == "nulls first" || parameter == "null first" || parameter == "first") {
271 config.options.default_null_order = DefaultOrderByNullType::NULLS_FIRST;
272 } else if (parameter == "nulls_last" || parameter == "nulls last" || parameter == "null last" ||
273 parameter == "last") {
274 config.options.default_null_order = DefaultOrderByNullType::NULLS_LAST;
275 } else if (parameter == "nulls_first_on_asc_last_on_desc" || parameter == "sqlite" || parameter == "mysql") {
276 config.options.default_null_order = DefaultOrderByNullType::NULLS_FIRST_ON_ASC_LAST_ON_DESC;
277 } else if (parameter == "nulls_last_on_asc_first_on_desc" || parameter == "postgres") {
278 config.options.default_null_order = DefaultOrderByNullType::NULLS_LAST_ON_ASC_FIRST_ON_DESC;
279 } else {
280 throw ParserException("Unrecognized parameter for option NULL_ORDER \"%s\", expected either NULLS FIRST, NULLS "
281 "LAST, SQLite, MySQL or Postgres",
282 parameter);
283 }
284}
285
286void DefaultNullOrderSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
287 config.options.default_null_order = DBConfig().options.default_null_order;
288}
289
290Value DefaultNullOrderSetting::GetSetting(ClientContext &context) {
291 auto &config = DBConfig::GetConfig(context);
292 switch (config.options.default_null_order) {
293 case DefaultOrderByNullType::NULLS_FIRST:
294 return "nulls_first";
295 case DefaultOrderByNullType::NULLS_LAST:
296 return "nulls_last";
297 case DefaultOrderByNullType::NULLS_FIRST_ON_ASC_LAST_ON_DESC:
298 return "nulls_first_on_asc_last_on_desc";
299 case DefaultOrderByNullType::NULLS_LAST_ON_ASC_FIRST_ON_DESC:
300 return "nulls_last_on_asc_first_on_desc";
301 default:
302 throw InternalException("Unknown null order setting");
303 }
304}
305
306//===--------------------------------------------------------------------===//
307// Disabled Optimizer
308//===--------------------------------------------------------------------===//
309void DisabledOptimizersSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
310 auto list = StringUtil::Split(input: input.ToString(), split: ",");
311 set<OptimizerType> disabled_optimizers;
312 for (auto &entry : list) {
313 auto param = StringUtil::Lower(str: entry);
314 StringUtil::Trim(str&: param);
315 if (param.empty()) {
316 continue;
317 }
318 disabled_optimizers.insert(x: OptimizerTypeFromString(str: param));
319 }
320 config.options.disabled_optimizers = std::move(disabled_optimizers);
321}
322
323void DisabledOptimizersSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
324 config.options.disabled_optimizers = DBConfig().options.disabled_optimizers;
325}
326
327Value DisabledOptimizersSetting::GetSetting(ClientContext &context) {
328 auto &config = DBConfig::GetConfig(context);
329 string result;
330 for (auto &optimizer : config.options.disabled_optimizers) {
331 if (!result.empty()) {
332 result += ",";
333 }
334 result += OptimizerTypeToString(type: optimizer);
335 }
336 return Value(result);
337}
338
339//===--------------------------------------------------------------------===//
340// Enable External Access
341//===--------------------------------------------------------------------===//
342void EnableExternalAccessSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
343 auto new_value = input.GetValue<bool>();
344 if (db && new_value) {
345 throw InvalidInputException("Cannot change enable_external_access setting while database is running");
346 }
347 config.options.enable_external_access = new_value;
348}
349
350void EnableExternalAccessSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
351 if (db) {
352 throw InvalidInputException("Cannot change enable_external_access setting while database is running");
353 }
354 config.options.enable_external_access = DBConfig().options.enable_external_access;
355}
356
357Value EnableExternalAccessSetting::GetSetting(ClientContext &context) {
358 auto &config = DBConfig::GetConfig(context);
359 return Value::BOOLEAN(value: config.options.enable_external_access);
360}
361
362//===--------------------------------------------------------------------===//
363// Enable FSST Vectors
364//===--------------------------------------------------------------------===//
365void EnableFSSTVectors::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
366 config.options.enable_fsst_vectors = input.GetValue<bool>();
367}
368
369void EnableFSSTVectors::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
370 config.options.enable_fsst_vectors = DBConfig().options.enable_fsst_vectors;
371}
372
373Value EnableFSSTVectors::GetSetting(ClientContext &context) {
374 auto &config = DBConfig::GetConfig(context);
375 return Value::BOOLEAN(value: config.options.enable_fsst_vectors);
376}
377
378//===--------------------------------------------------------------------===//
379// Allow Unsigned Extensions
380//===--------------------------------------------------------------------===//
381void AllowUnsignedExtensionsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
382 auto new_value = input.GetValue<bool>();
383 if (db && new_value) {
384 throw InvalidInputException("Cannot change allow_unsigned_extensions setting while database is running");
385 }
386 config.options.allow_unsigned_extensions = new_value;
387}
388
389void AllowUnsignedExtensionsSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
390 if (db) {
391 throw InvalidInputException("Cannot change allow_unsigned_extensions setting while database is running");
392 }
393 config.options.allow_unsigned_extensions = DBConfig().options.allow_unsigned_extensions;
394}
395
396Value AllowUnsignedExtensionsSetting::GetSetting(ClientContext &context) {
397 auto &config = DBConfig::GetConfig(context);
398 return Value::BOOLEAN(value: config.options.allow_unsigned_extensions);
399}
400
401//===--------------------------------------------------------------------===//
402// Enable Object Cache
403//===--------------------------------------------------------------------===//
404void EnableObjectCacheSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
405 config.options.object_cache_enable = input.GetValue<bool>();
406}
407
408void EnableObjectCacheSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
409 config.options.object_cache_enable = DBConfig().options.object_cache_enable;
410}
411
412Value EnableObjectCacheSetting::GetSetting(ClientContext &context) {
413 auto &config = DBConfig::GetConfig(context);
414 return Value::BOOLEAN(value: config.options.object_cache_enable);
415}
416
417//===--------------------------------------------------------------------===//
418// Enable HTTP Metadata Cache
419//===--------------------------------------------------------------------===//
420void EnableHTTPMetadataCacheSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
421 config.options.http_metadata_cache_enable = input.GetValue<bool>();
422}
423
424void EnableHTTPMetadataCacheSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
425 config.options.http_metadata_cache_enable = DBConfig().options.http_metadata_cache_enable;
426}
427
428Value EnableHTTPMetadataCacheSetting::GetSetting(ClientContext &context) {
429 auto &config = DBConfig::GetConfig(context);
430 return Value::BOOLEAN(value: config.options.http_metadata_cache_enable);
431}
432
433//===--------------------------------------------------------------------===//
434// Enable Profiling
435//===--------------------------------------------------------------------===//
436void EnableProfilingSetting::ResetLocal(ClientContext &context) {
437 auto &config = ClientConfig::GetConfig(context);
438 config.profiler_print_format = ClientConfig().profiler_print_format;
439 config.enable_profiler = ClientConfig().enable_profiler;
440 config.emit_profiler_output = ClientConfig().emit_profiler_output;
441}
442
443void EnableProfilingSetting::SetLocal(ClientContext &context, const Value &input) {
444 auto parameter = StringUtil::Lower(str: input.ToString());
445
446 auto &config = ClientConfig::GetConfig(context);
447 if (parameter == "json") {
448 config.profiler_print_format = ProfilerPrintFormat::JSON;
449 } else if (parameter == "query_tree") {
450 config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE;
451 } else if (parameter == "query_tree_optimizer") {
452 config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE_OPTIMIZER;
453 } else {
454 throw ParserException(
455 "Unrecognized print format %s, supported formats: [json, query_tree, query_tree_optimizer]", parameter);
456 }
457 config.enable_profiler = true;
458 config.emit_profiler_output = true;
459}
460
461Value EnableProfilingSetting::GetSetting(ClientContext &context) {
462 auto &config = ClientConfig::GetConfig(context);
463 if (!config.enable_profiler) {
464 return Value();
465 }
466 switch (config.profiler_print_format) {
467 case ProfilerPrintFormat::JSON:
468 return Value("json");
469 case ProfilerPrintFormat::QUERY_TREE:
470 return Value("query_tree");
471 case ProfilerPrintFormat::QUERY_TREE_OPTIMIZER:
472 return Value("query_tree_optimizer");
473 default:
474 throw InternalException("Unsupported profiler print format");
475 }
476}
477
478//===--------------------------------------------------------------------===//
479// Custom Extension Repository
480//===--------------------------------------------------------------------===//
481
482void CustomExtensionRepository::ResetLocal(ClientContext &context) {
483 ClientConfig::GetConfig(context).custom_extension_repo = ClientConfig().custom_extension_repo;
484}
485
486void CustomExtensionRepository::SetLocal(ClientContext &context, const Value &input) {
487 ClientConfig::GetConfig(context).custom_extension_repo = StringUtil::Lower(str: input.ToString());
488}
489
490Value CustomExtensionRepository::GetSetting(ClientContext &context) {
491 return Value(ClientConfig::GetConfig(context).custom_extension_repo);
492}
493
494//===--------------------------------------------------------------------===//
495// Enable Progress Bar
496//===--------------------------------------------------------------------===//
497
498void EnableProgressBarSetting::ResetLocal(ClientContext &context) {
499 auto &config = ClientConfig::GetConfig(context);
500 ProgressBar::SystemOverrideCheck(config);
501 config.enable_progress_bar = ClientConfig().enable_progress_bar;
502}
503
504void EnableProgressBarSetting::SetLocal(ClientContext &context, const Value &input) {
505 auto &config = ClientConfig::GetConfig(context);
506 ProgressBar::SystemOverrideCheck(config);
507 config.enable_progress_bar = input.GetValue<bool>();
508}
509
510Value EnableProgressBarSetting::GetSetting(ClientContext &context) {
511 return Value::BOOLEAN(value: ClientConfig::GetConfig(context).enable_progress_bar);
512}
513
514//===--------------------------------------------------------------------===//
515// Enable Progress Bar Print
516//===--------------------------------------------------------------------===//
517void EnableProgressBarPrintSetting::SetLocal(ClientContext &context, const Value &input) {
518 auto &config = ClientConfig::GetConfig(context);
519 ProgressBar::SystemOverrideCheck(config);
520 config.print_progress_bar = input.GetValue<bool>();
521}
522
523void EnableProgressBarPrintSetting::ResetLocal(ClientContext &context) {
524 auto &config = ClientConfig::GetConfig(context);
525 ProgressBar::SystemOverrideCheck(config);
526 config.print_progress_bar = ClientConfig().print_progress_bar;
527}
528
529Value EnableProgressBarPrintSetting::GetSetting(ClientContext &context) {
530 return Value::BOOLEAN(value: ClientConfig::GetConfig(context).print_progress_bar);
531}
532
533//===--------------------------------------------------------------------===//
534// Experimental Parallel CSV
535//===--------------------------------------------------------------------===//
536void ExperimentalParallelCSVSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
537 Printer::Print(str: "experimental_parallel_csv is deprecated and will be removed with the next release - the parallel "
538 "CSV reader is now standard and does not need to be manually enabled anymore 1");
539}
540
541void ExperimentalParallelCSVSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
542}
543
544Value ExperimentalParallelCSVSetting::GetSetting(ClientContext &context) {
545 return Value();
546}
547
548//===--------------------------------------------------------------------===//
549// Explain Output
550//===--------------------------------------------------------------------===//
551
552void ExplainOutputSetting::ResetLocal(ClientContext &context) {
553 ClientConfig::GetConfig(context).explain_output_type = ClientConfig().explain_output_type;
554}
555
556void ExplainOutputSetting::SetLocal(ClientContext &context, const Value &input) {
557 auto parameter = StringUtil::Lower(str: input.ToString());
558 if (parameter == "all") {
559 ClientConfig::GetConfig(context).explain_output_type = ExplainOutputType::ALL;
560 } else if (parameter == "optimized_only") {
561 ClientConfig::GetConfig(context).explain_output_type = ExplainOutputType::OPTIMIZED_ONLY;
562 } else if (parameter == "physical_only") {
563 ClientConfig::GetConfig(context).explain_output_type = ExplainOutputType::PHYSICAL_ONLY;
564 } else {
565 throw ParserException("Unrecognized output type \"%s\", expected either ALL, OPTIMIZED_ONLY or PHYSICAL_ONLY",
566 parameter);
567 }
568}
569
570Value ExplainOutputSetting::GetSetting(ClientContext &context) {
571 switch (ClientConfig::GetConfig(context).explain_output_type) {
572 case ExplainOutputType::ALL:
573 return "all";
574 case ExplainOutputType::OPTIMIZED_ONLY:
575 return "optimized_only";
576 case ExplainOutputType::PHYSICAL_ONLY:
577 return "physical_only";
578 default:
579 throw InternalException("Unrecognized explain output type");
580 }
581}
582
583//===--------------------------------------------------------------------===//
584// Extension Directory Setting
585//===--------------------------------------------------------------------===//
586void ExtensionDirectorySetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
587 auto new_directory = input.ToString();
588 config.options.extension_directory = input.ToString();
589}
590
591void ExtensionDirectorySetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
592 config.options.extension_directory = DBConfig().options.extension_directory;
593}
594
595Value ExtensionDirectorySetting::GetSetting(ClientContext &context) {
596 return Value(DBConfig::GetConfig(context).options.extension_directory);
597}
598
599//===--------------------------------------------------------------------===//
600// External Threads Setting
601//===--------------------------------------------------------------------===//
602void ExternalThreadsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
603 config.options.external_threads = input.GetValue<int64_t>();
604}
605
606void ExternalThreadsSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
607 config.options.external_threads = DBConfig().options.external_threads;
608}
609
610Value ExternalThreadsSetting::GetSetting(ClientContext &context) {
611 auto &config = DBConfig::GetConfig(context);
612 return Value::BIGINT(value: config.options.external_threads);
613}
614
615//===--------------------------------------------------------------------===//
616// File Search Path
617//===--------------------------------------------------------------------===//
618void FileSearchPathSetting::ResetLocal(ClientContext &context) {
619 auto &client_data = ClientData::Get(context);
620 client_data.file_search_path.clear();
621}
622
623void FileSearchPathSetting::SetLocal(ClientContext &context, const Value &input) {
624 auto parameter = input.ToString();
625 auto &client_data = ClientData::Get(context);
626 client_data.file_search_path = parameter;
627}
628
629Value FileSearchPathSetting::GetSetting(ClientContext &context) {
630 auto &client_data = ClientData::Get(context);
631 return Value(client_data.file_search_path);
632}
633
634//===--------------------------------------------------------------------===//
635// Force Compression
636//===--------------------------------------------------------------------===//
637void ForceCompressionSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
638 auto compression = StringUtil::Lower(str: input.ToString());
639 if (compression == "none" || compression == "auto") {
640 config.options.force_compression = CompressionType::COMPRESSION_AUTO;
641 } else {
642 auto compression_type = CompressionTypeFromString(str: compression);
643 if (compression_type == CompressionType::COMPRESSION_AUTO) {
644 auto compression_types = StringUtil::Join(input: ListCompressionTypes(), separator: ", ");
645 throw ParserException("Unrecognized option for PRAGMA force_compression, expected %s", compression_types);
646 }
647 config.options.force_compression = compression_type;
648 }
649}
650
651void ForceCompressionSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
652 config.options.force_compression = DBConfig().options.force_compression;
653}
654
655Value ForceCompressionSetting::GetSetting(ClientContext &context) {
656 auto &config = DBConfig::GetConfig(db&: *context.db);
657 return CompressionTypeToString(type: config.options.force_compression);
658}
659
660//===--------------------------------------------------------------------===//
661// Force Bitpacking mode
662//===--------------------------------------------------------------------===//
663void ForceBitpackingModeSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
664 auto mode_str = StringUtil::Lower(str: input.ToString());
665 if (mode_str == "none") {
666 config.options.force_bitpacking_mode = BitpackingMode::AUTO;
667 } else {
668 auto mode = BitpackingModeFromString(str: mode_str);
669 if (mode == BitpackingMode::AUTO) {
670 throw ParserException(
671 "Unrecognized option for force_bitpacking_mode, expected none, constant, constant_delta, "
672 "delta_for, or for");
673 }
674 config.options.force_bitpacking_mode = mode;
675 }
676}
677
678void ForceBitpackingModeSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
679 config.options.force_bitpacking_mode = DBConfig().options.force_bitpacking_mode;
680}
681
682Value ForceBitpackingModeSetting::GetSetting(ClientContext &context) {
683 return Value(BitpackingModeToString(mode: context.db->config.options.force_bitpacking_mode));
684}
685
686//===--------------------------------------------------------------------===//
687// Home Directory
688//===--------------------------------------------------------------------===//
689
690void HomeDirectorySetting::ResetLocal(ClientContext &context) {
691 ClientConfig::GetConfig(context).home_directory = ClientConfig().home_directory;
692}
693
694void HomeDirectorySetting::SetLocal(ClientContext &context, const Value &input) {
695 auto &config = ClientConfig::GetConfig(context);
696 config.home_directory = input.IsNull() ? string() : input.ToString();
697}
698
699Value HomeDirectorySetting::GetSetting(ClientContext &context) {
700 auto &config = ClientConfig::GetConfig(context);
701 return Value(config.home_directory);
702}
703
704//===--------------------------------------------------------------------===//
705// Integer Division
706//===--------------------------------------------------------------------===//
707void IntegerDivisionSetting::ResetLocal(ClientContext &context) {
708 ClientConfig::GetConfig(context).integer_division = ClientConfig().integer_division;
709}
710
711void IntegerDivisionSetting::SetLocal(ClientContext &context, const Value &input) {
712 auto &config = ClientConfig::GetConfig(context);
713 config.integer_division = input.GetValue<bool>();
714}
715
716Value IntegerDivisionSetting::GetSetting(ClientContext &context) {
717 auto &config = ClientConfig::GetConfig(context);
718 return Value(config.integer_division);
719}
720
721//===--------------------------------------------------------------------===//
722// Log Query Path
723//===--------------------------------------------------------------------===//
724void LogQueryPathSetting::ResetLocal(ClientContext &context) {
725 auto &client_data = ClientData::Get(context);
726 // TODO: verify that this does the right thing
727 client_data.log_query_writer = std::move(ClientData(context).log_query_writer);
728}
729
730void LogQueryPathSetting::SetLocal(ClientContext &context, const Value &input) {
731 auto &client_data = ClientData::Get(context);
732 auto path = input.ToString();
733 if (path.empty()) {
734 // empty path: clean up query writer
735 client_data.log_query_writer = nullptr;
736 } else {
737 client_data.log_query_writer = make_uniq<BufferedFileWriter>(args&: FileSystem::GetFileSystem(context), args&: path,
738 args: BufferedFileWriter::DEFAULT_OPEN_FLAGS);
739 }
740}
741
742Value LogQueryPathSetting::GetSetting(ClientContext &context) {
743 auto &client_data = ClientData::Get(context);
744 return client_data.log_query_writer ? Value(client_data.log_query_writer->path) : Value();
745}
746
747//===--------------------------------------------------------------------===//
748// Lock Configuration
749//===--------------------------------------------------------------------===//
750void LockConfigurationSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
751 auto new_value = input.GetValue<bool>();
752 config.options.lock_configuration = new_value;
753}
754
755void LockConfigurationSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
756 config.options.lock_configuration = DBConfig().options.lock_configuration;
757}
758
759Value LockConfigurationSetting::GetSetting(ClientContext &context) {
760 auto &config = DBConfig::GetConfig(context);
761 return Value::BOOLEAN(value: config.options.lock_configuration);
762}
763
764//===--------------------------------------------------------------------===//
765// Immediate Transaction Mode
766//===--------------------------------------------------------------------===//
767void ImmediateTransactionModeSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
768 config.options.immediate_transaction_mode = BooleanValue::Get(value: input);
769}
770
771void ImmediateTransactionModeSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
772 config.options.immediate_transaction_mode = DBConfig().options.immediate_transaction_mode;
773}
774
775Value ImmediateTransactionModeSetting::GetSetting(ClientContext &context) {
776 auto &config = DBConfig::GetConfig(context);
777 return Value::BOOLEAN(value: config.options.immediate_transaction_mode);
778}
779
780//===--------------------------------------------------------------------===//
781// Maximum Expression Depth
782//===--------------------------------------------------------------------===//
783
784void MaximumExpressionDepthSetting::ResetLocal(ClientContext &context) {
785 ClientConfig::GetConfig(context).max_expression_depth = ClientConfig().max_expression_depth;
786}
787
788void MaximumExpressionDepthSetting::SetLocal(ClientContext &context, const Value &input) {
789 ClientConfig::GetConfig(context).max_expression_depth = input.GetValue<uint64_t>();
790}
791
792Value MaximumExpressionDepthSetting::GetSetting(ClientContext &context) {
793 return Value::UBIGINT(value: ClientConfig::GetConfig(context).max_expression_depth);
794}
795
796//===--------------------------------------------------------------------===//
797// Maximum Memory
798//===--------------------------------------------------------------------===//
799void MaximumMemorySetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
800 config.options.maximum_memory = DBConfig::ParseMemoryLimit(arg: input.ToString());
801 if (db) {
802 BufferManager::GetBufferManager(db&: *db).SetLimit(config.options.maximum_memory);
803 }
804}
805
806void MaximumMemorySetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
807 config.SetDefaultMaxMemory();
808}
809
810Value MaximumMemorySetting::GetSetting(ClientContext &context) {
811 auto &config = DBConfig::GetConfig(context);
812 return Value(StringUtil::BytesToHumanReadableString(bytes: config.options.maximum_memory));
813}
814
815//===--------------------------------------------------------------------===//
816// Password Setting
817//===--------------------------------------------------------------------===//
818void PasswordSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
819 // nop
820}
821
822void PasswordSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
823 // nop
824}
825
826Value PasswordSetting::GetSetting(ClientContext &context) {
827 return Value();
828}
829
830//===--------------------------------------------------------------------===//
831// Perfect Hash Threshold
832//===--------------------------------------------------------------------===//
833
834void PerfectHashThresholdSetting::ResetLocal(ClientContext &context) {
835 ClientConfig::GetConfig(context).perfect_ht_threshold = ClientConfig().perfect_ht_threshold;
836}
837
838void PerfectHashThresholdSetting::SetLocal(ClientContext &context, const Value &input) {
839 auto bits = input.GetValue<int64_t>();
840 if (bits < 0 || bits > 32) {
841 throw ParserException("Perfect HT threshold out of range: should be within range 0 - 32");
842 }
843 ClientConfig::GetConfig(context).perfect_ht_threshold = bits;
844}
845
846Value PerfectHashThresholdSetting::GetSetting(ClientContext &context) {
847 return Value::BIGINT(value: ClientConfig::GetConfig(context).perfect_ht_threshold);
848}
849
850//===--------------------------------------------------------------------===//
851// Pivot Limit
852//===--------------------------------------------------------------------===//
853
854void PivotLimitSetting::ResetLocal(ClientContext &context) {
855 ClientConfig::GetConfig(context).pivot_limit = ClientConfig().pivot_limit;
856}
857
858void PivotLimitSetting::SetLocal(ClientContext &context, const Value &input) {
859 ClientConfig::GetConfig(context).pivot_limit = input.GetValue<uint64_t>();
860}
861
862Value PivotLimitSetting::GetSetting(ClientContext &context) {
863 return Value::BIGINT(value: ClientConfig::GetConfig(context).pivot_limit);
864}
865
866//===--------------------------------------------------------------------===//
867// PreserveIdentifierCase
868//===--------------------------------------------------------------------===//
869
870void PreserveIdentifierCase::ResetLocal(ClientContext &context) {
871 ClientConfig::GetConfig(context).preserve_identifier_case = ClientConfig().preserve_identifier_case;
872}
873
874void PreserveIdentifierCase::SetLocal(ClientContext &context, const Value &input) {
875 ClientConfig::GetConfig(context).preserve_identifier_case = input.GetValue<bool>();
876}
877
878Value PreserveIdentifierCase::GetSetting(ClientContext &context) {
879 return Value::BOOLEAN(value: ClientConfig::GetConfig(context).preserve_identifier_case);
880}
881
882//===--------------------------------------------------------------------===//
883// PreserveInsertionOrder
884//===--------------------------------------------------------------------===//
885void PreserveInsertionOrder::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
886 config.options.preserve_insertion_order = input.GetValue<bool>();
887}
888
889void PreserveInsertionOrder::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
890 config.options.preserve_insertion_order = DBConfig().options.preserve_insertion_order;
891}
892
893Value PreserveInsertionOrder::GetSetting(ClientContext &context) {
894 auto &config = DBConfig::GetConfig(context);
895 return Value::BOOLEAN(value: config.options.preserve_insertion_order);
896}
897
898//===--------------------------------------------------------------------===//
899// ExportLargeBufferArrow
900//===--------------------------------------------------------------------===//
901void ExportLargeBufferArrow::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
902 auto export_large_buffers_arrow = input.GetValue<bool>();
903
904 config.options.arrow_offset_size = export_large_buffers_arrow ? ArrowOffsetSize::LARGE : ArrowOffsetSize::REGULAR;
905}
906
907void ExportLargeBufferArrow::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
908 config.options.arrow_offset_size = DBConfig().options.arrow_offset_size;
909}
910
911Value ExportLargeBufferArrow::GetSetting(ClientContext &context) {
912 auto &config = DBConfig::GetConfig(context);
913 bool export_large_buffers_arrow = config.options.arrow_offset_size == ArrowOffsetSize::LARGE;
914 return Value::BOOLEAN(value: export_large_buffers_arrow);
915}
916
917//===--------------------------------------------------------------------===//
918// Profiler History Size
919//===--------------------------------------------------------------------===//
920
921void ProfilerHistorySize::ResetLocal(ClientContext &context) {
922 auto &client_data = ClientData::Get(context);
923 client_data.query_profiler_history->ResetProfilerHistorySize();
924}
925
926void ProfilerHistorySize::SetLocal(ClientContext &context, const Value &input) {
927 auto size = input.GetValue<int64_t>();
928 if (size <= 0) {
929 throw ParserException("Size should be >= 0");
930 }
931 auto &client_data = ClientData::Get(context);
932 client_data.query_profiler_history->SetProfilerHistorySize(size);
933}
934
935Value ProfilerHistorySize::GetSetting(ClientContext &context) {
936 return Value();
937}
938
939//===--------------------------------------------------------------------===//
940// Profile Output
941//===--------------------------------------------------------------------===//
942
943void ProfileOutputSetting::ResetLocal(ClientContext &context) {
944 ClientConfig::GetConfig(context).profiler_save_location = ClientConfig().profiler_save_location;
945}
946
947void ProfileOutputSetting::SetLocal(ClientContext &context, const Value &input) {
948 auto &config = ClientConfig::GetConfig(context);
949 auto parameter = input.ToString();
950 config.profiler_save_location = parameter;
951}
952
953Value ProfileOutputSetting::GetSetting(ClientContext &context) {
954 auto &config = ClientConfig::GetConfig(context);
955 return Value(config.profiler_save_location);
956}
957
958//===--------------------------------------------------------------------===//
959// Profiling Mode
960//===--------------------------------------------------------------------===//
961
962void ProfilingModeSetting::ResetLocal(ClientContext &context) {
963 ClientConfig::GetConfig(context).enable_profiler = ClientConfig().enable_profiler;
964 ClientConfig::GetConfig(context).enable_detailed_profiling = ClientConfig().enable_detailed_profiling;
965 ClientConfig::GetConfig(context).emit_profiler_output = ClientConfig().emit_profiler_output;
966}
967
968void ProfilingModeSetting::SetLocal(ClientContext &context, const Value &input) {
969 auto parameter = StringUtil::Lower(str: input.ToString());
970 auto &config = ClientConfig::GetConfig(context);
971 if (parameter == "standard") {
972 config.enable_profiler = true;
973 config.enable_detailed_profiling = false;
974 config.emit_profiler_output = true;
975 } else if (parameter == "detailed") {
976 config.enable_profiler = true;
977 config.enable_detailed_profiling = true;
978 config.emit_profiler_output = true;
979 } else {
980 throw ParserException("Unrecognized profiling mode \"%s\", supported formats: [standard, detailed]", parameter);
981 }
982}
983
984Value ProfilingModeSetting::GetSetting(ClientContext &context) {
985 auto &config = ClientConfig::GetConfig(context);
986 if (!config.enable_profiler) {
987 return Value();
988 }
989 return Value(config.enable_detailed_profiling ? "detailed" : "standard");
990}
991
992//===--------------------------------------------------------------------===//
993// Progress Bar Time
994//===--------------------------------------------------------------------===//
995
996void ProgressBarTimeSetting::ResetLocal(ClientContext &context) {
997 auto &config = ClientConfig::GetConfig(context);
998 ProgressBar::SystemOverrideCheck(config);
999 config.wait_time = ClientConfig().wait_time;
1000 config.enable_progress_bar = ClientConfig().enable_progress_bar;
1001}
1002
1003void ProgressBarTimeSetting::SetLocal(ClientContext &context, const Value &input) {
1004 auto &config = ClientConfig::GetConfig(context);
1005 ProgressBar::SystemOverrideCheck(config);
1006 config.wait_time = input.GetValue<int32_t>();
1007 config.enable_progress_bar = true;
1008}
1009
1010Value ProgressBarTimeSetting::GetSetting(ClientContext &context) {
1011 return Value::BIGINT(value: ClientConfig::GetConfig(context).wait_time);
1012}
1013
1014//===--------------------------------------------------------------------===//
1015// Schema
1016//===--------------------------------------------------------------------===//
1017void SchemaSetting::ResetLocal(ClientContext &context) {
1018 // FIXME: catalog_search_path is controlled by both SchemaSetting and SearchPathSetting
1019 auto &client_data = ClientData::Get(context);
1020 client_data.catalog_search_path->Reset();
1021}
1022
1023void SchemaSetting::SetLocal(ClientContext &context, const Value &input) {
1024 auto parameter = input.ToString();
1025 auto &client_data = ClientData::Get(context);
1026 client_data.catalog_search_path->Set(new_value: CatalogSearchEntry::Parse(input: parameter), set_type: CatalogSetPathType::SET_SCHEMA);
1027}
1028
1029Value SchemaSetting::GetSetting(ClientContext &context) {
1030 auto &client_data = ClientData::Get(context);
1031 return client_data.catalog_search_path->GetDefault().schema;
1032}
1033
1034//===--------------------------------------------------------------------===//
1035// Search Path
1036//===--------------------------------------------------------------------===//
1037void SearchPathSetting::ResetLocal(ClientContext &context) {
1038 // FIXME: catalog_search_path is controlled by both SchemaSetting and SearchPathSetting
1039 auto &client_data = ClientData::Get(context);
1040 client_data.catalog_search_path->Reset();
1041}
1042
1043void SearchPathSetting::SetLocal(ClientContext &context, const Value &input) {
1044 auto parameter = input.ToString();
1045 auto &client_data = ClientData::Get(context);
1046 client_data.catalog_search_path->Set(new_paths: CatalogSearchEntry::ParseList(input: parameter), set_type: CatalogSetPathType::SET_SCHEMAS);
1047}
1048
1049Value SearchPathSetting::GetSetting(ClientContext &context) {
1050 auto &client_data = ClientData::Get(context);
1051 auto &set_paths = client_data.catalog_search_path->GetSetPaths();
1052 return Value(CatalogSearchEntry::ListToString(input: set_paths));
1053}
1054
1055//===--------------------------------------------------------------------===//
1056// Temp Directory
1057//===--------------------------------------------------------------------===//
1058void TempDirectorySetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
1059 config.options.temporary_directory = input.ToString();
1060 config.options.use_temporary_directory = !config.options.temporary_directory.empty();
1061 if (db) {
1062 auto &buffer_manager = BufferManager::GetBufferManager(db&: *db);
1063 buffer_manager.SetTemporaryDirectory(config.options.temporary_directory);
1064 }
1065}
1066
1067void TempDirectorySetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
1068 config.options.temporary_directory = DBConfig().options.temporary_directory;
1069 config.options.use_temporary_directory = DBConfig().options.use_temporary_directory;
1070 if (db) {
1071 auto &buffer_manager = BufferManager::GetBufferManager(db&: *db);
1072 buffer_manager.SetTemporaryDirectory(config.options.temporary_directory);
1073 }
1074}
1075
1076Value TempDirectorySetting::GetSetting(ClientContext &context) {
1077 auto &buffer_manager = BufferManager::GetBufferManager(context);
1078 return Value(buffer_manager.GetTemporaryDirectory());
1079}
1080
1081//===--------------------------------------------------------------------===//
1082// Threads Setting
1083//===--------------------------------------------------------------------===//
1084void ThreadsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
1085 config.options.maximum_threads = input.GetValue<int64_t>();
1086 if (db) {
1087 TaskScheduler::GetScheduler(db&: *db).SetThreads(config.options.maximum_threads);
1088 }
1089}
1090
1091void ThreadsSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
1092 config.SetDefaultMaxThreads();
1093}
1094
1095Value ThreadsSetting::GetSetting(ClientContext &context) {
1096 auto &config = DBConfig::GetConfig(context);
1097 return Value::BIGINT(value: config.options.maximum_threads);
1098}
1099
1100//===--------------------------------------------------------------------===//
1101// Username Setting
1102//===--------------------------------------------------------------------===//
1103void UsernameSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
1104 // nop
1105}
1106
1107void UsernameSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) {
1108 // nop
1109}
1110
1111Value UsernameSetting::GetSetting(ClientContext &context) {
1112 return Value();
1113}
1114
1115} // namespace duckdb
1116