diff --git a/include/sqlgen.hpp b/include/sqlgen.hpp index ff629e6..71d066d 100644 --- a/include/sqlgen.hpp +++ b/include/sqlgen.hpp @@ -10,6 +10,7 @@ #include "sqlgen/Ref.hpp" #include "sqlgen/Result.hpp" #include "sqlgen/Varchar.hpp" +#include "sqlgen/col.hpp" #include "sqlgen/read.hpp" #include "sqlgen/write.hpp" diff --git a/include/sqlgen/col.hpp b/include/sqlgen/col.hpp new file mode 100644 index 0000000..1e7454d --- /dev/null +++ b/include/sqlgen/col.hpp @@ -0,0 +1,16 @@ +#ifndef SQLGEN_COL_HPP_ +#define SQLGEN_COL_HPP_ + +#include + +namespace sqlgen { + +template +struct Col {}; + +template +const auto col = Col<_name>{}; + +} // namespace sqlgen + +#endif diff --git a/include/sqlgen/dynamic/Limit.hpp b/include/sqlgen/dynamic/Limit.hpp new file mode 100644 index 0000000..08d82d4 --- /dev/null +++ b/include/sqlgen/dynamic/Limit.hpp @@ -0,0 +1,16 @@ +#ifndef SQLGEN_DYNAMIC_LIMIT_HPP_ +#define SQLGEN_DYNAMIC_LIMIT_HPP_ + +#include + +#include "Column.hpp" + +namespace sqlgen::dynamic { + +struct Limit { + size_t val; +}; + +} // namespace sqlgen::dynamic + +#endif diff --git a/include/sqlgen/dynamic/OrderBy.hpp b/include/sqlgen/dynamic/OrderBy.hpp new file mode 100644 index 0000000..f64938f --- /dev/null +++ b/include/sqlgen/dynamic/OrderBy.hpp @@ -0,0 +1,20 @@ +#ifndef SQLGEN_DYNAMIC_ORDERBY_HPP_ +#define SQLGEN_DYNAMIC_ORDERBY_HPP_ + +#include + +#include "Column.hpp" + +namespace sqlgen::dynamic { + +struct OrderBy { + struct Wrapper { + Column column; + bool desc = false; + }; + std::vector columns; +}; + +} // namespace sqlgen::dynamic + +#endif diff --git a/include/sqlgen/dynamic/SelectFrom.hpp b/include/sqlgen/dynamic/SelectFrom.hpp index 672ab79..aebde64 100644 --- a/include/sqlgen/dynamic/SelectFrom.hpp +++ b/include/sqlgen/dynamic/SelectFrom.hpp @@ -1,10 +1,13 @@ #ifndef SQLGEN_DYNAMIC_SELECTFROM_HPP_ #define SQLGEN_DYNAMIC_SELECTFROM_HPP_ +#include #include #include #include "Column.hpp" +#include "Limit.hpp" +#include "OrderBy.hpp" #include "Table.hpp" namespace sqlgen::dynamic { @@ -12,6 +15,8 @@ namespace sqlgen::dynamic { struct SelectFrom { Table table; std::vector columns; + std::optional order_by = std::nullopt; + std::optional limit = std::nullopt; }; } // namespace sqlgen::dynamic diff --git a/src/sqlgen/postgres/Connection.cpp b/src/sqlgen/postgres/Connection.cpp index 255f85d..8dcef20 100644 --- a/src/sqlgen/postgres/Connection.cpp +++ b/src/sqlgen/postgres/Connection.cpp @@ -122,7 +122,12 @@ std::string Connection::select_from_to_sql( const dynamic::SelectFrom& _stmt) const noexcept { using namespace std::ranges::views; + const auto order_by_to_str = [](const auto& _w) -> std::string { + return "\"" + _w.column.name + "\"" + (_w.desc ? " DESC" : ""); + }; + std::stringstream stream; + stream << "SELECT "; stream << internal::strings::join( ", ", internal::collect::vector(_stmt.columns | transform(get_name) | @@ -131,7 +136,20 @@ std::string Connection::select_from_to_sql( if (_stmt.table.schema) { stream << wrap_in_quotes(*_stmt.table.schema) << "."; } - stream << wrap_in_quotes(_stmt.table.name) << ";"; + stream << wrap_in_quotes(_stmt.table.name); + + if (_stmt.order_by) { + stream << " ORDER BY " + << internal::strings::join( + ", ", internal::collect::vector(_stmt.order_by->columns | + transform(order_by_to_str))); + } + + if (_stmt.limit) { + stream << " LIMIT " << _stmt.limit->val; + } + + stream << ";"; return stream.str(); } diff --git a/src/sqlgen/sqlite/Connection.cpp b/src/sqlgen/sqlite/Connection.cpp index 63da1ff..f414312 100644 --- a/src/sqlgen/sqlite/Connection.cpp +++ b/src/sqlgen/sqlite/Connection.cpp @@ -143,6 +143,10 @@ std::string Connection::select_from_to_sql( return "\"" + _col.name + "\""; }; + const auto order_by_to_str = [](const auto& _w) -> std::string { + return "\"" + _w.column.name + "\"" + (_w.desc ? " DESC" : ""); + }; + std::stringstream stream; stream << "SELECT "; stream << internal::strings::join( @@ -152,7 +156,20 @@ std::string Connection::select_from_to_sql( if (_stmt.table.schema) { stream << "\"" << *_stmt.table.schema << "\"."; } - stream << "\"" << _stmt.table.name << "\";"; + stream << "\"" << _stmt.table.name << "\""; + + if (_stmt.order_by) { + stream << " ORDER BY " + << internal::strings::join( + ", ", internal::collect::vector(_stmt.order_by->columns | + transform(order_by_to_str))); + } + + if (_stmt.limit) { + stream << " LIMIT " << _stmt.limit->val; + } + + stream << ";"; return stream.str(); }