summaryrefslogtreecommitdiffstats
path: root/src/sql
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2012-04-10 12:48:01 +0200
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2012-04-10 15:31:45 +0200
commit143c4d3e13a430b951f4f4f8c28db14303f80605 (patch)
tree2b89637b93fc7d81c674106008566010f986d67c /src/sql
parenta7ed81b557d593a8ddb43b71bf4bbf3b44ead070 (diff)
parente5337ad1b1fb02873ce7b5ca8db45f6fd8063352 (diff)
Merge remote-tracking branch 'origin/master' into api_changes
Conflicts: configure src/widgets/styles/qwindowsxpstyle.cpp tests/auto/gui/kernel/qwindow/qwindow.pro tests/auto/gui/kernel/qwindow/tst_qwindow.cpp Change-Id: I624b6d26abce9874c610c04954c1c45bc074bef3
Diffstat (limited to 'src/sql')
-rw-r--r--src/sql/drivers/ibase/qsql_ibase.cpp2
-rw-r--r--src/sql/drivers/psql/qsql_psql.cpp99
-rw-r--r--src/sql/drivers/sqlite/qsql_sqlite.cpp4
-rw-r--r--src/sql/kernel/qsql.qdoc24
-rw-r--r--src/sql/kernel/qsqldriver.cpp5
-rw-r--r--src/sql/kernel/qsqldriver.h2
-rw-r--r--src/sql/kernel/qsqlresult.cpp77
-rw-r--r--src/sql/models/qsqlquerymodel.cpp3
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.cpp17
-rw-r--r--src/sql/models/qsqltablemodel.cpp2
10 files changed, 123 insertions, 112 deletions
diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp
index 0da7f05cbf..6f47903de7 100644
--- a/src/sql/drivers/ibase/qsql_ibase.cpp
+++ b/src/sql/drivers/ibase/qsql_ibase.cpp
@@ -1847,7 +1847,7 @@ void QIBaseDriver::qHandleEventNotification(void *updatedResultBuffer)
if (eBuffer->subscriptionState == QIBaseEventBuffer::Subscribed) {
emit notification(i.key());
- emit notification(i.key(), QSqlDriver::UnknownSource);
+ emit notification(i.key(), QSqlDriver::UnknownSource, QVariant());
}
else if (eBuffer->subscriptionState == QIBaseEventBuffer::Starting)
eBuffer->subscriptionState = QIBaseEventBuffer::Subscribed;
diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp
index edeb5d1542..7889311996 100644
--- a/src/sql/drivers/psql/qsql_psql.cpp
+++ b/src/sql/drivers/psql/qsql_psql.cpp
@@ -123,14 +123,21 @@ inline void qPQfreemem(void *buffer)
class QPSQLDriverPrivate
{
public:
- QPSQLDriverPrivate() : connection(0), isUtf8(false), pro(QPSQLDriver::Version6), sn(0) {}
+ QPSQLDriverPrivate(QPSQLDriver *qq) : q(qq), connection(0), isUtf8(false), pro(QPSQLDriver::Version6), sn(0), pendingNotifyCheck(false) {}
+ QPSQLDriver *q;
PGconn *connection;
bool isUtf8;
QPSQLDriver::Protocol pro;
QSocketNotifier *sn;
QStringList seid;
+ mutable bool pendingNotifyCheck;
void appendTables(QStringList &tl, QSqlQuery &t, QChar type);
+ PGresult * exec(const char * stmt) const;
+ PGresult * exec(const QString & stmt) const;
+ QPSQLDriver::Protocol getPSQLVersion();
+ bool setEncodingUtf8();
+ void setDatestyle();
};
void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
@@ -157,6 +164,21 @@ void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
}
}
+PGresult * QPSQLDriverPrivate::exec(const char * stmt) const
+{
+ PGresult *result = PQexec(connection, stmt);
+ if (seid.size() && !pendingNotifyCheck) {
+ pendingNotifyCheck = true;
+ QMetaObject::invokeMethod(q, "_q_handleNotification", Qt::QueuedConnection, Q_ARG(int,0));
+ }
+ return result;
+}
+
+PGresult * QPSQLDriverPrivate::exec(const QString & stmt) const
+{
+ return exec(isUtf8 ? stmt.toUtf8().constData() : stmt.toLocal8Bit().constData());
+}
+
class QPSQLResultPrivate
{
public:
@@ -251,9 +273,7 @@ static QVariant::Type qDecodePSQLType(int t)
static void qDeallocatePreparedStmt(QPSQLResultPrivate *d)
{
const QString stmt = QLatin1String("DEALLOCATE ") + d->preparedStmtId;
- PGresult *result = PQexec(d->driver->connection,
- d->driver->isUtf8 ? stmt.toUtf8().constData()
- : stmt.toLocal8Bit().constData());
+ PGresult *result = d->driver->exec(stmt);
if (PQresultStatus(result) != PGRES_COMMAND_OK)
qWarning("Unable to free statement: %s", PQerrorMessage(d->driver->connection));
@@ -431,9 +451,7 @@ bool QPSQLResult::reset (const QString& query)
return false;
if (!driver()->isOpen() || driver()->isOpenError())
return false;
- d->result = PQexec(d->driver->connection,
- d->driver->isUtf8 ? query.toUtf8().constData()
- : query.toLocal8Bit().constData());
+ d->result = d->driver->exec(query);
return d->processResults();
}
@@ -564,9 +582,7 @@ bool QPSQLResult::prepare(const QString &query)
const QString stmtId = qMakePreparedStmtId();
const QString stmt = QString::fromLatin1("PREPARE %1 AS ").arg(stmtId).append(qReplacePlaceholderMarkers(query));
- PGresult *result = PQexec(d->driver->connection,
- d->driver->isUtf8 ? stmt.toUtf8().constData()
- : stmt.toLocal8Bit().constData());
+ PGresult *result = d->driver->exec(stmt);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
@@ -595,26 +611,24 @@ bool QPSQLResult::exec()
else
stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId).arg(params);
- d->result = PQexec(d->driver->connection,
- d->driver->isUtf8 ? stmt.toUtf8().constData()
- : stmt.toLocal8Bit().constData());
+ d->result = d->driver->exec(stmt);
return d->processResults();
}
///////////////////////////////////////////////////////////////////
-static bool setEncodingUtf8(PGconn* connection)
+bool QPSQLDriverPrivate::setEncodingUtf8()
{
- PGresult* result = PQexec(connection, "SET CLIENT_ENCODING TO 'UNICODE'");
+ PGresult* result = exec("SET CLIENT_ENCODING TO 'UNICODE'");
int status = PQresultStatus(result);
PQclear(result);
return status == PGRES_COMMAND_OK;
}
-static void setDatestyle(PGconn* connection)
+void QPSQLDriverPrivate::setDatestyle()
{
- PGresult* result = PQexec(connection, "SET DATESTYLE TO 'ISO'");
+ PGresult* result = exec("SET DATESTYLE TO 'ISO'");
int status = PQresultStatus(result);
if (status != PGRES_COMMAND_OK)
qWarning("%s", PQerrorMessage(connection));
@@ -665,10 +679,10 @@ static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin)
return QPSQLDriver::VersionUnknown;
}
-static QPSQLDriver::Protocol getPSQLVersion(PGconn* connection)
+QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion()
{
QPSQLDriver::Protocol serverVersion = QPSQLDriver::Version6;
- PGresult* result = PQexec(connection, "select version()");
+ PGresult* result = exec("select version()");
int status = PQresultStatus(result);
if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) {
QString val = QString::fromAscii(PQgetvalue(result, 0, 0));
@@ -691,7 +705,7 @@ static QPSQLDriver::Protocol getPSQLVersion(PGconn* connection)
//Client version before QPSQLDriver::Version9 only supports escape mode for bytea type,
//but bytea format is set to hex by default in PSQL 9 and above. So need to force the
//server use the old escape mode when connects to the new server with old client library.
- result = PQexec(connection, "SET bytea_output=escape; ");
+ result = exec("SET bytea_output=escape; ");
status = PQresultStatus(result);
} else if (serverVersion == QPSQLDriver::VersionUnknown) {
serverVersion = clientVersion;
@@ -726,7 +740,7 @@ QPSQLDriver::QPSQLDriver(PGconn *conn, QObject *parent)
init();
d->connection = conn;
if (conn) {
- d->pro = getPSQLVersion(d->connection);
+ d->pro = d->getPSQLVersion();
setOpen(true);
setOpenError(false);
}
@@ -734,7 +748,7 @@ QPSQLDriver::QPSQLDriver(PGconn *conn, QObject *parent)
void QPSQLDriver::init()
{
- d = new QPSQLDriverPrivate();
+ d = new QPSQLDriverPrivate(this);
}
QPSQLDriver::~QPSQLDriver()
@@ -826,9 +840,9 @@ bool QPSQLDriver::open(const QString & db,
return false;
}
- d->pro = getPSQLVersion(d->connection);
- d->isUtf8 = setEncodingUtf8(d->connection);
- setDatestyle(d->connection);
+ d->pro = d->getPSQLVersion();
+ d->isUtf8 = d->setEncodingUtf8();
+ d->setDatestyle();
setOpen(true);
setOpenError(false);
@@ -865,7 +879,7 @@ bool QPSQLDriver::beginTransaction()
qWarning("QPSQLDriver::beginTransaction: Database not open");
return false;
}
- PGresult* res = PQexec(d->connection, "BEGIN");
+ PGresult* res = d->exec("BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
PQclear(res);
setLastError(qMakeError(tr("Could not begin transaction"),
@@ -882,7 +896,7 @@ bool QPSQLDriver::commitTransaction()
qWarning("QPSQLDriver::commitTransaction: Database not open");
return false;
}
- PGresult* res = PQexec(d->connection, "COMMIT");
+ PGresult* res = d->exec("COMMIT");
bool transaction_failed = false;
@@ -915,7 +929,7 @@ bool QPSQLDriver::rollbackTransaction()
qWarning("QPSQLDriver::rollbackTransaction: Database not open");
return false;
}
- PGresult* res = PQexec(d->connection, "ROLLBACK");
+ PGresult* res = d->exec("ROLLBACK");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Could not rollback transaction"),
QSqlError::TransactionError, d));
@@ -1298,11 +1312,11 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
int socket = PQsocket(d->connection);
if (socket) {
+ // Add the name to the list of subscriptions here so that QSQLDriverPrivate::exec knows
+ // to check for notifications immediately after executing the LISTEN
+ d->seid << name;
QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
- if (PQresultStatus(PQexec(d->connection,
- d->isUtf8 ? query.toUtf8().constData()
- : query.toLocal8Bit().constData())
- ) != PGRES_COMMAND_OK) {
+ if (PQresultStatus(d->exec(query)) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to subscribe"), QSqlError::StatementError, d));
return false;
}
@@ -1311,9 +1325,11 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
d->sn = new QSocketNotifier(socket, QSocketNotifier::Read);
connect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
}
+ } else {
+ qWarning("QPSQLDriver::subscribeToNotificationImplementation: PQsocket didn't return a valid socket to listen on");
+ return false;
}
- d->seid << name;
return true;
}
@@ -1331,10 +1347,7 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
}
QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
- if (PQresultStatus(PQexec(d->connection,
- d->isUtf8 ? query.toUtf8().constData()
- : query.toLocal8Bit().constData())
- ) != PGRES_COMMAND_OK) {
+ if (PQresultStatus(d->exec(query)) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to unsubscribe"), QSqlError::StatementError, d));
return false;
}
@@ -1357,17 +1370,21 @@ QStringList QPSQLDriver::subscribedToNotifications() const
void QPSQLDriver::_q_handleNotification(int)
{
+ d->pendingNotifyCheck = false;
PQconsumeInput(d->connection);
PGnotify *notify = 0;
while((notify = PQnotifies(d->connection)) != 0) {
QString name(QLatin1String(notify->relname));
if (d->seid.contains(name)) {
+ QString payload;
+#if defined PG_VERSION_NUM && PG_VERSION_NUM-0 >= 70400
+ if (notify->extra)
+ payload = d->isUtf8 ? QString::fromUtf8(notify->extra) : QString::fromAscii(notify->extra);
+#endif
emit notification(name);
- if (notify->be_pid == PQbackendPID(d->connection))
- emit notification(name, QSqlDriver::SelfSource);
- else
- emit notification(name, QSqlDriver::OtherSource);
+ QSqlDriver::NotificationSource source = (notify->be_pid == PQbackendPID(d->connection)) ? QSqlDriver::SelfSource : QSqlDriver::OtherSource;
+ emit notification(name, source, payload);
}
else
qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.",
diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp
index deb29f8059..168500e5a8 100644
--- a/src/sql/drivers/sqlite/qsql_sqlite.cpp
+++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp
@@ -92,6 +92,9 @@ static QVariant::Type qGetColumnType(const QString &tpName)
return QVariant::Double;
if (typeName == QLatin1String("blob"))
return QVariant::ByteArray;
+ if (typeName == QLatin1String("boolean")
+ || typeName == QLatin1String("bool"))
+ return QVariant::Bool;
return QVariant::String;
}
@@ -413,6 +416,7 @@ bool QSQLiteResult::exec()
ba->size(), SQLITE_STATIC);
break; }
case QVariant::Int:
+ case QVariant::Bool:
res = sqlite3_bind_int(d->stmt, i + 1, value.toInt());
break;
case QVariant::Double:
diff --git a/src/sql/kernel/qsql.qdoc b/src/sql/kernel/qsql.qdoc
index 0762fa977e..394c255b35 100644
--- a/src/sql/kernel/qsql.qdoc
+++ b/src/sql/kernel/qsql.qdoc
@@ -39,30 +39,6 @@
*/
/*!
- \enum QSql::Confirm
- \compat
-
- This enum type describes edit confirmations.
-
- \value Yes
- \value No
- \value Cancel
-*/
-
-/*!
- \enum QSql::Op
- \compat
-
- This enum type describes edit operations.
-
- \value None
- \value Insert
- \value Update
- \value Delete
-*/
-
-
-/*!
\enum QSql::Location
This enum type describes special SQL navigation locations:
diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp
index 28847325d9..f48673f28f 100644
--- a/src/sql/kernel/qsqldriver.cpp
+++ b/src/sql/kernel/qsqldriver.cpp
@@ -133,10 +133,11 @@ QSqlDriver::~QSqlDriver()
/*!
\since 5.0
- \fn QSqlDriver::notification(const QString &name, NotificationSource source)
+ \fn QSqlDriver::notification(const QString &name, NotificationSource source, const QString & payload)
This signal is emitted when the database posts an event notification
- that the driver subscribes to. \a name identifies the event notification, \a source indicates the signal source.
+ that the driver subscribes to. \a name identifies the event notification, \a source indicates the signal source,
+ \a payload holds the extra data optionally delivered with the notification.
\sa subscribeToNotification()
*/
diff --git a/src/sql/kernel/qsqldriver.h b/src/sql/kernel/qsqldriver.h
index ff19d660da..b3c83fc678 100644
--- a/src/sql/kernel/qsqldriver.h
+++ b/src/sql/kernel/qsqldriver.h
@@ -122,7 +122,7 @@ public:
Q_SIGNALS:
void notification(const QString &name);
- void notification(const QString &name, NotificationSource source);
+ void notification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload);
protected:
virtual void setOpen(bool o);
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 16df1b8b06..f9dbae306b 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -114,16 +114,18 @@ public:
QString executedQuery;
QHash<int, QSql::ParamType> types;
QVector<QVariant> values;
- typedef QHash<QString, int> IndexMap;
+ typedef QHash<QString, QList<int> > IndexMap;
IndexMap indexes;
typedef QVector<QHolder> QHolderVector;
QHolderVector holders;
};
+static QString qFieldSerial(int);
+
QString QSqlResultPrivate::holderAt(int index) const
{
- return indexes.key(index);
+ return holders.size() > index ? holders.at(index).holderName : qFieldSerial(index);
}
// return a unique id for bound names
@@ -159,6 +161,8 @@ QString QSqlResultPrivate::positionalToNamedBinding()
for (int i = 0; i < n; ++i) {
QChar ch = sql.at(i);
if (ch == QLatin1Char('?') && !inQuote) {
+ // Update the holder position since we are changing the holder name lengths
+ holders[count].holderPos = result.size();
result += qFieldSerial(count++);
} else {
if (ch == QLatin1Char('\''))
@@ -188,7 +192,9 @@ QString QSqlResultPrivate::namedToPositionalBinding()
int pos = i + 2;
while (pos < n && qIsAlnum(sql.at(pos)))
++pos;
- indexes[sql.mid(i, pos - i)] = count++;
+ QString holder(sql.mid(i, pos - i));
+ indexes[holder].append(count++);
+ holders.append(QHolder(holder, i));
result += QLatin1Char('?');
i = pos;
} else {
@@ -199,6 +205,7 @@ QString QSqlResultPrivate::namedToPositionalBinding()
}
}
result.squeeze();
+ values.resize(holders.size());
return result;
}
@@ -610,27 +617,32 @@ bool QSqlResult::savePrepare(const QString& query)
*/
bool QSqlResult::prepare(const QString& query)
{
- int n = query.size();
+ if (d->holders.isEmpty()) {
+ int n = query.size();
- bool inQuote = false;
- int i = 0;
-
- while (i < n) {
- QChar ch = query.at(i);
- if (ch == QLatin1Char(':') && !inQuote
- && (i == 0 || query.at(i - 1) != QLatin1Char(':'))
- && (i + 1 < n && qIsAlnum(query.at(i + 1)))) {
- int pos = i + 2;
- while (pos < n && qIsAlnum(query.at(pos)))
- ++pos;
+ bool inQuote = false;
+ int i = 0;
- d->holders.append(QHolder(query.mid(i, pos - i), i));
- i = pos;
- } else {
- if (ch == QLatin1Char('\''))
- inQuote = !inQuote;
- ++i;
+ while (i < n) {
+ QChar ch = query.at(i);
+ if (ch == QLatin1Char(':') && !inQuote
+ && (i == 0 || query.at(i - 1) != QLatin1Char(':'))
+ && (i + 1 < n && qIsAlnum(query.at(i + 1)))) {
+ int pos = i + 2;
+ while (pos < n && qIsAlnum(query.at(pos)))
+ ++pos;
+
+ QString holder(query.mid(i, pos - i));
+ d->indexes[holder].append(d->holders.size());
+ d->holders.append(QHolder(holder, i));
+ i = pos;
+ } else {
+ if (ch == QLatin1Char('\''))
+ inQuote = !inQuote;
+ ++i;
+ }
}
+ d->values.resize(d->holders.size());
}
d->sql = query;
return true; // fake prepares should always succeed
@@ -653,7 +665,7 @@ bool QSqlResult::exec()
QString holder;
for (i = d->holders.count() - 1; i >= 0; --i) {
holder = d->holders.at(i).holderName;
- val = d->values.value(d->indexes.value(holder));
+ val = d->values.value(d->indexes.value(holder).value(0,-1));
QSqlField f(QLatin1String(""), val.type());
f.setValue(val);
query = query.replace(d->holders.at(i).holderPos,
@@ -697,7 +709,7 @@ bool QSqlResult::exec()
void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType paramType)
{
d->binds = PositionalBinding;
- d->indexes[qFieldSerial(index)] = index;
+ d->indexes[qFieldSerial(index)].append(index);
if (d->values.count() <= index)
d->values.resize(index + 1);
d->values[index] = val;
@@ -727,19 +739,14 @@ void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
d->binds = NamedBinding;
// if the index has already been set when doing emulated named
// bindings - don't reset it
- int idx = d->indexes.value(placeholder, -1);
- if (idx >= 0) {
+ QList<int> indexes = d->indexes.value(placeholder);
+ foreach (int idx, indexes) {
if (d->values.count() <= idx)
d->values.resize(idx + 1);
d->values[idx] = val;
- } else {
- d->values.append(val);
- idx = d->values.count() - 1;
- d->indexes[placeholder] = idx;
+ if (paramType != QSql::In || !d->types.isEmpty())
+ d->types[idx] = paramType;
}
-
- if (paramType != QSql::In || !d->types.isEmpty())
- d->types[idx] = paramType;
}
/*!
@@ -776,8 +783,8 @@ QVariant QSqlResult::boundValue(int index) const
*/
QVariant QSqlResult::boundValue(const QString& placeholder) const
{
- int idx = d->indexes.value(placeholder, -1);
- return d->values.value(idx);
+ QList<int> indexes = d->indexes.value(placeholder);
+ return d->values.value(indexes.value(0,-1));
}
/*!
@@ -798,7 +805,7 @@ QSql::ParamType QSqlResult::bindValueType(int index) const
*/
QSql::ParamType QSqlResult::bindValueType(const QString& placeholder) const
{
- return d->types.value(d->indexes.value(placeholder, -1), QSql::In);
+ return d->types.value(d->indexes.value(placeholder).value(0,-1), QSql::In);
}
/*!
diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp
index 341804f1ae..fefb87dcf5 100644
--- a/src/sql/models/qsqlquerymodel.cpp
+++ b/src/sql/models/qsqlquerymodel.cpp
@@ -591,7 +591,8 @@ QModelIndex QSqlQueryModel::indexInQuery(const QModelIndex &item) const
{
Q_D(const QSqlQueryModel);
if (item.column() < 0 || item.column() >= d->rec.count()
- || !d->rec.isGenerated(item.column()))
+ || !d->rec.isGenerated(item.column())
+ || item.column() >= d->colOffsets.size())
return QModelIndex();
return createIndex(item.row(), item.column() - d->colOffsets[item.column()],
item.internalPointer());
diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp
index 0387e5691f..a3d45576ae 100644
--- a/src/sql/models/qsqlrelationaltablemodel.cpp
+++ b/src/sql/models/qsqlrelationaltablemodel.cpp
@@ -379,16 +379,21 @@ void QSqlRelationalTableModelPrivate::clearCache()
keys will not be exposed through the model. The user or the
database is responsible for keeping referential integrity.
\li If a relation's display column name is also used as a column
- name in the main table, or if it is used as display column
+ name in the relational table, or if it is used as display column
name in more than one relation it will be aliased. The alias is
- is the relation's table name and display column name joined
- by an underscore (e.g. tablename_columnname). All occurrences
- of the duplicate display column name are aliased when
+ the relation's table name, display column name and a unique id
+ joined by an underscore (e.g. tablename_columnname_id).
+ QSqlRecord::fieldName() will return the aliased column name.
+ All occurrences of the duplicate display column name are aliased when
duplication is detected, but no aliasing is done to the column
names in the main table. The aliasing doesn't affect
QSqlRelation, so QSqlRelation::displayColumn() will return the
- original display column name, but QSqlRecord::fieldName() will
- return aliases.
+ original display column name.
+ \li The reference table name is aliased. The alias is the word "relTblAl"
+ and the relationed column index joined by an underscore
+ (e.g. relTblAl_2). The alias can be used to filter the table
+ (For example, setFilter("relTblAl_2='Oslo' OR
+ relTblAl_3='USA'")).
\li When using setData() the role should always be Qt::EditRole,
and when using data() the role should always be Qt::DisplayRole.
\endlist
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 20d2be36e1..f7198978dd 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -97,6 +97,7 @@ void QSqlTableModelPrivate::initRecordAndPrimaryIndex()
{
rec = db.record(tableName);
primaryIndex = db.primaryIndex(tableName);
+ initColOffsets(rec.count());
}
void QSqlTableModelPrivate::clear()
@@ -332,7 +333,6 @@ void QSqlTableModel::setTable(const QString &tableName)
clear();
d->tableName = tableName;
d->initRecordAndPrimaryIndex();
- d->initColOffsets(d->rec.count());
if (d->rec.count() == 0)
d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),