diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index d8e2b90c..279f3fb7 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -462,11 +462,22 @@ int DBBrowserDB::addRecord(const QString& sTableName) char *errmsg; if (!isOpen()) return false; - // add record is seldom called, for now this is ok - // but if we ever going to add a lot of records - // we should cache the parsed tables somewhere - sqlb::Table table = sqlb::Table::parseSQL(getObjectByName(sTableName).getsql()).first; - QString sInsertstmt = table.emptyInsertStmt(); + sqlb::Table table = getObjectByName(sTableName).table; + + // For tables without rowid we have to set the primary key by ourselves. We do so by querying for the largest value in the PK column + // and adding one to it. + QString sInsertstmt; + int pk_value; + if(table.isWithoutRowidTable()) + { + SqliteTableModel m(this, this); + m.setQuery(QString("SELECT MAX(`%1`) FROM `%2`;").arg(getObjectByName(sTableName).table.rowidColumn()).arg(sTableName)); + pk_value = m.data(m.index(0, 0)).toInt() + 1; + sInsertstmt = table.emptyInsertStmt(pk_value); + } else { + sInsertstmt = table.emptyInsertStmt(); + } + lastErrorMessage = ""; logSQL(sInsertstmt, kLogMsg_App); setRestorePoint(); @@ -477,7 +488,10 @@ int DBBrowserDB::addRecord(const QString& sTableName) qWarning() << "addRecord: " << lastErrorMessage; return -1; } else { - return sqlite3_last_insert_rowid(_db); + if(table.isWithoutRowidTable()) + return pk_value; + else + return sqlite3_last_insert_rowid(_db); } } diff --git a/src/sqlitetypes.cpp b/src/sqlitetypes.cpp index cda5ecf8..e3ae856f 100644 --- a/src/sqlitetypes.cpp +++ b/src/sqlitetypes.cpp @@ -156,28 +156,29 @@ QPair Table::parseSQL(const QString &sSQL) return qMakePair(Table(""), false); } -QString Table::emptyInsertStmt() const +QString Table::emptyInsertStmt(int pk_value) const { QString stmt = QString("INSERT INTO `%1`").arg(m_name); QStringList vals; QStringList fields; foreach(FieldPtr f, m_fields) { - if(f->notnull()) + if( f->primaryKey() && f->isInteger() ) { fields << f->name(); - if( f->primaryKey() && f->isInteger() ) - { + + if(pk_value != -1) + vals << QString::number(pk_value); + else vals << "NULL"; - } else { - if(f->isInteger()) - vals << "0"; - else - vals << "''"; - } - } - else - { + } else if(f->notnull()) { + fields << f->name(); + + if(f->isInteger()) + vals << "0"; + else + vals << "''"; + } else { // don't insert into fields with a default value // or we will never see it. if(f->defaultValue().length() == 0) @@ -228,7 +229,7 @@ QString Table::sql() const sql += "\n)"; // without rowid - if(m_rowidColumn != "_rowid_") + if(isWithoutRowidTable()) sql += " WITHOUT ROWID"; return sql + ";"; diff --git a/src/sqlitetypes.h b/src/sqlitetypes.h index 6065de47..59c3bdbe 100644 --- a/src/sqlitetypes.h +++ b/src/sqlitetypes.h @@ -82,9 +82,10 @@ public: /** * @brief Creates an empty insert statement. + * @param pk_value This optional parameter can be used to manually set a specific value for the primary key column * @return An sqlite conform INSERT INTO statement with empty values. (NULL,'',0) */ - QString emptyInsertStmt() const; + QString emptyInsertStmt(int pk_value = -1) const; /** * @brief Returns the CREATE TABLE statement for this table object @@ -98,6 +99,7 @@ public: void setField(int index, FieldPtr f) { m_fields[index] = f; } void setRowidColumn(const QString& rowid) { m_rowidColumn = rowid; } const QString& rowidColumn() const { return m_rowidColumn; } + bool isWithoutRowidTable() const { return m_rowidColumn != "_rowid_"; } void clear(); /**