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

Migrating a varchar to a bigint causes invalid charset instructions to appear #30539

Closed
James34Shaw100 opened this issue Nov 7, 2019 · 22 comments
Labels

Comments

@James34Shaw100
Copy link

James34Shaw100 commented Nov 7, 2019

  • Laravel Version: 6.5
  • PHP Version: 7.3.11
  • Database Driver & Version: MySQL - 5.7.27-0ubuntu0.18.04.1

Description:

While writing a migration to fix a bad database that had stored a foreign key as a varchar, I wrote the following migration:

Schema::table('jobseeker_qualifications', function (Blueprint $table) {
        $table->bigIncrements('id')->change();
        $table->unsignedBigInteger('user_id')->change();
        $table->unsignedBigInteger('jobseekers_education_id')->change();
        $table->foreign('user_id')->references('id')->on('users');
        $table->foreign('jobseekers_education_id')->references('id')->on('jobseeker_educations');
});

However, this above migration generated the following SQL:

ALTER TABLE jobseeker_qualifications
CHANGE id id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
CHANGE jobseekers_education_id jobseekers_education_id BIGINT UNSIGNED CHARACTER SET utf8 NOT NULL COLLATE `utf8_unicode_ci`,
CHANGE user_id user_id BIGINT UNSIGNED NOT NULL

Work Around: Removing the instructions related to the character set and running this query manually was successful.

Steps To Reproduce:

  1. Create a table containing a VARCHAR field that contains valid id values (only numbers).
  2. Run a migration similar to the above, requesting a change the VARCHAR to unsigned BIGINT.
@James34Shaw100 James34Shaw100 changed the title Migrating a varchar to a bigint causes bad charset instructions to appear Migrating a varchar to a bigint causes invalid charset instructions to appear Nov 7, 2019
@rimace
Copy link
Contributor

rimace commented Nov 8, 2019

What was the error message?

@James34Shaw100
Copy link
Author

James34Shaw100 commented Nov 11, 2019

What was the error message?

SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHARACTER SET utf8 NOT NULL COLLATE `utf8_unicode_ci`, CHANGE user_id user_id B' at line 3

Those character set and collate instructions should not have been there.

@staudenmeir
Copy link
Contributor

What version of the doctrine/dbal package are you using (run composer show)?

@James34Shaw100
Copy link
Author

What version of the doctrine/dbal package are you using (run composer show)?

Here:
doctrine/dbal v2.10.0

@staudenmeir
Copy link
Contributor

Can you try downgrading to 2.9.3?

It looks like this is the same bug: doctrine/dbal#3714

@James34Shaw100
Copy link
Author

Can you try downgrading to 2.9.3?
It looks like this is the same bug: doctrine/dbal#3714

It does indeed look like the same bug, I'll subscribe to that bug tracker to see when it's been fixed and I could update this ticket in turn.

I don't have the time at the moment to try the downgrade due to work pressures and the manual script work around is functional for the moment, but if I get a chance to I shall look in to it.

@driesvints
Copy link
Member

Seems like this is related to DBAL and not Laravel so going to close this one.

@Justin991q
Copy link

DBAL just closed the issue: see doctrine/dbal#3714 (comment)

@JohnyProkie
Copy link

Can please folks from Laravel and folks from Doctrine make an agreement and push this issue a bit further?
doctrine/dbal#3714 (comment)

Laravel says it's issue on Doctrine's side. Doctrine says it's issue on Laravel side. Meanwhile we are locked on older version of Doctrine when we want to keep our projects up-to-date.
Thank you in advance.

Please note this happened to us when changing varchar column to integer.

@lcobucci
Copy link

Hello everyone, I'm one of the core members of the Doctrine team 👋

As I mentioned on the issue in DBAL, I completely understand your frustration and am sorry for this inconvenience.

We really believe that the issue is related to how Laravel configures the DBAL objects to perform the comparisons and think that it was working previously due to a bug that got fixed.

