1#include "duckdb/parser/column_list.hpp"
2#include "duckdb/common/string.hpp"
3#include "duckdb/common/to_string.hpp"
4
5namespace duckdb {
6
7ColumnList::ColumnList(bool allow_duplicate_names) : allow_duplicate_names(allow_duplicate_names) {
8}
9void ColumnList::AddColumn(ColumnDefinition column) {
10 auto oid = columns.size();
11 if (!column.Generated()) {
12 column.SetStorageOid(physical_columns.size());
13 physical_columns.push_back(x: oid);
14 } else {
15 column.SetStorageOid(DConstants::INVALID_INDEX);
16 }
17 column.SetOid(columns.size());
18 AddToNameMap(column);
19 columns.push_back(x: std::move(column));
20}
21
22void ColumnList::Finalize() {
23 // add the "rowid" alias, if there is no rowid column specified in the table
24 if (name_map.find(x: "rowid") == name_map.end()) {
25 name_map["rowid"] = COLUMN_IDENTIFIER_ROW_ID;
26 }
27}
28
29void ColumnList::AddToNameMap(ColumnDefinition &col) {
30 if (allow_duplicate_names) {
31 idx_t index = 1;
32 string base_name = col.Name();
33 while (name_map.find(x: col.Name()) != name_map.end()) {
34 col.SetName(base_name + ":" + to_string(val: index++));
35 }
36 } else {
37 if (name_map.find(x: col.Name()) != name_map.end()) {
38 throw CatalogException("Column with name %s already exists!", col.Name());
39 }
40 }
41 name_map[col.Name()] = col.Oid();
42}
43
44ColumnDefinition &ColumnList::GetColumnMutable(LogicalIndex logical) {
45 if (logical.index >= columns.size()) {
46 throw InternalException("Logical column index %lld out of range", logical.index);
47 }
48 return columns[logical.index];
49}
50
51ColumnDefinition &ColumnList::GetColumnMutable(PhysicalIndex physical) {
52 if (physical.index >= physical_columns.size()) {
53 throw InternalException("Physical column index %lld out of range", physical.index);
54 }
55 auto logical_index = physical_columns[physical.index];
56 D_ASSERT(logical_index < columns.size());
57 return columns[logical_index];
58}
59
60ColumnDefinition &ColumnList::GetColumnMutable(const string &name) {
61 auto entry = name_map.find(x: name);
62 if (entry == name_map.end()) {
63 throw InternalException("Column with name \"%s\" does not exist", name);
64 }
65 auto logical_index = entry->second;
66 D_ASSERT(logical_index < columns.size());
67 return columns[logical_index];
68}
69
70const ColumnDefinition &ColumnList::GetColumn(LogicalIndex logical) const {
71 if (logical.index >= columns.size()) {
72 throw InternalException("Logical column index %lld out of range", logical.index);
73 }
74 return columns[logical.index];
75}
76
77const ColumnDefinition &ColumnList::GetColumn(PhysicalIndex physical) const {
78 if (physical.index >= physical_columns.size()) {
79 throw InternalException("Physical column index %lld out of range", physical.index);
80 }
81 auto logical_index = physical_columns[physical.index];
82 D_ASSERT(logical_index < columns.size());
83 return columns[logical_index];
84}
85
86const ColumnDefinition &ColumnList::GetColumn(const string &name) const {
87 auto entry = name_map.find(x: name);
88 if (entry == name_map.end()) {
89 throw InternalException("Column with name \"%s\" does not exist", name);
90 }
91 auto logical_index = entry->second;
92 D_ASSERT(logical_index < columns.size());
93 return columns[logical_index];
94}
95
96vector<string> ColumnList::GetColumnNames() const {
97 vector<string> names;
98 names.reserve(n: columns.size());
99 for (auto &column : columns) {
100 names.push_back(x: column.Name());
101 }
102 return names;
103}
104
105vector<LogicalType> ColumnList::GetColumnTypes() const {
106 vector<LogicalType> types;
107 types.reserve(n: columns.size());
108 for (auto &column : columns) {
109 types.push_back(x: column.Type());
110 }
111 return types;
112}
113
114bool ColumnList::ColumnExists(const string &name) const {
115 auto entry = name_map.find(x: name);
116 return entry != name_map.end();
117}
118
119PhysicalIndex ColumnList::LogicalToPhysical(LogicalIndex logical) const {
120 auto &column = GetColumn(logical);
121 if (column.Generated()) {
122 throw InternalException("Column at position %d is not a physical column", logical.index);
123 }
124 return column.Physical();
125}
126
127LogicalIndex ColumnList::PhysicalToLogical(PhysicalIndex index) const {
128 auto &column = GetColumn(physical: index);
129 return column.Logical();
130}
131
132LogicalIndex ColumnList::GetColumnIndex(string &column_name) const {
133 auto entry = name_map.find(x: column_name);
134 if (entry == name_map.end()) {
135 return LogicalIndex(DConstants::INVALID_INDEX);
136 }
137 if (entry->second == COLUMN_IDENTIFIER_ROW_ID) {
138 column_name = "rowid";
139 return LogicalIndex(COLUMN_IDENTIFIER_ROW_ID);
140 }
141 column_name = columns[entry->second].Name();
142 return LogicalIndex(entry->second);
143}
144
145ColumnList ColumnList::Copy() const {
146 ColumnList result(allow_duplicate_names);
147 for (auto &col : columns) {
148 result.AddColumn(column: col.Copy());
149 }
150 return result;
151}
152
153void ColumnList::Serialize(FieldWriter &writer) const {
154 writer.WriteRegularSerializableList(elements: columns);
155}
156
157ColumnList ColumnList::Deserialize(FieldReader &reader) {
158 ColumnList result;
159 auto columns = reader.ReadRequiredSerializableList<ColumnDefinition, ColumnDefinition>();
160 for (auto &col : columns) {
161 result.AddColumn(column: std::move(col));
162 }
163 return result;
164}
165
166ColumnList::ColumnListIterator ColumnList::Logical() const {
167 return ColumnListIterator(*this, false);
168}
169
170ColumnList::ColumnListIterator ColumnList::Physical() const {
171 return ColumnListIterator(*this, true);
172}
173
174} // namespace duckdb
175