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. Insert record into QSqlTableModel
Forum Updated to NodeBB v4.3 + New Features

Insert record into QSqlTableModel

Scheduled Pinned Locked Moved Solved General and Desktop
52 Posts 5 Posters 10.4k 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.
  • JonBJ JonB

    @tovax
    As I said, this may depend on when you do this with regard to when you submit your changes to the backend, which may cause the value to be altered. Print out what the value of the PK auto-increment is after you insert, or more to the point after you submit.

    Purely at a guess, comment out your record.setGenerated(Table::PrimaryKey, true); // true, and even your record.field(Table::PrimaryKey).setAutoValue(true);. Does this make a difference to whether it respects your value if you pass in a "missing" middle one?

    tovaxT Offline
    tovaxT Offline
    tovax
    wrote on last edited by
    #9

    @JonB The test result is: Whether "setGenerated" and "setAutoValue" are commented out or not, the primary key is always 0 before insertion. I think that's why we can't meet our expectations.
    So I'm confused about "setGenerated" and "setAutoValue", don't they mean automatic generation of primary keys?

    JonBJ 1 Reply Last reply
    0
    • JonBJ JonB

      @tovax
      As I said, this may depend on when you do this with regard to when you submit your changes to the backend, which may cause the value to be altered. Print out what the value of the PK auto-increment is after you insert, or more to the point after you submit.

      Purely at a guess, comment out your record.setGenerated(Table::PrimaryKey, true); // true, and even your record.field(Table::PrimaryKey).setAutoValue(true);. Does this make a difference to whether it respects your value if you pass in a "missing" middle one?

      tovaxT Offline
      tovaxT Offline
      tovax
      wrote on last edited by
      #10

      @JonB When I manually set a non duplicate value for the primary key, the record can be correctly inserted into the current row.

      1 Reply Last reply
      0
      • tovaxT tovax

        @JonB The test result is: Whether "setGenerated" and "setAutoValue" are commented out or not, the primary key is always 0 before insertion. I think that's why we can't meet our expectations.
        So I'm confused about "setGenerated" and "setAutoValue", don't they mean automatic generation of primary keys?

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

        @tovax said in Insert record into QSqlTableModel:

        So I'm confused about "setGenerated" and "setAutoValue", don't they mean automatic generation of primary keys?

        @JonB When I manually set a non duplicate value for the primary key, the record can be correctly inserted into the current row.

        Yes, they mean auto-generation. So they generate the next number, not some "middle" one! As you say, if you want to "force in" your own, missing number then you cannot ask it to auto-generate the value for you!

        You can probably disable auto-generate, insert your explicit one, and then re-enable auto-generate from then on?

        tovaxT 1 Reply Last reply
        2
        • JonBJ JonB

          @tovax said in Insert record into QSqlTableModel:

          So I'm confused about "setGenerated" and "setAutoValue", don't they mean automatic generation of primary keys?

          @JonB When I manually set a non duplicate value for the primary key, the record can be correctly inserted into the current row.

          Yes, they mean auto-generation. So they generate the next number, not some "middle" one! As you say, if you want to "force in" your own, missing number then you cannot ask it to auto-generate the value for you!

          You can probably disable auto-generate, insert your explicit one, and then re-enable auto-generate from then on?

          tovaxT Offline
          tovaxT Offline
          tovax
          wrote on last edited by
          #12

          @JonB I see. I'll try to add some code to generate the middle primary key as you suggest.

          JonBJ 1 Reply Last reply
          0
          • tovaxT tovax

            @JonB I see. I'll try to add some code to generate the middle primary key as you suggest.

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

            @tovax
            I will say one thing: you should not really be trying to do this at all! You're not "supposed" to go back and re-insert auto-gen keys if you have deleted one.

            Imagine you have one million rows. One of them has a "gap". How are you going to find that gap one? If you have to do it client/Qt side, the only way is to read all one million into the client and iterate them to find any gap. Not a good idea! Even if you try to use server-side SQL code to avoid downloading them all, I don't think your SQL will offer any (efficient) way of discovering the gap. So maybe thing again....??

            tovaxT 2 Replies Last reply
            0
            • JonBJ JonB

              @tovax
              I will say one thing: you should not really be trying to do this at all! You're not "supposed" to go back and re-insert auto-gen keys if you have deleted one.

              Imagine you have one million rows. One of them has a "gap". How are you going to find that gap one? If you have to do it client/Qt side, the only way is to read all one million into the client and iterate them to find any gap. Not a good idea! Even if you try to use server-side SQL code to avoid downloading them all, I don't think your SQL will offer any (efficient) way of discovering the gap. So maybe thing again....??

              tovaxT Offline
              tovaxT Offline
              tovax
              wrote on last edited by
              #14

              @JonB How can I insert a record in the current row, please?

              jsulmJ 1 Reply Last reply
              0
              • tovaxT tovax

                @JonB How can I insert a record in the current row, please?

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #15

                @tovax said in Insert record into QSqlTableModel:

                How can I insert a record in the current row, please?

                What do you mean? A record is a row. Do you want to update a row?

                tovaxT 1 Reply Last reply
                0
                • JonBJ JonB

                  @tovax
                  I will say one thing: you should not really be trying to do this at all! You're not "supposed" to go back and re-insert auto-gen keys if you have deleted one.

                  Imagine you have one million rows. One of them has a "gap". How are you going to find that gap one? If you have to do it client/Qt side, the only way is to read all one million into the client and iterate them to find any gap. Not a good idea! Even if you try to use server-side SQL code to avoid downloading them all, I don't think your SQL will offer any (efficient) way of discovering the gap. So maybe thing again....??

                  tovaxT Offline
                  tovaxT Offline
                  tovax
                  wrote on last edited by
                  #16

                  @JonB The database is local, and the data structure is completely controlled by myself, as long as the record can be inserted into the current row.

                  1 Reply Last reply
                  0
                  • jsulmJ jsulm

                    @tovax said in Insert record into QSqlTableModel:

                    How can I insert a record in the current row, please?

                    What do you mean? A record is a row. Do you want to update a row?

                    tovaxT Offline
                    tovaxT Offline
                    tovax
                    wrote on last edited by
                    #17

                    @jsulm It is similar to inserting a row of data in Excel table.

                    jsulmJ 1 Reply Last reply
                    0
                    • tovaxT tovax

                      @jsulm It is similar to inserting a row of data in Excel table.

                      jsulmJ Offline
                      jsulmJ Offline
                      jsulm
                      Lifetime Qt Champion
                      wrote on last edited by jsulm
                      #18

                      @tovax A SQL table is not like a Excel table: you do not insert rows in SQL at specific positions, there is nothing like that in SQL (no specific order of rows). So, what do you mean by "current row"?

                      tovaxT 2 Replies Last reply
                      0
                      • jsulmJ jsulm

                        @tovax A SQL table is not like a Excel table: you do not insert rows in SQL at specific positions, there is nothing like that in SQL (no specific order of rows). So, what do you mean by "current row"?

                        tovaxT Offline
                        tovaxT Offline
                        tovax
                        wrote on last edited by
                        #19

                        @jsulm The row which the mouse clicked.

                        jsulmJ 1 Reply Last reply
                        0
                        • jsulmJ jsulm

                          @tovax A SQL table is not like a Excel table: you do not insert rows in SQL at specific positions, there is nothing like that in SQL (no specific order of rows). So, what do you mean by "current row"?

                          tovaxT Offline
                          tovaxT Offline
                          tovax
                          wrote on last edited by
                          #20

                          @jsulm The help manual says:

                          bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
                          Inserts the record at position row. If row is negative, the record will be appended to the end.
                          
                          JonBJ 1 Reply Last reply
                          0
                          • tovaxT tovax

                            @jsulm The row which the mouse clicked.

                            jsulmJ Offline
                            jsulmJ Offline
                            jsulm
                            Lifetime Qt Champion
                            wrote on last edited by
                            #21
                            This post is deleted!
                            1 Reply Last reply
                            0
                            • tovaxT tovax

                              @jsulm The help manual says:

                              bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
                              Inserts the record at position row. If row is negative, the record will be appended to the end.
                              
                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by
                              #22

                              @tovax
                              Listen carefully! :) To emulate rows in Excel, you should not use any auto-incremented primary key in the database! That is not the way to do it, and leads to your "missing row" problem.

                              Instead, you must your own "row number" integer variable as a column. But not auto-incremented. Instead, you must fill it with the desired row number. And if you insert a row you must write code to renumber all the subsequent ones to allow for this one to go in, and if you delete a row you must write code to decerment all the higher ones to close the gap.

                              Trust me :D

                              tovaxT 1 Reply Last reply
                              0
                              • JonBJ JonB

                                @tovax
                                Listen carefully! :) To emulate rows in Excel, you should not use any auto-incremented primary key in the database! That is not the way to do it, and leads to your "missing row" problem.

                                Instead, you must your own "row number" integer variable as a column. But not auto-incremented. Instead, you must fill it with the desired row number. And if you insert a row you must write code to renumber all the subsequent ones to allow for this one to go in, and if you delete a row you must write code to decerment all the higher ones to close the gap.

                                Trust me :D

                                tovaxT Offline
                                tovaxT Offline
                                tovax
                                wrote on last edited by
                                #23

                                @JonB Thank you very much! According to your suggestion, I have implemented the insertion function. As you said, the primary key not auto-incremented, and renumber primary key before inserting.
                                Best regards!

                                void JCDemoDatabase::onInsertClicked()
                                {
                                    qDebug() << __FUNCTION__ << tableView->currentIndex().row();
                                
                                    // current row
                                    int32_t currentRowIndex = tableView->currentIndex().row();
                                
                                    // prepare insert primary key
                                    tableModel->database().transaction();
                                    insertPrimaryKey(tableModel, currentRowIndex);
                                
                                    // new record
                                    QSqlRecord record = tableModel->record();
                                    for (int32_t columnIndex = Table::Field::Min; columnIndex <= Table::Field::Max; columnIndex++) {
                                        record.setValue(Table::FieldText[columnIndex], QString("---"));
                                    }
                                    record.setValue(Table::PrimaryKey, currentRowIndex + 1);
                                
                                    // insert new record
                                    if (!tableModel->insertRecord(currentRowIndex, record)) {
                                        qDebug() << __FUNCTION__ << "Error 1: " << tableModel->lastError().text();
                                    }
                                
                                    // submit all
                                    if (tableModel->submitAll()) {
                                        tableModel->database().commit();
                                    } else {
                                        tableModel->database().rollback();
                                        qDebug() << __FUNCTION__ << "Error 2: " << tableModel->lastError().text();
                                    }
                                }
                                
                                int32_t JCDemoDatabase::insertPrimaryKey(QSqlTableModel *model, int32_t row)
                                {
                                    // TODO: invalid
                                    // model->record(rowIndex).setValue(Table::PrimaryKey, (rowIndex + 1));
                                
                                    // key
                                    int32_t oldMax = model->record(model->rowCount() - 1).value(Table::PrimaryKey).toInt();
                                    int32_t newMax = model->rowCount() + 1;
                                    if (oldMax < newMax) {
                                        oldMax = newMax;
                                    }
                                
                                    // backup
                                    for (int32_t rowIndex = 0; rowIndex < model->rowCount(); rowIndex++) {
                                        QSqlRecord record = model->record(rowIndex);
                                        record.setValue(Table::PrimaryKey, oldMax + 1 + rowIndex);
                                        model->setRecord(rowIndex, record);
                                    }
                                    if (model->submitAll()) {
                                        model->database().commit();
                                    } else {
                                        model->database().rollback();
                                        qDebug() << __FUNCTION__ << 1 << model->lastError().text();
                                    }
                                
                                    // less than "row"
                                    for (int32_t rowIndex = 0; rowIndex < row; rowIndex++) {
                                        QSqlRecord record = model->record(rowIndex);
                                        record.setValue(Table::PrimaryKey, rowIndex + 1);
                                        model->setRecord(rowIndex, record);
                                    }
                                    if (model->submitAll()) {
                                        model->database().commit();
                                    } else {
                                        model->database().rollback();
                                        qDebug() << __FUNCTION__ << 2 << model->lastError().text();
                                    }
                                
                                    // reserve row for currentRowIndex
                                
                                    // greater than "row"
                                    for (int32_t rowIndex = row; rowIndex < model->rowCount(); rowIndex++) {
                                        QSqlRecord record = model->record(rowIndex);
                                        record.setValue(Table::PrimaryKey, rowIndex + 2);
                                        model->setRecord(rowIndex, record);
                                    }
                                    if (model->submitAll()) {
                                        model->database().commit();
                                    } else {
                                        model->database().rollback();
                                        qDebug() << __FUNCTION__ << 3 << model->lastError().text();
                                    }
                                
                                    return row + 1;
                                }
                                
                                JonBJ 1 Reply Last reply
                                0
                                • tovaxT tovax

                                  @JonB Thank you very much! According to your suggestion, I have implemented the insertion function. As you said, the primary key not auto-incremented, and renumber primary key before inserting.
                                  Best regards!

                                  void JCDemoDatabase::onInsertClicked()
                                  {
                                      qDebug() << __FUNCTION__ << tableView->currentIndex().row();
                                  
                                      // current row
                                      int32_t currentRowIndex = tableView->currentIndex().row();
                                  
                                      // prepare insert primary key
                                      tableModel->database().transaction();
                                      insertPrimaryKey(tableModel, currentRowIndex);
                                  
                                      // new record
                                      QSqlRecord record = tableModel->record();
                                      for (int32_t columnIndex = Table::Field::Min; columnIndex <= Table::Field::Max; columnIndex++) {
                                          record.setValue(Table::FieldText[columnIndex], QString("---"));
                                      }
                                      record.setValue(Table::PrimaryKey, currentRowIndex + 1);
                                  
                                      // insert new record
                                      if (!tableModel->insertRecord(currentRowIndex, record)) {
                                          qDebug() << __FUNCTION__ << "Error 1: " << tableModel->lastError().text();
                                      }
                                  
                                      // submit all
                                      if (tableModel->submitAll()) {
                                          tableModel->database().commit();
                                      } else {
                                          tableModel->database().rollback();
                                          qDebug() << __FUNCTION__ << "Error 2: " << tableModel->lastError().text();
                                      }
                                  }
                                  
                                  int32_t JCDemoDatabase::insertPrimaryKey(QSqlTableModel *model, int32_t row)
                                  {
                                      // TODO: invalid
                                      // model->record(rowIndex).setValue(Table::PrimaryKey, (rowIndex + 1));
                                  
                                      // key
                                      int32_t oldMax = model->record(model->rowCount() - 1).value(Table::PrimaryKey).toInt();
                                      int32_t newMax = model->rowCount() + 1;
                                      if (oldMax < newMax) {
                                          oldMax = newMax;
                                      }
                                  
                                      // backup
                                      for (int32_t rowIndex = 0; rowIndex < model->rowCount(); rowIndex++) {
                                          QSqlRecord record = model->record(rowIndex);
                                          record.setValue(Table::PrimaryKey, oldMax + 1 + rowIndex);
                                          model->setRecord(rowIndex, record);
                                      }
                                      if (model->submitAll()) {
                                          model->database().commit();
                                      } else {
                                          model->database().rollback();
                                          qDebug() << __FUNCTION__ << 1 << model->lastError().text();
                                      }
                                  
                                      // less than "row"
                                      for (int32_t rowIndex = 0; rowIndex < row; rowIndex++) {
                                          QSqlRecord record = model->record(rowIndex);
                                          record.setValue(Table::PrimaryKey, rowIndex + 1);
                                          model->setRecord(rowIndex, record);
                                      }
                                      if (model->submitAll()) {
                                          model->database().commit();
                                      } else {
                                          model->database().rollback();
                                          qDebug() << __FUNCTION__ << 2 << model->lastError().text();
                                      }
                                  
                                      // reserve row for currentRowIndex
                                  
                                      // greater than "row"
                                      for (int32_t rowIndex = row; rowIndex < model->rowCount(); rowIndex++) {
                                          QSqlRecord record = model->record(rowIndex);
                                          record.setValue(Table::PrimaryKey, rowIndex + 2);
                                          model->setRecord(rowIndex, record);
                                      }
                                      if (model->submitAll()) {
                                          model->database().commit();
                                      } else {
                                          model->database().rollback();
                                          qDebug() << __FUNCTION__ << 3 << model->lastError().text();
                                      }
                                  
                                      return row + 1;
                                  }
                                  
                                  JonBJ Offline
                                  JonBJ Offline
                                  JonB
                                  wrote on last edited by JonB
                                  #24

                                  @tovax
                                  Hmm, I'm a bit worried about your algorithm. Depends how this works in your database, and how the updates/transactions work, but....

                                  I see when you insert you renumber upwards. If this is a unique/primary key, that will keep "bumping into" the number above which already exists (hasn't been renumbered yet). Which might error?

                                  If it were me: to renumber for an insert I would start from the highest number, increment that, prodceed downward through the numbers. To renumber for a delete, I would start from one above the delete, decrement, then proceed upward till the last row. Makes sense?

                                  Of course, your approach is incredibly slow (at least for a remote/full database, not just a local file) across a large number of rows. I take it you are not concerned about having a thousand or a million of them....?

                                  tovaxT 1 Reply Last reply
                                  0
                                  • Christian EhrlicherC Offline
                                    Christian EhrlicherC Offline
                                    Christian Ehrlicher
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #25

                                    A key in a db is there so it gets not reused. It's somehow contradicts the reason for a primary key... If a column with an id is deleted this id should not be used again. I also don't see why it should be needed in your case at all.

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

                                    JonBJ tovaxT 2 Replies Last reply
                                    1
                                    • Christian EhrlicherC Christian Ehrlicher

                                      A key in a db is there so it gets not reused. It's somehow contradicts the reason for a primary key... If a column with an id is deleted this id should not be used again. I also don't see why it should be needed in your case at all.

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

                                      @Christian-Ehrlicher
                                      (I believe) the reason is the OP is wanting to emulate "inserting a row of data in Excel table". So he wants a row number of some description to get the ordering. Which I have said he should implement himself, not make auto-increment do it. (He might still use an auto-inc for the PK to identify the row if he wishes, but a dedicated unique column for the ordered row number usage.)

                                      1 Reply Last reply
                                      0
                                      • Christian EhrlicherC Offline
                                        Christian EhrlicherC Offline
                                        Christian Ehrlicher
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #27

                                        A PK is not to be used for ordering or something else.

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

                                        JonBJ 1 Reply Last reply
                                        1
                                        • Christian EhrlicherC Christian Ehrlicher

                                          A PK is not to be used for ordering or something else.

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

                                          @Christian-Ehrlicher
                                          Um, that's what I've been saying.... Hence he needs something else for ordering.
                                          TBH it's not even the PK which is at issue here, it's the auto-increment being unsuitable for OP's ordering.

                                          tovaxT 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