Importateur en vrac Vbulletin : la valeur null dans la colonne "pinned_globally" de la relation "topics" viole la contrainte not-null

J’essaie de faire une importation avec l’importateur en masse de vBulletin. J’ai réussi à le faire fonctionner en grande partie. Il a créé des utilisateurs et des publications, mais les sujets ne sont pas créés.

Les éléments transmis à create_topics(topics) semblent corrects. Les éléments dans processed dans base.rb:create_records semblent corrects (skipped n’est pas défini). Mais aucun sujet n’est créé.

Voici l’erreur :

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

Mais si un sujet n’est pas épinglé globalement, quelle valeur devrait-il avoir ? J’essaie de commenter ce champ dans TOPIC_COLUMNS dans base.rb.

EDIT : Je pense que cela pourrait fonctionner, mais je ne le saurai pas avant un moment :

    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 a ajouté ceci :
      }
      t[:pinned_at] = created_at if row[8] == 1

      t
    end

C’est étrange, car cette colonne a une valeur par défaut ? A-t-elle une valeur par défaut dans votre base de données lorsque vous faites \\d topics ?

pinned_globally | boolean | | not null | false

Aha. Cela explique pourquoi ce n’est pas dans le code, je pense.

Mais cela ne résout pas le mystère.

pinned_globally    | boolean   |     | not null | false

EDIT :

L’IA aléatoire dit :

Peut-être s’agit-il d’un « outil d’insertion en masse » ?

Je ne parviens pas à trouver une source qui affirme de manière crédible ce que dit la citation ci-dessus, mais cela semble logique, dans le sens où le but est d’aller vite, donc sauter les valeurs par défaut semble être quelque chose qu’il ferait, et cela explique ce qui se passe, et, j’espère, la solution qui, je l’espère, a fonctionné.

Voici la documentation réelle ! PostgreSQL: Documentation: 18: COPY

Si une liste de colonnes est spécifiée, COPY TO ne copie que les données des colonnes spécifiées dans le fichier. Pour COPY FROM, chaque champ du fichier est inséré, dans l’ordre, dans la colonne spécifiée. Les colonnes de table non spécifiées dans la liste de colonnes COPY FROM recevront leurs valeurs par défaut.

Donc, si je lis bien, si un champ est dans la liste des champs, alors postgres copie aveuglément ce que vous lui donnez, et un champ vide/null est inséré au lieu de la valeur par défaut souhaitée.

Cela va de plus en plus lentement. Y a-t-il une raison de ne pas utiliser LIMIT 1000 comme le fait l’importateur normal ? Il semble que 885K sujets, c’est peut-être beaucoup à mordre en une seule fois ?

J’ai vérifié le script de ma dernière importation en masse et il contient bien un pinned_globally: false explicite, donc c’est apparemment nécessaire - c’est la seule valeur de colonne codée en dur explicite dans le code.

    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
      }

Bizarre car il n’a pas cela pour d’autres colonnes similaires not null, default false comme closed ou has_summary.

Ma dernière importation avec l’importateur en masse a traité plus de 3 millions de sujets en 2 heures environ. Peut-être avez-vous une fuite de mémoire ? Ou peut-être que votre code MySQL (ou quoi que vous utilisiez pour lire les données sources) est lent quelque part ?

Bonne nouvelle ! Tous les sujets ont été créés ! Mauvaise nouvelle ! aucun des messages n’y est connecté, mais j’espère que c’est parce que les messages ont été créés avant les sujets.

C’est étrange. J’étais pourtant sûr d’avoir une explication. :person_shrugging:

Les 7 millions de messages n’ont pris que quelques heures, mais les moins d’un million de sujets ont pris environ 4 heures.

C’est une vieille machine (qu’ils ont apparemment achetée juste pour le travail ?), et mysql est à distance. En regardant htop, il n’y a pas de fuite de mémoire évidente au niveau du système. J’ai effacé toutes les données et je suis en train de reconstruire les conteneurs pour voir si cela fonctionnera cette fois-ci.

Merci infiniment pour votre aide.

1 « J'aime »

Eh bien, maintenant l’importation de user_email échoue avec :

CONTEXTE :  COPY user_emails, ligne 1 : "1  \N      @gmail.com     true    2004-03-08 14:12:00 UTC 2004-03-08 14:12:00 UTC"

Cela m’a pris plusieurs heures supplémentaires, mais voici pourquoi : la fonction process_topic gère toutes ces valeurs par défaut.

Je suppose qu’il devrait y avoir un

topic[:pinned_globally] ||= false

ou peut-être

topic[:pinned_globally] ||= topic[:pinned_at].nil?
1 « J'aime »