/* * Copyright (c) 2021, Jan de Visser * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include namespace SQL::AST { RefPtr Select::execute(ExecutionContext& context) const { NonnullRefPtrVector columns; for (auto& table_descriptor : table_or_subquery_list()) { if (!table_descriptor.is_table()) TODO(); auto table = context.database->get_table(table_descriptor.schema_name(), table_descriptor.table_name()); if (!table) { return SQLResult::construct(SQL::SQLCommand::Select, SQL::SQLErrorCode::TableDoesNotExist, table_descriptor.table_name()); } if (result_column_list().size() == 1 && result_column_list()[0].type() == ResultType::All) { for (auto& col : table->columns()) { columns.append( create_ast_node( create_ast_node(table->parent()->name(), table->name(), col.name()), "")); } } } VERIFY(!result_column_list().is_empty()); if (result_column_list().size() != 1 || result_column_list()[0].type() != ResultType::All) { for (auto& col : result_column_list()) { if (col.type() == ResultType::All) // FIXME can have '*' for example in conjunction with computed columns return SQLResult::construct(SQL::SQLCommand::Select, SQL::SQLErrorCode::SyntaxError, "*"); columns.append(col); } } context.result = SQLResult::construct(); AK::NonnullRefPtr descriptor = AK::adopt_ref(*new TupleDescriptor); Tuple tuple(descriptor); Vector rows; descriptor->empend("__unity__"); tuple.append(Value(SQLType::Boolean, true)); rows.append(tuple); for (auto& table_descriptor : table_or_subquery_list()) { if (!table_descriptor.is_table()) TODO(); auto table = context.database->get_table(table_descriptor.schema_name(), table_descriptor.table_name()); if (table->num_columns() == 0) continue; auto old_descriptor_size = descriptor->size(); descriptor->extend(table->to_tuple_descriptor()); for (auto cartesian_row = rows.first(); cartesian_row.size() == old_descriptor_size; cartesian_row = rows.first()) { rows.remove(0); for (auto& table_row : context.database->select_all(*table)) { auto new_row = cartesian_row; new_row.extend(table_row); rows.append(new_row); } } } for (auto& row : rows) { context.current_row = &row; if (where_clause()) { auto where_result = where_clause()->evaluate(context); if (context.result->has_error()) return context.result; if (!where_result) continue; } tuple.clear(); for (auto& col : columns) { auto value = col.expression()->evaluate(context); if (context.result->has_error()) return context.result; tuple.append(value); } context.result->append(tuple); } return context.result; } }