pawelsalawa / sqlitestudio

A free, open source, multi-platform SQLite database manager.
https://sqlitestudio.pl
Other
4.67k stars 571 forks source link

Columns shift when inserting (bug?) #5076

Closed marcpley closed 2 weeks ago

marcpley commented 3 weeks ago

column_shift.sqlite3.tar.gz

Details

With the table attached, I insert a new row and I populate field0, field1 and field2: Capture d’écran du 2024-10-26 20-26-27 I validate the insert : Capture d’écran du 2024-10-26 20-27-39 and I refresh the data. Data of field1 and field2 are shifted to field2 and field3 : Capture d’écran du 2024-10-26 20-28-12 If removing the generated value on field TYPE, the bug disappear.

Bug 2 (?) : with this same table and generated value for TYPE, if I name the constraint : Capture d’écran du 2024-10-26 20-41-19 It is impossible to unset this parameter. When re-open this window, the checkbox is checked again.

pawelsalawa commented 3 weeks ago

Thanks for attaching the sample db for reproducing the problem! This is very helpful!

marcpley commented 2 weeks ago

Bug-fix proposal for bug 1 (Columns shift): /home/marc/Bureau/greli.net/sqlitestudio/SQLiteStudio3/guiSQLiteStudio/datagrid/sqltablemodel.cpp line 360 replace

        if (!modelColumn->canEdit())
            continue;

        item = itemsInRow[i++];

with

        item = itemsInRow[i++];

        if (!modelColumn->canEdit())
            continue;
pawelsalawa commented 2 weeks ago

I've applied your fix.

As for the second bug, I would suggest to look for it in sqlitecreatetable.cpp in function TokenList SqliteCreateTable::Column::Constraint::rebuildTokensFromContents().

This method is used to build constraint part of CREATE TABLE when you commit table structure changes.

If you find the problem, you might also need to apply appropriate fix in void FormatCreateTableColumnConstraint::formatInternal() in formatcreatetable.cpp (it's in enterprise formatter plugin), which is somewhat similar to the first file, but - as you may guess - it's used to build pretty-printed CREATE TABLE when you use "Format SQL" feature in SQL editor.

marcpley commented 2 weeks ago

I failed finding out the bug here. I think the problem is before this step, when validating the panel with OK button. The name of the constraint is kept when the checkbox is unchecked. And it's the name (stored I don't know where) that is used by rebuildTokensFromContents.

marcpley commented 2 weeks ago

Bug-fix proposal for bug 2: ../guiSQLiteStudio/constraints/columngeneratedpanel.cpp line 96 replace

    setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint."));

with

    if (ui->namedCheck->isChecked())//Bug 5076-2
        setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint."));

line 137 after

    if (ui->namedCheck->isChecked())
        constr->name = ui->namedEdit->text();

add

    else//Bug 5076-2
        constr->name.clear();
marcpley commented 2 weeks ago

../guiSQLiteStudio/constraints/columnprimarykeypanel.cpp line 65 replace ui->namedCheck->setEnabled(true); with ui->namedCheck->setChecked(true);//Bug 5076-2 line 89 add if (ui->namedCheck->isChecked())//Bug 5076-2 before setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint.")); line 125 after

    if (ui->namedCheck->isChecked())
        constr->name = ui->namedEdit->text();

add

    else//Bug 5076-2
        constr->name.clear();
marcpley commented 2 weeks ago

columnuniqueandnotnullpanel.cpp line 73 add if (ui->namedCheck->isChecked())//Bug 5076-2 before setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint.")); line 95 after

    if (ui->namedCheck->isChecked())
        constr->name = ui->namedEdit->text();

add

    else//Bug 5076-2
        constr->name.clear();
marcpley commented 2 weeks ago

columncollatepanel.cpp line 80 add if (ui->namedCheck->isChecked())//Bug 5076-2 before setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint.")); line 104 after

    if (ui->namedCheck->isChecked())
        constr->name = ui->namedEdit->text();

add

    else//Bug 5076-2
        constr->name.clear();
marcpley commented 2 weeks ago

columndefaultpanel.cpp line 92 add if (ui->namedCheck->isChecked())//Bug 5076-2 before setValidState(ui->namedEdit, nameOk, tr("Enter a name of the constraint.")); line 141 after

    if (ui->namedCheck->isChecked())
        constr->name = ui->namedEdit->text();

add

    else//Bug 5076-2
        constr->name.clear();
marcpley commented 2 weeks ago

Other constrain panels work (considering unnaming the constrain)

pawelsalawa commented 2 weeks ago

A note about setValidState - this method should be called no matter if checkbox is checked or not, because if checkbox is unchecked, the nameOk variable is true and this will remove "error indicator" from the line edit. If we add precondition for setValidState, then error indicator will not be cleared if user unchecks the checkbox.

Other than that it looks good and I've applied your changes. Thanks!

marcpley commented 1 week ago

Right ! I've tested a lot off modifications and I didn't see that this was unnecessary.