Sauvegarde au format SQLite impossible avec les dernières version de MariaDB #4374

Closed
opened 2 years ago by olivier.tetard · 11 comments

Les dernières versions de MariaDB exportent utilisent current_timestamp() en tant que fonction quand on exporte le format des tables SQL (via la commande SHOW CREATE TABLE). C’est ce résultat qui est utilisé pour créer les tables dans la base SQLite, or, l’utilisation de la fonction current_timestamp() n’est pas possible avec SQLite.

Ce problème a été introduit avec les dernières version de MariaDB (voir par exemple "ce rapport de bug":https://jira.mariadb.org/browse/MDEV-13377 ou cette discussion sur "StackOverflow":https://stackoverflow.com/questions/44722541/mariadb-current-timestamp-gets-changed-to-current-timestamp. Ce problème est par ailleurs "évoqué sur les forums de SPIP, ici":https://forum.spip.net/fr_270745.html#forum271721.

Un correctif bête et méchant est de modifier le code de SPIP pour permettre de changer l’appel à la fonction current_timestamp() vers la variable CURRENT_TIMESTAMP. Ça peut soit être fait dans le code de la fonction base_copier_table() en rajoutant le bout de code suivant ligne 604 :

        foreach($desc_source["field"] as $k => $v) {
            $desc_source["field"][$k] = str_replace("current_timestamp()", "CURRENT_TIMESTAMP", $v);
        }

(L’idéal serait de vérifier que la base de données source utilise bien la dernière version de MariaDB histoire d’éviter des appels inutiles à str_replace).

Les dernières versions de MariaDB exportent utilisent `current_timestamp()` en tant que fonction quand on exporte le format des tables SQL (via la commande `SHOW CREATE TABLE`). C’est ce résultat qui est utilisé pour créer les tables dans la base SQLite, or, l’utilisation de la fonction `current_timestamp()` n’est pas possible avec SQLite. Ce problème a été introduit avec les dernières version de MariaDB (voir par exemple "ce rapport de bug":https://jira.mariadb.org/browse/MDEV-13377 ou cette discussion sur "StackOverflow":https://stackoverflow.com/questions/44722541/mariadb-current-timestamp-gets-changed-to-current-timestamp. Ce problème est par ailleurs "évoqué sur les forums de SPIP, ici":https://forum.spip.net/fr_270745.html#forum271721. Un correctif bête et méchant est de modifier le code de SPIP pour permettre de changer l’appel à la fonction `current_timestamp()` vers la variable `CURRENT_TIMESTAMP`. Ça peut soit être fait dans le code de la fonction `base_copier_table()` en rajoutant le bout de code suivant ligne 604 : ``` foreach($desc_source["field"] as $k => $v) { $desc_source["field"][$k] = str_replace("current_timestamp()", "CURRENT_TIMESTAMP", $v); } ``` (L’idéal serait de vérifier que la base de données source utilise bien la dernière version de MariaDB histoire d’éviter des appels inutiles à `str_replace`).
b_b commented 2 years ago
Owner

Version cible 3.3 et report à faire en 3.2 + 3.1 donc.
Version cible mise à 4.0

Version cible 3.3 et report à faire en 3.2 + 3.1 donc. **Version cible mise à 4.0**
Owner

Je dirais qu’il faut plutôt :

  • soit modifier _sqlite_remplacements_definitions_table() dans ecrire/req/sqlite_generique.php
  • soit déclarer une fonction current_timestamp() dans ecrire/req/sqlite_fonctions.php qui retournerait l’équivalent de la fonction php time()
Je dirais qu’il faut plutôt : - soit modifier `_sqlite_remplacements_definitions_table()` dans ecrire/req/sqlite_generique.php - soit déclarer une fonction `current_timestamp()` dans ecrire/req/sqlite_fonctions.php qui retournerait l’équivalent de la fonction php `time()`
b_b commented 2 years ago
Owner

Statut changé à En cours

**Statut changé à En cours**
b_b commented 1 year ago
Owner

`marcimat, tu n'as pas encore envoyé de patch pour ça ?

`marcimat, tu n'as pas encore envoyé de patch pour ça ?
b_b commented 1 year ago
Owner

Un truc comme ça `marcimat ?

diff --git a/ecrire/req/sqlite_generique.php b/ecrire/req/sqlite_generique.php
index 8ed38dc0a5..00d61660ee 100644
--- a/ecrire/req/sqlite_generique.php
+++ b/ecrire/req/sqlite_generique.php
`` -2429,6 +2429,7 `` function _sqlite_remplacements_definitions_table($query, $autoinc = false) {
 		'/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
 		'/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'",
 		'/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'",
+		'/current_timestamp\(\)/' => 'CURRENT_TIMESTAMP'
 	);
 
 	// pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY

Un truc comme ça `marcimat ? ``` diff --git a/ecrire/req/sqlite_generique.php b/ecrire/req/sqlite_generique.php index 8ed38dc0a5..00d61660ee 100644 --- a/ecrire/req/sqlite_generique.php +++ b/ecrire/req/sqlite_generique.php `` -2429,6 +2429,7 `` function _sqlite_remplacements_definitions_table($query, $autoinc = false) { '/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''", '/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'", '/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'", + '/current_timestamp\(\)/' => 'CURRENT_TIMESTAMP' ); // pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY ```
b_b commented 1 year ago
Owner

En fait non, cf :

< marcimat‎ >  mais sqlite, n’a pas ON UPDATE
< marcimat‎ >  donc DEFAULT CURRENT_TIMESTAMP => ok
< marcimat‎ >  mais si y a ON UPDATE current_timestamp()
< marcimat‎ >  on n’a aucune solution en sqlite
< marcimat‎ >  autre que de passer par des triggers (comme d’autres bdd d’ailleurs)

https://stackoverflow.com/a/50429848

En fait non, cf : <pre> < marcimat‎ > mais sqlite, n’a pas ON UPDATE < marcimat‎ > donc DEFAULT CURRENT_TIMESTAMP => ok < marcimat‎ > mais si y a ON UPDATE current_timestamp() < marcimat‎ > on n’a aucune solution en sqlite < marcimat‎ > autre que de passer par des triggers (comme d’autres bdd d’ailleurs) </pre> https://stackoverflow.com/a/50429848
Owner

À fixer avant la release de la 3.3 ?

À fixer avant la release de la 3.3 ?
Owner

oui enfin le ON UPDATE CURRENT_TIMESTAMP c'est un problème pour faire tourner le Site en SQLite.
Pour faire le backup on a juste besoin que les tables soit bien créées dans sqlite pour pouvoir copier le contenu de mysql vers sqlite.
Donc je pense que le patch de b_b fait l'affaire...

oui enfin le `ON UPDATE CURRENT_TIMESTAMP` c'est un problème pour faire tourner le Site en SQLite. Pour faire le backup on a juste besoin que les tables soit bien créées dans sqlite pour pouvoir copier le contenu de mysql vers sqlite. Donc je pense que le patch de b_b fait l'affaire...
Owner

et 7a30fed7bb doit donc corriger le soucis
b_b : je l'ai remontée avant l'autre regexp sur le timestamp car sinon je pense on va rater la suppression du ON UPDATE ... justement qui va nous bloquer la creation de la table

Si tu pouvais nous faire un feedback Olivier qu'on fasse le report en 3.2 aussi ?

et https://git.spip.net/spip/spip/commit/7a30fed7bbe4bad2ae36d89bf309bc1dac08efda doit donc corriger le soucis b_b : je l'ai remontée avant l'autre regexp sur le timestamp car sinon je pense on va rater la suppression du `ON UPDATE ...` justement qui va nous bloquer la creation de la table Si tu pouvais nous faire un feedback Olivier qu'on fasse le report en 3.2 aussi ?
Owner

pas de feedback, on ferme
Statut changé à Fermé

pas de feedback, on ferme **Statut changé à Fermé**
Owner

Je viens de tester chez Infini (qui était concerné par le bug) et le patch fait bien le job, le dump fonctionne de nouveau, je report en 3.2 :)

https://git.spip.net/spip/spip/commit/ebe3911a

Je viens de tester chez Infini (qui était concerné par le bug) et le patch fait bien le job, le dump fonctionne de nouveau, je report en 3.2 :) https://git.spip.net/spip/spip/commit/ebe3911a
Sign in to join this conversation.
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.