0

I'm trying to pass an object called QMap<QString, QVariant>* collect_row and then I'm going to fill the second element with a QVariant value. The current value in the second element is 0.

I'm using this code to connect to a database and then copy the row from the database into the QMap<QString, QVariant>* collect_row.

DATABASE_STATUS Database::get_row_from(const QString& table_name, const QString& at_column_name, const QString& where_value_is_equal_to, QMap<QString, QVariant>* collect_row){
    /* Check if we are connected */
    if(!getInstance()->qSqlDatabase.isOpen())
        return DATABASE_STATUS_NOT_CONNECTED;

    QSqlQueryModel qSqlQueryModel;
    qSqlQueryModel.setQuery("SELECT * FROM " + table_name + " WHERE " + at_column_name + " = '" + where_value_is_equal_to + "'");
    QSqlRecord record = qSqlQueryModel.record(0);
    QList<QString> column_names = collect_row->keys();
    QList<QVariant> values_holders = collect_row->values();
    for(int i = 0; i < column_names.length(); i++){
        QVariant value_holder = values_holders.at(i);
        value_holder.setValue(record.value(record.indexOf(column_names.at(i))));
    }

    return DATABASE_STATUS_OK;
}

So here I have the column_names and I want to set QVariant values into the values_holders.

for(int i = 0; i < column_names.length(); i++){
    QVariant value_holder = values_holders.at(i);
    value_holder.setValue(record.value(record.indexOf(column_names.at(i))));
}

I want to write this code instead, but I cannot write values_holders.at(i).setValue() because that function does not exist.

for(int i = 0; i < column_names.length(); i++)
    values_holders.at(i).setValue(record.value(record.indexOf(column_names.at(i))));

database.cpp:72:30: error: no matching member function for call to 'setValue'
qvariant.h:560:23: note: candidate function template not viable: 'this' argument has type 'const QVariant', but method is not marked const

So that means I cannot change the element, even if there is a function called .setValue?

euraad
  • 2,467
  • 5
  • 30
  • 51
  • I haven't used Qt in a while, but I wonder if things like `QList values_holders = collect_row->values();` and `QVariant value_holder = values_holders.at(i);` are making copies of the values from the map and list respectively and you are modifying those copies instead of the objects in the map. – Retired Ninja Sep 30 '21 at 17:54
  • @RetiredNinja So you mean that they are not sharing the same memory? – euraad Sep 30 '21 at 18:01
  • You are probably coming from Java or C# background. But this is C++. C++ has value semantics, not reference semantics. You must learn to use references. Which will take you a while, I guess. Switching completely the mindset from reference semantics to value semantics is quite difficult. – HiFile.app - best file manager Sep 30 '21 at 20:33
  • IIRC Qt is Copy-on-Write, as Qt predates C++11. Qt detach & containers semantics always used to give me a headache. – jfh Sep 30 '21 at 20:49

1 Answers1

2

Use this code. Note that I changed the QMap pointer to reference. I believe the code should work though I have not tested it. But it is still super-ugly and very non-optimal. But I tried to do just minimal changes to your provided code.

DATABASE_STATUS Database::get_row_from(const QString& table_name, const QString& at_column_name, const QString& where_value_is_equal_to, QMap<QString, QVariant>& collect_row)
{
    /* Check if we are connected */
    if(!getInstance()->qSqlDatabase.isOpen())
        return DATABASE_STATUS_NOT_CONNECTED;

    QSqlQueryModel qSqlQueryModel;
    qSqlQueryModel.setQuery("SELECT * FROM " + table_name + " WHERE " + at_column_name + " = '" + where_value_is_equal_to + "'");
    QSqlRecord record = qSqlQueryModel.record(0);
    QList<QString> column_names = collect_row.keys();
    for(int i = 0; i < column_names.length(); i++){
        QString column_name = column_names.at(i);
        collect_row[column_name] = record.value(record.indexOf(column_name));
    }

    return DATABASE_STATUS_OK;
}