Меню

Миграция на DBAL 4 + Postgres

Вход
  • Gemorroj 10.03.2025 19:22
  • Gemorroj

    Обновлено 12.03.2025 15:55

    При миграции на DBAL 4 для Postgres нужно провести дополнительно ручную миграцию идентификаторов в БД - https://github.com/doctrine/dbal/blob/4.2.3/docs/en/how-to/postgresql-identity-migration.rst. Но предложенный скрипт миграции может не сработать из-за ограничения прав на изменение системных таблиц pg_depend и pg_attribute (ERROR: permission denied for table pg_depend).
     
    Как альтернативу, в интернетах предлагают такой вариант https://stackoverflow.com/questions/77907016/migration-to-identity-columns-on-postgresql-but-without-privileges-to-modify-pg#answer-78547244. Отлично, но я бы еще добавил проверку наличия sequence. Т.к. в реальной жизни имя sequence может отличаться от того, как его формирует скрипт.
     
    Доработанный скрипт:
    PostgreSQL
    CREATE OR REPLACE FUNCTION upgrade_serial_to_identity(table_name text, column_name text)
    RETURNS void
    LANGUAGE plpgsql
    AS $$
    DECLARE
        -- will hold the max value found in the sequence
        max_id integer;
     
        -- sequence name
        sequence_name text := table_name || '_' || column_name || '_seq';
    BEGIN
     
        -- check sequence
        IF NOT EXISTS (SELECT 0 FROM pg_class where relname = sequence_name)
        THEN
          RAISE EXCEPTION 'sequence does not exist: %', sequence_name;
        END IF;
     
        -- lock table
        EXECUTE format('LOCK %I;', table_name);
     
        -- get current maximum id
        EXECUTE format (
                'SELECT COALESCE(MAX(%I), 0) FROM %I;',
                 column_name,
                 table_name
        ) INTO max_id;
     
        -- drop the sequence
        EXECUTE format('DROP SEQUENCE %I CASCADE;', sequence_name);
     
        -- alter table so it now uses an identity, instead of the previously sequence
        EXECUTE format (
                'ALTER TABLE %I ALTER COLUMN %I ADD GENERATED BY DEFAULT AS IDENTITY (START WITH %s)',
                table_name,
                column_name,
                max_id + 1
        );
     
    END;
    $$

Удаление

Вы уверенны, что хотите удалить сообщение?

Это безвозвратная операция.

Отмена Удалить