简体   繁体   English

如何从 SOCI 查询中绑定 output?

[英]How do I bind output from a SOCI query?

The following code:generates error messages, which follow:以下代码:生成错误消息,如下:

bool UACmUsers::GetUser(int userid) {
    soci::session sql(dbU::Connection());
    sql << "SELECT userid, username, password FROM uac_users WHERE userid = \":user\"",
        soci::use(userid),
        soci::into(iDuserid,   indUserid),
        soci::into(sDusername, indUsername), // This is line 61.
        soci::into(sDpassword, indPassword);

    return true;
}

dbU::Connection() is a function generating the connection string. dbU::Connection()是一个 function 生成连接字符串。

iDuserid , sDusername , and sDpassword are private members of UACmUsers, of types int and std::string . iDuseridsDusernamesDpassword是 UACmUsers 的私有成员,类型为intstd::string

indUserid , indUsername , and indPassword are private members of UACmUsers, of type soci::indicator . indUseridindUsernameindPassword是 UACmUsers 的私有成员,属于 soci soci::indicator类型。

There is a second, overloaded, function searching for the username .还有第二个重载的 function 搜索username If I comment out this function so only the second one remains, the complier points to the same point in the second function.如果我注释掉这个 function 所以只剩下第二个,编译器指向第二个 function 中的同一点。

bool UACmUsers::GetUser(const wxString& username);

I have tried removing two of the indicators, this does not solve the problem.我已经尝试删除两个指标,但这并不能解决问题。

The errors:错误:

E:\cpp\lib\soci\soci-4.0.0\include\soci/exchange-traits.h(41): error C2065: 'x_type': undeclared identifier
E:\cpp\lib\soci\soci-4.0.0\include\soci/bind-values.h(207): note: see reference to class template instantiation 'soci::details::exchange_traits<T>' being compiled
        with
        [
            T=wxString
        ]
E:\cpp\lib\soci\soci-4.0.0\include\soci/bind-values.h(143): note: see reference to function template instantiation 'void soci::details::into_type_vector::exchange_<wxString,soci::indicator>(const soci::details::into_container<wxString,soci::indicator> &,...)' being compiled
E:\cpp\lib\soci\soci-4.0.0\include\soci/statement.h(50): note: see reference to function template instantiation 'void soci::details::into_type_vector::exchange<wxString,soci::indicator>(const soci::details::into_container<wxString,soci::indicator> &)' being compiled
E:\cpp\lib\soci\soci-4.0.0\include\soci/statement.h(199): note: see reference to function template instantiation 'void soci::details::statement_impl::exchange<wxString,soci::indicator>(const soci::details::into_container<wxString,soci::indicator> &)' being compiled
E:\cpp\lib\soci\soci-4.0.0\include\soci/ref-counted-statement.h(92): note: see reference to function template instantiation 'void soci::statement::exchange<wxString,soci::indicator>(const soci::details::into_container<wxString,soci::indicator> &)' being compiled
E:\cpp\lib\soci\soci-4.0.0\include\soci/once-temp-type.h(49): note: see reference to function template instantiation 'void soci::details::ref_counted_statement::exchange<const soci::details::into_container<wxString,soci::indicator>>(T &)' being compiled
        with
        [
            T=const soci::details::into_container<wxString,soci::indicator>
        ]
E:\cpp\dev\Manager\src\UAC\models\UACmUsers.cpp(61): note: see reference to function template instantiation 'soci::details::once_temp_type &soci::details::once_temp_type::operator ,<wxString,soci::indicator>(const soci::details::into_container<wxString,soci::indicator> &)' being compiled

Can someone help me get SOCI to behave?有人可以帮我让 SOCI 表现得更好吗?


This is part of a project on GitHub .这是GitHub项目的一部分。 Links to the header and source files containing the above code.指向header和包含上述代码的文件的链接。

Your strings aren't standard strings.您的字符串不是标准字符串。 wxString likely has no conversion support in SOCI. wxString 在 SOCI 中可能没有转换支持。

Either do the conversions, or extend the type conversions.要么进行转换,要么扩展类型转换。 Perhaps not the most efficient but works:也许不是最有效但有效:

namespace soci {
    template <> struct type_conversion<wxString> {
        typedef std::string base_type;

        static void from_base(base_type const& s, indicator ind, wxString& ws) {
            if (ind == i_null)
                ws.clear();
            else
                ws = s;
        }

        static void to_base(const wxString& ws, base_type& s, indicator& ind) {
            s = ws.ToStdString();
            ind = i_ok;
        }
    };
} // namespace soci

Full Demo完整演示

#include <iomanip>
#include <iostream>
#include <soci/boost-tuple.h>
#include <soci/mysql/soci-mysql.h>
#include <soci/soci.h>
#include <soci/use.h>
#include <wx/string.h>

namespace soci {
    template <> struct type_conversion<wxString> {
        typedef std::string base_type;

        static void from_base(base_type const& s, indicator ind, wxString& ws) {
            if (ind == i_null)
                ws.clear();
            else
                ws = s;
        }

        static void to_base(const wxString& ws, base_type& s, indicator& ind) {
            s = ws.ToStdString();
            ind = i_ok;
        }
    };
} // namespace soci

using namespace std::string_literals;

namespace dbU {
    static soci::connection_parameters
        parms("mysql://db=test user=root password='root'");

    auto Connection() { return soci::session(parms); }

    void setup() {
        try {
            dbU::Connection()
                .create_table("uac_users")
                .column("userid", soci::data_type::dt_integer)
                .primary_key("userid", "userid")
                .column("username", soci::data_type::dt_string)
                .column("password", soci::data_type::dt_string);
        } catch (soci::mysql_soci_error const& e) {
            std::cout << "Table already exists\n";
        }

        {
            using Rec = boost::tuple<int, std::string, std::string>;
            Rec rec;

            auto db = dbU::Connection();
            soci::statement st =
                (db.prepare << "insert into uac_users values (:id, :name, :pwd)",
                 soci::use(rec));

            for (auto vals : { Rec
                    { 11, "one"s, "bar"s },
                    { 12, "two"s, "gjb"s },
                    { 13, "three"s, "guerr"s },
                    { 14, "four"s, "sbhe"s },
                    { 15, "five"s, "svir"s }, })
            {
                try {
                    rec = vals;
                    st.execute(true);
                } catch (soci::mysql_soci_error const& e) {
                    std::cout << e.what() << "\n";
                }
            }
        }
    }
} // namespace dbU

struct X {
    int iDuserid;
    wxString sDusername, sDpassword;
    soci::indicator indUserid, indUsername, indPassword;

    bool foo(int userid) {
        soci::session sql(dbU::Connection());

        sql << R"(SELECT userid, username, password FROM uac_users WHERE userid = ":user")",
            soci::use(userid), soci::into(iDuserid, indUserid),
            soci::into(sDusername, indUsername), // This is line 27
            soci::into(sDpassword, indPassword);

        std::cout << "last: " << sql.get_last_query() << "\n";

        return true;
    }
};

int main() {
    dbU::setup();

    X x;
    x.foo(12);

    std::cout << x.iDuserid << " " << std::quoted(x.sDusername.ToStdString())
              << " " << std::quoted(x.sDpassword.ToStdString()) << "\n";
}

Prints印刷

last: SELECT userid, username, password FROM uac_users WHERE userid = ":user"
12 "two" "gjb"

Or on a subsequent run:或者在随后的运行中:

Table already exists                                
Duplicate entry '11' for key 'PRIMARY' while executing "insert into uac_users values (:id, :name, :pwd)" with :id=11, :name="one", :pwd="bar".
Duplicate entry '12' for key 'PRIMARY' while executing "insert into uac_users values (:id, :name, :pwd)" with :id=12, :name="two", :pwd="gjb".
Duplicate entry '13' for key 'PRIMARY' while executing "insert into uac_users values (:id, :name, :pwd)" with :id=13, :name="three", :pwd="guerr".
Duplicate entry '14' for key 'PRIMARY' while executing "insert into uac_users values (:id, :name, :pwd)" with :id=14, :name="four", :pwd="sbhe".               
Duplicate entry '15' for key 'PRIMARY' while executing "insert into uac_users values (:id, :name, :pwd)" with :id=15, :name="five", :pwd="svir".               
last: SELECT userid, username, password FROM uac_users WHERE userid = ":user"                                                       
12 "two" "gjb"                                                                                                                       

And the table contains该表包含

在此处输入图像描述

NOTES笔记

In the sample there appears to be a memory leak when the insert statements throw.在示例中,当插入语句抛出时,似乎存在 memory 泄漏。 I guess this need to be reported upstream.我想这需要在上游报告。

THINK TWICE before storing passwords in a database.在将密码存储到数据库之前三思而后行。 Proper security rules of thumb:适当的安全经验法则:

  • Never store passwords.永远不要存储密码。 Period.时期。
  • Always store hashes始终存储哈希
  • Do NOT use fast hashes or non-cryptographically strong hashes (no MD5 or SHA bullshit, use PKDBF2, scrypt or similar )不要使用快速散列或非加密强散列(没有 MD5 或 SHA 废话,使用PKDBF2、scrypt 或类似的
  • Always use a per-user salt始终使用每个用户的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM