Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Error "no matching member function for call to bindValue"
QtWS25 Last Chance

Error "no matching member function for call to bindValue"

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 5 Posters 2.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    davidino
    wrote on last edited by davidino
    #1

    Goodmorning to all,
    I'm using Qt version 5.14.0 and I'm tring to develop a database with SQL.
    The problem is that when I call the method bindValue, I get the error:

    no matching member function for call to bindValue
    candidate function not viable: requires 3 arguments, but 2 were provided

    The sample code is the shown below:

    #ifndef ALBUMDAO_H
    #define ALBUMDAO_H
    
    class QSqlDatabase;
    
    #include "album.h"
    
    #include <QList>
    
    class AlbumDao
    {
        public:
            AlbumDao(QSqlDatabase& database);
            void init()	const;
    
            void addAlbum(Album& album) const;
            void updateAlbum(const	Album&	album)	const;
            void removeAlbum(int	id)	const;
            QList<Album*>	albums()	const;
    
        private:
            QSqlDatabase& mDatabase;
    };
    
    #endif // ALBUMDAO_H
    
    
    #include "albumdao.h"
    
    #include <QSqlDatabase>
    #include <QSqlQuery>
    #include <QSql>
    #include <QVariant>
    
    #include "databasemanager.h"
    
    AlbumDao::AlbumDao(QSqlDatabase &database) :
        mDatabase(database)
    {
    
    }
    
    void AlbumDao::init() const
    {
        if (!mDatabase.tables().contains("albums"))	{
            QSqlQuery query(mDatabase);
            query.exec("CREATE TABLE albums (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
        }
    }
    
    void AlbumDao::addAlbum(Album &album) const
    {
        QSqlQuery query(mDatabase);
        query.prepare("INSERT INTO albums (name) VALUES (:name)");
        query.bindValue(":name", album.name());
        query.exec();
        album.setId(query.lastInsertId().toInt());
    }
    
    void AlbumDao::updateAlbum(const Album &album) const
    {
        QSqlQuery query(mDatabase);
        query.prepare("UPDATE albums SET name = (:name) WHERE id = (:id)");
        query.bindValue(":name", album.name());
        query.bindValue(":id", album.id());
        query.exec();
        //DatabaseManager::debugQuery(query);
    }
    
    void AlbumDao::removeAlbum(int id) const
    {
        QSqlQuery query(mDatabase);
        query.prepare("DELETE FROM albums WHERE id = (:id)");
        query.bindValue(":id", id);
        query.exec();
    }
    
    QList<Album *> AlbumDao::albums() const
    {
        QSqlQuery query("SELECT * FROM albums", mDatabase);
        query.exec();
        QList<Album*> list;
        while(query.next())	{
            Album* album = new Album();
            album->setId(query.value("id").toInt());
            album->setName(query.value("name").toString());
            list.append(album);
        }
        return list;
    }
    
    

    Have you got any advices?
    Thank you in advanced.

    aha_1980A 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #9

      @davidino said in Error "no matching member function for call to bindValue":

      mDatabase(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))),
      albumDao(*mDatabase)

      This is wrong on so many levels.

      First: don't store a QSqlDatabase member variable like explained in a warning in the QSqlDatabase documentation.
      Second: even less as a pointer
      Third: if you have to deference QSqlDatabase, it means you are already having issues in your design.

      Are you using only the default connection ? If so, then there's no need to pass anything around as it is the connection used when you don't pass any specific parameter to e.g. QSqlQuery.
      If you have several different connections, then pass their name around so the classes concerned can all QSqlDatabase::database to get the correct connection to use.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      5
      • D davidino

        Goodmorning to all,
        I'm using Qt version 5.14.0 and I'm tring to develop a database with SQL.
        The problem is that when I call the method bindValue, I get the error:

        no matching member function for call to bindValue
        candidate function not viable: requires 3 arguments, but 2 were provided

        The sample code is the shown below:

        #ifndef ALBUMDAO_H
        #define ALBUMDAO_H
        
        class QSqlDatabase;
        
        #include "album.h"
        
        #include <QList>
        
        class AlbumDao
        {
            public:
                AlbumDao(QSqlDatabase& database);
                void init()	const;
        
                void addAlbum(Album& album) const;
                void updateAlbum(const	Album&	album)	const;
                void removeAlbum(int	id)	const;
                QList<Album*>	albums()	const;
        
            private:
                QSqlDatabase& mDatabase;
        };
        
        #endif // ALBUMDAO_H
        
        
        #include "albumdao.h"
        
        #include <QSqlDatabase>
        #include <QSqlQuery>
        #include <QSql>
        #include <QVariant>
        
        #include "databasemanager.h"
        
        AlbumDao::AlbumDao(QSqlDatabase &database) :
            mDatabase(database)
        {
        
        }
        
        void AlbumDao::init() const
        {
            if (!mDatabase.tables().contains("albums"))	{
                QSqlQuery query(mDatabase);
                query.exec("CREATE TABLE albums (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
            }
        }
        
        void AlbumDao::addAlbum(Album &album) const
        {
            QSqlQuery query(mDatabase);
            query.prepare("INSERT INTO albums (name) VALUES (:name)");
            query.bindValue(":name", album.name());
            query.exec();
            album.setId(query.lastInsertId().toInt());
        }
        
        void AlbumDao::updateAlbum(const Album &album) const
        {
            QSqlQuery query(mDatabase);
            query.prepare("UPDATE albums SET name = (:name) WHERE id = (:id)");
            query.bindValue(":name", album.name());
            query.bindValue(":id", album.id());
            query.exec();
            //DatabaseManager::debugQuery(query);
        }
        
        void AlbumDao::removeAlbum(int id) const
        {
            QSqlQuery query(mDatabase);
            query.prepare("DELETE FROM albums WHERE id = (:id)");
            query.bindValue(":id", id);
            query.exec();
        }
        
        QList<Album *> AlbumDao::albums() const
        {
            QSqlQuery query("SELECT * FROM albums", mDatabase);
            query.exec();
            QList<Album*> list;
            while(query.next())	{
                Album* album = new Album();
                album->setId(query.value("id").toInt());
                album->setName(query.value("name").toString());
                list.append(album);
            }
            return list;
        }
        
        

        Have you got any advices?
        Thank you in advanced.

        aha_1980A Offline
        aha_1980A Offline
        aha_1980
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi @davidino,

        query.bindValue(":name", album.name());

        You mean here? So please provide the function signature of Album::name().

        Btw.: Why are you using Qt 5.14? It is not released yet. Have you tried 5.12.x or 5.13.x?

        Regards

        Qt has to stay free or it will die.

        1 Reply Last reply
        2
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #3

          @davidino said in Error "no matching member function for call to bindValue":

          no matching member function for call to bindValue

          Hi
          Could you try to include
          #include <QVariant>
          in the albumdao.cpp

          Not that. ( thx jonb )

          also as a note:
          You dont need to keep the database around to be used with QSqlQuery
          as it has a default connection concept.
          Which allows to simply open the database in some part of the application and
          simply do QSqlQuery query; ( anywhere in the app)
          and it will use the default database.
          https://doc.qt.io/Qt-5/qsqldatabase.html

          also Docs says
          "
          Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior. "

          So make sure you are not jumping into that trap :)

          JonBJ 1 Reply Last reply
          0
          • mrjjM mrjj

            @davidino said in Error "no matching member function for call to bindValue":

            no matching member function for call to bindValue

            Hi
            Could you try to include
            #include <QVariant>
            in the albumdao.cpp

            Not that. ( thx jonb )

            also as a note:
            You dont need to keep the database around to be used with QSqlQuery
            as it has a default connection concept.
            Which allows to simply open the database in some part of the application and
            simply do QSqlQuery query; ( anywhere in the app)
            and it will use the default database.
            https://doc.qt.io/Qt-5/qsqldatabase.html

            also Docs says
            "
            Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior. "

            So make sure you are not jumping into that trap :)

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #4

            @mrjj
            I was indeed tempted by your answer, but the OP's code already shows

            #include <QVariant>
            

            in the albumdao.cpp. Which leaves @aha_1980's

            So please provide the function signature of Album::name().

            though it seems likely that will just be a string... ah, if it is perhaps(?) a std::string that won't work without some coercion.

            Make sure whatever your Qt 5.14 is it has not lost the https://doc.qt.io/qt-5/qsqlquery.html#bindValue overload! Also, I assume you are getting a compile-time error (check the line number and tell us which line it is?), but you should anyway test the run-time return value of your prepare() (plus exec() etc.) statements.

            1 Reply Last reply
            2
            • D Offline
              D Offline
              davidino
              wrote on last edited by davidino
              #5

              Hello,
              Thank you all for your support. I'm surprised that after a few hours, I received these many answers :).
              For info, the error is signed as Semantic Error.

              To @aha_1980, yes it's query.bindValue(":name", album.name()); Thank you. Regarding the Qt version, I've build image and sdk from the last release of meta-boot2qt (open-source version) for a raspberrypi0 board.
              QtVersion.png

              To @mrjj, regarding the fact that QSqlQuey doesn't need the reference to database, how do I set the database name and driver that are meant to be used (MYQSL in my case)? An if I have multiple databases?
              Regarding the class that I post, thank you for your observation. Actually I have a class "databaseManager", where I create the database object, and take care of its deletion. Then I've created other classes like "albumdao" that I posted, where I add queries, otherwise databaseManager would have been very long. Since the database is passed as reference, it's not up to "albumdao" to delete the database but to "databaseManager". Isn't it as safe as getting it using database()? (in both case, the database deletion is perform by database class). Thank you for your comment, I could be wrong.

              To @JonB Yes, the method still has the following signature:
              void bindValue(int pos, const QVariant& val, QSql::ParamType type = QSql::In);, even though I specify the third argument, it doesn't work,
              I could run the project both prepare and exec return true. Thank you,

              Below album code:

              #include "album.h"
              
              Album::Album(const QString &name) :
                  mId(-1),
                  mName(name)
              {
              
              }
              
              int Album::id() const
              {
                  return mId;
              }
              
              void Album::setId(int id)
              {
                  mId = id;
              }
              
              QString Album::name() const
              {
                  return mName;
              }
              
              void Album::setName(const QString &name)
              {
                  mName = name;
              }
              
              
              #ifndef ALBUM_H
              #define ALBUM_H
              
              #include "gallery-core_global.h"
              #include <QString>
              
              class GALLERYCORE_EXPORT Album
              {
              public:
                  explicit Album(const QString& name = "");
                  int id() const;
                  void setId(int id);
                  QString	name() const;
                  void setName(const QString& name);
              
              private:
                  int mId;
                  QString mName;
              };
              
              #endif // ALBUM_H
              
              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #6

                Hi,

                QSqlDatabase::addDatabase has a parameter which allows you to have several different connections.

                QSqlDatabase::database allows you to retrieve the connection with the given name.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                2
                • D Offline
                  D Offline
                  davidino
                  wrote on last edited by davidino
                  #7

                  Hello @SGaist,
                  thank you for your answer. Yes, in my databaseManager I use, the following and I pass the newly created database to albumdao as reference:

                  DatabaseManager::DatabaseManager(const QString &path) :
                        mDatabase(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))),
                        albumDao(*mDatabase)
                  {}
                  

                  Now I understand that using QSqlDatabase::database I can retrieve the database by name without providing the reference as I did, I could simply pass the name.
                  Do you think that it could be convenient that I open an issue in QtBug?
                  Thank you.

                  JonBJ 1 Reply Last reply
                  0
                  • D davidino

                    Hello @SGaist,
                    thank you for your answer. Yes, in my databaseManager I use, the following and I pass the newly created database to albumdao as reference:

                    DatabaseManager::DatabaseManager(const QString &path) :
                          mDatabase(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))),
                          albumDao(*mDatabase)
                    {}
                    

                    Now I understand that using QSqlDatabase::database I can retrieve the database by name without providing the reference as I did, I could simply pass the name.
                    Do you think that it could be convenient that I open an issue in QtBug?
                    Thank you.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #8

                    @davidino
                    Sorry, I'm lost as to what "bug" you want to report?

                    new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))

                    This creates a copy of the QSqlDatabase returned by addDatabase(). I don't know what the consequences of that might be?

                    1 Reply Last reply
                    2
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #9

                      @davidino said in Error "no matching member function for call to bindValue":

                      mDatabase(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))),
                      albumDao(*mDatabase)

                      This is wrong on so many levels.

                      First: don't store a QSqlDatabase member variable like explained in a warning in the QSqlDatabase documentation.
                      Second: even less as a pointer
                      Third: if you have to deference QSqlDatabase, it means you are already having issues in your design.

                      Are you using only the default connection ? If so, then there's no need to pass anything around as it is the connection used when you don't pass any specific parameter to e.g. QSqlQuery.
                      If you have several different connections, then pass their name around so the classes concerned can all QSqlDatabase::database to get the correct connection to use.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      5
                      • D Offline
                        D Offline
                        davidino
                        wrote on last edited by davidino
                        #10

                        Hello SGaist and jonB,
                        thank you for messages. I open this post for the queryBind error (which is the one that I'm going to ask to QtBug), but I received many good advices. I've changed the code as follow:

                        databaseManager:

                        #ifndef DATABASEMANAGER_H
                        #define DATABASEMANAGER_H
                        
                        #include <QString>
                        #include "albumdao.h"
                        #include "picturedao.h"
                        
                        class QSqlDatabase;
                        
                        const QString DATABASE_FILENAME = "gallery.db";
                        
                        class DatabaseManager
                        {
                            public:
                                static DatabaseManager& instance();
                                ~DatabaseManager();
                        
                            protected:
                                DatabaseManager(const QString& path	= DATABASE_FILENAME);
                                DatabaseManager& operator=(const DatabaseManager& rhs);
                        
                            public:
                                const QString mDataBasePath;
                                const AlbumDao albumDao;
                                const PictureDao pictureDao;
                        };
                        
                        #endif // DATABASEMANAGER_H
                        
                        
                        #include "databasemanager.h"
                        #include	<QSqlDatabase>
                        
                        DatabaseManager &DatabaseManager::instance()
                        {
                            static DatabaseManager singleton;
                            return singleton;
                        }
                        
                        DatabaseManager::~DatabaseManager()
                        {
                            QSqlDatabase::database(mDataBasePath).close();
                        }
                        
                        DatabaseManager::DatabaseManager(const QString &path) :
                            mDataBasePath(path),
                            albumDao(path),
                            pictureDao(path)
                        {
                            QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE", path);
                            database.open();
                            // Called after opening database
                            albumDao.init();
                            pictureDao.init();
                        }
                        
                        

                        albumDao:

                        #ifndef ALBUMDAO_H
                        #define ALBUMDAO_H
                        
                        class QSqlDatabase;
                        
                        #include "album.h"
                        #include <QList>
                        
                        class AlbumDao
                        {
                            public:
                                explicit AlbumDao(QString database);
                                void init()	const;
                        
                                void addAlbum(Album& album) const;
                                void updateAlbum(const	Album&	album)	const;
                                void removeAlbum(int	id)	const;
                                QList<Album*>	albums()	const;
                        
                            private:
                                QString mDatabaseName;
                        };
                        
                        #endif // ALBUMDAO_H
                        
                        
                        #include "albumdao.h"
                        
                        #include <QSqlDatabase>
                        #include <QSqlQuery>
                        #include <QSql>
                        #include <QVariant>
                        #include <QDebug>
                        
                        #include "databasemanager.h"
                        
                        AlbumDao::AlbumDao(QString database) :
                            mDatabaseName(database)
                        {
                        
                        }
                        
                        void AlbumDao::init() const
                        {
                            QSqlDatabase database = QSqlDatabase::database(mDatabaseName);
                            if (!database.tables().contains("albums"))	{
                                QSqlQuery query(database);
                                query.exec("CREATE TABLE albums (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
                            }
                        }
                        
                        void AlbumDao::addAlbum(Album &album) const
                        {
                            bool tempBool;
                            QSqlDatabase database = QSqlDatabase::database(mDatabaseName);
                            QSqlQuery query(database);
                            tempBool=query.prepare("INSERT INTO albums (name) VALUES (:name)");
                            qDebug() << "prepare: " << tempBool << endl;
                            query.bindValue(":name", album.name());
                            tempBool=query.exec();
                            qDebug() << "exec: " << tempBool << endl;
                            album.setId(query.lastInsertId().toInt());
                        }
                        
                        void AlbumDao::updateAlbum(const Album &album) const
                        {
                            QSqlDatabase database = QSqlDatabase::database(mDatabaseName);
                            QSqlQuery query(database);
                            query.prepare("UPDATE albums SET name = (:name) WHERE id = (:id)");
                            query.bindValue(":name", album.name());
                            query.bindValue(":id", album.id());
                            query.exec();
                            //DatabaseManager::debugQuery(query);
                        }
                        
                        void AlbumDao::removeAlbum(int id) const
                        {
                            QSqlDatabase database = QSqlDatabase::database(mDatabaseName);
                            QSqlQuery query(database);
                            query.prepare("DELETE FROM albums WHERE id = (:id)");
                            query.bindValue(":id", id);
                            query.exec();
                        }
                        
                        QList<Album *> AlbumDao::albums() const
                        {
                            QSqlDatabase database = QSqlDatabase::database(mDatabaseName);
                            QSqlQuery query("SELECT * FROM albums", database);
                            query.exec();
                            QList<Album*> list;
                            while(query.next())	{
                                Album* album = new Album();
                                album->setId(query.value("id").toInt());
                                album->setName(query.value("name").toString());
                                list.append(album);
                            }
                            return list;
                        }
                        

                        Is it correct in this way?
                        Thank you.

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #11

                          No, the second parameter is not the path to your database, it's the name of the connection.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0
                          • D Offline
                            D Offline
                            davidino
                            wrote on last edited by davidino
                            #12

                            Hello @SGaist,
                            thank you for your post I've changed as follow.

                            DatabaseManager::DatabaseManager(const QString &connectionName) :
                                mDataBaseName(connectionName),
                                albumDao(connectionName),
                                pictureDao(connectionName)
                            {
                                QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE", connectionName);
                                // Database path
                                database.setDatabaseName(connectionName + ".dB");
                                database.open();
                                // Called after opening database
                                albumDao.init();
                                pictureDao.init();
                            }
                            

                            Thank you again for your always helpful advice. I'll ask to QtBug regarding the Semantic error with "bindValue"

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved