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. insertRecord failure with QSqlRelationalTableModel
QtWS25 Last Chance

insertRecord failure with QSqlRelationalTableModel

Scheduled Pinned Locked Moved Unsolved General and Desktop
pyqt6qsqlrelational
5 Posts 3 Posters 428 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.
  • P Offline
    P Offline
    peterloron
    wrote on 7 Apr 2024, 02:30 last edited by
    #1

    I have an application (posted below) which has a QSqlRelationalTableModel connected to a simple Sqlite db with two tables. The data from the db shows up in the QTableView as expected, which the referenced data properly filled in. However, when I try to insert a record, I get the following error:

    NOT NULL constraint failed: people.city Unable to fetch row

    It seems like the value I set in the record for the people.city field isn't making it into the insert? Any help would be appreciated. Thanks.

    #!/usr/bin/env python
    
    import sys
    from PyQt6.QtSql import *
    from PyQt6.QtCore import Qt
    from PyQt6.QtWidgets import (QApplication, QMainWindow, QTableView)
    
    class MainWindow(QMainWindow):
      def __init__(self):
        super().__init__()
    
        # set up main window
        self.resize(1024,700)
    
        self.model = QSqlRelationalTableModel()
        self.model.setTable("people")
        self.model.setEditStrategy(QSqlTableModel.EditStrategy.OnFieldChange)
        self.model.setHeaderData(2, Qt.Orientation.Horizontal, "city")
        self.model.setRelation(2, QSqlRelation("city", "id", "name"))
    
        self.view = QTableView()
        self.view.setModel(self.model)
        self.view.setItemDelegate(QSqlRelationalDelegate(self.view))
        self.view.setSortingEnabled(True)
        self.view.sortByColumn(1, Qt.SortOrder.AscendingOrder)
        self.view.verticalHeader().setVisible(False)
        self.view.doubleClicked.connect(self.onAddRow)
        
        self.setCentralWidget(self.view)
        self.view.resizeColumnsToContents()
        self.model.select()
    
    
      def onAddRow(self, s):
        self.model.select()
        new_rec = self.model.record()
        new_rec.setValue("name", 'Eliza')
        new_rec.setValue("city", 2)
        res = self.model.insertRecord(-1, new_rec)
        if res:
          print("insert ok")
        else:
          print("insert failed")
          print(self.model.lastError().text())
    
        self.model.submitAll()
        self.model.select()
    
    
    # Establish connection to our database.
    def dbConnect():
      con = QSqlDatabase.addDatabase("QSQLITE")
      con.setDatabaseName('db.sqlite')
      if not con.open():
        print("DB connect error")
        sys.exit(1)
    
    def createFakeData():
      query = QSqlQuery()
      query.exec("DROP TABLE people")
      query.exec("DROP TABLE city")
    
      query.exec("CREATE TABLE people(id INTEGER PRIMARY KEY, name VARCHAR(40) NOT NULL, city INTEGER NOT NULL)")
      query.exec("CREATE TABLE city(id INTEGER PRIMARY KEY, name VARCHAR(40) NOT NULL)")
    
      query.exec("INSERT INTO people(name, city) VALUES('Helen', 1)")
      query.exec("INSERT INTO people(name, city) VALUES('Juan', 2)")
      query.exec("INSERT INTO city(name) VALUES('Seattle')")
      query.exec("INSERT INTO city(name) VALUES('Tokyo')")
    
    
    def main():
      app = QApplication(sys.argv)
      dbConnect()
      createFakeData()
      w = MainWindow()
      w.show()
      app.exec()
    
    if __name__ == '__main__':
        main()
    
    
    J 1 Reply Last reply 7 Apr 2024, 07:24
    0
    • P peterloron
      7 Apr 2024, 02:30

      I have an application (posted below) which has a QSqlRelationalTableModel connected to a simple Sqlite db with two tables. The data from the db shows up in the QTableView as expected, which the referenced data properly filled in. However, when I try to insert a record, I get the following error:

      NOT NULL constraint failed: people.city Unable to fetch row

      It seems like the value I set in the record for the people.city field isn't making it into the insert? Any help would be appreciated. Thanks.

      #!/usr/bin/env python
      
      import sys
      from PyQt6.QtSql import *
      from PyQt6.QtCore import Qt
      from PyQt6.QtWidgets import (QApplication, QMainWindow, QTableView)
      
      class MainWindow(QMainWindow):
        def __init__(self):
          super().__init__()
      
          # set up main window
          self.resize(1024,700)
      
          self.model = QSqlRelationalTableModel()
          self.model.setTable("people")
          self.model.setEditStrategy(QSqlTableModel.EditStrategy.OnFieldChange)
          self.model.setHeaderData(2, Qt.Orientation.Horizontal, "city")
          self.model.setRelation(2, QSqlRelation("city", "id", "name"))
      
          self.view = QTableView()
          self.view.setModel(self.model)
          self.view.setItemDelegate(QSqlRelationalDelegate(self.view))
          self.view.setSortingEnabled(True)
          self.view.sortByColumn(1, Qt.SortOrder.AscendingOrder)
          self.view.verticalHeader().setVisible(False)
          self.view.doubleClicked.connect(self.onAddRow)
          
          self.setCentralWidget(self.view)
          self.view.resizeColumnsToContents()
          self.model.select()
      
      
        def onAddRow(self, s):
          self.model.select()
          new_rec = self.model.record()
          new_rec.setValue("name", 'Eliza')
          new_rec.setValue("city", 2)
          res = self.model.insertRecord(-1, new_rec)
          if res:
            print("insert ok")
          else:
            print("insert failed")
            print(self.model.lastError().text())
      
          self.model.submitAll()
          self.model.select()
      
      
      # Establish connection to our database.
      def dbConnect():
        con = QSqlDatabase.addDatabase("QSQLITE")
        con.setDatabaseName('db.sqlite')
        if not con.open():
          print("DB connect error")
          sys.exit(1)
      
      def createFakeData():
        query = QSqlQuery()
        query.exec("DROP TABLE people")
        query.exec("DROP TABLE city")
      
        query.exec("CREATE TABLE people(id INTEGER PRIMARY KEY, name VARCHAR(40) NOT NULL, city INTEGER NOT NULL)")
        query.exec("CREATE TABLE city(id INTEGER PRIMARY KEY, name VARCHAR(40) NOT NULL)")
      
        query.exec("INSERT INTO people(name, city) VALUES('Helen', 1)")
        query.exec("INSERT INTO people(name, city) VALUES('Juan', 2)")
        query.exec("INSERT INTO city(name) VALUES('Seattle')")
        query.exec("INSERT INTO city(name) VALUES('Tokyo')")
      
      
      def main():
        app = QApplication(sys.argv)
        dbConnect()
        createFakeData()
        w = MainWindow()
        w.show()
        app.exec()
      
      if __name__ == '__main__':
          main()
      
      
      J Offline
      J Offline
      JonB
      wrote on 7 Apr 2024, 07:24 last edited by JonB 4 Jul 2024, 07:31
      #2

      @peterloron said in insertRecord failure with QSqlRelationalTableModel:

      query.exec("INSERT INTO people(name, city) VALUES('Helen', 1)")

      This is the first statement you execute when both tables are empty. At this point there is no row in city which has value 1 in its id column. That is where

      NOT NULL constraint failed: people.city Unable to fetch row
      

      comes from as Qt tries to insert the row/fetch it back.

      Switch the order in your code so that it puts rows into city table before it puts rows into people.

      If the error comes during onAddRow(), make sure city table has a row with value of 2 and has been read into memory.

      1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on 7 Apr 2024, 12:38 last edited by
        #3

        Hi and welcome to devnet,

        As @JonB suggested, the order of table setup in a database is crucial. You can't use a relation if the target of the relation does not exist. Start by building all the leaf tables and then go back up creating the one that uses then and so on and so forth.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        J 1 Reply Last reply 7 Apr 2024, 13:15
        0
        • SGaistS SGaist
          7 Apr 2024, 12:38

          Hi and welcome to devnet,

          As @JonB suggested, the order of table setup in a database is crucial. You can't use a relation if the target of the relation does not exist. Start by building all the leaf tables and then go back up creating the one that uses then and so on and so forth.

          J Offline
          J Offline
          JonB
          wrote on 7 Apr 2024, 13:15 last edited by
          #4

          @SGaist
          That is what is thought/wrote initially. But the OP wrote "insertRecord failure". If that comes in onAddRow() that is after the population, and he does have self.model.select() there, so I am not sure. He should verify what that select() puts into the the city table.

          SGaistS 1 Reply Last reply 7 Apr 2024, 19:04
          0
          • J JonB
            7 Apr 2024, 13:15

            @SGaist
            That is what is thought/wrote initially. But the OP wrote "insertRecord failure". If that comes in onAddRow() that is after the population, and he does have self.model.select() there, so I am not sure. He should verify what that select() puts into the the city table.

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on 7 Apr 2024, 19:04 last edited by
            #5

            @JonB one of the issue is that the database initialization is not done in the correct order and assumes the values of the cities ID.

            All in all, it should use a Foreign Key to properly map the city to the user. This would properly structure the relation between the tables.

            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
            0

            1/5

            7 Apr 2024, 02:30

            • Login

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