Coverage Report

Created: 2026-03-31 07:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/duckdb/src/parser/column_definition.cpp
Line
Count
Source
1
#include "duckdb/parser/column_definition.hpp"
2
#include "duckdb/parser/parsed_expression_iterator.hpp"
3
#include "duckdb/parser/expression/columnref_expression.hpp"
4
#include "duckdb/parser/expression/cast_expression.hpp"
5
#include "duckdb/common/exception/parser_exception.hpp"
6
7
namespace duckdb {
8
9
ColumnDefinition::ColumnDefinition(string name_p, LogicalType type_p)
10
653k
    : name(std::move(name_p)), type(std::move(type_p)) {
11
653k
}
12
13
ColumnDefinition::ColumnDefinition(string name_p, LogicalType type_p, unique_ptr<ParsedExpression> expression,
14
                                   TableColumnType category)
15
2.97k
    : name(std::move(name_p)), type(std::move(type_p)), category(category), expression(std::move(expression)) {
16
2.97k
}
17
18
1.46k
ColumnDefinition ColumnDefinition::Copy() const {
19
1.46k
  ColumnDefinition copy(name, type);
20
1.46k
  copy.oid = oid;
21
1.46k
  copy.storage_oid = storage_oid;
22
1.46k
  copy.expression = expression ? expression->Copy() : nullptr;
23
1.46k
  copy.compression_type = compression_type;
24
1.46k
  copy.category = category;
25
1.46k
  copy.comment = comment;
26
1.46k
  copy.tags = tags;
27
1.46k
  return copy;
28
1.46k
}
29
30
0
const ParsedExpression &ColumnDefinition::DefaultValue() const {
31
0
  if (!HasDefaultValue()) {
32
0
    if (Generated()) {
33
0
      throw InternalException("Calling DefaultValue() on a generated column");
34
0
    }
35
0
    throw InternalException("DefaultValue() called on a column without a default value");
36
0
  }
37
0
  return *expression;
38
0
}
39
40
3.04k
bool ColumnDefinition::HasDefaultValue() const {
41
3.04k
  if (Generated()) {
42
0
    return false;
43
0
  }
44
3.04k
  return expression != nullptr;
45
3.04k
}
46
47
0
void ColumnDefinition::SetDefaultValue(unique_ptr<ParsedExpression> default_value) {
48
0
  if (Generated()) {
49
0
    throw InternalException("Calling SetDefaultValue() on a generated column");
50
0
  }
51
0
  this->expression = std::move(default_value);
52
0
}
53
54
335k
const LogicalType &ColumnDefinition::Type() const {
55
335k
  return type;
56
335k
}
57
58
4.48k
LogicalType &ColumnDefinition::TypeMutable() {
59
4.48k
  return type;
60
4.48k
}
61
62
0
void ColumnDefinition::SetType(const LogicalType &type) {
63
0
  this->type = type;
64
0
}
65
66
1.31M
const string &ColumnDefinition::Name() const {
67
1.31M
  return name;
68
1.31M
}
69
2.39k
void ColumnDefinition::SetName(const string &name) {
70
2.39k
  this->name = name;
71
2.39k
}
72
73
0
const Value &ColumnDefinition::Comment() const {
74
0
  return comment;
75
0
}
76
77
0
void ColumnDefinition::SetComment(const Value &comment) {
78
0
  this->comment = comment;
79
0
}
80
81
2.99k
const duckdb::CompressionType &ColumnDefinition::CompressionType() const {
82
2.99k
  return compression_type;
83
2.99k
}
84
85
0
void ColumnDefinition::SetCompressionType(duckdb::CompressionType compression_type) {
86
0
  this->compression_type = compression_type;
87
0
}
88
89
0
const storage_t &ColumnDefinition::StorageOid() const {
90
0
  return storage_oid;
91
0
}
92
93
159
LogicalIndex ColumnDefinition::Logical() const {
94
159
  return LogicalIndex(oid);
95
159
}
96
97
3
PhysicalIndex ColumnDefinition::Physical() const {
98
3
  return PhysicalIndex(storage_oid);
99
3
}
100
101
655k
void ColumnDefinition::SetStorageOid(storage_t storage_oid) {
102
655k
  this->storage_oid = storage_oid;
103
655k
}
104
105
655k
const column_t &ColumnDefinition::Oid() const {
106
655k
  return oid;
107
655k
}
108
109
655k
void ColumnDefinition::SetOid(column_t oid) {
110
655k
  this->oid = oid;
111
655k
}
112
113
0
const TableColumnType &ColumnDefinition::Category() const {
114
0
  return category;
115
0
}
116
117
667k
bool ColumnDefinition::Generated() const {
118
667k
  return category == TableColumnType::GENERATED;
119
667k
}
120
121
//===--------------------------------------------------------------------===//
122
// Generated Columns (VIRTUAL)
123
//===--------------------------------------------------------------------===//
124
125
19
static void VerifyColumnRefs(const ParsedExpression &expr) {
126
19
  ParsedExpressionIterator::VisitExpression<ColumnRefExpression>(expr, [&](const ColumnRefExpression &column_ref) {
127
19
    if (column_ref.IsQualified()) {
128
0
      throw ParserException(
129
0
          "Qualified (tbl.name) column references are not allowed inside of generated column expressions");
130
0
    }
131
19
  });
132
19
}
133
134
6
static void InnerGetListOfDependencies(ParsedExpression &expr, vector<string> &dependencies) {
135
6
  if (expr.GetExpressionType() == ExpressionType::COLUMN_REF) {
136
4
    auto columnref = expr.Cast<ColumnRefExpression>();
137
4
    auto &name = columnref.GetColumnName();
138
4
    dependencies.push_back(name);
139
4
  }
140
6
  ParsedExpressionIterator::EnumerateChildren(expr, [&](const ParsedExpression &child) {
141
2
    if (expr.GetExpressionType() == ExpressionType::LAMBDA) {
142
0
      throw NotImplementedException("Lambda functions are currently not supported in generated columns.");
143
0
    }
144
2
    InnerGetListOfDependencies((ParsedExpression &)child, dependencies);
145
2
  });
146
6
}
147
148
4
void ColumnDefinition::GetListOfDependencies(vector<string> &dependencies) const {
149
4
  D_ASSERT(Generated());
150
4
  InnerGetListOfDependencies(*expression, dependencies);
151
4
}
152
153
325k
string ColumnDefinition::GetName() const {
154
325k
  return name;
155
325k
}
156
157
329k
LogicalType ColumnDefinition::GetType() const {
158
329k
  return type;
159
329k
}
160
161
19
void ColumnDefinition::SetGeneratedExpression(unique_ptr<ParsedExpression> new_expr) {
162
19
  category = TableColumnType::GENERATED;
163
164
19
  if (new_expr->HasSubquery()) {
165
0
    throw ParserException("Expression of generated column \"%s\" contains a subquery, which isn't allowed", name);
166
0
  }
167
168
19
  VerifyColumnRefs(*new_expr);
169
19
  if (type.id() == LogicalTypeId::ANY) {
170
13
    expression = std::move(new_expr);
171
13
    return;
172
13
  }
173
  // Always wrap the expression in a cast, that way we can always update the cast when we change the type
174
  // Except if the type is LogicalType::ANY (no type specified)
175
6
  expression = make_uniq_base<ParsedExpression, CastExpression>(type, std::move(new_expr));
176
6
}
177
178
0
void ColumnDefinition::ChangeGeneratedExpressionType(const LogicalType &type) {
179
0
  D_ASSERT(Generated());
180
  // First time the type is set, add a cast around the expression
181
0
  D_ASSERT(this->type.id() == LogicalTypeId::ANY);
182
0
  expression = make_uniq_base<ParsedExpression, CastExpression>(type, std::move(expression));
183
  // Every generated expression should be wrapped in a cast on creation
184
  // D_ASSERT(generated_expression->type == ExpressionType::OPERATOR_CAST);
185
  // auto &cast_expr = generated_expression->Cast<CastExpression>();
186
  // auto base_expr = std::move(cast_expr.child);
187
  // generated_expression = make_uniq_base<ParsedExpression, CastExpression>(type, std::move(base_expr));
188
0
}
189
190
8
const ParsedExpression &ColumnDefinition::GeneratedExpression() const {
191
8
  D_ASSERT(Generated());
192
8
  return *expression;
193
8
}
194
195
0
ParsedExpression &ColumnDefinition::GeneratedExpressionMutable() {
196
0
  D_ASSERT(Generated());
197
0
  return *expression;
198
0
}
199
200
} // namespace duckdb