Skip to content

Support for returning objects inside columns #1273

@trevornagy

Description

@trevornagy

This is an issue regarding 2 different items that both fall under the same category: returning named objects rather than tuples to provide an easier API to work with.

Item 1
I would like to perform a select * query with a left join (and return all data from both tables) and instead of returning tuples, I would return the objects of both tables (as it’s a select *).

After digging around in your examples and code I see you have sqlite_orm::object, which is defined underneath sqlite_orm::asterisk. To my confusion, the following code compiles (but returns tuples, which I don’t want in this scenario):

    return dbStorage->select(
        sqlite_orm::columns(
            sqlite_orm::asterisk<X>(), sqlite_orm::asterisk <Y>()
        ),
        sqlite_orm::left_join<Y>(sqlite_orm::on(
            sqlite_orm::c(&Y:: Key) == &X::Key
        )), orderBySql, sqlite_orm::limit(limitCount.value_or(-1))
    );

But the same code using sqlite_orm::object, does not:

    return dbStorage->select(
        sqlite_orm::columns(
            sqlite_orm::object<X>(), sqlite_orm::object<Y>()
        ),
        sqlite_orm::left_join<Y>(sqlite_orm::on(
            sqlite_orm::c(&Y:: Key) == &X::Key
        )), orderBySql, sqlite_orm::limit(limitCount.value_or(-1))
    );

The reasoning why I want to return the objects instead of tuples is that X and Y each have 5-10 properties which would result in a large return tuple in the first example, all with unnamed return types. It’s easier for the developer to use the API that example 2 provides.

The error is as follows: sqlite_orm.h(8754,61): error C2280: 'V sqlite_orm::row_extractor<V,void>::extract(sqlite3_stmt *,int) const': attempting to reference a deleted function

To mitigate this issue, my current strategy is to make a new struct Z that contains the all of the properties of X and Y and use std::make_from_tuple, like so:

    template <typename T, typename... Args>
    std::vector<T> ConvertTuplesToStructs(std::vector<std::tuple<Args...>>&& tuples)
    {
        std::vector<T> results;
        results.reserve(tuples.size());

        for (auto& tuple : tuples)
        {
            results.push_back(std::make_from_tuple<T>(std::move(tuple)));
        }

        return results;
    }

This leads into item 2.

Item 2
It would be nice if there was an API that allowed us to return new named structs that contain all of the return type members from a query. For example, I run this query:

        dbStorage->select(
            sqlite_orm::columns(
                &X::col1, 
                &X::col2,
                &X::col3, 
                &Y::col1
            ),
            sqlite_orm::join<Y>(
                sqlite_orm::on(sqlite_orm::c(&Y::Key) == &X::Key)
            )
        );

This will return a vector of tuples of 4 unnamed values, however, if in the future I update it to retrieve 5 values and the new value is in before &X::col1, all of the callers retrieving the 0th to 4th value will have to change their code. Once again, I can mitigate this using my approach above with the method ConvertTuplesToStructs and some other struct Z containing duplicates of the members X::col1, X::col2, X::col3, Y::col1. It would be nice however, if something like this was built into the API, where the developer could specify the return type struct.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions