Doctrine / MySQL mediumtext + ненужные ALTER TABLEs - PullRequest
0 голосов
/ 18 марта 2020

Работает на mysql 5.7 + Doctrine 2.7 / DBAL 2.9, с:

/**
 * @ORM\Entity()
 */
class Entity {
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100000, nullable=true)
     */
    private $bigText;
}

orm: schema-tool: create создает таблицу Entity:

CREATE TABLE `Entity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bigText` mediumtext COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Тем не менее, схема-инструмент учитывает таблицу, нуждающуюся в обновлении. Запуск orm:schema-tool:update --dump-sql дает:

ALTER TABLE Entity CHANGE bigText bigText MEDIUMTEXT DEFAULT NULL;

Выполнение обновления работает нормально, но не помогает: оно все равно будет думать, что таблица нуждается в обновлении.

Я отслеживал проблему в методе diffColumn Doctrine \ DBAL \ Schema \ Comparator, где сравниваются PlatformOptions текущего и будущего определения столбца. У будущего столбца нет PlatformOptions (что имеет смысл, поскольку, я полагаю, его еще нет на платформе), в то время как в текущем столбце они есть, а именно charset и collation, в моем тестовом примере здесь используются значения по умолчанию: ['charset' => 'utf8', 'collation' => 'utf8_unicode_ci'], которые устанавливаются для объекта Column с помощью Doctrine\DBAL\Schema\MySqlSchemaManager->_getPortableTableColumnDefinition().

. Немного покопавшись в источнике, я обнаружил, что могу использовать EventListeners: потому что Doctrine\DBAL\Schema\AbstractSchemaManager->_getPortableTableColumnList() будет генерировать событие onSchemaColumnDefinition, и если я установлю $event->preventDefault() там и создаю свой собственный объект Column и использую $event->setColumn($column), я могу обойти MySqlSchemaManager->_getPortableTableColumnDefinition(). Или я могу go и поиграть с другой стороной и изменить схему, созданную из классов / аннотаций, и использовать postGenerateSchemaTable (что гораздо проще и кажется менее странным, чем возиться с onSchemaColumnDefinition). Хотя я немного больше узнал о внутренних потоках, это кажется слишком сложным, чтобы обрабатывать средний текст в MySQL без постоянного создания ненужных ALTER TABLE.

Конечно, я могу полностью обойти проблему, использование type = "text" вместо type = "string" + фиксированная длина (что я понял, когда просматривал здесь вопросы, прежде чем задавать этот вопрос), но из любопытства: я упускаю что-то фундаментальное для работы с полями фиксированной длины в MySQL которые попадают в длину среднего текста?

...