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. How to correctly drop all tables from an sqlite database using `QSqlQuery::execBatch()`?
Forum Updated to NodeBB v4.3 + New Features

How to correctly drop all tables from an sqlite database using `QSqlQuery::execBatch()`?

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 6.5k Views 1 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.
  • D Offline
    D Offline
    devjb
    wrote on 31 Mar 2022, 13:44 last edited by
    #1

    I do successfully insert values appended to QVariantLists to my sql database using QSqlQuery::addBindValue(QVariantList) in several places using positional placeholders and calling QSqlQuery::execBatch(). This usually works flawlessly.

    However I wanted to do the same for a DROP TABLE IF EXISTS-statement as well where I dynamically get all tables from my database and drop them. After lots of debugging, I can still not figure out what I am doing wrong.

    This is what I am trying to do:

    			QSqlQuery dropQuery(db);
    			dropQuery.prepare("DROP TABLE IF EXISTS ?");
    			QVariantList tables;
    			auto tableNames = db.tables();
    			tableNames.removeAll("sqlite_sequence");
    			for (const auto& tableName : qAsConst(tableNames)) {
    				tables << tableName;
    			}
    			dropQuery.addBindValue(tables);
    			if (!dropQuery.execBatch()) {
    					qDebug() << "Unable to drop Tables: " 
    								% dropQuery.lastError().text() 
    								% " at: " 
    								% dropQuery.lastQuery();
    			}
    

    Which always fails with:

    Unable to drop Tables: Parameter count mismatch at: DROP TABLE IF EXISTS ?

    When I simply do the same thing using multiple calls to QSqlQuery::exec() it all works fine:

    			QSqlQuery dropQuery(db);
    			QString dropQueryString = "DROP TABLE IF EXISTS %1";
    			auto tableNames = db.tables();
    			tableNames.removeAll("sqlite_sequence");
    			bool allTablesDropped = true;
    			for (const auto& tableName : qAsConst(tableNames)) {
    				if (!dropQuery.exec(dropQueryString.arg(tableName))) {
    					allTablesDropped = false;
    					break;
    				}
    			}
    			if (!allTablesDropped) {
    				[...]
    			}
    

    Any ideas what could cause this?

    Thanks in advance

    J 1 Reply Last reply 31 Mar 2022, 13:58
    0
    • D devjb
      31 Mar 2022, 13:44

      I do successfully insert values appended to QVariantLists to my sql database using QSqlQuery::addBindValue(QVariantList) in several places using positional placeholders and calling QSqlQuery::execBatch(). This usually works flawlessly.

      However I wanted to do the same for a DROP TABLE IF EXISTS-statement as well where I dynamically get all tables from my database and drop them. After lots of debugging, I can still not figure out what I am doing wrong.

      This is what I am trying to do:

      			QSqlQuery dropQuery(db);
      			dropQuery.prepare("DROP TABLE IF EXISTS ?");
      			QVariantList tables;
      			auto tableNames = db.tables();
      			tableNames.removeAll("sqlite_sequence");
      			for (const auto& tableName : qAsConst(tableNames)) {
      				tables << tableName;
      			}
      			dropQuery.addBindValue(tables);
      			if (!dropQuery.execBatch()) {
      					qDebug() << "Unable to drop Tables: " 
      								% dropQuery.lastError().text() 
      								% " at: " 
      								% dropQuery.lastQuery();
      			}
      

      Which always fails with:

      Unable to drop Tables: Parameter count mismatch at: DROP TABLE IF EXISTS ?

      When I simply do the same thing using multiple calls to QSqlQuery::exec() it all works fine:

      			QSqlQuery dropQuery(db);
      			QString dropQueryString = "DROP TABLE IF EXISTS %1";
      			auto tableNames = db.tables();
      			tableNames.removeAll("sqlite_sequence");
      			bool allTablesDropped = true;
      			for (const auto& tableName : qAsConst(tableNames)) {
      				if (!dropQuery.exec(dropQueryString.arg(tableName))) {
      					allTablesDropped = false;
      					break;
      				}
      			}
      			if (!allTablesDropped) {
      				[...]
      			}
      

      Any ideas what could cause this?

      Thanks in advance

      J Offline
      J Offline
      JonB
      wrote on 31 Mar 2022, 13:58 last edited by
      #2

      @devjb
      You seem to be doing two things wrong (if I understand your code right):

      • In the first case you are producing a single DROP TABLE IF EXISTS table1 table2 ... tablen statement. Only you know SQLite, but I would not have thought that is acceptable, surely you have to drop one table at a time?

      • In the first case you are using "bound variables" for the SQL statement. Only certain SQLite statements accept bound values. INSERT VALUES statements do. DROP TABLE likely do not.

      D 1 Reply Last reply 21 Apr 2022, 20:47
      0
      • J JonB
        31 Mar 2022, 13:58

        @devjb
        You seem to be doing two things wrong (if I understand your code right):

        • In the first case you are producing a single DROP TABLE IF EXISTS table1 table2 ... tablen statement. Only you know SQLite, but I would not have thought that is acceptable, surely you have to drop one table at a time?

        • In the first case you are using "bound variables" for the SQL statement. Only certain SQLite statements accept bound values. INSERT VALUES statements do. DROP TABLE likely do not.

        D Offline
        D Offline
        devjb
        wrote on 21 Apr 2022, 20:47 last edited by
        #3

        @JonB said in How to correctly drop all tables from an sqlite database using &#x60;QSqlQuery::execBatch()&#x60;?:

        @devjb
        You seem to be doing two things wrong (if I understand your code right):

        • In the first case you are producing a single DROP TABLE IF EXISTS table1 table2 ... tablen statement. Only you know SQLite, but I would not have thought that is acceptable, surely you have to drop one table at a time?

        Not exactly. Placeholders will be respected by execBatch() in a way that the queries are executed for each member of the QVariantList. You only have to make sure to contain the same number of QVariants for each QVariantList.
        For an INSERT statement, this does work fine.

        However, your assumption

        • In the first case you are using "bound variables" for the SQL statement. Only certain SQLite statements accept bound values. INSERT VALUES statements do. DROP TABLE likely do not.

        is correct. It is even documented in the sqlite c library. DROP statements do not support binding.

        I see a lot of improvement potential both in the Qt documentation as well as in the internal query error management though.

        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