How to make Qt aware of the QMYSQL driver

20,374

Solution 1

Try opening the shared library with dlopen() and see if it loads and if not, what dlerror() tells you. I always run into similar problems on Windows. LoadLibrary()/GetLastError() saved me numerous times (last time it was because of a wrong version of some libiconv/libintl DLL). Running ldd on the plugin may also help.

If dlopen() works fine, try to load the plugin with QPluginLoader. If it doesn't load, then check the buildkey of the plugin. I usually do it the dirty way by running strings on the plugin and then looking for strings like "buildkey" or "QT_PLUGIN_VERIFICATION_DATA". Just looking at the build key and around it may give you an idea. For example, you may realize that you have compiled your plugin in the release mode while your application is compiled in the debug mode. In such case the build key won't match and the plugin won't load. Everything in the build key must match your configuration. Note that the version and the build key are checked differently: the build key must match exactly (or match some black magic called QT_BUILD_KEY_COMPAT), but in the version only the major version must match exactly, the minor version must be the version of Qt the plugin was compiled with or later and the patch level is ignored. So if your plugin was compiled with Qt 4.x.y then it will work with Qt versions 4.z.* where z>=x. This actually makes sense.

If the build key looks okay (which is unlikely if you got to this point), you may wish to look at QLibraryPrivate::isPlugin() source code to figure out what's wrong, but that doesn't look like an easy task to me (although running this in a debugger may help).

If QPluginLoader does load the plugin, check if it is in the right directory and has correct permissions. If you still didn't solve the problem by this point, it's time to look at the SQL module source code that actually loads these plugins. But it is extremely unlikely. I ran into this problem many, many times and it was always either the library not loading or the build key not matching.

Another way to go after QPluginLoader loads the plugin successfully is to use strace to figure out whether the program at least tries to open the plugin file. Searching for something like "sqldrivers" or "plugins" in the strace output should also give away the directory where Qt is searching for its plugins and specifically SQL drivers.

Update

Is it possible to compile the driver as a static plugin and don't worry about anything? Let's try:

d:\Qt4\src\plugins\sqldrivers\psql>qmake CONFIG+=static LIBS+=-Ld:/programs/Post
greSQL/lib INCLUDEPATH+=d:/programs/PostgreSQL/include
d:\Qt4\src\plugins\sqldrivers\psql>make

It compiles fine and now I got libqsqlpsql.a (release) and libqsqlpsqld.a (debug) in QTDIR/plugins/sqldrivers (it is the right place on Windows). I am using PostgreSQL driver here, but I don't think it will be any different for MySQL which I just don't have installed. Ok, let's compile some real program with it:

d:\alqualos\pr\archserv>qmake QTPLUGIN+=qsqlpsql PREFIX=d:/alqualos LIBS+=-Ld:/g
nu/lib INCLUDEPATH+=d:/gnu/include LIBS+=-Ld:/programs/PostgreSQL/lib LIBS+=-lpq

Note that I had to manually link to libpq, otherwise the linker would complain about undefined references. The funny thing is, qmake knows that qsqlpsql is located in QTDIR/plugins/sqldrivers and sets compiler and linker options accordingly. So it still needs to be in the right place to work, only you don't have to worry about your users running into the same problem as it is only used during compilation. An alternative would be to just use LIBS+=-Lpath/to/plugin LIBS+=-lqsqlpsql instead of QTPLUGIN+=qsqlpsql, at least the docs say that it should work, but I haven't tested it.

In order for the application to actually use the plugin I had to put the following in my main unit (CPP file):

#include <QtPlugin>
Q_IMPORT_PLUGIN(qsqlpsql)

It works! Also, from what I've been able to figure out from the sources, the build key and the version are checked only when a plugin is dynamically loaded (all the relevant stuff is in the QLibrary's private class, not even QPluginLoader's). So the resulting executable may (or may not, depending on the binary compatibility) work even with different versions and builds of Qt, although using it with older versions may trigger some bugs that were fixed later.

It is also worth noting that the order for loading SQL drivers is this: use the driver statically linked into Qt if available, then look for a driver registered manually with QSqlDatabase::registerSqlDriver(), then look for a driver statically imported into the application (the way described above), and finally try to load a shared plugin. So when you link statically, your users won't be able to use dynamically linked drivers they may already have, but will be able to use drivers linked statically into Qt (like in Ubuntu).

Solution 2

I compiled QT first and then realised that I need mysql as well. So I compiled mysql plugin by executing following command in QT-DIR\src\plugins\sqldrivers\mysql folder.

Mysql plugin compile command

