src/sql/models/qsqlrelationaltablemodel.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtSql module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qsqlrelationaltablemodel.h"
       
    43 
       
    44 #include "qhash.h"
       
    45 #include "qstringlist.h"
       
    46 #include "qsqldatabase.h"
       
    47 #include "qsqldriver.h"
       
    48 #include "qsqlerror.h"
       
    49 #include "qsqlfield.h"
       
    50 #include "qsqlindex.h"
       
    51 #include "qsqlquery.h"
       
    52 #include "qsqlrecord.h"
       
    53 
       
    54 #include "qsqltablemodel_p.h"
       
    55 
       
    56 #include "qdebug.h"
       
    57 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 /*!
       
    61     \class QSqlRelation
       
    62     \brief The QSqlRelation class stores information about an SQL foreign key.
       
    63 
       
    64     QSqlRelation is a helper class for QSqlRelationalTableModel. See
       
    65     QSqlRelationalTableModel::setRelation() and
       
    66     QSqlRelationalTableModel::relation() for details.
       
    67 
       
    68     \sa QSqlRelationalTableModel, QSqlRelationalDelegate,
       
    69         {Relational Table Model Example}
       
    70 */
       
    71 
       
    72 /*!
       
    73     \fn QSqlRelation::QSqlRelation()
       
    74 
       
    75     Constructs an invalid QSqlRelation object.
       
    76 
       
    77     For such an object, the tableName(), indexColumn(), and
       
    78     displayColumn() functions return an empty string.
       
    79 
       
    80     \sa isValid()
       
    81 */
       
    82 
       
    83 /*!
       
    84     \fn QSqlRelation::QSqlRelation(const QString &tableName, const QString &indexColumn,
       
    85                                    const QString &displayColumn)
       
    86 
       
    87     Constructs a QSqlRelation object, where \a tableName is the SQL
       
    88     table name to which a foreign key refers, \a indexColumn is the
       
    89     foreign key, and \a displayColumn is the field that should be
       
    90     presented to the user.
       
    91 
       
    92     \sa tableName(), indexColumn(), displayColumn()
       
    93 */
       
    94 
       
    95 /*!
       
    96     \fn QString QSqlRelation::tableName() const
       
    97 
       
    98     Returns the name of the table to which a foreign key refers.
       
    99 */
       
   100 
       
   101 /*!
       
   102     \fn QString QSqlRelation::indexColumn() const
       
   103 
       
   104     Returns the index column from table tableName() to which a
       
   105     foreign key refers.
       
   106 */
       
   107 
       
   108 /*!
       
   109     \fn QString QSqlRelation::displayColumn() const
       
   110 
       
   111     Returns the column from table tableName() that should be
       
   112     presented to the user instead of a foreign key.
       
   113 */
       
   114 
       
   115 /*!
       
   116     \fn bool QSqlRelation::isValid() const
       
   117 
       
   118     Returns true if the QSqlRelation object is valid; otherwise
       
   119     returns false.
       
   120 */
       
   121 
       
   122 struct QRelation
       
   123 {
       
   124     public:
       
   125         QRelation(): model(0),m_parent(0),m_dictInitialized(false){}
       
   126         void init(QSqlRelationalTableModel *parent, const QSqlRelation &relation);
       
   127 
       
   128         void populateModel();
       
   129 
       
   130         bool isDictionaryInitialized();
       
   131         void populateDictionary();
       
   132         void clearDictionary();
       
   133 
       
   134         void clear();
       
   135         bool isValid();
       
   136 
       
   137         QSqlRelation rel;
       
   138         QSqlTableModel *model;
       
   139         QHash<QString, QVariant> dictionary;//maps keys to display values
       
   140 
       
   141     private:
       
   142         QSqlRelationalTableModel *m_parent;
       
   143         bool m_dictInitialized;
       
   144 };
       
   145 
       
   146 /*
       
   147     A QRelation must be initialized before it is considered valid.
       
   148     Note: population of the model and dictionary are kept separate
       
   149           from initialization, and are populated on an as needed basis.
       
   150 */
       
   151 void QRelation::init(QSqlRelationalTableModel *parent, const QSqlRelation &relation)
       
   152 {
       
   153     Q_ASSERT(parent != NULL);
       
   154     m_parent = parent;
       
   155     rel = relation;
       
   156 }
       
   157 
       
   158 void QRelation::populateModel()
       
   159 {
       
   160     if (!isValid())
       
   161         return;
       
   162     Q_ASSERT(m_parent != NULL);
       
   163 
       
   164     if (!model) {
       
   165         model = new QSqlTableModel(m_parent, m_parent->database());
       
   166         model->setTable(rel.tableName());
       
   167         model->select();
       
   168     }
       
   169 }
       
   170 
       
   171 bool QRelation::isDictionaryInitialized()
       
   172 {
       
   173     return m_dictInitialized;
       
   174 }
       
   175 
       
   176 void QRelation::populateDictionary()
       
   177 {
       
   178     if (!isValid())
       
   179         return;
       
   180 
       
   181     if (model ==  NULL)
       
   182         populateModel();
       
   183 
       
   184     QSqlRecord record;
       
   185     QString indexColumn;
       
   186     QString displayColumn;
       
   187     for (int i=0; i < model->rowCount(); ++i) {
       
   188         record = model->record(i);
       
   189 
       
   190         indexColumn = rel.indexColumn();
       
   191         if (m_parent->database().driver()->isIdentifierEscaped(indexColumn, QSqlDriver::FieldName))
       
   192             indexColumn = m_parent->database().driver()->stripDelimiters(indexColumn, QSqlDriver::FieldName);
       
   193 
       
   194         displayColumn = rel.displayColumn();
       
   195         if (m_parent->database().driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName))
       
   196             displayColumn = m_parent->database().driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName);
       
   197 
       
   198         dictionary[record.field(indexColumn).value().toString()] =
       
   199             record.field(displayColumn).value();
       
   200     }
       
   201     m_dictInitialized = true;
       
   202 }
       
   203 
       
   204 void QRelation::clearDictionary()
       
   205 {
       
   206     dictionary.clear();
       
   207     m_dictInitialized = false;
       
   208 }
       
   209 
       
   210 void QRelation::clear()
       
   211 {
       
   212     delete model;
       
   213     model = 0;
       
   214     clearDictionary();
       
   215 }
       
   216 
       
   217 bool QRelation::isValid()
       
   218 {
       
   219     return (rel.isValid() && m_parent != NULL);
       
   220 }
       
   221 
       
   222 class QSqlRelationalTableModelPrivate: public QSqlTableModelPrivate
       
   223 {
       
   224     Q_DECLARE_PUBLIC(QSqlRelationalTableModel)
       
   225 public:
       
   226     QSqlRelationalTableModelPrivate()
       
   227         : QSqlTableModelPrivate()
       
   228     {}
       
   229     QString relationField(const QString &tableName, const QString &fieldName) const;
       
   230 
       
   231     int nameToIndex(const QString &name) const;
       
   232     mutable QVector<QRelation> relations;
       
   233     QSqlRecord baseRec; // the record without relations
       
   234     void clearChanges();
       
   235     void clearEditBuffer();
       
   236     void clearCache();
       
   237     void revertCachedRow(int row);
       
   238 
       
   239     void translateFieldNames(int row, QSqlRecord &values) const;
       
   240 };
       
   241 
       
   242 static void qAppendWhereClause(QString &query, const QString &clause1, const QString &clause2)
       
   243 {
       
   244     if (clause1.isEmpty() && clause2.isEmpty())
       
   245         return;
       
   246     if (clause1.isEmpty() || clause2.isEmpty())
       
   247         query.append(QLatin1String(" WHERE (")).append(clause1).append(clause2);
       
   248     else
       
   249         query.append(QLatin1String(" WHERE (")).append(clause1).append(
       
   250                         QLatin1String(") AND (")).append(clause2);
       
   251     query.append(QLatin1String(") "));
       
   252 }
       
   253 
       
   254 void QSqlRelationalTableModelPrivate::clearChanges()
       
   255 {
       
   256     for (int i = 0; i < relations.count(); ++i) {
       
   257         QRelation &rel = relations[i];
       
   258         rel.clear();
       
   259     }
       
   260 }
       
   261 
       
   262 void QSqlRelationalTableModelPrivate::revertCachedRow(int row)
       
   263 {
       
   264     QSqlTableModelPrivate::revertCachedRow(row);
       
   265 }
       
   266 
       
   267 int QSqlRelationalTableModelPrivate::nameToIndex(const QString &name) const
       
   268 {
       
   269     QString fieldname = name;
       
   270     if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName))
       
   271         fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName);
       
   272     return baseRec.indexOf(fieldname);
       
   273 }
       
   274 
       
   275 void QSqlRelationalTableModelPrivate::clearEditBuffer()
       
   276 {
       
   277     editBuffer = baseRec;
       
   278 }
       
   279 
       
   280 /*!
       
   281     \reimp
       
   282 */
       
   283 void QSqlRelationalTableModelPrivate::clearCache()
       
   284 {
       
   285     for (int i = 0; i < relations.count(); ++i)
       
   286         relations[i].clearDictionary();
       
   287 
       
   288     QSqlTableModelPrivate::clearCache();
       
   289 }
       
   290 
       
   291 /*!
       
   292     \class QSqlRelationalTableModel
       
   293     \brief The QSqlRelationalTableModel class provides an editable
       
   294     data model for a single database table, with foreign key support.
       
   295 
       
   296     \ingroup database
       
   297     \inmodule QtSql
       
   298 
       
   299     QSqlRelationalTableModel acts like QSqlTableModel, but allows
       
   300     columns to be set as foreign keys into other database tables.
       
   301 
       
   302     \table
       
   303     \row \o \inlineimage noforeignkeys.png
       
   304          \o \inlineimage foreignkeys.png
       
   305     \endtable
       
   306 
       
   307     The screenshot on the left shows a plain QSqlTableModel in a
       
   308     QTableView. Foreign keys (\c city and \c country) aren't resolved
       
   309     to human-readable values. The screenshot on the right shows a
       
   310     QSqlRelationalTableModel, with foreign keys resolved into
       
   311     human-readable text strings.
       
   312 
       
   313     The following code snippet shows how the QSqlRelationalTableModel
       
   314     was set up:
       
   315 
       
   316     \snippet examples/sql/relationaltablemodel/relationaltablemodel.cpp 0
       
   317     \codeline
       
   318     \snippet examples/sql/relationaltablemodel/relationaltablemodel.cpp 1
       
   319     \snippet examples/sql/relationaltablemodel/relationaltablemodel.cpp 2
       
   320 
       
   321     The setRelation() function calls establish a relationship between
       
   322     two tables. The first call specifies that column 2 in table \c
       
   323     employee is a foreign key that maps with field \c id of table \c
       
   324     city, and that the view should present the \c{city}'s \c name
       
   325     field to the user. The second call does something similar with
       
   326     column 3.
       
   327 
       
   328     If you use a read-write QSqlRelationalTableModel, you probably
       
   329     want to use QSqlRelationalDelegate on the view. Unlike the default
       
   330     delegate, QSqlRelationalDelegate provides a combobox for fields
       
   331     that are foreign keys into other tables. To use the class, simply
       
   332     call QAbstractItemView::setItemDelegate() on the view with an
       
   333     instance of QSqlRelationalDelegate:
       
   334 
       
   335     \snippet examples/sql/relationaltablemodel/relationaltablemodel.cpp 4
       
   336 
       
   337     The \l{sql/relationaltablemodel} example illustrates how to use
       
   338     QSqlRelationalTableModel in conjunction with
       
   339     QSqlRelationalDelegate to provide tables with foreigh key
       
   340     support.
       
   341 
       
   342     \image relationaltable.png
       
   343 
       
   344     Notes:
       
   345 
       
   346     \list
       
   347     \o The table must have a primary key declared.
       
   348     \o The table's primary key may not contain a relation to
       
   349        another table.
       
   350     \o If a relational table contains keys that refer to non-existent
       
   351        rows in the referenced table, the rows containing the invalid
       
   352        keys will not be exposed through the model. The user or the
       
   353        database is responsible for keeping referential integrity.
       
   354     \o If a relation's display column name is also used as a column
       
   355        name in the main table, or if it is used as display column
       
   356        name in more than one relation it will be aliased. The alias is
       
   357        is the relation's table name and display column name joined
       
   358        by an underscore (e.g. tablename_columnname). All occurrences
       
   359        of the duplicate display column name are aliased when
       
   360        duplication is detected, but no aliasing is done to the column
       
   361        names in the main table. The aliasing doesn't affect
       
   362        QSqlRelation, so QSqlRelation::displayColumn() will return the
       
   363        original display column name, but QSqlRecord::fieldName() will
       
   364        return aliases.
       
   365     \o When using setData() the role should always be Qt::EditRole,
       
   366        and when using data() the role should always be Qt::DisplayRole.
       
   367     \endlist
       
   368 
       
   369     \sa QSqlRelation, QSqlRelationalDelegate,
       
   370         {Relational Table Model Example}
       
   371 */
       
   372 
       
   373 
       
   374 /*!
       
   375     Creates an empty QSqlRelationalTableModel and sets the parent to \a parent
       
   376     and the database connection to \a db. If \a db is not valid, the
       
   377     default database connection will be used.
       
   378 */
       
   379 QSqlRelationalTableModel::QSqlRelationalTableModel(QObject *parent, QSqlDatabase db)
       
   380     : QSqlTableModel(*new QSqlRelationalTableModelPrivate, parent, db)
       
   381 {
       
   382 }
       
   383 
       
   384 /*!
       
   385     Destroys the object and frees any allocated resources.
       
   386 */
       
   387 QSqlRelationalTableModel::~QSqlRelationalTableModel()
       
   388 {
       
   389 }
       
   390 
       
   391 /*!
       
   392     \reimp
       
   393 */
       
   394 QVariant QSqlRelationalTableModel::data(const QModelIndex &index, int role) const
       
   395 {
       
   396     Q_D(const QSqlRelationalTableModel);
       
   397 
       
   398     if (role == Qt::DisplayRole && index.column() > 0 && index.column() < d->relations.count() &&
       
   399             d->relations.value(index.column()).isValid()) {
       
   400         QRelation &relation = d->relations[index.column()];
       
   401         if (!relation.isDictionaryInitialized())
       
   402             relation.populateDictionary();
       
   403 
       
   404         //only perform a dictionary lookup for the display value
       
   405         //when the value at index has been changed or added.
       
   406         //At an unmodified index, the underlying model will
       
   407         //already have the correct display value.
       
   408         QVariant v;
       
   409         switch (d->strategy) {
       
   410             case OnFieldChange:
       
   411                 break;
       
   412             case OnRowChange:
       
   413                 if (index.row() == d->editIndex || index.row() == d->insertIndex) {
       
   414                     v = d->editBuffer.value(index.column());
       
   415                 }
       
   416                 break;
       
   417             case OnManualSubmit:
       
   418                 const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
       
   419                 v = row.rec.value(index.column());
       
   420                 break;
       
   421         }
       
   422         if (v.isValid())
       
   423             return relation.dictionary[v.toString()];
       
   424     }
       
   425     return QSqlTableModel::data(index, role);
       
   426 }
       
   427 
       
   428 /*!
       
   429     Sets the data for the \a role in the item with the specified \a
       
   430     index to the \a value given. Depending on the edit strategy, the
       
   431     value might be applied to the database at once, or it may be
       
   432     cached in the model.
       
   433 
       
   434     Returns true if the value could be set, or false on error (for
       
   435     example, if \a index is out of bounds).
       
   436 
       
   437     For relational columns, \a value must be the index, not the
       
   438     display value. The index must also exist in the referenced
       
   439     table, otherwise the function returns false.
       
   440 
       
   441     \sa editStrategy(), data(), submit(), revertRow()
       
   442 */
       
   443 bool QSqlRelationalTableModel::setData(const QModelIndex &index, const QVariant &value,
       
   444                                        int role)
       
   445 {
       
   446     Q_D(QSqlRelationalTableModel);
       
   447     if ( role == Qt::EditRole && index.column() > 0 && index.column() < d->relations.count()
       
   448             && d->relations.value(index.column()).isValid()) {
       
   449         QRelation &relation = d->relations[index.column()];
       
   450         if (!relation.isDictionaryInitialized())
       
   451             relation.populateDictionary();
       
   452         if (!relation.dictionary.contains(value.toString()))
       
   453             return false;
       
   454     }
       
   455     return QSqlTableModel::setData(index, value, role);
       
   456 }
       
   457 
       
   458 /*!
       
   459     Lets the specified \a column be a foreign index specified by \a relation.
       
   460 
       
   461     Example:
       
   462 
       
   463     \snippet examples/sql/relationaltablemodel/relationaltablemodel.cpp 0
       
   464     \codeline
       
   465     \snippet examples/sql/relationaltablemodel/relationaltablemodel.cpp 1
       
   466 
       
   467     The setRelation() call specifies that column 2 in table \c
       
   468     employee is a foreign key that maps with field \c id of table \c
       
   469     city, and that the view should present the \c{city}'s \c name
       
   470     field to the user.
       
   471 
       
   472     Note: The table's primary key may not contain a relation to another table.
       
   473 
       
   474     \sa relation()
       
   475 */
       
   476 void QSqlRelationalTableModel::setRelation(int column, const QSqlRelation &relation)
       
   477 {
       
   478     Q_D(QSqlRelationalTableModel);
       
   479     if (column < 0)
       
   480         return;
       
   481     if (d->relations.size() <= column)
       
   482         d->relations.resize(column + 1);
       
   483     d->relations[column].init(this, relation);
       
   484 }
       
   485 
       
   486 /*!
       
   487     Returns the relation for the column \a column, or an invalid
       
   488     relation if no relation is set.
       
   489 
       
   490     \sa setRelation(), QSqlRelation::isValid()
       
   491 */
       
   492 QSqlRelation QSqlRelationalTableModel::relation(int column) const
       
   493 {
       
   494     Q_D(const QSqlRelationalTableModel);
       
   495     return d->relations.value(column).rel;
       
   496 }
       
   497 
       
   498 QString QSqlRelationalTableModelPrivate::relationField(const QString &tableName,
       
   499                         const QString &fieldName) const
       
   500 {
       
   501     QString ret;
       
   502     ret.reserve(tableName.size() + fieldName.size() + 1);
       
   503     ret.append(tableName).append(QLatin1Char('.')).append(fieldName);
       
   504 
       
   505     return ret;
       
   506 }
       
   507 
       
   508 /*!
       
   509     \reimp
       
   510 */
       
   511 QString QSqlRelationalTableModel::selectStatement() const
       
   512 {
       
   513     Q_D(const QSqlRelationalTableModel);
       
   514     QString query;
       
   515 
       
   516     if (tableName().isEmpty())
       
   517         return query;
       
   518     if (d->relations.isEmpty())
       
   519         return QSqlTableModel::selectStatement();
       
   520 
       
   521     QString tList;
       
   522     QString fList;
       
   523     QString where;
       
   524 
       
   525     QSqlRecord rec = d->baseRec;
       
   526     QStringList tables;
       
   527     const QRelation nullRelation;
       
   528 
       
   529     // Count how many times each field name occurs in the record
       
   530     QHash<QString, int> fieldNames;
       
   531     QStringList fieldList;
       
   532     for (int i = 0; i < rec.count(); ++i) {
       
   533         QSqlRelation relation = d->relations.value(i, nullRelation).rel;
       
   534         QString name;
       
   535         if (relation.isValid())
       
   536         {
       
   537             // Count the display column name, not the original foreign key
       
   538             name = relation.displayColumn();
       
   539             if (d->db.driver()->isIdentifierEscaped(name, QSqlDriver::FieldName))
       
   540                 name = d->db.driver()->stripDelimiters(name, QSqlDriver::FieldName);
       
   541 
       
   542             QSqlRecord rec = database().record(relation.tableName());
       
   543             for (int i = 0; i < rec.count(); ++i) {
       
   544                 if (name.compare(rec.fieldName(i), Qt::CaseInsensitive) == 0) {
       
   545                     name = rec.fieldName(i);
       
   546                     break;
       
   547                 }
       
   548             }
       
   549         }
       
   550         else
       
   551             name = rec.fieldName(i);
       
   552         fieldNames.insert(name, fieldNames.value(name, 0) + 1);
       
   553         fieldList.append(name);
       
   554     }
       
   555 
       
   556     for (int i = 0; i < rec.count(); ++i) {
       
   557         QSqlRelation relation = d->relations.value(i, nullRelation).rel;
       
   558         if (relation.isValid()) {
       
   559             QString relTableAlias = QString::fromLatin1("relTblAl_%1").arg(i);
       
   560             if (!fList.isEmpty())
       
   561                 fList.append(QLatin1String(", "));
       
   562             fList.append(d->relationField(relTableAlias,relation.displayColumn()));
       
   563 
       
   564             // If there are duplicate field names they must be aliased
       
   565             if (fieldNames.value(fieldList[i]) > 1) {
       
   566                 QString relTableName = relation.tableName();
       
   567                 if (d->db.driver()->isIdentifierEscaped(relTableName, QSqlDriver::TableName))
       
   568                     relTableName = d->db.driver()->stripDelimiters(relTableName, QSqlDriver::TableName);
       
   569                 QString displayColumn = relation.displayColumn();
       
   570                 if (d->db.driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName))
       
   571                     displayColumn = d->db.driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName);
       
   572                 fList.append(QString::fromLatin1(" AS %1_%2_%3").arg(relTableName).arg(displayColumn).arg(fieldNames.value(fieldList[i])));
       
   573                 fieldNames.insert(fieldList[i], fieldNames.value(fieldList[i])-1);
       
   574             }
       
   575 
       
   576             // this needs fixing!! the below if is borken.
       
   577             tables.append(relation.tableName().append(QLatin1Char(' ')).append(relTableAlias));
       
   578             if(!where.isEmpty())
       
   579                 where.append(QLatin1String(" AND "));
       
   580             where.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName)));
       
   581             where.append(QLatin1String(" = "));
       
   582             where.append(d->relationField(relTableAlias, relation.indexColumn()));
       
   583         } else {
       
   584             if (!fList.isEmpty())
       
   585                 fList.append(QLatin1String(", "));
       
   586             fList.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName)));
       
   587         }
       
   588     }
       
   589     if (!tables.isEmpty())
       
   590         tList.append(tables.join(QLatin1String(", ")));
       
   591     if (fList.isEmpty())
       
   592         return query;
       
   593     if(!tList.isEmpty())
       
   594         tList.prepend(QLatin1String(", "));
       
   595     tList.prepend(tableName());
       
   596     query.append(QLatin1String("SELECT "));
       
   597     query.append(fList).append(QLatin1String(" FROM ")).append(tList);
       
   598     qAppendWhereClause(query, where, filter());
       
   599 
       
   600     QString orderBy = orderByClause();
       
   601     if (!orderBy.isEmpty())
       
   602         query.append(QLatin1Char(' ')).append(orderBy);
       
   603 
       
   604     return query;
       
   605 }
       
   606 
       
   607 /*!
       
   608     Returns a QSqlTableModel object for accessing the table for which
       
   609     \a column is a foreign key, or 0 if there is no relation for the
       
   610     given \a column.
       
   611 
       
   612     The returned object is owned by the QSqlRelationalTableModel.
       
   613 
       
   614     \sa setRelation(), relation()
       
   615 */
       
   616 QSqlTableModel *QSqlRelationalTableModel::relationModel(int column) const
       
   617 {
       
   618     Q_D(const QSqlRelationalTableModel);
       
   619     if ( column < 0 || column >= d->relations.count())
       
   620         return 0;
       
   621 
       
   622     QRelation &relation = const_cast<QSqlRelationalTableModelPrivate *>(d)->relations[column];
       
   623     if (!relation.isValid())
       
   624         return 0;
       
   625 
       
   626     if (!relation.model)
       
   627         relation.populateModel();
       
   628     return relation.model;
       
   629 }
       
   630 
       
   631 /*!
       
   632     \reimp
       
   633 */
       
   634 void QSqlRelationalTableModel::revertRow(int row)
       
   635 {
       
   636     QSqlTableModel::revertRow(row);
       
   637 }
       
   638 
       
   639 /*!
       
   640     \reimp
       
   641 */
       
   642 void QSqlRelationalTableModel::clear()
       
   643 {
       
   644     Q_D(QSqlRelationalTableModel);
       
   645     d->clearChanges();
       
   646     d->relations.clear();
       
   647     QSqlTableModel::clear();
       
   648 }
       
   649 
       
   650 /*!
       
   651     \reimp
       
   652 */
       
   653 bool QSqlRelationalTableModel::select()
       
   654 {
       
   655     return QSqlTableModel::select();
       
   656 }
       
   657 
       
   658 /*!
       
   659     \reimp
       
   660 */
       
   661 void QSqlRelationalTableModel::setTable(const QString &table)
       
   662 {
       
   663     Q_D(QSqlRelationalTableModel);
       
   664 
       
   665     // memorize the table before applying the relations
       
   666     d->baseRec = d->db.record(table);
       
   667 
       
   668     QSqlTableModel::setTable(table);
       
   669 }
       
   670 
       
   671 /*! \internal
       
   672  */
       
   673 void QSqlRelationalTableModelPrivate::translateFieldNames(int row, QSqlRecord &values) const
       
   674 {
       
   675     Q_Q(const QSqlRelationalTableModel);
       
   676 
       
   677     for (int i = 0; i < values.count(); ++i) {
       
   678         int realCol = q->indexInQuery(q->createIndex(row, i)).column();
       
   679         if (realCol != -1 && relations.value(realCol).isValid()) {
       
   680             QVariant v = values.value(i);
       
   681             values.replace(i, baseRec.field(realCol));
       
   682             values.setValue(i, v);
       
   683         }
       
   684     }
       
   685 }
       
   686 
       
   687 /*!
       
   688     \reimp
       
   689 */
       
   690 bool QSqlRelationalTableModel::updateRowInTable(int row, const QSqlRecord &values)
       
   691 {
       
   692     Q_D(QSqlRelationalTableModel);
       
   693 
       
   694     QSqlRecord rec = values;
       
   695     d->translateFieldNames(row, rec);
       
   696 
       
   697     return QSqlTableModel::updateRowInTable(row, rec);
       
   698 }
       
   699 
       
   700 /*!
       
   701     \reimp
       
   702 */
       
   703 bool QSqlRelationalTableModel::insertRowIntoTable(const QSqlRecord &values)
       
   704 {
       
   705     Q_D(QSqlRelationalTableModel);
       
   706 
       
   707     QSqlRecord rec = values;
       
   708     d->translateFieldNames(0, rec);
       
   709 
       
   710     return QSqlTableModel::insertRowIntoTable(rec);
       
   711 }
       
   712 
       
   713 /*!
       
   714     \reimp
       
   715 */
       
   716 QString QSqlRelationalTableModel::orderByClause() const
       
   717 {
       
   718     Q_D(const QSqlRelationalTableModel);
       
   719 
       
   720     const QSqlRelation rel = d->relations.value(d->sortColumn).rel;
       
   721     if (!rel.isValid())
       
   722         return QSqlTableModel::orderByClause();
       
   723 
       
   724     QString s = QLatin1String("ORDER BY ");
       
   725     s.append(d->relationField(QLatin1String("relTblAl_") + QString::number(d->sortColumn),
       
   726                     rel.displayColumn()));
       
   727     s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC");
       
   728     return s;
       
   729 }
       
   730 
       
   731 /*!
       
   732     \reimp
       
   733 */
       
   734 bool QSqlRelationalTableModel::removeColumns(int column, int count, const QModelIndex &parent)
       
   735 {
       
   736     Q_D(QSqlRelationalTableModel);
       
   737 
       
   738     if (parent.isValid() || column < 0 || column + count > d->rec.count())
       
   739         return false;
       
   740 
       
   741     for (int i = 0; i < count; ++i) {
       
   742         d->baseRec.remove(column);
       
   743         if (d->relations.count() > column)
       
   744             d->relations.remove(column);
       
   745     }
       
   746     return QSqlTableModel::removeColumns(column, count, parent);
       
   747 }
       
   748 
       
   749 QT_END_NAMESPACE