A C++ ORM for MySQL, inspired by sqlite_orm.
mysql_orm
manages your queries to a MySQL database with an intuitive syntax and as much type-checking as possible at compile-time (hence reducing risks that a query is ill-formed).
Consider the following structure:
struct Record
{
uint32_t id;
int i;
std::string s;
};
We can create a table from this structure the following way:
auto table_records = make_table("records",
make_column<&Record::id>("id"),
make_column<&Record::i>("i"),
make_column<&Record::s>("s"));
mysql_orm
automatically deduces the types of the fields and the one of the structure (which we call the model).
If the fields do not refer to the same model, an error is raised at compile-time.
We can now make a database connection from the table:
auto connection = mysql_orm::Connection("localhost", 3306, "username", "password", "database");
auto database = make_database(connection, table_records);
Any number of tables may be supplied when constructing a database.
Any model whose table is given to the database may be used when performing a query with the database
object.
Note that all tables must refer to distinct models.
A SELECT
query on a model is written the following way:
std::vector<Records> records = database.getAll<Record>()();
The database automatically chooses the table for Record
on which to perform the query.
By default all fields are selected.
Some fields only may be selected by giving as template arguments the pointer to the attributes to select:
std::vector<Records> records = database.getAll<&Record::id, &Record::s>()();
This is the same as:
SELECT `id`, `s` FROM `records`
SQL clauses are chained using operator()
s:
database.getAll<Record>()(Where{c<&Record::i>{} = 3})(Limit<1>{})();
is equivalent to:
SELECT * FROM `records` WHERE `records`.`i`=3 LIMIT 1
In order to build conditions correctly for WHERE
and assignments for SET
, you need to user one of the c
and ref
classes.
c
is templated on a pointer to an attribute.
When put in an operation, it will be substituted by the column corresponding to the attribute.
In the above example, c<&Record::i>{}
was changed to records.i
.
ref
takes a reference to the variable it is given, as opposed to taking it by value.
Let us look at the following:
int i = 4;
auto query = database.getAll<Record>()(Where{c<&Record::i>{}=ref{i});
query();
i = 2;
query();
The first call to query
translates to
SELECT * FROM `records` WHERE `records`.`i`=4
While the second translates to
SELECT * FROM `records` WHERE `records`.`i`=2
Had we written c<&Record::i>{}=i
, both calls would have been evaluated with i=4
.
- Joins.
- Constraints on multiple columns (
UNIQUE(a, b)
).