qmake "INCLUDEPATH+=$$quote(C:\Program Files\MySQL\MySQL Server 5.5\include)" "LIBS+=$$quote(C:\Program Files\MySQL\MySQL Server 5.5\lib\libmysql.lib)" mysql.pro

Plugings are then created in created in folder QT-DIR\plugins\sqldrivers. However, when I tried to use it in my code. It failed with following error.

Error msg

QSqlDatabase: QMYSQLDriver driver not loaded

Solution

After some googling and checking Path variable I realised that the Mysql server lib ( C:\Program Files\MySQL\MySQL Server 5.5\lib) directory was not in my Path variable. I expect that the dll in this folder are used by the plugin at runtime. After including Mysql server lib in Path variable everything worked smoothly. Hope this information saves some hair on other programmers scalp, as I uprooted quite a few. :D

Solution 3

Last time I looked at this you needed to rebuild Qt from source and include the appropriate MySQL source.

Building Qt from the sources is not hard, it just takes a while. You are likely to have the required tools already.

A possible workaround may be to access the back-end over ODBC instead.

Solution 4

In order for your app to pick up the plugin at runtime, the shared library implementing the MySQL plugin needs to be placed in the correct directory. The best way of determining that directory is to check the output of QCoreApplication::libraryPaths. You can also force specific paths by using a qt.conf file.

Please note that plugins must be placed in subdirectories within the plugin path, and the final part of the path name (i.e., the parent directory of the shared libraries) cannot be changed. SQL drivers need to go in a directory named sqldrivers, i.e. <pluginpath>/sqldrivers. For more details on plugin directories, see How to Create Qt Plugins.

Solution 5

I was experiencing this same issue as well. I've been installing and experimenting with a lot of different Python tools and UIs. I then uninstalled everything python related. I did a fresh install of Python 3.2, PyQT 3.2, and Eric5. No more errors with the QMySQL driver.

Share:
20,374
Raphael
Author by

Raphael

I've been programming professionally for the past 9 years. Currently, my speciality is iOS development (though I still dwell in the backend world from time to time using Node or Python). I've been using Swift since it was first released in 2014 and the app that I've worked on for the past 3 years (Hole19) has been consistently rated 5 stars, with 99% of crash-free users and it was often featured on the App Store. On behalf of Hole19, I have attended WWDC 2016 in San Francisco. Before working on Hole19, I worked on a few consulting agencies and had extensive freelancing experience. Over the years, I have developed several mobile and web apps both big and small.

Updated on July 09, 2022

