Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
sauvegarde_script_sql [2014/04/08 09:12] tyrtamos |
sauvegarde_script_sql [2014/04/08 10:22] (Version actuelle) tyrtamos |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ====== Sauvegarde | + | ====== Sauvegarde |
- | [en cours de modification le 8/4/2014] | + | [modification le 8/4/2014: refonte complète de la page] |
===== Solution de base ===== | ===== Solution de base ===== | ||
Ligne 164: | Ligne 164: | ||
</ | </ | ||
- | Qui devient: | + | qui devient: |
<code python> | <code python> | ||
Ligne 174: | Ligne 174: | ||
Autre problème, mais cette fois-ci avec cx_freeze pour Python 2.7 (pas de problème avec Python 3): | Autre problème, mais cette fois-ci avec cx_freeze pour Python 2.7 (pas de problème avec Python 3): | ||
- | Alors que sans cx_freeze, les lignes de script retournées par iterdump sont correctement encodées, avec cx_freeze, les caractères accentués des données fournissent des erreurs d' | + | Alors que sans cx_freeze, les lignes de script retournées par "iterdump" |
En fait, alors que les données lues dans les tables sont en unicode, ce n'est pas le cas des lignes de script retournées par iterdump. | En fait, alors que les données lues dans les tables sont en unicode, ce n'est pas le cas des lignes de script retournées par iterdump. | ||
- | La correction est évidente: dans toutes les lignes du fichier dump.py qui contiennent un " | + | La correction est évidente: dans toutes les lignes du fichier dump.py qui contiennent un " |
<code python> | <code python> | ||
Ligne 217: | Ligne 217: | ||
==== Conversion d'une base de données sqlite3 en script SQL ==== | ==== Conversion d'une base de données sqlite3 en script SQL ==== | ||
+ | <code python> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | # python v2.7 | ||
+ | import os | ||
+ | import codecs | ||
+ | import sqlite3 | ||
+ | |||
+ | from sqlite3dump import _iterdump as iterdump | ||
+ | |||
+ | ############################################################################# | ||
+ | def base2script(base, | ||
+ | """ | ||
+ | base: la base de données (nom du fichier avec son chemin) | ||
+ | | ||
+ | | ||
+ | """ | ||
+ | # ouvre la base de données sqlite3 | ||
+ | try: | ||
+ | cnx = sqlite3.connect(base) | ||
+ | cnx.execute(" | ||
+ | except sqlite3.Error, | ||
+ | print u" | ||
+ | return | ||
+ | | ||
+ | # convertit la base sqlite3 en script SQL | ||
+ | with codecs.open(script, | ||
+ | for i, ligne in enumerate(iterdump(cnx)): | ||
+ | f.write(u' | ||
+ | | ||
+ | # ferme la base | ||
+ | cnx.close() | ||
+ | </ | ||
==== Conversion d'un script SQL en base de données sqlite3 ==== | ==== Conversion d'un script SQL en base de données sqlite3 ==== | ||
+ | |||
+ | <code python> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | # python v2.7 | ||
+ | |||
+ | import os | ||
+ | import codecs | ||
+ | import sqlite3 | ||
+ | |||
+ | from sqlite3dump import _iterdump as iterdump | ||
+ | |||
+ | ############################################################################# | ||
+ | def script2base(script, | ||
+ | """ | ||
+ | | ||
+ | base: la base de données (nom du fichier avec son chemin) | ||
+ | | ||
+ | """ | ||
+ | # lit et charge en mémoire le script SQL | ||
+ | with codecs.open(script, | ||
+ | scriptsql = f.read() | ||
+ | | ||
+ | # supprime la base si elle existe déjà | ||
+ | if os.path.exists(base): | ||
+ | os.remove(base) | ||
+ | | ||
+ | # ouvre la base de données sqlite3 et crée un curseur | ||
+ | try: | ||
+ | cnx = sqlite3.connect(base) | ||
+ | cnx.execute(" | ||
+ | cur = cnx.cursor() | ||
+ | except sqlite3.Error, | ||
+ | print u" | ||
+ | return | ||
+ | | ||
+ | # exécute le script pour reconstruire la base de données sqlite3 | ||
+ | try: | ||
+ | cur.executescript(scriptsql) | ||
+ | except sqlite3.Error, | ||
+ | print u" | ||
+ | cur.close() | ||
+ | cnx.close() | ||
+ | return | ||
+ | | ||
+ | # ferme la base de données | ||
+ | cur.close() | ||
+ | cnx.close() | ||
+ | </ | ||
==== Tester la validité d'une modification de script SQL ==== | ==== Tester la validité d'une modification de script SQL ==== | ||
+ | Voilà le code proposé pour tester si un script modifié respecte bien les contraintes d' | ||
+ | Au lieu d' | ||
+ | Par ailleurs, il faut retrouver les requêtes complètes pour les exécuter, car elles peuvent être présentées en plusieurs lignes. Il y a une méthode intéressante pour ça, qui s' | ||
+ | Enfin, puisque c'est un test de déverminage, | ||
+ | <code python> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | # python v2.7 | ||
+ | import os | ||
+ | import codecs | ||
+ | import sqlite3 | ||
+ | from sqlite3dump import _iterdump as iterdump | ||
+ | |||
+ | ############################################################################# | ||
+ | def script2base_test(script, | ||
+ | """ | ||
+ | | ||
+ | base: la base de données (nom du fichier avec son chemin) | ||
+ | | ||
+ | """ | ||
+ | | ||
+ | # supprime la base si elle existe déjà et s'il s'agit d'un fichier disque | ||
+ | if base!=": | ||
+ | os.remove(base) | ||
+ | |||
+ | # ouvre la base de données sqlite3 | ||
+ | try: | ||
+ | cnx = sqlite3.connect(base) | ||
+ | cnx.execute(" | ||
+ | cur = cnx.cursor() | ||
+ | except sqlite3.Error, | ||
+ | print u" | ||
+ | return | ||
+ | | ||
+ | # lit et charge en mémoire le script SQL | ||
+ | with codecs.open(script, | ||
+ | scriptsql = f.readlines() | ||
+ | nbl = len(scriptsql) # nombre de lignes du script SQL | ||
+ | | ||
+ | # lit et exécute le script SQL, requête par requête | ||
+ | i = 0 # compteur de lignes | ||
+ | r = 0 # compteur de requêtes | ||
+ | c = 0 # compteur d' | ||
+ | while i<nbl: | ||
+ | buffer = scriptsql[i] | ||
+ | while not sqlite3.complete_statement(buffer.encode(' | ||
+ | # NB: avec python 2, " | ||
+ | i += 1 | ||
+ | buffer += scriptsql[i] | ||
+ | | ||
+ | if buffer.strip() not in [u" | ||
+ | try: | ||
+ | cur.execute(buffer) | ||
+ | cnx.commit() | ||
+ | except sqlite3.Error, | ||
+ | cnx.rollback() | ||
+ | c += 1 | ||
+ | print u"num ligne: %d; num requête: %d; Erreur: %s; requête: \n%s" % (i, r, err.args[0], | ||
+ | | ||
+ | i += 1 # nouvelle ligne attendue | ||
+ | r += 1 # nouvelle requête attendue | ||
+ | | ||
+ | # fermeture et effacement de la base temporaire | ||
+ | cur.close() | ||
+ | cnx.close() | ||
+ | | ||
+ | # message de fin | ||
+ | print u" | ||
+ | </ | ||
+ | |||
+ | Exemple d' | ||
+ | |||
+ | <code python> | ||
+ | # test d' | ||
+ | script = " | ||
+ | script2base_test(script) | ||
+ | </ | ||
+ | |||
+ | Si, par exemple, la requête numéro 805 (ligne 884) déclenche une erreur, voilà le message affiché: | ||
+ | |||
+ | < | ||
+ | num ligne: 884; num requête: 805; Erreur: foreign key constraint failed; requête: | ||
+ | INSERT INTO " | ||
+ | </ | ||
+ | Il y a une faute de frappe sur le nom de pays (" | ||