bool TSqlObject::remove() { syncToSqlRecord(); QString del = TActionContext::currentDatabase().driver()->sqlStatement(QSqlDriver::DeleteStatement, tableName(), *static_cast<QSqlRecord *>(this), false); if (del.isEmpty()) { sqlError = QSqlError(QLatin1String("Unable to delete row"), QString(), QSqlError::StatementError); return false; } del.append(" WHERE "); int revIndex = metaObject()->indexOfProperty(REVISION_PROPERTY_NAME); if (revIndex >= 0) { bool ok; int revsion = property(REVISION_PROPERTY_NAME).toInt(&ok); if (!ok || revsion <= 0) { sqlError = QSqlError(QLatin1String("Unable to convert the 'revision' property to an int"), QString(), QSqlError::UnknownError); tError("Unable to convert the 'revsion' property to an int, %s", qPrintable(objectName())); return false; } del.append(TSqlQuery::escapeIdentifier(REVISION_PROPERTY_NAME)); del.append("=").append(TSqlQuery::formatValue(revsion)); del.append(" AND "); } const char *pkName = metaObject()->property(metaObject()->propertyOffset() + primaryKeyIndex()).name(); if (primaryKeyIndex() < 0 || !pkName) { QString msg = QString("Not found the primary key for table ") + tableName(); sqlError = QSqlError(msg, QString(), QSqlError::StatementError); tError("%s", qPrintable(msg)); return false; } del.append(TSqlQuery::escapeIdentifier(pkName)); del.append("=").append(TSqlQuery::formatValue(property(pkName))); tSystemDebug("SQL statement: %s", qPrintable(del)); QSqlQuery query(TActionContext::currentDatabase()); bool res = query.exec(del); sqlError = query.lastError(); if (!res) { tSystemError("SQL delete error: %s", qPrintable(sqlError.text())); return false; } // Optimistic lock check if (query.numRowsAffected() != 1) { if (revIndex >= 0) { QString msg = QString("Row was updated or deleted from table ") + tableName() + QLatin1String(" by another transaction"); sqlError = QSqlError(msg, QString(), QSqlError::UnknownError); throw SqlException(msg, __FILE__, __LINE__); } tWarn("Row was deleted by another transaction, %s", qPrintable(tableName())); } clear(); return true; }
QPair<QString, QVariant::Type> TableSchema::getPrimaryKeyFieldType() const { QPair<QString, QVariant::Type> pair; int index = primaryKeyIndex(); if (index >= 0) { QSqlField f = tableFields.field(index); pair = QPair<QString, QVariant::Type>(f.name(), f.type()); } return pair; }
/*! Deletes the record with this primary key from the database. */ bool TSqlObject::remove() { if (isNew()) { sqlError = QSqlError(QLatin1String("No record to remove"), QString(), QSqlError::UnknownError); tWarn("Unable to remove the '%s' object. Create it before!", metaObject()->className()); return false; } QSqlDatabase &database = Tf::currentSqlDatabase(databaseId()); QString del = database.driver()->sqlStatement(QSqlDriver::DeleteStatement, tableName(), *static_cast<QSqlRecord *>(this), false); if (del.isEmpty()) { sqlError = QSqlError(QLatin1String("Unable to delete row"), QString(), QSqlError::StatementError); return false; } del.append(" WHERE "); int revIndex = -1; for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); ++i) { const char *propName = metaObject()->property(i).name(); QByteArray prop = QByteArray(propName).toLower(); if (prop == LockRevision) { bool ok; int revision = property(propName).toInt(&ok); if (!ok || revision <= 0) { sqlError = QSqlError(QLatin1String("Unable to convert the 'revision' property to an int"), QString(), QSqlError::UnknownError); tError("Unable to convert the 'revision' property to an int, %s", qPrintable(objectName())); return false; } del.append(QLatin1String(propName)); del.append("=").append(TSqlQuery::formatValue(revision, database)); del.append(" AND "); revIndex = i; break; } } const char *pkName = metaObject()->property(metaObject()->propertyOffset() + primaryKeyIndex()).name(); if (primaryKeyIndex() < 0 || !pkName) { QString msg = QString("Primary key not found for table ") + tableName() + QLatin1String(". Create a primary key!"); sqlError = QSqlError(msg, QString(), QSqlError::StatementError); tError("%s", qPrintable(msg)); return false; } del.append(QLatin1String(pkName)); del.append("=").append(TSqlQuery::formatValue(value(pkName), database)); TSqlQuery query(database); bool ret = query.exec(del); sqlError = query.lastError(); if (ret) { // Optimistic lock check if (query.numRowsAffected() != 1) { if (revIndex >= 0) { QString msg = QString("Row was updated or deleted from table ") + tableName() + QLatin1String(" by another transaction"); sqlError = QSqlError(msg, QString(), QSqlError::UnknownError); throw SqlException(msg, __FILE__, __LINE__); } tWarn("Row was deleted by another transaction, %s", qPrintable(tableName())); } clear(); } return ret; }
/*! Updates the corresponding record with the properties of the object. */ bool TSqlObject::update() { if (isNew()) { sqlError = QSqlError(QLatin1String("No record to update"), QString(), QSqlError::UnknownError); tWarn("Unable to update the '%s' object. Create it before!", metaObject()->className()); return false; } QSqlDatabase &database = Tf::currentSqlDatabase(databaseId()); QString where(" WHERE "); // Updates the value of 'updated_at' or 'modified_at' property bool updflag = false; int revIndex = -1; for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); ++i) { const char *propName = metaObject()->property(i).name(); QByteArray prop = QByteArray(propName).toLower(); if (!updflag && (prop == UpdatedAt || prop == ModifiedAt)) { setProperty(propName, QDateTime::currentDateTime()); updflag = true; } else if (revIndex < 0 && prop == LockRevision) { bool ok; int oldRevision = property(propName).toInt(&ok); if (!ok || oldRevision <= 0) { sqlError = QSqlError(QLatin1String("Unable to convert the 'revision' property to an int"), QString(), QSqlError::UnknownError); tError("Unable to convert the 'revision' property to an int, %s", qPrintable(objectName())); return false; } setProperty(propName, oldRevision + 1); revIndex = i; where.append(QLatin1String(propName)); where.append("=").append(TSqlQuery::formatValue(oldRevision, database)); where.append(" AND "); } else { // continue } } QString upd; // UPDATE Statement upd.reserve(255); upd.append(QLatin1String("UPDATE ")).append(tableName()).append(QLatin1String(" SET ")); int pkidx = metaObject()->propertyOffset() + primaryKeyIndex(); const char *pkName = metaObject()->property(pkidx).name(); if (primaryKeyIndex() < 0 || !pkName) { QString msg = QString("Primary key not found for table ") + tableName() + QLatin1String(". Create a primary key!"); sqlError = QSqlError(msg, QString(), QSqlError::StatementError); tError("%s", qPrintable(msg)); return false; } QVariant origpkval = value(pkName); where.append(QLatin1String(pkName)); where.append("=").append(TSqlQuery::formatValue(origpkval, database)); // Restore the value of primary key QObject::setProperty(pkName, origpkval); for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); ++i) { const char *propName = metaObject()->property(i).name(); QVariant newval = QObject::property(propName); QVariant recval = QSqlRecord::value(QLatin1String(propName)); if (i != pkidx && recval.isValid() && recval != newval) { upd.append(QLatin1String(propName)); upd.append(QLatin1Char('=')); upd.append(TSqlQuery::formatValue(newval, database)); upd.append(QLatin1String(", ")); } } if (!upd.endsWith(QLatin1String(", "))) { tSystemDebug("SQL UPDATE: Same values as that of the record. No need to update."); return true; } upd.chop(2); syncToSqlRecord(); upd.append(where); TSqlQuery query(database); bool ret = query.exec(upd); sqlError = query.lastError(); if (ret) { // Optimistic lock check if (revIndex >= 0 && query.numRowsAffected() != 1) { QString msg = QString("Row was updated or deleted from table ") + tableName() + QLatin1String(" by another transaction"); sqlError = QSqlError(msg, QString(), QSqlError::UnknownError); throw SqlException(msg, __FILE__, __LINE__); } } return ret; }
bool TSqlObject::update() { if (isNew()) { sqlError = QSqlError(QLatin1String("No record to update"), QString(), QSqlError::UnknownError); tWarn("Unable to update the '%s' object. Create it before!", metaObject()->className()); return false; } QString where(" WHERE "); int revIndex = metaObject()->indexOfProperty(REVISION_PROPERTY_NAME); if (revIndex >= 0) { bool ok; int oldRevision = property(REVISION_PROPERTY_NAME).toInt(&ok); if (!ok || oldRevision <= 0) { sqlError = QSqlError(QLatin1String("Unable to convert the 'revision' property to an int"), QString(), QSqlError::UnknownError); tError("Unable to convert the 'revision' property to an int, %s", qPrintable(objectName())); return false; } setProperty(REVISION_PROPERTY_NAME, oldRevision + 1); where.append(TSqlQuery::escapeIdentifier(REVISION_PROPERTY_NAME)); where.append("=").append(TSqlQuery::formatValue(oldRevision)); where.append(" AND "); } // Updates the value of 'updated_at' property for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); ++i) { const char *propName = metaObject()->property(i).name(); if (QLatin1String("updated_at") == propName) { setProperty(propName, QDateTime::currentDateTime()); break; } } syncToSqlRecord(); QString upd = TActionContext::currentDatabase().driver()->sqlStatement(QSqlDriver::UpdateStatement, tableName(), *static_cast<QSqlRecord *>(this), false); if (upd.isEmpty()) { sqlError = QSqlError(QLatin1String("No Fields to update"), QString(), QSqlError::StatementError); return false; } const char *pkName = metaObject()->property(metaObject()->propertyOffset() + primaryKeyIndex()).name(); if (primaryKeyIndex() < 0 || !pkName) { QString msg = QString("Not found the primary key for table ") + tableName(); sqlError = QSqlError(msg, QString(), QSqlError::StatementError); tError("%s", qPrintable(msg)); return false; } where.append(TSqlQuery::escapeIdentifier(pkName)); where.append("=").append(TSqlQuery::formatValue(property(pkName))); upd.append(where); tSystemDebug("SQL statement: %s", qPrintable(upd)); QSqlQuery query(TActionContext::currentDatabase()); bool res = query.exec(upd); sqlError = query.lastError(); if (!res) { tSystemError("SQL update error: %s", qPrintable(sqlError.text())); return false; } // Optimistic lock check if (revIndex >= 0 && query.numRowsAffected() != 1) { QString msg = QString("Row was updated or deleted from table ") + tableName() + QLatin1String(" by another transaction"); sqlError = QSqlError(msg, QString(), QSqlError::UnknownError); throw SqlException(msg, __FILE__, __LINE__); } return true; }