-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConstraint.cpp
More file actions
179 lines (145 loc) · 5.37 KB
/
Constraint.cpp
File metadata and controls
179 lines (145 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//
// Created by Piotrek Rybiec on 04/05/2025.
//
#include <fmt/core.h>
#include <fmt/ranges.h>
#include "Table.hpp"
#include "Constraint.hpp"
#include "Database.hpp"
auto Constraint::getType() const -> ConstraintType {
return type;
}
auto Constraint::getName() const -> const std::string& {
return name;
}
auto Constraint::toString() const -> std::string {
return name;
}
auto Constraint::validate(const Row& row, const Table& table, const Database& base) const -> bool {
//throw std::runtime_error("base Constraint::validate has been called, which is incorrect.");
return validate(row, table);
}
auto PrimaryKeyConstraint::getColumnNames() const -> const std::vector<std::string>& {
return column_names;
}
auto PrimaryKeyConstraint::toString() const -> std::string {
return fmt::format("PRIMARY KEY ({})", fmt::join(column_names, ", "));
}
auto PrimaryKeyConstraint::validate(const Row& row, const Table& table, const Database& base) const -> bool {
return validate(row, table);
}
auto PrimaryKeyConstraint::validate(const Row& row, const Table& table) const -> bool {
// all columns from pk must exist in row and can't be null
for (const auto& col_name : column_names) {
if (!row.hasColumn(col_name)) {
return false;
}
if (row.getValue(col_name).isNull()) {
return false; // primary key columns cannot be null
}
}
for (const auto& existing_row : table.getRows()) {
bool matches = true;
for (const auto& col_name : column_names) {
if (!existing_row.hasColumn(col_name) ||
existing_row.getValue(col_name) != row.getValue(col_name)) {
matches = false;
break;
}
}
// if all columns match, we have a duplicate - primary key constraint violated
if (matches) {
return false;
}
}
return true;
}
auto ForeignKeyConstraint::validate(const Row& row, const Table& table) const -> bool {
if (!row.hasColumn(column_name)) return false;
const auto& value = row.getValue(column_name);
if (value.isNull()) return true; // allow nulls
return false; // without database context, we can't validate foreign key references
}
auto ForeignKeyConstraint::validate(const Row& row, const Table& table, const Database& base) const -> bool {
if (!row.hasColumn(column_name)) return false;
if (!base.tableExists(ref_table)) return false;
auto ref_table_obj = base.getTable(ref_table);
if (!ref_table_obj) return false;
const auto& value = row.getValue(column_name);
if (value.isNull()) return true; // allow nulls
// check if value exists
for (const auto& ref_row : ref_table_obj->getRows()) {
if (ref_row.hasColumn(ref_column) && (ref_row.getValue(ref_column) == value)) {
return true;
}
}
return false;
}
auto ForeignKeyConstraint::getColumnName() const -> const std::string& {
return column_name;
}
auto ForeignKeyConstraint::getRefTable() const -> const std::string& {
return ref_table;
}
auto ForeignKeyConstraint::getRefColumn() const -> const std::string& {
return ref_column;
}
auto ForeignKeyConstraint::toString() const -> std::string {
return fmt::format("FOREIGN KEY ({}) REFERENCES {}({})", column_name, ref_table, ref_column);
}
auto UniqueConstraint::getColumnNames() const -> const std::vector<std::string>& {
return column_names;
}
auto UniqueConstraint::toString() const -> std::string {
return fmt::format("UNIQUE ({})", fmt::join(column_names, ", "));
}
auto UniqueConstraint::validate(const Row& row, const Table& table) const -> bool {
for (const auto& col_name : column_names) {
if (!row.hasColumn(col_name)) {
return false;
}
if (row.getValue(col_name).isNull()) {
return true; // null values don't violate uniqueness
}
}
for (const auto& existing_row : table.getRows()) {
bool matches = true;
for (const auto& col_name : column_names) {
if (!existing_row.hasColumn(col_name) ||
existing_row.getValue(col_name).isNull() ||
existing_row.getValue(col_name) != row.getValue(col_name)) {
matches = false;
break;
}
}
// if all columns match, we have a duplicate
if (matches) {
return false;
}
}
return true; // no dups
}
auto UniqueConstraint::validate(const Row& row, const Table& table, const Database& base) const -> bool {
return validate(row, table);
}
auto NotNullConstraint::getColumnName() const -> const std::string& {
return column_name;
}
auto NotNullConstraint::toString() const -> std::string {
return fmt::format("NOT NULL ({})", column_name);
}
auto NotNullConstraint::validate(const Row& row, const Table& table) const -> bool {
return !row.getValue(column_name).isNull();
}
auto NotNullConstraint::validate(const Row& row, const Table& table, const Database& database) const -> bool {
return validate(row, table);
}
auto DefaultConstraint::getColumnName() const -> const std::string& {
return column_name;
}
auto DefaultConstraint::getDefaultValue() const -> const Value& {
return default_value;
}
auto DefaultConstraint::toString() const -> std::string {
return fmt::format("DEFAULT {} FOR {}", default_value.toString(), column_name);
}