Maximum number of boundValues QSqlQuery
-
wrote on 23 Jul 2018, 21:50 last edited by Stephocke
Hi guys,
i build some own classes and functions to build my query strings. It seems working till I build a multi insert including 100 rows and 11 values per row. I got the error: parameter count mismatch. I found a functions some time ago to maintain my query strings (posted below). The executed query is fine, if I copy, paste and execute the stmt directly in SQLiteStudio there is no error.
I made some further tests and i realized the the maximum number of boundValues must be 1.000. I can insert exactly 90 rows. I get the error if my rows have a number>91.
I am using Visual Studio 2015 IDE and compiler and Qt 5.9.1
Is there a know limit of boundValues?QString qtdb::getLastExecutedQuery(const QSqlQuery & query) { QString sql = query.executedQuery(); int nbBindValues = query.boundValues().size(); for (int i = 0, j = 0; j < nbBindValues;) { int s = sql.indexOf(QLatin1Char('\''), i); i = sql.indexOf(QLatin1Char('?'), i); if (i < 1) { break; } if (s < i && s > 0) { i = sql.indexOf(QLatin1Char('\''), s + 1) + 1; if (i < 2) { break; } } else { const QVariant &var = query.boundValue(j); QSqlField field(QLatin1String(""), var.type()); if (var.isNull()) { field.clear(); } else { field.setValue(var); } QString formatV = query.driver()->formatValue(field); sql.replace(i, 1, formatV); i += formatV.length(); ++j; } } return sql; }
-
Hi And welcome to the forums.
its seems to be using a vector internally
so i do not think there should be a fixed limit besides memory.
https://code.woboq.org/qt5/qtbase/src/sql/kernel/qsqlquery.cpp.html
-
Hi and welcome to devnet,
Can you share the query that triggers that ?
-
wrote on 23 Jul 2018, 22:07 last edited byThis post is deleted!
-
wrote on 23 Jul 2018, 22:29 last edited by Stephocke
update: If I prepare the query a second time with the debugger string, the stmt is executed successfully ... strange. So its really looks like a limit of boundValues
(a row is a customer container including "dbEntities"{columnName, QVariant value, operator})bool qtdb::dbInsert::query() { if (rows.size() == 0) return true; qry.prepare(str()); for (int i = 0; i < rows.size(); i++) { for (int j = 0; j < cols; j++) { qry.addBindValue(rows[i].getEntry(j)->getValue()); } } QString debugger = getLastExecutedQuery(qry); qry.prepare(debugger); bool success = qry.exec(); lastInsertId = qry.lastInsertId().isValid() ? qry.lastInsertId().toInt() : -1; return success; }
The unprepared stmt the qry receiving from the member function str() looks like:
INSERT INTO patients (id,name,tw_start,tw_end,xCoordinate,yCoordinate,service,duration,id_session,id_problem,type) VALUES (?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?),(?,?,?,?,?,?,?,?,?,?,?)There is no unique constraint fail of the database.
-
wrote on 24 Jul 2018, 01:04 last edited by Stephocke
I build a "small" example of what is happening ... and 1000 boundValues are the limit.
I can insert 200 rows but "parameter count missmatch" from rows>200#include <QtCore/QCoreApplication> #include <QtSql> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSqlDatabase database; database = QSqlDatabase::addDatabase("QSQLITE"); database.setDatabaseName("testDb.sqlite"); if (!database.open()) { qDebug() << "cannot open database"; return 0; } QSqlQuery query; std::vector<QVariant> aux{ "coolio",2.78,13.5,1 }; std::vector<QVariant> binds; binds.push_back(1); binds.insert(binds.end(), aux.begin(), aux.end()); binds.reserve(1250); QString insertStr = "INSERT INTO testTable (id,desc,firstDouble,secondDouble,firstInt) VALUES (?,?,?,?,?)"; for (int i = 2; i < 200; i++) { insertStr += ",(?,?,?,?,?)"; binds.push_back(i); binds.insert(binds.end(), aux.begin(), aux.end()); } query.prepare(insertStr); for (auto& e : binds) query.addBindValue(e); if (!query.exec()) { qDebug() << "cannot insert into database"; qDebug() << query.lastError().text(); } else { qDebug() << "yes!"; } database.close(); return a.exec(); }
-
I build a "small" example of what is happening ... and 1000 boundValues are the limit.
I can insert 200 rows but "parameter count missmatch" from rows>200#include <QtCore/QCoreApplication> #include <QtSql> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSqlDatabase database; database = QSqlDatabase::addDatabase("QSQLITE"); database.setDatabaseName("testDb.sqlite"); if (!database.open()) { qDebug() << "cannot open database"; return 0; } QSqlQuery query; std::vector<QVariant> aux{ "coolio",2.78,13.5,1 }; std::vector<QVariant> binds; binds.push_back(1); binds.insert(binds.end(), aux.begin(), aux.end()); binds.reserve(1250); QString insertStr = "INSERT INTO testTable (id,desc,firstDouble,secondDouble,firstInt) VALUES (?,?,?,?,?)"; for (int i = 2; i < 200; i++) { insertStr += ",(?,?,?,?,?)"; binds.push_back(i); binds.insert(binds.end(), aux.begin(), aux.end()); } query.prepare(insertStr); for (auto& e : binds) query.addBindValue(e); if (!query.exec()) { qDebug() << "cannot insert into database"; qDebug() << query.lastError().text(); } else { qDebug() << "yes!"; } database.close(); return a.exec(); }
Hi
i think maybe its the
SQLITE_LIMIT_VARIABLE_NUMBER (default value: 999).
you are hitting ?
https://www.sqlite.org/c3ref/bind_blob.html -
wrote on 24 Jul 2018, 07:26 last edited by
I think what you are looking for is https://doc.qt.io/qt-5/qsqlquery.html#execBatch
The maximum number of batch rows is determined by your database MS SQL Server has 250 limit if I'm not mistaken
-
wrote on 25 Jul 2018, 15:45 last edited by
I think you are right, it must be SQLITE_LIMIT_VARIABLE_NUMBER
I have found this function within the documentation and i want to try to increase the limit.
sqlite3_limit(sqlite3*, int id, int newVal);
But I am completely overwhelmed. It is again typical C ++, instructions from experts for experts. I already noticed I cannot include <qsql_sqlite.h> - there is no such header file. So I thought mabye I have to set some includes within the project->properties->linker - add an include path and a .lib. On the official homepage of sqlite I am not able to find a .lib and header file download. I already downloaded some .dlls and the complete source code. Do I have to build my own lib from the source code? I never did this before. Did I just miss the right Qt include header? Or do i have to download the source code of qsql_sqlite.h and qsql_sqlite.cpp and paste it into the Qt path?
What do I have to do? -
Hi
im no expert but i think you dont need to compile it again.
please see here
https://stackoverflow.com/questions/34415351/adding-a-custom-sqlite-function-to-a-qt-application
note the sqlite3_initialize
that should allow u to call sqlite3_limit -
wrote on 25 Jul 2018, 16:48 last edited by Stephocke
Thank you, I dont know this post. I will use it as soon as I can access sqlite components in my project. But as i said, there is no sqlite related in my Qt folder. There isnt even a "src" folder. No sqlite.h, no third party folder, no sql_sqlite.h, no sqlite3.h, no qsqlite.lib. There is only a qsqlite.dll within .../plugins/qsqldirver
-
you have to use the sqlite3.h from the related qt source package - it is not shipped with the binary package since it is normally not needed at all.
-
wrote on 25 Jul 2018, 17:01 last edited by Stephocke
Ok, thx. A completely different solution, from one problem to the next to call one function, that is out of proportion. Then i dont need it either. I'll add an if(i>1000) compute the corresponding string, prepare the query again and fire the stmt successfully.
-
Ok, thx. A completely different solution, from one problem to the next to call one function, that is out of proportion. Then i dont need it either. I'll add an if(i>1000) compute the corresponding string, prepare the query again and fire the stmt successfully.
@Stephocke
Well getting the header is not overly complicated.
If you used the online installer to install Qt, you just
open maintenance.exe in Qt folder
and select the source under the Qt u are using.
but if the workaround is acceptable, i guess its easier.
1/14