PDA

View Full Version : QSqlRecord becoming invalid



mikro
2nd October 2006, 22:51
hi,
i have subclassed QAbstractTableModel to make a model that works easily with tables that have a primary key. in the beginning i fill a QMap with the contents of the table like this:


void IndexedTableModel::setTable(QString mtable) {
this->table = mtable;
tableData.clear();
// try to find an index:
QSqlIndex idx = db.driver()->primaryIndex (table);
Q_ASSERT(idx.count() == 1);
indexColumn = idx.fieldName(0);

QString sql = "SELECT * FROM " + table;
QSqlQuery query(sql);
int row=0;
while (query.next()) {
QSqlRecord rec = query.record();
int idxval = rec.field(indexColumn).value().toInt();

// as the rownumber can be unlike the value of the primary key
// i store the information in a map:
RowContent[row] = idxval;

tableData[row] = rec;
row++;
}
}


as long as every cell in the table has a content everything works fine, i read the stuff into the model and can edit it. The problem happens when i come across a row that does not have any data apart from that in the primary key column. i had some debugging input at the end of the above function that assured me that tableData[row].count() is 3 as expected.
but when i try to edit one of the empty cells my function to find the QSqlField for this cell called from setData() bails out:



QSqlField IndexedTableModel::FieldToIndex(const QModelIndex &index) {
int row = index.row();
int col = index.column();
int idx = RowContent[row];
qDebug() << "searching for row " << row << " column " << col << " index " << idx;

if (!index.isValid()) {
qDebug() << "..index was invalid ";
return QSqlField();
}
QSqlRecord rec = tableData[idx];
if (rec.count() <= col) {
qDebug() << "..the record has only " << rec.count() << " columns " << " but you want column " << col;
return QSqlField();
} else {
return rec.field(col);
}
}

will tell me that the record has 0 columns. Anybody knows why?

wysota
2nd October 2006, 23:13
Maybe a bit offtopic, but aren't you trying to double the functionality of QSqlTableModel?

mikro
2nd October 2006, 23:29
maybe ;)
but it seemed to me that QSqlTableModel would not use the indexes as hoped for. :o
i just had some problemes with the models that were there and thought it would be easy to create my own model. well it has once again taken me days for what are not more than 300 lines.. mainly because i came across problems like this on different occasions. also when i was trying to build some sql-statements using information from the Fields i would fail because of invalid fields coming from perfectly legal queries that simply returned some empty fields. For some time i had the theorie that QSqlRecord would have invalid fields wherever it encountered empty columns.
But then i realized that at the end of setTable() the tableData[row].count() was still > 0 only when i tried to access the record which i stored in tableData again later would its count() be 0.
how can this be?

wysota
3rd October 2006, 06:22
maybe ;)
but it seemed to me that QSqlTableModel would not use the indexes as hoped for. :o
Correct me if I'm wrong, but it is the database which should use indexes, not the model.


i just had some problemes with the models that were there and thought it would be easy to create my own model. well it has once again taken me days for what are not more than 300 lines.. mainly because i came across problems like this on different occasions.
Then maybe if QSqlTableModel doesn't fit you, you could subclass the table model and extend it with the functionality you want instead of subclassing an abstract model directly.


also when i was trying to build some sql-statements using information from the Fields i would fail because of invalid fields coming from perfectly legal queries that simply returned some empty fields. For some time i had the theorie that QSqlRecord would have invalid fields wherever it encountered empty columns.
But then i realized that at the end of setTable() the tableData[row].count() was still > 0 only when i tried to access the record which i stored in tableData again later would its count() be 0.
how can this be?

Hard to say. Could you provide a minimal compilable example which reproduces the problem (for example one that only uses QSqlQuery)?

mikro
3rd October 2006, 14:40
Correct me if I'm wrong, but it is the database which should use indexes, not the model.

yes, but the model should be aware of the existence of the indexes. The QSqlTableModel would always fail when trying to insert new rows because it didn't know that they need to have the autoincremented primary key. I would get new rows in my tableview but on trying to edit them it would fail because those empty rows could not be made to connect with the database which refused anything without a decent key.


Then maybe if QSqlTableModel doesn't fit you, you could subclass the table model and extend it with the functionality you want instead of subclassing an abstract model directly.
i don't know if that would have made my live easier - i assumed that i would have had to rewrite a lot of basic stuff (beginning with the setTable() -Method which obviously needed to keep track of which column held the primary key and in which row of the model i could find which index.) Therefore i deemed it easier to begin with a tabula rasa - having just the basic functionality in the class i am subclassing lessening the chance of incompatibilities between how the tablemodel wanted to access the table and how i thought it should.
Plus of course there is a nice example in the f...ine manual, so i could get started by just using this... always a big plus when you are still a beginner like me ;)


Hard to say. Could you provide a minimal compilable example which reproduces the problem (for example one that only uses QSqlQuery)?

well i did that and once i had a smaller project i started to realise some things... well as always it was my fault :o
now everyhing works. but as i made it anyway i'll attach the project that i created. Maybe someone can use this as a reference when he tries to create his own tablelike-database model. Just compile and run and point the fieldialog to the test.db in the datadirectory.

mikro
3rd October 2006, 18:00
bugfix: wouldn't know the columns unless there allready were some data in the table