mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:02:45 +00:00 
			
		
		
		
	LibSQL+SQLServer: Return the new Result class from statement executions
We can now TRY anything that returns a SQL::Result or an AK::Error.
This commit is contained in:
		
							parent
							
								
									d9055de7ea
								
							
						
					
					
						commit
						6620f19979
					
				
					 11 changed files with 337 additions and 337 deletions
				
			
		|  | @ -13,65 +13,67 @@ | |||
| 
 | ||||
| namespace SQL::AST { | ||||
| 
 | ||||
| RefPtr<SQLResult> Select::execute(ExecutionContext& context) const | ||||
| Result Select::execute(ExecutionContext& context) const | ||||
| { | ||||
|     NonnullRefPtrVector<ResultColumn> columns; | ||||
| 
 | ||||
|     auto const& result_column_list = this->result_column_list(); | ||||
|     VERIFY(!result_column_list.is_empty()); | ||||
| 
 | ||||
|     for (auto& table_descriptor : table_or_subquery_list()) { | ||||
|         if (!table_descriptor.is_table()) | ||||
|             return SQLResult::construct(SQLCommand::Select, SQLErrorCode::NotYetImplemented, "Sub-selects are not yet implemented"); | ||||
|         auto table_def_or_error = context.database->get_table(table_descriptor.schema_name(), table_descriptor.table_name()); | ||||
|         if (table_def_or_error.is_error()) | ||||
|             return SQLResult::construct(SQLCommand::Select, SQLErrorCode::InternalError, table_def_or_error.error()); | ||||
|         auto table = table_def_or_error.value(); | ||||
|         if (!table) { | ||||
|             return SQLResult::construct(SQLCommand::Select, SQLErrorCode::TableDoesNotExist, table_descriptor.table_name()); | ||||
|         } | ||||
|             return { SQLCommand::Select, SQLErrorCode::NotYetImplemented, "Sub-selects are not yet implemented"sv }; | ||||
| 
 | ||||
|         if (result_column_list().size() == 1 && result_column_list()[0].type() == ResultType::All) { | ||||
|             for (auto& col : table->columns()) { | ||||
|         auto table_def = TRY(context.database->get_table(table_descriptor.schema_name(), table_descriptor.table_name())); | ||||
|         if (!table_def) | ||||
|             return { SQLCommand::Select, SQLErrorCode::TableDoesNotExist, table_descriptor.table_name() }; | ||||
| 
 | ||||
|         if (result_column_list.size() == 1 && result_column_list[0].type() == ResultType::All) { | ||||
|             for (auto& col : table_def->columns()) { | ||||
|                 columns.append( | ||||
|                     create_ast_node<ResultColumn>( | ||||
|                         create_ast_node<ColumnNameExpression>(table->parent()->name(), table->name(), col.name()), | ||||
|                         create_ast_node<ColumnNameExpression>(table_def->parent()->name(), table_def->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) | ||||
|     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, SQLErrorCode::SyntaxError, "*"); | ||||
|                 return { SQLCommand::Select, SQLErrorCode::SyntaxError, "*"sv }; | ||||
|             } | ||||
| 
 | ||||
|             columns.append(col); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     context.result = SQLResult::construct(); | ||||
|     AK::NonnullRefPtr<TupleDescriptor> descriptor = AK::adopt_ref(*new TupleDescriptor); | ||||
|     context.result = Result { SQLCommand::Select }; | ||||
| 
 | ||||
|     auto descriptor = adopt_ref(*new TupleDescriptor); | ||||
|     Tuple tuple(descriptor); | ||||
|     Vector<Tuple> rows; | ||||
|     descriptor->empend("__unity__"); | ||||
|     descriptor->empend("__unity__"sv); | ||||
|     tuple.append(Value(SQLType::Boolean, true)); | ||||
|     rows.append(tuple); | ||||
| 
 | ||||
|     for (auto& table_descriptor : table_or_subquery_list()) { | ||||
|         if (!table_descriptor.is_table()) | ||||
|             return SQLResult::construct(SQLCommand::Select, SQLErrorCode::NotYetImplemented, "Sub-selects are not yet implemented"); | ||||
|         auto table_def_or_error = context.database->get_table(table_descriptor.schema_name(), table_descriptor.table_name()); | ||||
|         if (table_def_or_error.is_error()) | ||||
|             return SQLResult::construct(SQLCommand::Select, SQLErrorCode::InternalError, table_def_or_error.error()); | ||||
|         auto table = table_def_or_error.value(); | ||||
|         if (table->num_columns() == 0) | ||||
|             return { SQLCommand::Select, SQLErrorCode::NotYetImplemented, "Sub-selects are not yet implemented"sv }; | ||||
| 
 | ||||
|         auto table_def = TRY(context.database->get_table(table_descriptor.schema_name(), table_descriptor.table_name())); | ||||
|         if (table_def->num_columns() == 0) | ||||
|             continue; | ||||
| 
 | ||||
|         auto old_descriptor_size = descriptor->size(); | ||||
|         descriptor->extend(table->to_tuple_descriptor()); | ||||
|         descriptor->extend(table_def->to_tuple_descriptor()); | ||||
| 
 | ||||
|         for (auto cartesian_row = rows.first(); cartesian_row.size() == old_descriptor_size; cartesian_row = rows.first()) { | ||||
|             rows.remove(0); | ||||
|             auto table_rows_or_error = context.database->select_all(*table); | ||||
|             if (table_rows_or_error.is_error()) | ||||
|                 return SQLResult::construct(SQLCommand::Select, SQLErrorCode::InternalError, table_rows_or_error.error()); | ||||
|             for (auto& table_row : table_rows_or_error.value()) { | ||||
|             auto table_rows = TRY(context.database->select_all(*table_def)); | ||||
| 
 | ||||
|             for (auto& table_row : table_rows) { | ||||
|                 auto new_row = cartesian_row; | ||||
|                 new_row.extend(table_row); | ||||
|                 rows.append(new_row); | ||||
|  | @ -80,7 +82,7 @@ RefPtr<SQLResult> Select::execute(ExecutionContext& context) const | |||
|     } | ||||
| 
 | ||||
|     bool has_ordering { false }; | ||||
|     AK::NonnullRefPtr<TupleDescriptor> sort_descriptor = AK::adopt_ref(*new TupleDescriptor); | ||||
|     auto sort_descriptor = adopt_ref(*new TupleDescriptor); | ||||
|     for (auto& term : m_ordering_term_list) { | ||||
|         sort_descriptor->append(TupleElementDescriptor { .order = term.order() }); | ||||
|         has_ordering = true; | ||||
|  | @ -89,18 +91,21 @@ RefPtr<SQLResult> Select::execute(ExecutionContext& context) const | |||
| 
 | ||||
|     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 (context.result->is_error()) | ||||
|                 return context.result.release_value(); | ||||
|             if (!where_result) | ||||
|                 continue; | ||||
|         } | ||||
| 
 | ||||
|         tuple.clear(); | ||||
| 
 | ||||
|         for (auto& col : columns) { | ||||
|             auto value = col.expression()->evaluate(context); | ||||
|             if (context.result->has_error()) | ||||
|                 return context.result; | ||||
|             if (context.result->is_error()) | ||||
|                 return context.result.release_value(); | ||||
|             tuple.append(value); | ||||
|         } | ||||
| 
 | ||||
|  | @ -108,39 +113,43 @@ RefPtr<SQLResult> Select::execute(ExecutionContext& context) const | |||
|             sort_key.clear(); | ||||
|             for (auto& term : m_ordering_term_list) { | ||||
|                 auto value = term.expression()->evaluate(context); | ||||
|                 if (context.result->has_error()) | ||||
|                     return context.result; | ||||
|                 if (context.result->is_error()) | ||||
|                     return context.result.release_value(); | ||||
|                 sort_key.append(value); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         context.result->insert(tuple, sort_key); | ||||
|     } | ||||
| 
 | ||||
|     if (m_limit_clause != nullptr) { | ||||
|         size_t limit_value = NumericLimits<size_t>::max(); | ||||
|         size_t offset_value = 0; | ||||
| 
 | ||||
|         auto limit = m_limit_clause->limit_expression()->evaluate(context); | ||||
|         if (!limit.is_null()) { | ||||
|             auto limit_value_maybe = limit.to_u32(); | ||||
|             if (!limit_value_maybe.has_value()) { | ||||
|                 return SQLResult::construct(SQLCommand::Select, SQLErrorCode::SyntaxError, "LIMIT clause must evaluate to an integer value"); | ||||
|             } | ||||
|             if (!limit_value_maybe.has_value()) | ||||
|                 return { SQLCommand::Select, SQLErrorCode::SyntaxError, "LIMIT clause must evaluate to an integer value"sv }; | ||||
| 
 | ||||
|             limit_value = limit_value_maybe.value(); | ||||
|         } | ||||
|         size_t offset_value = 0; | ||||
| 
 | ||||
|         if (m_limit_clause->offset_expression() != nullptr) { | ||||
|             auto offset = m_limit_clause->offset_expression()->evaluate(context); | ||||
|             if (!offset.is_null()) { | ||||
|                 auto offset_value_maybe = offset.to_u32(); | ||||
|                 if (!offset_value_maybe.has_value()) { | ||||
|                     return SQLResult::construct(SQLCommand::Select, SQLErrorCode::SyntaxError, "OFFSET clause must evaluate to an integer value"); | ||||
|                 } | ||||
|                 if (!offset_value_maybe.has_value()) | ||||
|                     return { SQLCommand::Select, SQLErrorCode::SyntaxError, "OFFSET clause must evaluate to an integer value"sv }; | ||||
| 
 | ||||
|                 offset_value = offset_value_maybe.value(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         context.result->limit(offset_value, limit_value); | ||||
|     } | ||||
| 
 | ||||
|     return context.result; | ||||
|     return context.result.release_value(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy Flynn
						Timothy Flynn