Serenity Operating System
1/*
2 * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibSQL/AST/AST.h>
8#include <LibSQL/Database.h>
9#include <LibSQL/Meta.h>
10#include <LibSQL/Row.h>
11
12namespace SQL::AST {
13
14ResultOr<ResultSet> Update::execute(ExecutionContext& context) const
15{
16 auto const& schema_name = m_qualified_table_name->schema_name();
17 auto const& table_name = m_qualified_table_name->table_name();
18 auto table_def = TRY(context.database->get_table(schema_name, table_name));
19
20 Vector<Row> matched_rows;
21
22 for (auto& table_row : TRY(context.database->select_all(*table_def))) {
23 context.current_row = &table_row;
24
25 if (auto const& where_clause = this->where_clause()) {
26 auto where_result = TRY(where_clause->evaluate(context)).to_bool();
27 if (!where_result.has_value() || !where_result.value())
28 continue;
29 }
30
31 TRY(matched_rows.try_append(move(table_row)));
32 }
33
34 ResultSet result { SQLCommand::Update };
35
36 for (auto& update_column : m_update_columns) {
37 auto row_value = TRY(update_column.expression->evaluate(context));
38
39 for (auto& table_row : matched_rows) {
40 auto& row_descriptor = *table_row.descriptor();
41
42 for (auto const& column_name : update_column.column_names) {
43 if (!table_row.has(column_name))
44 return Result { SQLCommand::Update, SQLErrorCode::ColumnDoesNotExist, column_name };
45
46 auto column_index = row_descriptor.find_if([&](auto element) { return element.name == column_name; }).index();
47 auto column_type = row_descriptor[column_index].type;
48
49 if (!row_value.is_type_compatible_with(column_type))
50 return Result { SQLCommand::Update, SQLErrorCode::InvalidValueType, column_name };
51
52 table_row[column_index] = row_value;
53 }
54
55 TRY(context.database->update(table_row));
56 result.insert_row(table_row, {});
57 }
58 }
59
60 return result;
61}
62
63}