1 | #include "duckdb/common/bind_helpers.hpp" |
2 | #include "duckdb/common/common.hpp" |
3 | #include "duckdb/common/types.hpp" |
4 | #include "duckdb/common/exception.hpp" |
5 | #include "duckdb/common/types/value.hpp" |
6 | #include "duckdb/common/case_insensitive_map.hpp" |
7 | #include <numeric> |
8 | |
9 | namespace duckdb { |
10 | |
11 | Value ConvertVectorToValue(vector<Value> set) { |
12 | if (set.empty()) { |
13 | return Value::EMPTYLIST(child_type: LogicalType::BOOLEAN); |
14 | } |
15 | return Value::LIST(values: std::move(set)); |
16 | } |
17 | |
18 | vector<bool> ParseColumnList(const vector<Value> &set, vector<string> &names, const string &loption) { |
19 | vector<bool> result; |
20 | |
21 | if (set.empty()) { |
22 | throw BinderException("\"%s\" expects a column list or * as parameter" , loption); |
23 | } |
24 | // list of options: parse the list |
25 | case_insensitive_map_t<bool> option_map; |
26 | for (idx_t i = 0; i < set.size(); i++) { |
27 | option_map[set[i].ToString()] = false; |
28 | } |
29 | result.resize(new_size: names.size(), x: false); |
30 | for (idx_t i = 0; i < names.size(); i++) { |
31 | auto entry = option_map.find(x: names[i]); |
32 | if (entry != option_map.end()) { |
33 | result[i] = true; |
34 | entry->second = true; |
35 | } |
36 | } |
37 | for (auto &entry : option_map) { |
38 | if (!entry.second) { |
39 | throw BinderException("\"%s\" expected to find %s, but it was not found in the table" , loption, |
40 | entry.first.c_str()); |
41 | } |
42 | } |
43 | return result; |
44 | } |
45 | |
46 | vector<bool> ParseColumnList(const Value &value, vector<string> &names, const string &loption) { |
47 | vector<bool> result; |
48 | |
49 | // Only accept a list of arguments |
50 | if (value.type().id() != LogicalTypeId::LIST) { |
51 | // Support a single argument if it's '*' |
52 | if (value.type().id() == LogicalTypeId::VARCHAR && value.GetValue<string>() == "*" ) { |
53 | result.resize(new_size: names.size(), x: true); |
54 | return result; |
55 | } |
56 | throw BinderException("\"%s\" expects a column list or * as parameter" , loption); |
57 | } |
58 | auto &children = ListValue::GetChildren(value); |
59 | // accept '*' as single argument |
60 | if (children.size() == 1 && children[0].type().id() == LogicalTypeId::VARCHAR && |
61 | children[0].GetValue<string>() == "*" ) { |
62 | result.resize(new_size: names.size(), x: true); |
63 | return result; |
64 | } |
65 | return ParseColumnList(set: children, names, loption); |
66 | } |
67 | |
68 | vector<idx_t> ParseColumnsOrdered(const vector<Value> &set, vector<string> &names, const string &loption) { |
69 | vector<idx_t> result; |
70 | |
71 | if (set.empty()) { |
72 | throw BinderException("\"%s\" expects a column list or * as parameter" , loption); |
73 | } |
74 | |
75 | // Maps option to bool indicating if its found and the index in the original set |
76 | case_insensitive_map_t<std::pair<bool, idx_t>> option_map; |
77 | for (idx_t i = 0; i < set.size(); i++) { |
78 | option_map[set[i].ToString()] = {false, i}; |
79 | } |
80 | result.resize(new_size: option_map.size()); |
81 | |
82 | for (idx_t i = 0; i < names.size(); i++) { |
83 | auto entry = option_map.find(x: names[i]); |
84 | if (entry != option_map.end()) { |
85 | result[entry->second.second] = i; |
86 | entry->second.first = true; |
87 | } |
88 | } |
89 | for (auto &entry : option_map) { |
90 | if (!entry.second.first) { |
91 | throw BinderException("\"%s\" expected to find %s, but it was not found in the table" , loption, |
92 | entry.first.c_str()); |
93 | } |
94 | } |
95 | return result; |
96 | } |
97 | |
98 | vector<idx_t> ParseColumnsOrdered(const Value &value, vector<string> &names, const string &loption) { |
99 | vector<idx_t> result; |
100 | |
101 | // Only accept a list of arguments |
102 | if (value.type().id() != LogicalTypeId::LIST) { |
103 | // Support a single argument if it's '*' |
104 | if (value.type().id() == LogicalTypeId::VARCHAR && value.GetValue<string>() == "*" ) { |
105 | result.resize(new_size: names.size(), x: 0); |
106 | std::iota(first: std::begin(cont&: result), last: std::end(cont&: result), value: 0); |
107 | return result; |
108 | } |
109 | throw BinderException("\"%s\" expects a column list or * as parameter" , loption); |
110 | } |
111 | auto &children = ListValue::GetChildren(value); |
112 | // accept '*' as single argument |
113 | if (children.size() == 1 && children[0].type().id() == LogicalTypeId::VARCHAR && |
114 | children[0].GetValue<string>() == "*" ) { |
115 | result.resize(new_size: names.size(), x: 0); |
116 | std::iota(first: std::begin(cont&: result), last: std::end(cont&: result), value: 0); |
117 | return result; |
118 | } |
119 | return ParseColumnsOrdered(set: children, names, loption); |
120 | } |
121 | |
122 | } // namespace duckdb |
123 | |