Comments

  • Raphael
    Raphael almost 2 years

    I'm trying to access a MySql database from a Qt application but I get the following error:

    QSqlDatabase: QMYSQL driver not loaded
    QSqlDatabase: available drivers: QSQLITE QSQLITE2
    

    I find this very strange cause I have libqsqlmysql.so on my Qt folder. I have even tried to compile the MySql driver as a static plugin and add it to my .pro file as:

    QTPLUGIN += qsqlmysql
    

    But this also generates the same runtime error (it must've found the plugin cause there's no error compiling the application)

    What am I missing? I would like to avoid having to compile Qt from source cause this will have to work seamlessly on the deploy machines as well.

    BTW: Even though I'm developing and testing on Linux I will need to support Windows. Will I experience this same issue on Windows? How can I compile and link the MySql driver in both Linux and Windows?

    The solution:

    After following @Sergey's recommendations I did an strace of the application redirecting the output to grep so I could search for 'mysql' and for my surprise the application wasn't looking for the plugin at QTDIR/plugins/sqldrivers where I had libqsqlmysql.so, it was looking at QTDIR/lib. After copying the plugin to the lib folder the MySql connection worked.

  • Raphael
    Raphael over 13 years
    That's strange cause I have both the MySql driver source and it's binaries (Isn't this enough?). And if I build Qt from source how would I deploy my application that now depends on a custom build of Qt?
  • Dirk Eddelbuettel
    Dirk Eddelbuettel over 13 years
    It would not be a custom build. You are still configuring with standard options, you are simply adding the possibility of using MySQL.
  • Sergei Tachenov
    Sergei Tachenov over 13 years
    @Raphael, building Qt from source won't break the binary compatibility unless you use some non-standard configuration. But usually it is not necessary. The problem is that anyone installing your application will have to deal with driver installation problem too. ODBC is a pain to configure in Linux, so it will also lead to deployment problems I think.
  • Raphael
    Raphael over 13 years
    QPluginLoader did load the plugin (although I must confess I've cheated, after dlopen() didn't open libqsqlmysql.so I realized I had it on the wrong directory and moved it to the right one). It seems that this won't be an easy issue. Is there a good C++ library to access MySql that I could use as an alternative? (preferably a high-level one. Something that is easy to connect to the database as in Java or Python)
  • Raphael
    Raphael over 13 years
    I have moved the plugin to the appropriate directory and QPluginLoader did load the pluging, however that did not change the outcome of my attempt to connect to the database
  • Sergei Tachenov
    Sergei Tachenov over 13 years
    @Raphael, No, I always used Qt for this and found it very good although it does have its own faults (like lack of timezones support in QDateTime). Does Qt still complain about driver not loaded after you got it to load properly with QPluginLoader? Are you sure it's in the right place? You could use strace to figure out whether it tries to open the plugin file. I'm really interested in this issue.
  • Raphael
    Raphael over 13 years
    @Sergey - Yes it's still complaining about the missing driver. I believe it's now in the right place because QPlugingLoader seems to be loading it just fine. The driver is in libqsqlmysql.so is it not? I'll try strace to see what I can find out about this. PS: I'm using the Qt Developer Tools (Qt SDK + Qt Creator) downloaded straight from Nokia. Shouldn't it have this driver enabled by default?
  • Mihai Limbășan
    Mihai Limbășan over 13 years
    What happens if you run ldd on the plugin shared library? Perhaps it can't resolve symbols from a dependent library.
  • Mihai Limbășan
    Mihai Limbășan over 13 years
    @Raphael: No, due to licensing issues (of which, by the way, you'll need to be aware if you're going to be distributing binaries!) Nokia can't or doesn't want to redistribute binaries linked against libmysqlclient.
  • Sergei Tachenov
    Sergei Tachenov over 13 years
    @Raphael, QPluginLoader will load the plugin no matter where it is as long as you specify the correct path. SQL drivers, on the other hand, need to be in something like QtLibDir/plugins/sqldrivers/ where QtLibDir is usually something like /usr/lib/qt4 or /usr/local/lib/qt4. Yes, it's libqsqlmysql.so. Note that most Linux users don't download binaries from vendor sites but install from repository instead. Ubuntu has Qt4 in repository with MYSQL driver enabled, for example.
  • Raphael
    Raphael over 13 years
    Isn't there a way to build the MySql driver as a static plugin and then link my application to the it? This would be awesome, no dependencies, no need to have Qt build to accept the plugin.
  • Raphael
    Raphael over 13 years
    Just to clarify, I have already built the driver both as a shared library and as a static. Is there anyway to link against the static one and load the driver?
  • Raphael
    Raphael over 13 years
    Ok, I finally did the strace you recomended and found the problem: Although Qt has a libqsqlmysql.so in the QTDIR/plugins/sqldriver folder, the application looks at QTDIR/lib. Thank you so much for your help.
  • Sergei Tachenov
    Sergei Tachenov over 13 years
    @Raphael, glad I could help. I know how annoying this problem can be. I'll look into static plugin technique and update my answer if I can get it to work. Note that in this case the version of Qt on the target machine must probably match the version of Qt the plugin was built with. Although in Windows it won't matter much as you're probably going to distribute Qt DLLs with the program, and in Linux users usually know how to install Qt with MYSQL enabled from the repository.
  • Sergei Tachenov
    Sergei Tachenov over 13 years
    @Raphael, I tested the static way and edited the answer. And I'm curious, when you mention QTDIR/lib, do you mean QTDIR/lib/plugins/sqldrivers (the usual place for plugins on Linux) or did you put it exactly in QTDIR/lib (which would be rather strange)?
  • Raphael
    Raphael over 13 years
    @Sergey - It was looking exactly at QTDIR/lib (which I also found strange as all of the documentation that I read said it should be at the plugins directory). I had my plugin the the sqldrivers directory but the appplication wasn't even looking there, STRACE showed that it would look at QTDIR/lib and than complain that there was no driver.
  • Raphael
    Raphael over 13 years
    @Sergey - Thank you for providing the static alternative, I'll try it tomorrow.
  • Sergei Tachenov
    Sergei Tachenov over 13 years
    @Raphael, that's very strange. The way how it figures out the list of directories to look in is very complicated, but then it unconditionally adds "sqldrivers" to it. So it could be QTDIR/plugins/sqldrivers, QTDIR/lib/plugins/sqldrivers or even QTDIR/sqldrivers, QTDIR/lib/sqldrivers or wherever-your-app-is/sqldrivers, but QTDIR/lib? Oh my god.
  • KIRAN K J
    KIRAN K J over 12 years
    i got the same problem in ubuntu.please help me
  • shiv chawla
    shiv chawla almost 12 years
    I tried all possible ways but this thing worked. Though, I still don't understand why do we have to place those libraries in this particular folder.