6

I finally fixed my MySQL connection in C++ Qt. However, when I try to bind values, I get the following error:

QSqlError("2036", "QMYSQL3: Unable to bind value", "Using unsupported buffer type: 1701052421  (parameter: 1)")

I have these files:

Engine.h:

#ifndef ENGINE_H
#define ENGINE_H

#include "database/mysql.h"

class engine
{
private:
    static mysql* _mysql;
public:
    static void initialize();
    static void destroy();

    static mysql get_mysql();
};

#endif // ENGINE_H

Engine.cpp:

#include "engine.h"
#include "entities/member_controller.h"
#include <QDebug>

mysql* engine::_mysql;

void engine::initialize()
{
    _mysql = new mysql();

    member* mem = member_controller::get_member(1);
    qDebug() << "mem name = " << mem->getFirstName() << " " << mem->getSecondName();
    delete mem;
}

void engine::destroy()
{
    delete _mysql;
}

mysql engine::get_mysql()
{
    return *_mysql;
}

mysql.h:

#ifndef MYSQL_H
#define MYSQL_H

#include <QtSql>
#include <QString>
#include "mysql_result.h"

class mysql
{
private:
    QSqlDatabase db;
public:
    mysql();
    ~mysql();
    mysql_result create_result(QString query);
    QSqlError error();

    QSqlQuery query_prepare(QString query1)
    {
        QSqlQuery query(this->db);
        query.prepare(query1);
//        this->query = query;
        return query;
    }
};

#endif // MYSQL_H

(query_prepare body temp. in header file just to test)

mysql.cpp

#include "mysql.h"

mysql::mysql()
{
    this->db = QSqlDatabase::addDatabase("QMYSQL", "QMYSQL");
    this->db.setHostName("localhost");
    this->db.setUserName("root");
    this->db.setPassword("Eequi4");
    this->db.setDatabaseName("test");
    this->db.open();
}

mysql::~mysql()
{
}

QSqlError mysql::error()
{
    return this->db.lastError();
}

member_controller.h:

#ifndef MEMBER_CONTROLLER_H
#define MEMBER_CONTROLLER_H

#include <QString>
#include "member.h"

class member_controller
{
public:
   static member* get_member(unsigned int id);
   static member* get_member(QString email);
};

#endif // MEMBER_CONTROLLER_H

member_controller.cpp:

#include "member_controller.h"
#include "database/mysql_result.h"

#include "engine.h"
#include "database/mysql_result.h"
#include <QtSql/QSqlQuery>

member* member_controller::get_member(unsigned int id)
{
    QSqlQuery result = engine::get_mysql().query_prepare("SELECT * FROM members WHERE member_id = :mem_id");
    result.bindValue(":mem_id", id);

    if (result.exec() && result.first())
    {
        return new member(id, result.value("first_name").toString(), result.value("second_name").toString(), result.value("screen_name").toString(), result.value("email").toString(), result.value("status").toString());
    }
    else
    {
        qDebug() << engine::get_mysql().error() << "\n";
        qDebug() << result.lastError() << "\n";
    }

    return new member(0, "", "", "", "", "");
}

I hope this is all the code needed. I tried using questionmark except of :mem_id but no luck either.

