1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:07:47 +00:00

LibSQL: Introduce SELECT ... LIMIT xxx OFFSET yyy

What it says on the tin.
This commit is contained in:
Jan de Visser 2022-01-12 11:41:58 -05:00 committed by Andreas Kling
parent 7fc901d1b3
commit 6e9f06fc9f
5 changed files with 166 additions and 7 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/NumericLimits.h>
#include <LibSQL/AST/AST.h>
#include <LibSQL/Database.h>
#include <LibSQL/Meta.h>
@ -69,7 +70,7 @@ RefPtr<SQLResult> Select::execute(ExecutionContext& context) const
rows.remove(0);
auto table_rows_or_error = context.database->select_all(*table);
if (table_rows_or_error.is_error())
return SQLResult::construct(SQLCommand::Create, SQLErrorCode::InternalError, table_rows_or_error.error());
return SQLResult::construct(SQLCommand::Select, SQLErrorCode::InternalError, table_rows_or_error.error());
for (auto& table_row : table_rows_or_error.value()) {
auto new_row = cartesian_row;
new_row.extend(table_row);
@ -114,6 +115,31 @@ RefPtr<SQLResult> Select::execute(ExecutionContext& context) const
}
context.result->insert(tuple, sort_key);
}
if (m_limit_clause != nullptr) {
size_t limit_value = NumericLimits<size_t>::max();
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");
}
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");
}
offset_value = offset_value_maybe.value();
}
}
context.result->limit(offset_value, limit_value);
}
return context.result;
}

View file

@ -21,6 +21,7 @@ set(SOURCES
Row.cpp
Serializer.cpp
SQLClient.cpp
SQLResult.cpp
TreeNode.cpp
Tuple.cpp
Value.cpp

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2022, Jan de Visser <jan@de-visser.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibSQL/SQLResult.h>
namespace SQL {
void SQLResult::insert(Tuple const& row, Tuple const& sort_key)
{
m_has_results = true;
m_result_set.insert_row(row, sort_key);
}
void SQLResult::limit(size_t offset, size_t limit)
{
if (offset > 0) {
if (offset > m_result_set.size()) {
m_result_set.clear();
return;
}
m_result_set.remove(0, offset);
}
if (m_result_set.size() > limit) {
m_result_set.remove(limit, m_result_set.size() - limit);
}
}
}

View file

@ -111,12 +111,8 @@ class SQLResult : public Core::Object {
C_OBJECT(SQLResult)
public:
void insert(Tuple const& row, Tuple const& sort_key)
{
m_has_results = true;
m_result_set.insert_row(row, sort_key);
}
void insert(Tuple const& row, Tuple const& sort_key);
void limit(size_t offset, size_t limit);
SQLCommand command() const { return m_command; }
int updated() const { return m_update_count; }
int inserted() const { return m_insert_count; }