/src/serenity/Userland/Libraries/LibSQL/AST/Insert.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Jan de Visser <jan@de-visser.net> |
3 | | * Copyright (c) 2021, Mahmoud Mandour <ma.mandourr@gmail.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <LibSQL/AST/AST.h> |
9 | | #include <LibSQL/Database.h> |
10 | | #include <LibSQL/Meta.h> |
11 | | #include <LibSQL/Row.h> |
12 | | |
13 | | namespace SQL::AST { |
14 | | |
15 | | ResultOr<ResultSet> Insert::execute(ExecutionContext& context) const |
16 | 0 | { |
17 | 0 | auto table_def = TRY(context.database->get_table(m_schema_name, m_table_name)); |
18 | |
|
19 | 0 | Row row(table_def); |
20 | 0 | for (auto& column : m_column_names) { |
21 | 0 | if (!row.has(column)) |
22 | 0 | return Result { SQLCommand::Insert, SQLErrorCode::ColumnDoesNotExist, column }; |
23 | 0 | } |
24 | | |
25 | 0 | ResultSet result { SQLCommand::Insert }; |
26 | 0 | TRY(result.try_ensure_capacity(m_chained_expressions.size())); |
27 | |
|
28 | 0 | for (auto& row_expr : m_chained_expressions) { |
29 | 0 | for (auto& column_def : table_def->columns()) { |
30 | 0 | if (!m_column_names.contains_slow(column_def->name())) |
31 | 0 | row[column_def->name()] = column_def->default_value(); |
32 | 0 | } |
33 | |
|
34 | 0 | auto row_value = TRY(row_expr->evaluate(context)); |
35 | 0 | VERIFY(row_value.type() == SQLType::Tuple); |
36 | | |
37 | 0 | auto values = row_value.to_vector().release_value(); |
38 | |
|
39 | 0 | if (m_column_names.is_empty() && values.size() != row.size()) |
40 | 0 | return Result { SQLCommand::Insert, SQLErrorCode::InvalidNumberOfValues, ByteString::empty() }; |
41 | | |
42 | 0 | for (auto ix = 0u; ix < values.size(); ix++) { |
43 | 0 | auto& tuple_descriptor = *row.descriptor(); |
44 | | // In case of having column names, this must succeed since we checked for every column name for existence in the table. |
45 | 0 | auto element_index = m_column_names.is_empty() ? ix : tuple_descriptor.find_if([&](auto element) { return element.name == m_column_names[ix]; }).index(); |
46 | 0 | auto element_type = tuple_descriptor[element_index].type; |
47 | |
|
48 | 0 | if (!values[ix].is_type_compatible_with(element_type)) |
49 | 0 | return Result { SQLCommand::Insert, SQLErrorCode::InvalidValueType, table_def->columns()[element_index]->name() }; |
50 | | |
51 | 0 | row[element_index] = move(values[ix]); |
52 | 0 | } |
53 | | |
54 | 0 | TRY(context.database->insert(row)); |
55 | 0 | result.insert_row(row, {}); |
56 | 0 | } |
57 | | |
58 | 0 | return result; |
59 | 0 | } |
60 | | |
61 | | } |