如何从 boost::mysql::row 获取元数据?

How can I get metadata from boost::mysql::row?

如何将元数据从元素获取到 boost::mysql::row?

void print_employee(const boost::mysql::row& employee)
    {
        std::cout << "Employee '"
                  << employee.values()[0] << std::endl;

我如何从这里获取元数据?我想提取这个特定值的列名

    const boost::mysql::field_metadata &column = employee[0];
    std::cout << column.original_field_name() << std::endl;
}



    std::vector<boost::mysql::row> employees = result.read_all();
    for (const auto& employee: employees)
    {
        print_employee(employee);
    }

与此文档相关:https://anarthal.github.io/mysql/mysql/resultsets.html#mysql.resultsets.metadata 而这个 https://anarthal.github.io/mysql/

问题是 boost::mysql::row 中没有 属性 original_field_name 和其他因为它们在 ::field_metadata.

知道怎么连接子类2就好了。 肯定有办法,只是没找到

字段元数据描述了一个行集,而不是单个行(因为在 SQL 模型中,结果集中的每一行都具有完全相同的元数据)。

因此,假设您有一个名为 Test 的数据库,其中包含一条 table 消息,您可以使用每一行的元数据,如下所示:

#include <boost/mysql.hpp>
#include <iostream>
using boost::asio::ip::tcp;

int main()
{
    boost::asio::io_context ctx;
    boost::mysql::tcp_connection conn(ctx);

    boost::mysql::connection_params params("su", "su", "Test");
    conn.connect(tcp::endpoint{{}, boost::mysql::default_port}, params);

    auto rs = conn.query("SELECT * FROM Message;");
    std::vector<boost::mysql::field_metadata> const& meta = rs.fields();

    for (auto&& r : rs.read_all()) {
        std::cout << " ---- row:\n";
        std::vector<boost::mysql::value> const& v = r.values();

        for (size_t i = 0; i < meta.size(); ++i) {
            std::cout << "\tcol:" << meta[i].original_field_name() << " val:" << v[i] << "\n";;
        }
    }
}

在我的系统上,打印出类似

的内容
 ---- row:
    col:message_id val:165
    col:login_sender_id val:1
    col:login_recipient_id val:2
    col:date val:2021-02-01 02:24:22.000000
    col:content val:ahoi
    col:dialog_id val:1
    col:read_by_recipient val:1
 ---- row:
    col:message_id val:166
    col:login_sender_id val:2
    col:login_recipient_id val:1
    col:date val:2021-02-01 02:24:25.000000
    col:content val:bye
    col:dialog_id val:1
    col:read_by_recipient val:1
 ---- row:
...
etc.

更优雅

一些明智的 usings/auto 它变得不那么麻烦:

#include <boost/mysql.hpp>
#include <iostream>
using boost::asio::ip::tcp;
using boost::mysql::tcp_connection;

int main()
{
    boost::asio::io_context ctx;
    tcp_connection conn(ctx);

    conn.connect(tcp::endpoint{{}, boost::mysql::default_port}, {"su", "su", "Test"});

    auto rs = conn.query("SELECT * FROM Message;");
    auto& meta = rs.fields();

    for (auto&& r : rs.read_all()) {
        std::cout << " ---- row:\n";
        auto& v = r.values();

        for (size_t i = 0; i < meta.size(); ++i) {
            std::cout << "\tcol:" << meta[i].original_field_name() << " val:" << v[i] << "\n";;
        }
    }
}

樱桃在上面

为了减少使用整数索引的麻烦,您可以在视图中隐藏所有内容:

auto meta_view(resultset& rs) {
    auto all = std::make_shared<std::vector<row> >(rs.read_all());
    auto row_view = [meta = rs.fields(), all](row const& r) {
        return std::views::iota(0ul, meta.size()) |
            std::views::transform([&](size_t idx) {
                   return std::tie(r.values()[idx], meta[idx]);
               });
    };
    return *all | std::views::transform(row_view);
}

Note, this plays tricks to solve issues with lifetime and the result is not very efficient. So, maybe just accept the crummy-ness of the interface and take this example as inspiration for other things

现在客户端代码可以

auto rs = conn.query("SELECT * FROM Message;");

for (auto&& r : meta_view(rs)) {
    std::cout << " ---- row:\n";
    for (auto&& [val, meta] : r) {
        std::cout << "\tcol:" << meta.original_field_name()
                  << " val:" << val << "\n";
    }
}

仍在打印相同的输出。 (std::ranges 需要 c++20)