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. MSSQL with unixODBC and FreeTDS
Forum Updated to NodeBB v4.3 + New Features

MSSQL with unixODBC and FreeTDS

Scheduled Pinned Locked Moved Unsolved General and Desktop
32 Posts 5 Posters 5.0k Views 2 Watching
  • 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.
  • J Offline
    J Offline
    Jonas Kvinge
    wrote on 7 Mar 2020, 08:13 last edited by
    #15

    I traced the query result from restore headeronly with wireshark and it's t here.

    1 Reply Last reply
    0
    • H Offline
      H Offline
      hskoglund
      wrote on 7 Mar 2020, 15:44 last edited by
      #16

      Yeah, makes sense, since you mentioned: "The same SQL query works fine using tsql (freeTDS diagnostic tool)." which presumably utilizes the TDS same stream as Qt.

      H 1 Reply Last reply 7 Mar 2020, 19:44
      0
      • H hskoglund
        7 Mar 2020, 15:44

        Yeah, makes sense, since you mentioned: "The same SQL query works fine using tsql (freeTDS diagnostic tool)." which presumably utilizes the TDS same stream as Qt.

        H Offline
        H Offline
        hskoglund
        wrote on 7 Mar 2020, 19:44 last edited by
        #17

        What else to do on a Saturday evening? Found an old VM with MSSQLServer 2008 and the Northwind db on it, made a backupfile of it, then wrote a small QT console app that just either does:

        "select * from sys.databases"
        or "restore headeronly from disk = 'C:/Northwind.bak'"

        First I tested the Qt app on Windows, both statements worked (as expected). Then I launched a fresh Ubuntu 19.10 VM, installed Qt and did:
        sudo apt-get install unixodbc unixodbc-dev freetds-dev tdsodbc

        Run the same program, the "select * ..." worked (also as expected) but the "restore ..." failed the same way (the query returns ok, but next() fails).

        And of course, if I tested with osql, first I made a 1-line text file, containing one of the 2 SQL commands above, and then tried:

        osql -S dsn1 -U sa -P adminsa < commandfile
        

        (dsn1 is defined in my .freetds.conf and .odbc.ini in my ~)
        And both SQL commands worked. Which means I reproduced your openSUSE experience on Ubuntu 19.10 and Qt 5.14. (Also I could see the traffic on port 1433 using tcpdump)

        This pretty much points the finger on Qt's ODBC plugin libqsqlodbc.so :-(

        1 Reply Last reply
        0
        • C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 7 Mar 2020, 19:54 last edited by
          #18

          @hskoglund said in MSSQL with unixODBC and FreeTDS:

          This pretty much points the finger on Qt's ODBC plugin libqsqlodbc.so :-(

          Why? You're using the same one on Windows, or?

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          H 1 Reply Last reply 7 Mar 2020, 20:15
          0
          • C Christian Ehrlicher
            7 Mar 2020, 19:54

            @hskoglund said in MSSQL with unixODBC and FreeTDS:

            This pretty much points the finger on Qt's ODBC plugin libqsqlodbc.so :-(

            Why? You're using the same one on Windows, or?

            H Offline
            H Offline
            hskoglund
            wrote on 7 Mar 2020, 20:15 last edited by
            #19

            @Christian-Ehrlicher Yes, it's the same Qt .cpp code for Windows and Linux, so I'm thinking it's something wrong during the handoff of TDS traffic between Qt and the underlying ODBC driver, i.e. on Windows it's a .dll from Microsoft (where it works) and on Ubuntu it's /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so.

            1 Reply Last reply
            0
            • H Offline
              H Offline
              hskoglund
              wrote on 8 Mar 2020, 00:29 last edited by hskoglund 3 Aug 2020, 00:30
              #20

              Continuing with "What to do on a Saturday evening...", found the culprit and I've built a working libqsqlodbc.so. It is indeed some kind of handoff problem, I could see all the 52 field descriptors were being returned ok (yes "restore headeronly..." returns 52 columns!) but when time come to the fetch, it failed in QODBCResult::fetchFirst() on Ubuntu, but not on WIndows.

              Here's the culprit/patched part of qsql_odbc.cpp:

              ...
              bool QODBCResult::fetchFirst()
              {
                  Q_D(QODBCResult);
                  if (isForwardOnly() && at() != QSql::BeforeFirstRow)
                      return false;
                  SQLRETURN r;
                  d->clearValues();
                  if (isForwardOnly()) {
                      return fetchNext();
                  }
              // line 1133 qsql_odbc.cpp: following 3 lines are replaced with a SQLFetch
              //    r = SQLFetchScroll(d->hStmt,
              //                       SQL_FETCH_FIRST,
              //                       0);
                  r = SQLFetch(d->hStmt);
                  if (r != SQL_SUCCESS) {
                      if (r != SQL_NO_DATA)
                          setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
                              "Unable to fetch first"), QSqlError::ConnectionError, d));
                      return false;
                  }
                  setAt(0);
                  return true;
              }
              ... 
              

              SQLFetchScroll() is an ODBC 3.0-flavored function and maybe it's too advanced for FreeTDS, so on a lark I replaced it with the legacy ODBC 2.0 SQLFetch(), voila!

              But, as @Christian-Ehrlicher says above, this is not really a bug in Qt, rather FreeTDS/unixODBC stumbling with ODBC 2.0/3.0 differences or something. So consider it a workaround. So feel free to debug more/deeper and submit a bugreport :-)

              P.S. If you want to build it yourself, it's pretty easy, start MaintenanceTool and select Sources. Then open
              ~/Qt/5.14.1/Src/qtbase/src/plugins/sqldrivers/sqldrivers.pro
              from Qt Creator, edit odbc/qsql_odbc.cpp as per above, and then just rebuild the project. A new directory will appear in the directory above, i.e.
              ~/Qt/5.14.1/Src/qtbase/src/plugins/build-sqldrivers-Desktop_Qt_5_14_1_GCC_64bit-Release and in that directory you'll find the new, working libqsqlodbc.so in ../plugins/sqldrivers

              1 Reply Last reply
              3
              • C Offline
                C Offline
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on 8 Mar 2020, 07:41 last edited by
                #21

                @hskoglund said in MSSQL with unixODBC and FreeTDS:

                So consider it a workaround. So feel free to debug more/deeper and submit a bugreport

                Why? We don't support ODBC2 anymore.

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                1 Reply Last reply
                0
                • H Offline
                  H Offline
                  hskoglund
                  wrote on 8 Mar 2020, 16:22 last edited by
                  #22

                  Indeed, Qt doesn't. I was thinking of submitting a bug report somewhere to unixODBC or FreeTDS

                  J 1 Reply Last reply 8 Mar 2020, 16:38
                  0
                  • H hskoglund
                    8 Mar 2020, 16:22

                    Indeed, Qt doesn't. I was thinking of submitting a bug report somewhere to unixODBC or FreeTDS

                    J Offline
                    J Offline
                    Jonas Kvinge
                    wrote on 8 Mar 2020, 16:38 last edited by
                    #23

                    @hskoglund
                    Thanks for doing all the debugging on this.
                    I already did submit a bug report to Qt: https://bugreports.qt.io/browse/QTBUG-82724
                    But if you think the problem is in FreeTDS or unixODBC, maybe we should submit a bug report there instead.

                    H 1 Reply Last reply 8 Mar 2020, 17:08
                    0
                    • J Jonas Kvinge
                      8 Mar 2020, 16:38

                      @hskoglund
                      Thanks for doing all the debugging on this.
                      I already did submit a bug report to Qt: https://bugreports.qt.io/browse/QTBUG-82724
                      But if you think the problem is in FreeTDS or unixODBC, maybe we should submit a bug report there instead.

                      H Offline
                      H Offline
                      hskoglund
                      wrote on 8 Mar 2020, 17:08 last edited by
                      #24

                      @Jonas-Kvinge Yeah, it seems to me like there's some forgotten corner in unixODBC or FreeTDS that handle SQL commands, and someone forgot to upgrade that to ODBC3 support for "restore...".

                      On the other hand, there already is a isFreeTDSDriver boolean var in qsql_odbc.cpp that's used for some workarounds, like turning off Unicode support(!): unicode = unicode && !isFreeTDSDriver

                      So I mean, since the infrastructure is already in place in qsql_odbc.cpp to detect the presence of FreeTDS, you could suggest in your bug report that Qt implements yet another workaround, e.g.

                      if (isFreeTDSDriver) 
                          r = SQLFetch(d->hStmt);
                      else
                          r = SQLFetchScroll(d->hStmt,SQL_FETCH_FIRST,0);
                      

                      (Or we download the sources of unixODBC and FreeTDS and start digging. Maybe next Saturday :-)

                      J 1 Reply Last reply 9 Mar 2020, 17:43
                      1
                      • H hskoglund
                        8 Mar 2020, 17:08

                        @Jonas-Kvinge Yeah, it seems to me like there's some forgotten corner in unixODBC or FreeTDS that handle SQL commands, and someone forgot to upgrade that to ODBC3 support for "restore...".

                        On the other hand, there already is a isFreeTDSDriver boolean var in qsql_odbc.cpp that's used for some workarounds, like turning off Unicode support(!): unicode = unicode && !isFreeTDSDriver

                        So I mean, since the infrastructure is already in place in qsql_odbc.cpp to detect the presence of FreeTDS, you could suggest in your bug report that Qt implements yet another workaround, e.g.

                        if (isFreeTDSDriver) 
                            r = SQLFetch(d->hStmt);
                        else
                            r = SQLFetchScroll(d->hStmt,SQL_FETCH_FIRST,0);
                        

                        (Or we download the sources of unixODBC and FreeTDS and start digging. Maybe next Saturday :-)

                        J Offline
                        J Offline
                        Jonas Kvinge
                        wrote on 9 Mar 2020, 17:43 last edited by
                        #25

                        @hskoglund
                        I modified the qodbc driver but I still can't make it work. I tried both with Qt 5.14.1 and the dev branch. Am I missing something?
                        I'm using openSUSE tumbleweed (up to date) with unixODBC 2.3.7 and FreeTDS ODBC driver 1.1.20

                        In checkHasSQLFetchScroll() I just added || isFreeTDSDriver

                        In bool QODBCResult::fetchFirst():

                        if (d->hasSQLFetchScroll)
                               r = SQLFetchScroll(d->hStmt, SQL_FETCH_FIRST, 0);
                           else
                               r = SQLFetch(d->hStmt);
                        

                        If you want to test my code, it's all on GitHub:
                        https://github.com/jonaski/sqlrestore
                        Look at the freetds branch, the modified qodbc driver is in 3rdparty and will exposed as QODBCX , select QODBCX in test settings AND restart the program (that's the statically compiled driver in 3rdparty)

                        H 1 Reply Last reply 9 Mar 2020, 19:18
                        0
                        • J Jonas Kvinge
                          9 Mar 2020, 17:43

                          @hskoglund
                          I modified the qodbc driver but I still can't make it work. I tried both with Qt 5.14.1 and the dev branch. Am I missing something?
                          I'm using openSUSE tumbleweed (up to date) with unixODBC 2.3.7 and FreeTDS ODBC driver 1.1.20

                          In checkHasSQLFetchScroll() I just added || isFreeTDSDriver

                          In bool QODBCResult::fetchFirst():

                          if (d->hasSQLFetchScroll)
                                 r = SQLFetchScroll(d->hStmt, SQL_FETCH_FIRST, 0);
                             else
                                 r = SQLFetch(d->hStmt);
                          

                          If you want to test my code, it's all on GitHub:
                          https://github.com/jonaski/sqlrestore
                          Look at the freetds branch, the modified qodbc driver is in 3rdparty and will exposed as QODBCX , select QODBCX in test settings AND restart the program (that's the statically compiled driver in 3rdparty)

                          H Offline
                          H Offline
                          hskoglund
                          wrote on 9 Mar 2020, 19:18 last edited by
                          #26

                          @Jonas-Kvinge You were 99% there :-)

                          Only thing you forgot, since you altered the odbc.json file to just contain "QODBCX", you also need to add it the list of kosher names in main.cpp's QODBCDriverPlugin::create(), i.e. change line 62 in main.cpp from

                          if (name == QLatin1String("QODBC") || name == QLatin1String("QODBC3")) {
                          

                          to

                          if (name == QLatin1String("QODBC") || name == QLatin1String("QODBC3") || name == QLatin1String("QODBCX")) {
                          

                          P.S. I can see in your logging: "d->hasSQLFetchScroll: false" and this warning rears its ugly head:
                          "QODBCDriver::checkHasSQLFetchScroll: Warning - Driver doesn't support scrollable result sets, use forward only mode for queries"
                          Maybe you neutered qsql_odbc.cpp too much, because other SQL commands like Select works without the patch, but maybe better safe than sorry.

                          P.P.S. I see you're using QThread for the database calls, I never got around to doing that, right now I have some really slooow SQLServers to interface with, maybe I could use some of your QThreading code...

                          J 1 Reply Last reply 9 Mar 2020, 19:47
                          1
                          • H hskoglund
                            9 Mar 2020, 19:18

                            @Jonas-Kvinge You were 99% there :-)

                            Only thing you forgot, since you altered the odbc.json file to just contain "QODBCX", you also need to add it the list of kosher names in main.cpp's QODBCDriverPlugin::create(), i.e. change line 62 in main.cpp from

                            if (name == QLatin1String("QODBC") || name == QLatin1String("QODBC3")) {
                            

                            to

                            if (name == QLatin1String("QODBC") || name == QLatin1String("QODBC3") || name == QLatin1String("QODBCX")) {
                            

                            P.S. I can see in your logging: "d->hasSQLFetchScroll: false" and this warning rears its ugly head:
                            "QODBCDriver::checkHasSQLFetchScroll: Warning - Driver doesn't support scrollable result sets, use forward only mode for queries"
                            Maybe you neutered qsql_odbc.cpp too much, because other SQL commands like Select works without the patch, but maybe better safe than sorry.

                            P.P.S. I see you're using QThread for the database calls, I never got around to doing that, right now I have some really slooow SQLServers to interface with, maybe I could use some of your QThreading code...

                            J Offline
                            J Offline
                            Jonas Kvinge
                            wrote on 9 Mar 2020, 19:47 last edited by
                            #27

                            @hskoglund
                            I'm doing that: https://github.com/jonaski/sqlrestore/blob/freetds/3rdparty/qsqlodbc/qsql_odbc_main.cpp#L57

                            1 Reply Last reply
                            0
                            • H Offline
                              H Offline
                              hskoglund
                              wrote on 9 Mar 2020, 20:59 last edited by
                              #28

                              @Jonas-Kvinge Sorry, you're right, that bug was mine, not yours. It was introduced because your qsql_odbc_main.cpp and h didn't make it into my build on Ubuntu 19.10 (with FreeTDS 1.1.6 and unixODBC 2.30).

                              You see, I didn't use your app to test the plugin, instead I copied everything from your 3rd party dir into my copy of 5.14.1's sources (into ~/Qt/5.14.1/Src/qtbase/src/plugins/sqldrivers/odbc) and then I rebuilt libqsqlodbc.so using Qt Creator and the vanilla ~/Qt/5.14.1/Src/qtbase/src/plugins/sqldrivers/odbc/sqldrivers.pro file (which means it compiled with the standard 5.1.41 main.cpp, not your new qsql_odbc_main.cpp and qsql_odbc.main.h)

                              Anyways, your qsql_odbc.cpp got compiled and it worked as I said nicely with my simple test program, just a Qt console app, standard .pro file expect that "QT += sql" is added, and here's the main.cpp:

                              #include <QCoreApplication>
                              #include <QTextStream>
                              #include <QDir>
                              #include <QtSql/QSqlDatabase>
                              #include <QtSql/QSqlRecord>
                              #include <QtSql/QSqlError>
                              #include <QSqlQuery>
                              
                              int main(int argc, char *argv[])
                              {
                                  QCoreApplication a(argc, argv);
                              
                              // try to load the SQL ODBC plugin
                                  auto db = QSqlDatabase::addDatabase("QODBCX");
                                  if (!db.isValid())
                                      qFatal("addDatabase(QODBC) failed :-(");
                              
                              // prepare the args
                                  QString sServerIP = "192.168.1.100";
                                  QString sDatabase = "northwind";
                                  QString sUsername = "sa";
                                  QString sPassword = "password";
                              
                              // setup dummy DSN name and where the freeTDS .so driver file is
                                  QString sDSN      = "dsn1";
                                  QString sFilename = "/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so";
                              
                              // create an .odbc.ini file on our home directory
                                  QFile fOdbc(QDir::homePath() + "/.odbc.ini");
                                  if (!fOdbc.open(QFile::WriteOnly | QFile::Text))
                                      qFatal("open ~/.odbc.ini for write failed");
                              
                                  QTextStream tsOdbc(&fOdbc);
                                  tsOdbc << "[" << sDSN << "]"           << "\n";
                                  tsOdbc << "Driver     = " << sFilename << "\n";
                                  tsOdbc << "Servername = " << sDSN      << "\n";
                                  tsOdbc << "Database   = " << sDatabase << "\n";
                                  tsOdbc.flush();
                                  fOdbc.close();
                              
                              // create a .freetds.conf file on our home directory
                                  QFile fFreeTds(QDir::homePath() + "/.freetds.conf");
                                  if (!fFreeTds.open(QFile::WriteOnly | QFile::Text))
                                      qFatal("open ~/.freetds.conf for write failed");
                              
                                  QTextStream tsFT(&fFreeTds);
                                  tsFT << "[" << sDSN << "]"        << "\n";
                                  tsFT << "host = " <<  sServerIP   << "\n";
                                  tsFT << "port = 1433"             << "\n";
                                  tsFT << "tds version = 7.0"       << "\n";
                                  tsFT.flush();
                                  fFreeTds.close();
                              
                                  db.setDatabaseName(sDSN);
                                  if (!db.open(sUsername,sPassword))
                                      qFatal("open() failed, error = '%s'",qUtf8Printable(db.lastError().text()));
                              
                                  QTextStream cout(stdout);
                              
                              // party on the db, using either the "restore.. " or the "select.."
                                  auto query = QSqlQuery("restore headeronly from disk = 'C:/northwind.bak'");
                                  //auto query = QSqlQuery("select * from sys.tables");
                                  auto columns = query.record().count();
                                  while (query.next())
                                      for (auto c = 0; (c < columns); ++c)
                                          cout << QString::number(c) << " : " << query.value(c).toString() << "\n";
                              
                              // that's all folks
                                  db.close();
                              }
                              

                              Note: I had to use "tds version = 7.0" in my .freetds.cont file, otherwise I couldn't establish contact with my MSSQLServer 2008R2.

                              Maybe you could try my test console app and see if it works on your openSUSE tumbleweed...

                              J 1 Reply Last reply 9 Mar 2020, 22:01
                              1
                              • H hskoglund
                                9 Mar 2020, 20:59

                                @Jonas-Kvinge Sorry, you're right, that bug was mine, not yours. It was introduced because your qsql_odbc_main.cpp and h didn't make it into my build on Ubuntu 19.10 (with FreeTDS 1.1.6 and unixODBC 2.30).

                                You see, I didn't use your app to test the plugin, instead I copied everything from your 3rd party dir into my copy of 5.14.1's sources (into ~/Qt/5.14.1/Src/qtbase/src/plugins/sqldrivers/odbc) and then I rebuilt libqsqlodbc.so using Qt Creator and the vanilla ~/Qt/5.14.1/Src/qtbase/src/plugins/sqldrivers/odbc/sqldrivers.pro file (which means it compiled with the standard 5.1.41 main.cpp, not your new qsql_odbc_main.cpp and qsql_odbc.main.h)

                                Anyways, your qsql_odbc.cpp got compiled and it worked as I said nicely with my simple test program, just a Qt console app, standard .pro file expect that "QT += sql" is added, and here's the main.cpp:

                                #include <QCoreApplication>
                                #include <QTextStream>
                                #include <QDir>
                                #include <QtSql/QSqlDatabase>
                                #include <QtSql/QSqlRecord>
                                #include <QtSql/QSqlError>
                                #include <QSqlQuery>
                                
                                int main(int argc, char *argv[])
                                {
                                    QCoreApplication a(argc, argv);
                                
                                // try to load the SQL ODBC plugin
                                    auto db = QSqlDatabase::addDatabase("QODBCX");
                                    if (!db.isValid())
                                        qFatal("addDatabase(QODBC) failed :-(");
                                
                                // prepare the args
                                    QString sServerIP = "192.168.1.100";
                                    QString sDatabase = "northwind";
                                    QString sUsername = "sa";
                                    QString sPassword = "password";
                                
                                // setup dummy DSN name and where the freeTDS .so driver file is
                                    QString sDSN      = "dsn1";
                                    QString sFilename = "/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so";
                                
                                // create an .odbc.ini file on our home directory
                                    QFile fOdbc(QDir::homePath() + "/.odbc.ini");
                                    if (!fOdbc.open(QFile::WriteOnly | QFile::Text))
                                        qFatal("open ~/.odbc.ini for write failed");
                                
                                    QTextStream tsOdbc(&fOdbc);
                                    tsOdbc << "[" << sDSN << "]"           << "\n";
                                    tsOdbc << "Driver     = " << sFilename << "\n";
                                    tsOdbc << "Servername = " << sDSN      << "\n";
                                    tsOdbc << "Database   = " << sDatabase << "\n";
                                    tsOdbc.flush();
                                    fOdbc.close();
                                
                                // create a .freetds.conf file on our home directory
                                    QFile fFreeTds(QDir::homePath() + "/.freetds.conf");
                                    if (!fFreeTds.open(QFile::WriteOnly | QFile::Text))
                                        qFatal("open ~/.freetds.conf for write failed");
                                
                                    QTextStream tsFT(&fFreeTds);
                                    tsFT << "[" << sDSN << "]"        << "\n";
                                    tsFT << "host = " <<  sServerIP   << "\n";
                                    tsFT << "port = 1433"             << "\n";
                                    tsFT << "tds version = 7.0"       << "\n";
                                    tsFT.flush();
                                    fFreeTds.close();
                                
                                    db.setDatabaseName(sDSN);
                                    if (!db.open(sUsername,sPassword))
                                        qFatal("open() failed, error = '%s'",qUtf8Printable(db.lastError().text()));
                                
                                    QTextStream cout(stdout);
                                
                                // party on the db, using either the "restore.. " or the "select.."
                                    auto query = QSqlQuery("restore headeronly from disk = 'C:/northwind.bak'");
                                    //auto query = QSqlQuery("select * from sys.tables");
                                    auto columns = query.record().count();
                                    while (query.next())
                                        for (auto c = 0; (c < columns); ++c)
                                            cout << QString::number(c) << " : " << query.value(c).toString() << "\n";
                                
                                // that's all folks
                                    db.close();
                                }
                                

                                Note: I had to use "tds version = 7.0" in my .freetds.cont file, otherwise I couldn't establish contact with my MSSQLServer 2008R2.

                                Maybe you could try my test console app and see if it works on your openSUSE tumbleweed...

                                J Offline
                                J Offline
                                Jonas Kvinge
                                wrote on 9 Mar 2020, 22:01 last edited by
                                #29

                                @hskoglund
                                I found the problem. I Made a query without bindValue and it worked.
                                In my code I changed:

                                query.prepare("RESTORE HEADERONLY FROM DISK = :bakfile");
                                query.bindValue(":bakfile", bakfile);
                                

                                to

                                query.prepare(QString("RESTORE HEADERONLY FROM DISK = '%1'").arg(bakfile));
                                
                                H 1 Reply Last reply 9 Mar 2020, 22:28
                                0
                                • SGaistS Offline
                                  SGaistS Offline
                                  SGaist
                                  Lifetime Qt Champion
                                  wrote on 9 Mar 2020, 22:09 last edited by
                                  #30

                                  Hi,

                                  Not all SQL operations support binding values especially when they are implementation specific.

                                  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
                                  1
                                  • J Jonas Kvinge
                                    9 Mar 2020, 22:01

                                    @hskoglund
                                    I found the problem. I Made a query without bindValue and it worked.
                                    In my code I changed:

                                    query.prepare("RESTORE HEADERONLY FROM DISK = :bakfile");
                                    query.bindValue(":bakfile", bakfile);
                                    

                                    to

                                    query.prepare(QString("RESTORE HEADERONLY FROM DISK = '%1'").arg(bakfile));
                                    
                                    H Offline
                                    H Offline
                                    hskoglund
                                    wrote on 9 Mar 2020, 22:28 last edited by
                                    #31

                                    @Jonas-Kvinge Nice! @SGaist Totally agree, long time ago I got bitten by the SQL binding bugs, and since I started with Qt I always use the QString("sql %1 %2 etc").arg().arg()... construction.

                                    (And as I understand it, since around the turn of the century, there's no difference in SQL Server performance between using prepare/bind and QString::arg())

                                    1 Reply Last reply
                                    0
                                    • SGaistS Offline
                                      SGaistS Offline
                                      SGaist
                                      Lifetime Qt Champion
                                      wrote on 9 Mar 2020, 22:33 last edited by SGaist 3 Sept 2020, 22:35
                                      #32

                                      @hskoglund IIRC binding values has additional benefits when having types other than string. And it helps secure dynamically created queries.

                                      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
                                      4

                                      24/32

                                      8 Mar 2020, 17:08

                                      • Login

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