fnc12/sqlite_orm

Do not understand select statement generation

juandent opened this issue · 3 comments

I am returning from a long time not using sqlite_orm and found something peculiar:

why does this statement:

auto firstNames = storage.select(columns(m->*&Employee::firstName || " " || m->*&Employee::lastName,
                                         &Employee::firstName || " " || &Employee::lastName),
                                 inner_join<m>(on(m->*&Employee::reportsTo == &Employee::employeeId)));

produce this sql:

SELECT ("m"."FirstName" || ' ') || "m"."LastName", 1 
FROM "employees" 
INNER JOIN "employees" "m" 
ON "m"."ReportsTo" = "employees"."EmployeeId" 

-- taken from self_join.cpp

Regards,
Juan

@juandent what do you expect to produce instead?

I see that the problem is the literal 1 as the value of the second column.
This is because you are or'ing a pointer-to-member with a C string literal and its result with another pointer-to-member. sqlite_orm can overload the ||-operator only for sqlite_orm types, not for C++ builtin types alone in an expression.
The first column expression works, because m->*&Employee::firstName forms a type in the sqlite_orm namespace.

You have multiple options to help sqlite_orm to create an expression where overloaded operators work.
I would form a table reference as the canonical way in modern C++:

constexpr auto employee = c<Employee>();
// employee->*&Employee::firstName || " " || employee->*&Employee::lastName

auto firstNames = storage.select(columns(m->*&Employee::firstName || " " || m->*&Employee::lastName,
                                         employee->*&Employee::firstName || " " || employee->*&Employee::lastName),
                                 inner_join<m>(on(m->*&Employee::reportsTo == employee->*&Employee::employeeId)));

Technically you don't need the repeated employee->*, but it's easier on the brain :)

Thanks!