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

Fix changing column from int to bigint with autoincrement #2916

Merged
merged 1 commit into from
Nov 20, 2017
Merged

Fix changing column from int to bigint with autoincrement #2916

merged 1 commit into from
Nov 20, 2017

Conversation

icewind1991
Copy link
Contributor

Currently it tries to alter the column type to BIGSERIAL which is not a valid type to be used in an ALTER TABLE query.

Also it currently drops the default which breaks the auto increment.

cc @nickvergessen

Copy link
Member

@lcobucci lcobucci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rebase your branch to sync to the latest changes of master

$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
}

if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) {
if ($columnDiff->fromColumn) {
$oldTypeIsNumeric = $columnDiff->fromColumn->getType()->getName() === Type::INTEGER || $columnDiff->fromColumn->getType()->getName() === Type::BIGINT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't rely on Type::getName(), use instance of instead.

if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) {
if ($columnDiff->fromColumn) {
$oldTypeIsNumeric = $columnDiff->fromColumn->getType()->getName() === Type::INTEGER || $columnDiff->fromColumn->getType()->getName() === Type::BIGINT;
$newTypeIsNumeric = $column->getType()->getName() === Type::INTEGER || $column->getType()->getName() === Type::BIGINT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't rely on Type::getName(), use instance of instead.

@@ -419,6 +419,29 @@ public function testListNegativeColumnDefaultValue()
self::assertEquals(-1.1, $columns['col_decimal']->getDefault());
self::assertEquals('(-1)', $columns['col_string']->getDefault());
}

public function testAlterTableAutoIncrementBigInt()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: void missing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add @group 2916 to a docblock here


public function testAlterTableAutoIncrementBigInt()
{
$tableFrom = new \Doctrine\DBAL\Schema\Table('autoinc_table_bitgint');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please simplify the FQCN

$tableFrom = $this->_sm->listTableDetails('autoinc_table_bitgint');
self::assertTrue($tableFrom->getColumn('id')->getAutoincrement());

$tableTo = new \Doctrine\DBAL\Schema\Table('autoinc_table_bitgint');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please simplify the FQCN

$column = $tableTo->addColumn('id', 'bigint');
$column->setAutoincrement(true);

$c = new \Doctrine\DBAL\Schema\Comparator();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please simplify the FQCN

$c = new \Doctrine\DBAL\Schema\Comparator();
$diff = $c->diffTable($tableFrom, $tableTo);
self::assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
self::assertEquals(array("ALTER TABLE autoinc_table_bitgint ALTER id TYPE BIGINT"), $this->_conn->getDatabasePlatform()->getAlterTableSQL($diff));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertSame() is more appropriated here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also use short-array syntax

@icewind1991
Copy link
Contributor Author

@lcobucci all done

Copy link
Member

@lcobucci lcobucci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job, some more nitpicks 😜

Just to understand, is this needed only for PGSQL 10+ compatibility? I mean, I didn't see any issue reporting this before.
This question is just to categorise this PR correctly.

I've already checked, this operation breaks badly on PGSQL 9.x too


$c = new Comparator();
$diff = $c->diffTable($tableFrom, $tableTo);
self::assertInstanceOf('Doctrine\DBAL\Schema\TableDiff', $diff, "There should be a difference and not false being returned from the table comparison");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use TableDiff::class instead

$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query;
}

if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) {
if ($columnDiff->fromColumn) {
Copy link
Member

@lcobucci lcobucci Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about extracting this if block to a private method? I think that something like this would improve the readability a bit:

private function hasDefaultTypeChanged(ColumnDiff $columnDiff, Column $newColumn) : bool
{
    $defaultTypeChanged = $columnDiff->hasChanged('type');

    if ( ! $columnDiff->fromColumn || ! $defaultTypeChanged) {
        return $defaultTypeChanged;
    }

    $oldTypeIsNumeric = $this->isNumericType($columnDiff->fromColumn->getType());
    $newTypeIsNumeric = $this->isNumericType($newColumn->getType());

    return ! ($oldTypeIsNumeric && $newTypeIsNumeric && $newColumn->getDefault() === null)
}

We might improve things there (specially naming wise), but I think it makes things easier and more understandable 😄

@lcobucci
Copy link
Member

One last request, could add some info on the commit msg on why this is needed? BTW thanks for ensuring that the commit history is organised =)

@lcobucci
Copy link
Member

Ahhh I forgot one more thing, can you please add a test for the reverse operation too? bigint -> int

@icewind1991
Copy link
Contributor Author

done

- SERIAL and BIGSERIAL are not true types and can't be used in ALTER TABLE expressions
- When changing between int and bigint auto increment fields the default should no be dropped
  to preserve the link between the column and the sequence.
@lcobucci lcobucci merged commit 0e8ad2c into doctrine:master Nov 20, 2017
lcobucci added a commit that referenced this pull request Nov 20, 2017
@lcobucci
Copy link
Member

@icewind1991 🚢 and backported to 2.6.x (with some minor improvements). Thanks for your contribution!

@icewind1991 icewind1991 deleted the postgres-int-to-bigint branch November 21, 2017 13:43
@icewind1991
Copy link
Contributor Author

Any chance of getting things backported to 2.5.x? We're stuck with supporting php 5.6/7.0 for the foreseeable future

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants