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
9namespace duckdb {
10
11Value 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
18vector<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
46vector<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
68vector<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
98vector<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