Details
-
Bug
-
Resolution: Out of scope
-
P4: Low
-
4.5.2
-
None
Description
Platform
Linux
Platform details
cat /proc/version
Linux version 2.6.28 (root@tux) (gcc version 4.3.2 (GCC) ) #2 SMP PREEMPT Sun Apr 19 17:33:52 CEST 2009
glibc 2.7
gcc 4.3.3
uname -m
i686
Compilers
GCC
Compiler details
gcc version 4.3.3
Steps to reproduce / test case
Given is a small database schema consisting of three tables. First table ("products") consists of two columns "id" and "name". "id" is the primary key. The second table ("parts") looks exactly the same. The third table ("parts_used_by_product") is used to model a n:m relation between both tables. It consists of two columns which together form the primary key of that table and are each a foreign key to "products" and to "parts". See "dbschema.sql" in the attached example for details. If an instance of QSqlRelationalTableModel is used on the table "parts_used_by_products", and via QSqlRelation the second column is mapped to the table "parts", a call to "removeRow()" of that model will fail. Even worse, the call returns true, but does not remove the record from the database. On stderr the program writes:
"QSqlQuery::value: not positioned on a valid record"
If the QSqlRelationalTableModel instance is replaced with an instance of QSqlTable model, everything works fine. I tried it with a sqlite3 database and also with a postgres 8.3 database, with the same result so I dont't think there's a problem with the used DBMS. Please see the attached example program for better understanding.
There might be a problem in "qsqltablemodel.cpp" in line 236. Snipped is from Qt 4.5.2 as shipped with qtsdk 2009.03.
QSqlRecord QSqlTableModelPrivate::primaryValues(int row) { QSqlRecord record; if (!query.seek(row)) { error = query.lastError(); return record; } if (primaryIndex.isEmpty()) { record = rec; for (int i = 0; i < record.count(); ++i) record.setValue(i, query.value(i)); } else { record = primaryIndex; for (int i = 0; i < record.count(); ++i) record.setValue(i, query.value(rec.indexOf(record.fieldName(i)))); <------236 } return record; }
There seem to be two problems:
- "record" containts the field names "products_id" and "parts_id", but "rec" contains "products_id" and "name". So the value for
the second field is always an empty QVariant which leads later to a SQL command like this: "DELETE FROM parts_used_by_product WHERE products_id = 1 AND parts_id IS NULL;" This statement will not delete any rows ever, because parts_id is never NULL. - "query" contains not the two numeric fields from table "parts_used_by_product" but the first numeric column and the textual replacement for the second column defined via the QSqlRelation. So even if first is fixed, the call to "removeRows()" would still fail.
The SQL used by "query" for reference:
SELECT "parts_used_by_product"."products_id", "relTblAl_1"."name" FROM "parts_used_by_product", "parts" "relTblAl_1" WHERE ("parts_used_by_product"."parts_id" = "relTblAl_1"."id") AND (products_id = 1)