I don't know Laravel so much to solve this but feel free to ping me in a PR or on Doctrine's slack channel and I'll do my best to support the resolution of this issue.

@JohnyProkie thanks for pointing us here and @driesvints and other Laravel maintainers for their hard work on building bridges between the two projects 🤟

@JohnyProkie
Copy link

@lcobucci Thank you a lot for stepping in!

@driesvints
Copy link
Member

Let's figure this out. If anyone could help pinpoint where we can implement a fix that'd be great.

@lcobucci thanks for your hard work on Doctrine as well :)

@driesvints driesvints reopened this Nov 29, 2019
@driesvints driesvints added the bug label Nov 29, 2019
@lcobucci
Copy link

lcobucci commented Nov 29, 2019

@driesvints I haven't debugged anything but

$options['customSchemaOptions'] = [
'collation' => '',
];
might give us a clue.

Laravel should make sure to not set the charset/collation info on the objects while performing the changes.

@driesvints
Copy link
Member

@lcobucci it does seem that only applies to json and binary columns while the issue here is changing a column type from varchar to bigint so I'm not sure if that's the actual culprit?

if (in_array($fluent['type'], ['json', 'binary'])) {
$options['customSchemaOptions'] = [
'collation' => '',
];
}

@lcobucci
Copy link

lcobucci commented Dec 2, 2019

@driesvints that's the problem. As @AlterTable explained it:

But when it's original type was varchar/text, there is a implicit change: the charset definition should be removed. Neither Laravel nor Doctrine handled this.
I think there are two ways to fix this, one is add extra checks in \Doctrine\DBAL\Schema\Table::changeColumn, another is modify Laravel migrate, add checks after changed attributes are set. I prefer the second one.

Laravel should define characterset and collation as null to remove that info.

Does this help?

@driesvints
Copy link
Member

@lcobucci heya, it does. I think this is indeed the correct way to go forward. I currently don't have time to work on this so if anyone is experiencing this issue and wants to move this forward, feel free to send in a PR.

@yahya09
Copy link

yahya09 commented Dec 9, 2019

Hi all, if anyone on Laravel 6.x & doctrine/dbal 2.10 experiencing this issue, the quick fix is to set charset and collation to empty string on column change statement. For example:

$table->integer('resource_type')->default(0)->charset('')->collation('')->change();

It does work on my case where previous column type is string (varchar).
Looks like someone has already sent PR to fix this, but I hope solution above still help before the PR merged.

@squatto
Copy link
Contributor

squatto commented Feb 11, 2020

Hi all, if anyone on Laravel 6.x & doctrine/dbal 2.10 experiencing this issue, the quick fix is to set charset and collation to empty string on column change statement. For example:

$table->integer('resource_type')->default(0)->charset('')->collation('')->change();

It does work on my case where previous column type is string (varchar).
Looks like someone has already sent PR to fix this, but I hope solution above still help before the PR merged.

This unfortunately isn't working for me for some reason. I've tried null and '' for charset and collation and I still get the same error. I'm going from string to bigInteger:

$table->bigInteger('number')
      ->charset('')
      ->collation('')
      ->change();

I finally ended up just running the raw query:

\DB::statement('alter table orders modify number bigint not null');

@taylorotwell
Copy link
Member

Fixed by fccdf7c

@strtz
Copy link

strtz commented Jun 10, 2020

still present in:
"php": "^7.2",
"laravel/framework": "^6.0",
"doctrine/dbal": "^2.10",

error while trying to change column from text to blob

workaround for me was to make a intermediary migration that runs above the alter and drop the column and recreate it for both fwd and reverse migration

Doctrine\DBAL\Driver\PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CHARACTER SET utf8mb4 DEFAULT NULL' at line 1") /var/www/****/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:66

@osbre
Copy link
Contributor

osbre commented Jul 2, 2020

@strtz try to update dependencies

@vannakdev
Copy link

Fixed by fccdf7c

It worked thanks @taylorotwell

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

No branches or pull requests