развитие QSqlRecord

Нас самом деле делать наследника от QSqlRecord нет никакой необходимости.

Но тем не менее на начальном этапе мы попробовали это сделать и потом убедились, что это лишнее.

QSqlRecord это самостоятельный класс, без родителя. По сути это удобная обертка над полями одной строки.

Заполнение информации в QSqlRecord  происходит в классе модели данных QSqlQueryModel, а именно в функции record.

Получив QSqlRecord по номеру строки из модели данных его можно копировать, сравнивать с другим QSqlRecord, присваивать, то есть удобно манипулировать данными строки..

То есть это все про удобство манипулирования строками.

После того как у нас произошло развитие класса модели данных QSqlTableModel в  PblSqlRelationalTabelModel показалось, что возникла необходимость форкнуть и класс QSqlRecord, чтобы исполЬзовать преимущества нового развития. Но это не так.

Дело в том, что QSqlRecord самодостаточен. Он содержит все поля строки, которые формирует selectStatement функция. А selectStatement принадлежит модели данных.

Примечание: как оказалось впоследствие на самом деле делать наследника от QSqlRecord нет никакой необходимости, смотрите последнюю версию sql форк.

Но тем не менее представляем наследника QSqlRecord: PblSqlRecord.

В PblSqlRecord нам надо содержать информацию о полях с внешней связью. Точнее какое дополнительное поле является id внешней связи для заданного номера поля (если конечно такое есть).

По сути PblSqlRecord добавляет карту QHash соответствия оригинальных relation полей и полей, где лежат их id связей. 

Может показаться, что добавлять служебную информацию надо как-то в конструкторах класса наследника PblSqlRecord. Но тогда в конструкторах нам нужен доступ к классу модели данных, то есть ссылку/указатель на него надо передавать в конструктор как параметр.

QSqlRecord();
QSqlRecord(const QSqlRecord& other);
QSqlRecord& operator=(const QSqlRecord& other);

Выше представлен стандартный набор конструкторов:правило 3.

Но на самом деле добавить карту соответствия полей можно в методе record модели данных, в котором единственно и происходит создание об'екта  QSqlRecord.

Вот функция record класса QSqlQueryModel.

QSqlRecord QSqlQueryModel::record(int row) const
{
    Q_D(const QSqlQueryModel);
    if (row < 0)
        return d->rec;

    QSqlRecord rec = d->rec; // вызывается конструктор копирования, d->rec пустой (это только набор полей)
for (int i = 0; i < rec.count(); i) rec.setValue(i, data(createIndex(row, i), Qt::EditRole)); return rec; }

Вопрос: как лучше поступить?

Можно полностью переопределить функцию record в нашем классе наследнике (PblSqlRelationalTableModel). И в PblSqlRelationalTableModel будет своя record, а QSqlQueryModel будет своя функция record .

Можно попытаться оставить QSqlQueryModel::record и как-то выкрутится через каст.Например подойдет вариант reinterpretet_cast:

PblSqlRecord pblRec = reinterpret_cast(QSqlQueryModel::record(row));

Далее надо после reinterpret_cast все данные экземпляра PblSqlRecord не забыть проинициализировать.

И еще есть третий вариант, как нам кажется более логичный и правильный, но строчек кода будет побольше. Во первый надо переопределить конструктор копирования с не тривиальным передаваемым параметром (ссылка на объект копирования предка). А именно речь об этом
PblSqlRecord(const QSqlRecord& other);

class Q_SQL_EXPORT PblSqlRecord: public QSqlRecord
{
public:
    PblSqlRecord();
    PblSqlRecord(const PblSqlRecord& other);    // конструктор копирования стандартный
    PblSqlRecord(const QSqlRecord& other);      // конструктор копирования не стандартный (для функции record)
    
    PblSqlRecord& operator=(const PblSqlRecord& other);

Именно в этом случае мы сможет выполнить строку кода:

PblSqlRecord pblRec(QSqlQueryModel::record(row));

И все будет работать ОК. То есть получается, что мы передаем параметром в конструктор копирования ссылку на объект родителя, что нам и нужно.(см.конструкторы, деструкторы)

Как можно еще решить данную проблему - думаю уже достаточно вариантов и не будем до поры до времени об этом беспокоится.

Вообще-то напрашивается вариант конструктора перемещения, но это стандарт С11, в Qt 4.8.1 вроде бы ещё не используемый. Надо будет попробовать.