mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 19:11:39 -06:00
When updating a field try to respect the affinity data type if possible
When modifying the value of a field in the Browse Data tab, we used to always hand over the new value to SQLite as text. This works most of the time but can cause problems e.g. when a CHECK constraint checks the data type of the value and expects something other than text. It is also a pretty lazy approach in general. This commit checks if the new value matches the affinity data type of the column, and if it does hands over the new value as the correct data type. See issue #1952.
This commit is contained in:
@@ -1398,7 +1398,7 @@ bool DBBrowserDB::deleteRecords(const sqlb::ObjectIdentifier& table, const QStri
|
||||
}
|
||||
|
||||
bool DBBrowserDB::updateRecord(const sqlb::ObjectIdentifier& table, const std::string& column,
|
||||
const QString& rowid, const QByteArray& value, bool itsBlob, const sqlb::StringVector& pseudo_pk)
|
||||
const QString& rowid, const QByteArray& value, int force_type, const sqlb::StringVector& pseudo_pk)
|
||||
{
|
||||
waitForDbRelease();
|
||||
if (!isOpen()) return false;
|
||||
@@ -1439,13 +1439,17 @@ bool DBBrowserDB::updateRecord(const sqlb::ObjectIdentifier& table, const std::s
|
||||
if(sqlite3_prepare_v2(_db, sql.toUtf8(), -1, &stmt, nullptr) != SQLITE_OK)
|
||||
success = 0;
|
||||
if(success == 1) {
|
||||
if(itsBlob)
|
||||
if(force_type == SQLITE_BLOB)
|
||||
{
|
||||
if(sqlite3_bind_blob(stmt, 1, rawValue, value.length(), SQLITE_STATIC))
|
||||
success = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else if(force_type == SQLITE_INTEGER) {
|
||||
if(sqlite3_bind_int(stmt, 1, value.toInt()))
|
||||
success = -1;
|
||||
} else if(force_type == SQLITE_FLOAT) {
|
||||
if(sqlite3_bind_double(stmt, 1, value.toDouble()))
|
||||
success = -1;
|
||||
} else {
|
||||
if(sqlite3_bind_text(stmt, 1, rawValue, value.length(), SQLITE_STATIC))
|
||||
success = -1;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ private:
|
||||
public:
|
||||
QString addRecord(const sqlb::ObjectIdentifier& tablename);
|
||||
bool deleteRecords(const sqlb::ObjectIdentifier& table, const QStringList& rowids, const sqlb::StringVector& pseudo_pk = {});
|
||||
bool updateRecord(const sqlb::ObjectIdentifier& table, const std::string& column, const QString& rowid, const QByteArray& value, bool itsBlob, const sqlb::StringVector& pseudo_pk = {});
|
||||
bool updateRecord(const sqlb::ObjectIdentifier& table, const std::string& column, const QString& rowid, const QByteArray& value, int force_type = 0, const sqlb::StringVector& pseudo_pk = {});
|
||||
|
||||
bool createTable(const sqlb::ObjectIdentifier& name, const sqlb::FieldVector& structure);
|
||||
bool renameTable(const std::string& schema, const std::string& from_table, const std::string& to_table);
|
||||
|
||||
@@ -466,7 +466,26 @@ bool SqliteTableModel::setTypedData(const QModelIndex& index, bool isBlob, const
|
||||
if(oldValue == newValue && oldValue.isNull() == newValue.isNull())
|
||||
return true;
|
||||
|
||||
if(m_db.updateRecord(m_query.table(), m_headers.at(column), cached_row.at(0), newValue, isBlob, m_query.rowIdColumns()))
|
||||
// Determine type. If the BLOB flag is set, it's always BLOB. If the affinity data type of the modified column is something numeric,
|
||||
// we check if the new value is also numeric. In that case we can safely set the data type to INTEGER or FLOAT. In all other cases we
|
||||
// default to TEXT.
|
||||
int type = SQLITE_TEXT;
|
||||
if(isBlob)
|
||||
{
|
||||
type = SQLITE_BLOB;
|
||||
} else if(m_vDataTypes.at(column) == SQLITE_INTEGER) {
|
||||
bool ok;
|
||||
newValue.toInt(&ok);
|
||||
if(ok)
|
||||
type = SQLITE_INTEGER;
|
||||
} else if(m_vDataTypes.at(column) == SQLITE_FLOAT) {
|
||||
bool ok;
|
||||
newValue.toFloat(&ok);
|
||||
if(ok)
|
||||
type = SQLITE_FLOAT;
|
||||
}
|
||||
|
||||
if(m_db.updateRecord(m_query.table(), m_headers.at(column), cached_row.at(0), newValue, type, m_query.rowIdColumns()))
|
||||
{
|
||||
cached_row[column] = newValue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user