Joshua Bakker
  • 2,288
  • 3
  • 30
  • 63
  • 1
    Have you tried [rebuilding the SQL driver](http://stackoverflow.com/a/23165805/1771479)? – agold Oct 15 '15 at 07:55
  • You know how I can do that on Windows? I'm sorry if this is a noob question. Does it matter if I build a Qt 5.4 driver and use it in 5.5? – Joshua Bakker Oct 15 '15 at 14:20
  • 1
    See: http://doc.qt.io/qt-5/sql-driver.html#how-to-build-the-qmysql-plugin-on-windows – agold Oct 15 '15 at 14:26
  • I tried, but make wasn't a recognized program or w/e, so I downloaded GnuWin32 with make.exe, and used it after qmake, but nothing made a new .dll. Maybe I just misunderstand it. With using make, I got the error: make (e=2): The system cannot find the file specified. – Joshua Bakker Oct 15 '15 at 14:54
  • 1
    look here for compiling: https://fecub.wordpress.com/2014/08/12/compilecreate-mysql-driver-for-qt5-on-windows/ – fecub Oct 16 '15 at 08:10
  • I see `qDebug() << engine::get_mysql().error() << "\n"; qDebug() << result.lastError() << "\n";` in your code so error message should be 2 lines, but you've posted just one.Please post both. – Alex Oct 26 '15 at 15:59
  • try to change `result.bindValue(":mem_id", id);` to ` result.bindValue(":mem_id", QVariant(id));` – Alex Oct 26 '15 at 16:02
  • That didn't work, first error is all empty strings. Second error is what i posted. – Joshua Bakker Oct 26 '15 at 17:16
  • @JoshuaBakker what about converting parameter to `QVariant` type? – Alex Oct 26 '15 at 18:58
  • @Alex did what you said but it didn't work unfortunately. – Joshua Bakker Oct 26 '15 at 18:59
  • Absolutely the same error message? – Alex Oct 26 '15 at 19:00
  • @JoshuaBakker just found this question on SO : http://stackoverflow.com/a/23165805/4421474 check your driver – Alex Oct 26 '15 at 19:09
  • I tried rebuilding the MySQL driver without luck but I will try again since I'm programmer and I'm not about to give up lol. – Joshua Bakker Oct 26 '15 at 19:32

1 Answers1

5

I am not C++ or Qt expert and have no possibility to debug your code.

But just because of curiosity I've started to investigate your code and found suspicious line (the 2nd one) in your code:

mysql_result result = engine::get_mysql().create_result("SELECT * FROM members WHERE member_id = ?");

Since I am not expert and you didn't provide any includes I don't know neither what is your engine namespace nor function get_mysql() return type nor create_result return.

So I did some guess: get_mysql() probably return QSqlDatabase object? isn't it?

But that type does not support any create_result method! So I stuck there.

Next thanks to google I've found your another question made a week ago. I would please to include such important information in your post next time, so people can see your classes and functions like:

mysql_result mysql::create_result(QString query)
{
    return mysql_result(this->db.exec(query));
}

and

mysql_result::mysql_result(QSqlQuery query)
{
    this->query = query;
}

Now I can understand what that 2nd line of your code is trying to do.

The suspicious thing I see here is return mysql_result(this->db.exec(query));. That seems according to the function names that you are trying to execute query and get result from mysql server.

But according to the algorithm I see in your member_controller::get_member it seems to me that you are only on prepare stage but not executing yet. I see that Qt documentation is not clear enough (and again i am not an expert) because: Executes a SQL statement on the database and returns a QSqlQuery object. And technically you can say that you have QSqlQuery as a result and you can expect that this result is absolutely the same as if you do:

//mysql_result mysql::create_result(QString query)
QSqlQuery  mysql::query_prepare(QString query)
{
    QSqlQuery query(this->db);
    query.prepare(query);
    this->query = query;
    return this->query;
}

But IMHO it isn't. In your case it is already executed, that is why you can't bind any parameter later. So I would suggest you to change your mysql_result mysql::create_result(QString query) or create another function QSqlQuery mysql::query_prepare(QString query) which has more sense to me. and change your first lines of code to:

member* member_controller::get_member(int id)
{
    QSqlQuery query = engine::get_mysql().query_prepare("SELECT * FROM members WHERE member_id = ?");
    query.addBindValue(value);

    if (query.exec() && query.first())
...
...

And very last point I don't understand why are you trying to reinvent the weel? If you already have Qt mysql classes which looks very good to me why do you create your own class and methods with one line to call Qt method like:

void mysql_result::add_parameter(QVariant value)
{
    this->queryObject.addBindValue(value);
}

Sorry but IMHO that is not very good idea and has almost no sense.

UPDATE Looking into your updated code I see:

 result.bindValue(":mem_id", id);

where result type is QSqlQuery so you are calling to the native method bindValue where second parameter according to documentation is const QVariant & val. So I would change your call to:

 result.bindValue(":mem_id", QVariant(id));

or

 QVariant mem_id(id);
 result.bindValue(":mem_id", mem_id);
Community
  • 1
  • 1
Alex
  • 16,739
  • 1
  • 28
  • 51
  • **And very last point I don't understand why are you trying to reinvent the weel? If you already have Qt mysql classes which looks very good to me why do you create your own class and methods with one line to call Qt method like:** - Because queryObject isn't public. I like doing it this way except for getQueryObject().addBindValue. – Joshua Bakker Oct 16 '15 at 14:47
  • `public` is just OOP term it has nothing almost nothing common with security. So I still don't see any good reason to make code more complicated. **I like doing it this way** ok, that is your code and your project sure you can do whatever you want and the way you like. – Alex Oct 16 '15 at 15:04
  • I mean i dont want a getter for the QSqlQuery object and then call the function from there i'd thought this way it'd be better. But as comments suggested i'll try to rebuild the mysql driver. Engine is a static class which holds all variables of the program all instances etc. – Joshua Bakker Oct 16 '15 at 15:15
  • I see no reason to *rebuild the mysql driver* yet. To test my way it takes just 5 min. Did you try? – Alex Oct 16 '15 at 15:20
  • Excuse me, i'm not at home now just keeping track of SO. I'll try either when im on the train with my laptop or when im home. – Joshua Bakker Oct 16 '15 at 15:30
  • Alex I still get the error with using your query_prepare function. Sorry about late response I had vacation and haven't touched my laptop since I got other things to do. – Joshua Bakker Oct 26 '15 at 15:38
  • You should post your question properly with all your code involved to get help here. Nobody can guess your code :-) – Alex Oct 26 '15 at 15:40
  • Thanks for the tip Alex, I added almost all the code except for one class (which is useless to post here). I might start another bounty, might be a waste of my rep but I don't think there's a different way. – Joshua Bakker Oct 26 '15 at 15:52
  • That is up to you :-) I will try to help anyway. – Alex Oct 26 '15 at 15:55