1#include "duckdb/parser/statement/copy_statement.hpp"
2
3namespace duckdb {
4
5CopyStatement::CopyStatement() : SQLStatement(StatementType::COPY_STATEMENT), info(make_uniq<CopyInfo>()) {
6}
7
8CopyStatement::CopyStatement(const CopyStatement &other) : SQLStatement(other), info(other.info->Copy()) {
9 if (other.select_statement) {
10 select_statement = other.select_statement->Copy();
11 }
12}
13
14string CopyStatement::CopyOptionsToString(const string &format,
15 const case_insensitive_map_t<vector<Value>> &options) const {
16 if (format.empty() && options.empty()) {
17 return string();
18 }
19 string result;
20
21 result += " (";
22 if (!format.empty()) {
23 result += " FORMAT ";
24 result += format;
25 }
26 for (auto it = options.begin(); it != options.end(); it++) {
27 if (!format.empty() || it != options.begin()) {
28 result += ", ";
29 }
30 auto &name = it->first;
31 auto &values = it->second;
32
33 result += name + " ";
34 if (values.empty()) {
35 // Options like HEADER don't need an explicit value
36 // just providing the name already sets it to true
37 } else if (values.size() == 1) {
38 result += values[0].ToSQLString();
39 } else {
40 result += "( ";
41 for (idx_t i = 0; i < values.size(); i++) {
42 if (i) {
43 result += ", ";
44 }
45 result += values[i].ToSQLString();
46 }
47 result += " )";
48 }
49 }
50 result += " )";
51 return result;
52}
53
54// COPY table-name (c1, c2, ..)
55string TablePart(const CopyInfo &info) {
56 string result;
57
58 if (!info.catalog.empty()) {
59 result += KeywordHelper::WriteOptionallyQuoted(text: info.catalog) + ".";
60 }
61 if (!info.schema.empty()) {
62 result += KeywordHelper::WriteOptionallyQuoted(text: info.schema) + ".";
63 }
64 D_ASSERT(!info.table.empty());
65 result += KeywordHelper::WriteOptionallyQuoted(text: info.table);
66
67 // (c1, c2, ..)
68 if (!info.select_list.empty()) {
69 result += " (";
70 for (idx_t i = 0; i < info.select_list.size(); i++) {
71 if (i > 0) {
72 result += ", ";
73 }
74 result += KeywordHelper::WriteOptionallyQuoted(text: info.select_list[i]);
75 }
76 result += " )";
77 }
78 return result;
79}
80
81string CopyStatement::ToString() const {
82 string result;
83
84 result += "COPY ";
85 if (info->is_from) {
86 D_ASSERT(!select_statement);
87 result += TablePart(info: *info);
88 result += " FROM";
89 result += StringUtil::Format(fmt_str: " %s", params: SQLString(info->file_path));
90 result += CopyOptionsToString(format: info->format, options: info->options);
91 } else {
92 if (select_statement) {
93 // COPY (select-node) TO ...
94 result += "(" + select_statement->ToString() + ")";
95 } else {
96 result += TablePart(info: *info);
97 }
98 result += " TO ";
99 result += StringUtil::Format(fmt_str: "%s", params: SQLString(info->file_path));
100 result += CopyOptionsToString(format: info->format, options: info->options);
101 }
102 return result;
103}
104
105unique_ptr<SQLStatement> CopyStatement::Copy() const {
106 return unique_ptr<CopyStatement>(new CopyStatement(*this));
107}
108
109} // namespace duckdb
110