Vbulletin bulk importer: значение NULL в столбце "pinned_globally" отношения "topics" нарушает ограничение not-null

Я пытаюсь выполнить импорт с помощью массового импортера vBulletin. Мне удалось настроить его так, чтобы он в основном справлялся с задачей. Пользователи и сообщения были созданы, но темы не создаются.

Данные, передаваемые в create_topics(topics), выглядят верно. Данные в processed в base.rb:create_records также корректны (поле skipped не установлено). Однако темы не создаются.

Вот ошибка:

ERROR:  null value in column "pinned_globally" of relation "topics" violates not-null constraint

Но если тема не закреплена глобально, какое значение должно быть у этого поля? Я пытаюсь закомментировать это поле в TOPIC_COLUMNS в файле base.rb.

РЕДАКТИРОВАНИЕ: Думаю, это может помочь, но узнаю точно не скоро:

    create_topics(topics) do |row|
      created_at = Time.zone.at(row[5])

      t = {
        imported_id: row[0],
        title: normalize_text(row[1]),
        category_id: category_id_from_imported_id(row[2]),
        user_id: user_id_from_imported_id(row[3]),
        closed: row[4] == 0,
        created_at: created_at,
        views: row[6] || 0,
        visible: row[7] == 1,
        pinned_globally: row[8] == 1 # <============== JP добавил это:
      }
      t[:pinned_at] = created_at if row[8] == 1

      t
    end

Странно, учитывая, что у этого столбца есть значение по умолчанию? Есть ли у него значение по умолчанию в вашей базе данных, если выполнить \d topics?

pinned_globally | boolean | | not null | false

Ага. Думаю, теперь понятно, почему этого нет в коде.

Но загадка всё ещё не разгадана.

pinned_globally    | boolean   |     | not null | false

РЕДАКТИРОВАНИЕ:

Случайный ИИ говорит:

Может быть, это и есть «инструмент массовой вставки»?

Мне не удалось найти авторитетный источник, подтверждающий то, что утверждается в приведённой цитате, но это звучит логично: раз цель — скорость, то пропуск значений по умолчанию кажется вполне вероятным поведением. Это также объясняет происходящее и, надеюсь, подтвердит решение, которое я всё ещё жду.

Вот настоящая документация! PostgreSQL: Documentation: 18: COPY

Если указан список столбцов, команда COPY TO копирует в файл только данные из указанных столбцов. Для COPY FROM каждое поле в файле вставляется по порядку в соответствующий указанный столбец. Столбцы таблицы, не указанные в списке столбцов команды COPY FROM, получат свои значения по умолчанию.

Так что, если я правильно понимаю, если поле включено в список полей, PostgreSQL слепо копирует то, что вы ему дали, и вместо желаемого значения по умолчанию вставляется пустое значение или NULL.

Процесс замедляется всё больше. Есть ли причина не использовать LIMIT 1000, как это делает обычный импортер? Кажется, что 885 тысяч тем — это слишком много для одной порции?"}

Я проверил скрипт для последнего массового импорта, который я делал, и в нём действительно явно указано pinned_globally: false, так что, похоже, это необходимо — это единственное явно прописанное значение столбца в коде.

    create_topics(topics) do |row|
      t = {
        imported_id: row[0],
        title: my_normalize_text(row[1]),
        category_id: category_id_from_imported_id(row[2]),
        user_id: user_id_from_imported_id(row[3]),
        created_at: Time.zone.at(row[4]),
        pinned_globally: false
      }

Странно, что для других подобных столбцов с not null, default false, таких как closed или has_summary, этого нет.

При последнем импорте с помощью массового импортера было обработано более 3 миллионов тем примерно за 2 часа. Возможно, у вас утечка памяти? Или, может быть, ваш код MySQL (или то, что вы используете для чтения исходных данных), работает медленно в каком-то месте?

Отличные новости! Все темы созданы! Плохие новости: ни один пост не связан с ними, но, возможно, это потому, что посты были созданы до тем.

Это действительно странно. Я был уверен, что у меня есть объяснение. :person_shrugging:

7 миллионов постов заняли всего пару часов, а менее 1 миллиона тем — около 4 часов.

Это старый сервер (который, по словам, купили специально для этой задачи?), и mysql находится удалённо. Просматривая htop, я не вижу очевидной утечки памяти на уровне системы. Я очистил все данные и пересоздаю контейнеры, чтобы проверить, сработает ли это в этот раз.

Огромное спасибо за вашу помощь.

Что ж, теперь импорт user_email завершается с ошибкой:

CONTEXT:  COPY user_emails, строка 1: "1  \N      @gmail.com     true    2004-03-08 14:12:00 UTC 2004-03-08 14:12:00 UTC"

Мне потребовалось ещё несколько часов, но вот почему — функция process_topic обрабатывает все эти значения по умолчанию.

Похоже, должно быть

topic[:pinned_globally] ||= false

или, возможно,

topic[:pinned_globally] ||= topic[:pinned_at].nil?