Erreur de migration : `ActiveRecord::NotNullViolation: PG::NotNullViolation: ERREUR : la colonne « private_message » contient des valeurs null`

Je suis en train de mettre à niveau un site et cela échoue avec l’erreur PG::NotNullViolation: ERROR: column "private_message" contains null values. Je ne parviens pas à trouver où se trouve la colonne private_message. Il n’y a aucun plugin non officiel.

Ah. Attends. Voici ceci :

(Voir la trace complète en exécutant la tâche avec --trace)                                                                                            
I, [2020-08-18T18:19:13.253667 #1]  INFO -- : == 20200818084329 UpdatePrivateMessageOnPostSearchData: migration en cours ============= 
-- execute("DELETE FROM post_search_data\nWHERE post_id IN (\n  SELECT posts.id\n  FROM posts\n  LEFT JOIN topics ON topics.id = posts.topic_id\n  WHERE topics.id IS NULL\n)\n")
   -> 21.9072s                                                                                                       
-- execute("DELETE FROM post_search_data\nWHERE post_id IN (\n  SELECT post_search_data.post_id\n  FROM post_search_data\n  LEFT JOIN posts ON posts.id = post_search_data.post_id\n  WHERE posts.id IS NULL\n)\n")                                                                       
   -> 47.2663s
-- execute("UPDATE post_search_data\nSET private_message = true\nFROM posts\nINNER JOIN topics ON topics.id = posts.topic_id AND topics.archetype = 'private_message'\nWHERE posts.id = post_search_data.post_id\n")                                                                      
   -> 107.2137s             
-- execute("UPDATE post_search_data\nSET private_message = false\nFROM posts\nINNER JOIN topics ON topics.id = posts.topic_id AND topics.archetype <> 'private_message'\nWHERE posts.id = post_search_data.post_id\n")
   -> 834.3738s                                                                                                                              
-- change_column_null(:post_search_data, :private_message, false)

Salut @tgxworld, je pense que cela est dû à

Hmm, c’est étrange… pourriez-vous exécuter les requêtes suivantes dans la console Rails et me fournir les résultats ?

DB.query_single(<<~SQL)
SELECT COUNT(*) FROM post_search_data
SQL

DB.query_single(<<~SQL)
SELECT COUNT(*)
FROM post_search_data
LEFT JOIN posts ON posts.id = post_search_data.post_id
LEFT JOIN topics ON topics.id = posts.topic_id 
WHERE topics.id IS NULL
SQL

DB.query_single(<<~SQL)
SELECT COUNT(*)
FROM post_search_data
LEFT JOIN posts ON posts.id = post_search_data.post_id
WHERE posts.id IS NULL
SQL

DB.query_single(<<~SQL)
SELECT COUNT(*)
FROM post_search_data
INNER JOIN posts ON posts.id = post_search_data.post_id
INNER JOIN topics ON topics.id = posts.topic_id
SQL
[2] pry(main)> 
[3] pry(main)> DB.query_single(<<~SQL)
[3] pry(main)* SELECT COUNT(*) FROM post_search_data
[3] pry(main)* SQL
=> [2200178]
[4] pry(main)> 
[5] pry(main)> DB.query_single(<<~SQL)
[5] pry(main)* SELECT COUNT(*)
[5] pry(main)* FROM post_search_data
[5] pry(main)* LEFT JOIN posts ON posts.id = post_search_data.post_id
[5] pry(main)* LEFT JOIN topics ON topics.id = posts.topic_id 
[5] pry(main)* WHERE topics.id IS NULL
[5] pry(main)* SQL

=> [39]
[6] pry(main)> 
[7] pry(main)> DB.query_single(<<~SQL)
[7] pry(main)* SELECT COUNT(*)
[7] pry(main)* FROM post_search_data
[7] pry(main)* LEFT JOIN posts ON posts.id = post_search_data.post_id
[7] pry(main)* WHERE posts.id IS NULL
[7] pry(main)* SQL
=> [0]
[8] pry(main)> 
[9] pry(main)> DB.query_single(<<~SQL)
[9] pry(main)* SELECT COUNT(*)
[9] pry(main)* FROM post_search_data
[9] pry(main)* INNER JOIN posts ON posts.id = post_search_data.post_id
[9] pry(main)* INNER JOIN topics ON topics.id = posts.topic_id
[9] pry(main)* SQL

Il semble que le dernier comptage n’ait pas été exécuté.

Désolé. Je continue à me faire avoir par le clic pour copier qui ne prend pas en compte le saut de ligne du terminal.

[2] pry(main)>
[3] pry(main)> DB.query_single(<<~SQL)
[3] pry(main)* SELECT COUNT(*)
[3] pry(main)* FROM post_search_data
[3] pry(main)* INNER JOIN posts ON posts.id = post_search_data.post_id
[3] pry(main)* INNER JOIN topics ON topics.id = posts.topic_id
[3] pry(main)* SQL
=> [2200797]

Désolé que vous deviez exécuter toutes les requêtes ensemble :slight_smile: sinon, la création de nouveaux posts faussera le comptage.

C’est tellement évident quand tu le dis… Et c’était plus de travail d’exécuter seulement une requête !

[1] pry(main)> DB.query_single(<<~SQL)
[1] pry(main)* SELECT COUNT(*) FROM post_search_data
[1] pry(main)* SQL
=> [2200995]
[2] pry(main)> 
[3] pry(main)> DB.query_single(<<~SQL)
[3] pry(main)* SELECT COUNT(*)
[3] pry(main)* FROM post_search_data
[3] pry(main)* LEFT JOIN posts ON posts.id = post_search_data.post_id
[3] pry(main)* LEFT JOIN topics ON topics.id = posts.topic_id 
[3] pry(main)* WHERE topics.id IS NULL
[3] pry(main)* SQL
=> [39]
[4] pry(main)> 
[5] pry(main)> DB.query_single(<<~SQL)
[5] pry(main)* SELECT COUNT(*)
[5] pry(main)* FROM post_search_data
[5] pry(main)* LEFT JOIN posts ON posts.id = post_search_data.post_id
[5] pry(main)* WHERE posts.id IS NULL
[5] pry(main)* SQL
=> [0]
[6] pry(main)> 
[7] pry(main)> DB.query_single(<<~SQL)
[7] pry(main)* SELECT COUNT(*)
[7] pry(main)* FROM post_search_data
[7] pry(main)* INNER JOIN posts ON posts.id = post_search_data.post_id
[7] pry(main)* INNER JOIN topics ON topics.id = posts.topic_id
[7] pry(main)* SQL
=> [2200956]
[8] pry(main)> 

@pfaffman Je voulais juste confirmer que cela a été résolu conformément à notre chef de projet ?

Désolé, Alan. Oui, cela a bien été résolu. Merci pour ton aide sur ce coup-là !

Pour toute autre personne rencontrant ce problème, si vous exécutez simplement ./launcher rebuild app, vous ne devriez rencontrer aucun problème, sauf que votre site pourrait être hors ligne pendant un certain temps pendant que la partie bootstrap de la reconstruction migre la base de données. C’est l’option sûre et facile, et sauf si vous avez une installation en deux conteneurs, c’est ce que vous ferez de toute façon.

Je ne voulais pas que le site soit hors ligne pendant tout le processus de bootstrap. Pour ce grand forum (5 millions de publications et environ 50 000 pages vues par jour ?), ma solution (que j’ai trouvée uniquement grâce à l’aide d’Alan) a été de lancer le bootstrap avec les migrations post-mise à jour désactivées (les migrations ont pris virtuellement aucun temps), de démarrer le nouveau conteneur, puis d’exécuter les migrations post-mise à jour (les migrations ont pris 20 à 40 minutes — je ne faisais pas vraiment attention à l’heure).

Si cela intéresse quelqu’un d’autre, j’ai depuis appris que l’exécution de la mise à jour avec docker_manager permet de faire cela beaucoup plus en douceur. C’est donc ce que je recommande si quelqu’un d’autre a un grand forum et rencontre des problèmes avec le bootstrap.