Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mysql adapter: Changing the STORED status #1953

Open
killua-eu opened this issue Feb 3, 2021 · 6 comments
Open

Mysql adapter: Changing the STORED status #1953

killua-eu opened this issue Feb 3, 2021 · 6 comments

Comments

@killua-eu
Copy link

I encountered an error when using the literal type to change columns.

use Phinx\Db\Adapter\MysqlAdapter;
use Phinx\Util\Literal;

class ContactsGenerated2 extends Phinx\Migration\AbstractMigration
{
    public function change()
    {
        $this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
        $this->table('t_contacts', [
                'id' => false,
                'primary_key' => ['c_uid'],
                'engine' => 'InnoDB',
                'encoding' => 'utf8mb4',
                'collation' => 'utf8mb4_0900_ai_ci',
                'row_format' => 'DYNAMIC',
            ])
            ->changeColumn('c_fn', Literal::from("varchar(255) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (`c_json`->>'$.fn') VIRTUAL"), [
                'null' => true,
            ])
            ->update();
        $this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
    }
}

As long as I change only the json path c_json->>'$.to.something.else', all works well, but changing VIRTUAL to STORED or vice-versa fails with

PDOException: SQLSTATE[HY000]: General error: 3106 'Changing the STORED status' is not supported for generated columns. in /srv/varwwwhtml/glued-skeleton/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/PdoAdapter.php:194...

I think that when the STORED status is changed, the changed column needs to get dropped and recreated.

@garas
Copy link
Member

garas commented Feb 3, 2021

Phinx doesn't handle generated columns.

You should removeColumn(), then addColumn().

@killua-eu
Copy link
Author

killua-eu commented Feb 4, 2021

Well actually Phinx handles generated columns well enough, just not consistently. There's support through the literal type that kind of works. Sometimes changeColumn() is just fine, on other occasions removeColumn() and addColumn() is required. From what I've seen so far here a list of what works with changeColumn() and where it does not:

  • change a GENERATED VIRTUAL column into a differently GENERATED VIRTUAL column
  • change a GENERATED STORED column into a differently GENERATED STORED column
  • change a classical (STORED) column into a GENERATED STORED column
  • change a GENERATED STORED column into classical STORED column
  • change a classical (STORED) column into a GENERATED VIRTUAL column
  • change a GENERATED STORED column into a GENERATED VIRTUAL column

Since a majority of the use cases work already, I'd really welcome if phinx would eventually support the latter two cases where things fail. Maybe this could be a nice addition for v0.13?

@garas
Copy link
Member

garas commented Feb 4, 2021

It is limitations of MySQL:

  • Virtual generated columns cannot be altered to stored generated columns, or vice versa. To work around this, drop the column, then add it with the new definition.
  • Nongenerated columns can be altered to stored but not virtual generated columns.
  • Stored but not virtual generated columns can be altered to nongenerated columns. The stored generated values become the values of the nongenerated column.

Phinx doesn't handle generated columns, but support comes through column definition with Literal::from().

@killua-eu
Copy link
Author

You're rephrasing what I wrote, so its hard not to agree :) Does the fact that mysql has limitations prevent phinx from picking up a workaround to achieve consistent behaviour? I believe that being able to rely on consistency even though the underlying database is lacking is one of the best reasons for using phinx, don't you?

@garas
Copy link
Member

garas commented Feb 4, 2021

To add workarounds, Phinx needs generated columns support first.

@zdenekgebauer
Copy link

I found another problem with generated columns and NULL on MariaDB :

->addColumn(
'cs', 
Literal::from("varchar(50) GENERATED ALWAYS AS (JSON_VALUE(`translations`,'$.name.cs')) VIRTUAL UNIQUE")

generates:

 ADD `cs` varchar(50) GENERATED ALWAYS AS (JSON_VALUE(`translations`,'$.name.cs')) VIRTUAL UNIQUE NULL,

which causes syntax error, because SQL must not contains "NUL" nor "NOT NUL" . Is there any way how ommit NULL/NOT NULL ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants