1#include "duckdb/execution/physical_plan_generator.hpp"
2#include "duckdb/execution/operator/persistent/physical_copy_to_file.hpp"
3#include "duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp"
4#include "duckdb/execution/operator/persistent/physical_fixed_batch_copy.hpp"
5#include "duckdb/planner/operator/logical_copy_to_file.hpp"
6
7namespace duckdb {
8
9unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalCopyToFile &op) {
10 auto plan = CreatePlan(op&: *op.children[0]);
11 bool preserve_insertion_order = PhysicalPlanGenerator::PreserveInsertionOrder(context, plan&: *plan);
12 bool supports_batch_index = PhysicalPlanGenerator::UseBatchIndex(context, plan&: *plan);
13 auto &fs = FileSystem::GetFileSystem(context);
14 op.file_path = fs.ExpandPath(path: op.file_path);
15 if (op.use_tmp_file) {
16 op.file_path += ".tmp";
17 }
18 if (op.per_thread_output || op.partition_output || !op.partition_columns.empty() || op.overwrite_or_ignore) {
19 // hive-partitioning/per-thread output does not care about insertion order, and does not support batch indexes
20 preserve_insertion_order = false;
21 supports_batch_index = false;
22 }
23 auto mode = CopyFunctionExecutionMode::REGULAR_COPY_TO_FILE;
24 if (op.function.execution_mode) {
25 mode = op.function.execution_mode(preserve_insertion_order, supports_batch_index);
26 }
27 if (mode == CopyFunctionExecutionMode::BATCH_COPY_TO_FILE) {
28 if (!supports_batch_index) {
29 throw InternalException("BATCH_COPY_TO_FILE can only be used if batch indexes are supported");
30 }
31 // batched copy to file
32 if (op.function.desired_batch_size) {
33 auto copy = make_uniq<PhysicalFixedBatchCopy>(args&: op.types, args&: op.function, args: std::move(op.bind_data),
34 args&: op.estimated_cardinality);
35 copy->file_path = op.file_path;
36 copy->use_tmp_file = op.use_tmp_file;
37 copy->children.push_back(x: std::move(plan));
38 return std::move(copy);
39 } else {
40 auto copy = make_uniq<PhysicalBatchCopyToFile>(args&: op.types, args&: op.function, args: std::move(op.bind_data),
41 args&: op.estimated_cardinality);
42 copy->file_path = op.file_path;
43 copy->use_tmp_file = op.use_tmp_file;
44 copy->children.push_back(x: std::move(plan));
45 return std::move(copy);
46 }
47 }
48 // COPY from select statement to file
49 auto copy = make_uniq<PhysicalCopyToFile>(args&: op.types, args&: op.function, args: std::move(op.bind_data), args&: op.estimated_cardinality);
50 copy->file_path = op.file_path;
51 copy->use_tmp_file = op.use_tmp_file;
52 copy->overwrite_or_ignore = op.overwrite_or_ignore;
53 copy->filename_pattern = op.filename_pattern;
54 copy->per_thread_output = op.per_thread_output;
55 copy->partition_output = op.partition_output;
56 copy->partition_columns = op.partition_columns;
57 copy->names = op.names;
58 copy->expected_types = op.expected_types;
59 copy->parallel = mode == CopyFunctionExecutionMode::PARALLEL_COPY_TO_FILE;
60
61 copy->children.push_back(x: std::move(plan));
62 return std::move(copy);
63}
64
65} // namespace duckdb
66