| Compiler version | Minimum C++ standard required |
|---|---|
| GCC | -std=c++20 |
-
Make sure to include the library and the database interface
#include <ORM/ORM.hpp>
-
Initiate your table
Any struct or class can be a table. Just use
webframe::ORM::property<type, column name>to define the columns.struct Users { property<int, "id"> id; property<std::string, "username"> username; property<std::string, "password"> hashed_password; };
-
Initiate a relationship
Any column can be used for a relationship. Just use
webframe::ORM::relationship<relationship type, mapping property>to define the column.struct Post { property<int, "id"> id; property<std::string, "content"> content; }; struct User { property<int, "id"> id; property<std::string, "username"> username; property<std::string, "password"> hashed_password; relationship<RelationshipTypes::one2many, &Post::id> posts; };
- You can also create a separate mapping table:
struct UserPost { property<int, "id"> id; relationship<RelationshipTypes::one2one, &User::id> author; relationship<RelationshipTypes::one2one, &Post::id> post; };
-
Initiate your queries
Note: The queries should be declared as
constexpr. For easy usage, they should be declared asstaticif declared in classes/structures.struct UserPost { property<int, "id"> id; relationship<RelationshipTypes::one2one, &User::id> author; relationship<RelationshipTypes::one2one, &Post::id> post; static constexpr auto select_all = select(&UserPost::id, &User::id, &User::username, &Post::id, &Post::content) .join((P<&UserPost::author> == P<&User::id>) && (P<&UserPost::post> == P<&Post::id>)); // or static constexpr auto select_all = select(&UserPost::id, &User::id, &User::username, &Post::id, &Post::content) .join(P<&UserPost::author> == P<&User::id>) .join(P<&UserPost::post> == P<&Post::id>); static constexpr auto select_all_where_user_id_is_greater_than = select(&UserPost::id, &User::id, &User::username, &Post::id, &Post::content) .join((P<&UserPost::author> == P<&User::id>) && (P<&UserPost::post> == P<&Post::id>)) .filter(P<&User::id> > Placeholder<int>); };
or
constexpr auto select_all_users_and_posts = select(&UserPost::id, &User::id, &User::username, &Post::id, &Post::content) .join((P<&UserPost::author> == P<&User::id>) && (P<&UserPost::post> == P<&Post::id>)); //or constexpr auto select_all_users_and_posts = select(&UserPost::id, &User::id, &User::username, &Post::id, &Post::content) .join(P<&UserPost::author> == P<&User::id>) .join(P<&UserPost::post> == P<&Post::id>); constexpr auto select_all_where_user_id_is_greater_than = select(&UserPost::id, &User::id, &User::username, &Post::id, &Post::content) .join((P<&UserPost::author> == P<&User::id>) && (P<&UserPost::post> == P<&Post::id>)) .filter(P<&User::id> > Placeholder<int>);
Note: We highly recommend using your own
classornamespacewhere to put the relevant queries that you would like to use. If you want to prevent the use of some of the queries, make sure to use proper encapsulation. -
How to use your queries
- Request calls
If the database and the table(s) are setup as shown above, the requests should be used in the following way:
auto collection = UserPost::select_all(); //or auto collection = select_all_users_and_posts(); auto collection = select_all_where_user_id_is_greater_than(5);
- Access different columns of the output rows
for (auto row : collection) { std::cout << row.get<&User::id>() << ", "; }
Note: Even if the request's output is 1 row, it is still returned as collection (std::list) of the rows.
- Request calls
If the database and the table(s) are setup as shown above, the requests should be used in the following way:
Check example/ for more information.
-
Type-strict queries
Webframe::ORM allows you to develop your queries as lambdas behind the scenes. This leads to later on passing values to those lambdas and it will fill the placeholders with them. However, it also checks the types of the parameters and compares them to those of the placeholders. If something doesn't match you get compile-time error which prevents bugs later.
-
Query optimization compile-time
Webframe::ORM allows you to write your join conditions and filter conditions as boolean expression and it optimizes all of them compile-time for faster execution runtime.
-
SQL injection prevention
All database interfaces have their own SQL injection protection in case you want to use query parameters. Webframe::ORM gives easy-to-use interface to the bridges between databases' API and the ORM which is meant to use the native API's SQL injection protection keeping you 100% safe from this kind of attack.
- Limits fix
-
[LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value]
-
- Result type
- Member pointers and standard types
- Get references by member pointer
- Get references by table class
- Get references by index
- Rules
- IN / NOT IN
- CRUD operations
- Read / select
- COUNT(*) / COUNT(...)
SELECT [ ALL | DISTINCT | DISTINCTROW ] [ HIGH_PRIORITY ] [ STRAIGHT_JOIN ] [ SQL_SMALL_RESULT | SQL_BIG_RESULT ] [ SQL_BUFFER_RESULT ] [ SQL_CACHE | SQL_NO_CACHE ] [ SQL_CALC_FOUND_ROWS ] expressions FROM tables [[LEFT | RIGHT | INNER] JOIN table] [WHERE conditions] [GROUP BY expressions] [HAVING condition] [ORDER BY expression [ ASC | DESC ]] [LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value] INTO [ OUTFILE 'file_name' options | DUMPFILE 'file_name' | @variable1, @variable2, ... @variable_n] [FOR UPDATE | LOCK IN SHARE MODE];
- Read / select
- Transferring the abstract database implementation from v1.1 to v2 using the new SQL-free query style
- Implement free MySQL driver
- Implement free MongoDB driver
- Auto-migrating on startup
- Keep track of latest migration done
- Apply new migrations if any
- C++ Migrations tool
- Run tests with SQL and NoSQL databases