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

Fixtures force autoincrement on ID column #10045

Closed
1 of 3 tasks
thinkingmedia opened this issue Jan 16, 2017 · 8 comments
Closed
1 of 3 tasks

Fixtures force autoincrement on ID column #10045

thinkingmedia opened this issue Jan 16, 2017 · 8 comments

Comments

@thinkingmedia
Copy link
Contributor

This is a (multiple allowed):

  • bug

  • enhancement

  • feature-discussion (RFC)

  • CakePHP Version: 3.3.11

  • Platform and Target: Apache2, MySQL, PHP 7.1, Bash on Windows 10

What you did

Created a fixture that imports the schema.

What happened

Here is the production table named ratings. Notice that by design it does not have an auto-increment on the primary ID column. This table stores film ratings and I use the numeric age as the primary key.

CREATE TABLE `ratings` (
  `id` int(11) NOT NULL,
  `key` char(5) COLLATE utf8mb4_unicode_ci NOT NULL,
  `title` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
  KEY `created` (`created`),
  KEY `updated` (`updated`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

When I created a fixture for ratings and used the schema import feature. The fixture manager created a table with an auto-increment ID. This creates problems for my code.

Here's the fixture table that was created.

CREATE TABLE `ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key` char(5) COLLATE utf8mb4_unicode_ci NOT NULL,
  `title` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
  KEY `created` (`created`),
  KEY `updated` (`updated`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Ignore the AUTO_INCREMENT=20 as I dumped the create statement as the tests ran.

What you expected to happen

Should not create an auto-increment column unless the source table has that attribute.

@markstory
Copy link
Member

It looks like this is happening during schema generation, after the reflection is complete. The MySqlSchema class does that here. I'm pretty sure this is a backwards compatibility shim that was intended to help migrating from 2.x easier.

Old fixtures would never have the autoIncrement key set in their $fields as that key didn't exist in 2.x.

@thinkingmedia
Copy link
Contributor Author

I added this to my fixture, and it outputs false.

    public function __construct()
    {
        parent::__construct();
        /* @var Connection $conn */
        $conn = ConnectionManager::get('test', false);
        var_dump($this->_schema->hasAutoincrement());
    }

So the schema object is being built correctly. The PHP debugger shows that autoIncrement is set to NULL for the ID column.

So I don't think this is a problem with the MySqlSchema class, but I could be wrong. I need to look closer at it.

@thinkingmedia
Copy link
Contributor Author

@markstory oh you're correct!

This is the part here.

        $addAutoIncrement = (
            [$name] == (array)$table->primaryKey() &&
            !$table->hasAutoIncrement()
        );

This forces an auto-increment if there is a primary key and no auto-increment in the schema.

@thinkingmedia
Copy link
Contributor Author

Do you think we could have this piece of logic removed in 3.4? I looked again at the code this morning, and there is no work around for it. Either we remove it or we add some way of disabling it temporary.

In order to get my tests to work. I did this (for anyone else having the issue).

/**
 * RatingsFixture
 */
class RatingsFixture extends GemsFixture
{
    /**
     * @param ConnectionInterface|Connection $db
     * @return bool
     */
    public function create(ConnectionInterface $db)
    {
        $result = parent::create($db);
        if ($result) {
            $db->transactional(function () use ($db) {
                $db->disableConstraints(function () use ($db) {
                    $db->execute("ALTER TABLE `test_ahtag`.`ratings` CHANGE COLUMN `id` `id` INT(11) NOT NULL");
                });
            });
        }
        return $result;
    }
}

@markstory
Copy link
Member

@thinkingmedia We could try removing that logic. Not generating the same primary key as the source table had/fixture defined is under the umbrella of defect. The solution for app developers would be to add 'autoIncrement' => true to their fixture definitions.

@thinkingmedia
Copy link
Contributor Author

@markstory I'm good now with my hack. We could mark this for 3.4 as a deprecated fix for 2.0 migrations.

@markstory markstory assigned markstory and unassigned markstory Jan 17, 2017
@markstory markstory modified the milestones: 3.3.13, 3.3.14 Jan 29, 2017
@markstory markstory modified the milestones: 3.3.14, 3.3.15, 3.4.1 Feb 6, 2017
@markstory markstory modified the milestones: 3.4.1, 3.4.2 Feb 18, 2017
@thinkingmedia
Copy link
Contributor Author

@markstory I was tempted to open a PR today for this. Do you think it should be changed or should we just leave it as is for now.

@markstory
Copy link
Member

I think it would be good if schema reflection resulted in the same table being generated by the fixtures. This could be something that goes into 3.5.0. I think we'd need to document this behavior change to folks who might be relying on it.

@markstory markstory modified the milestones: 3.4.2, 3.4.3 Feb 23, 2017
@markstory markstory modified the milestones: 3.4.3, 3.4.4 Mar 10, 2017
@markstory markstory modified the milestones: 3.4.4, 3.4.5 Mar 29, 2017
@markstory markstory modified the milestones: 3.4.5, 3.4.6 Apr 10, 2017
@markstory markstory modified the milestones: 3.4.6, 3.4.7 May 3, 2017
@markstory markstory modified the milestones: 3.4.7, 3.4.8 May 20, 2017
markstory added a commit that referenced this issue Jun 14, 2017
When autoIncrement has been set to a specific value we shouldn't
overwrite the user's request. This allows integer keys to exist without
autoincrement being set.

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

No branches or pull requests

2 participants