0

I want to send QSqlQueryModel to the another client with QDatastream and QTcpSocket. I want to remove some rows and add few extra rows to QSqlQueryModel (without changing the database) and send it to the client like this pseudocode:-

QTcpSocket socket;
socket.setSocketDescriptor(handle);
socket.waitForReadyRead(WAIT_TIME);

QByteArray req = socket->readAll();
QDataStream reqstream(&req,QIODevice::ReadOnly);

QSqlQueryModel MyModel;
....
// fetch data with MyModel
// add/remove some rows from that model without adding/removing them from actual database
....

QByteArray res;
QDataStream resstream(&res,QIODevice::WriteOnly);
resstrem << MyModel;
socket.write(res);

How can I achieve this without creating new deep copy of Model. On the client side, it should only receive a model with data so I can show it in QML.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
LightSith
  • 795
  • 12
  • 27
  • What do you mean by *without creating new deep copy*? – eyllanesc Feb 06 '20 at 15:43
  • @eyllanesc I mean not using for loop to copy all records in new QList. something like this:- https://media.geeksforgeeks.org/wp-content/uploads/copy-constructor1.png – LightSith Feb 06 '20 at 16:44
  • 1
    @尤金寶 漢子 you can't send Qt object through TCP. You can send only some data. In `QSqlQueryModel` data (item) is in indexes. Each index has row and column. You can't get every index without loop. You'll need build map or something for send your model copy. You can inherit from `QSqlQueryModel` and overload `data()` method to build map for send, but I think that all you can do with it. Ther easeast way to do this is to write `QSqlQuery`. – Shtol Krakov Feb 10 '20 at 17:08

2 Answers2

1

You cannot do what you want in Qt, or anything else for that matter without creating a "deep copy."

If you are using a real database, not SQLite or some other low end storage method which doesn't use a database engine, you can do what you want without doing the transfer. Read up on temporary tables for your chosen database. You can SELECT INTO a temporary table. This is much more efficient because a database with an active engine will just create a cursor of pointers but treat it like a real table. If the resulting cursor is too big for RAM it will write it to some temporary scratch area.

After that just have your client tell the server app to DROP the rows you want to remove from the temporary table and INSERT the rows you want to add. Just have to be certain your server operates on the temporary table from that point on.

NOTE: if you are working from a really bad spreadsheet example which binds a data result to a spreadsheet from within the GUI thread, you can't fix that. Every official example I've found on-line is really bad. Never ever do database I/O in the primary event loop.

You might want to get a copy of this book as well. It will not contain the answer to this question but it does contain many working database examples.

user3450148
  • 851
  • 5
  • 13
1

The purpose of any descendant of QAbstractItemModel is to adopt some data to views (widgets) which can present them.

So basically you are trying do something what is outside of design of this class. Its like trying to hit the nail with a shovel. It is possible, but dangerous and not recommended.

Just read debase data using QSqlQuery (use hammer) iterate over a rows read columns and store them in some serialization format. You can use QDataStream for that:

    QDataStream out{&socket};

    QSqlQuery query{"SELECT country FROM artist"};
    while (query.next()) {
        out << query.value(0).toString();
    }

It is possible to make this asynchronous.

Marek R
  • 32,568
  • 6
  • 55
  • 140