2017-01-17 2 views
0

Contexte:
Un script python 3.6 est mise à jour une base de données SQLite plusieurs fois par jour en utilisant le module sqlite3.
La base de données est ~ 500Mo, chaque mise à jour ajoute ~ 250Ko.Créer des correctifs de base de données mise à jour Sqlite tout

Problème:
je livrerai toutes les versions mises à jour de la base de données et souhaite réduire la taille des données transférées. En d'autres termes, je souhaite transférer uniquement le contenu mis à jour (via un type de patch).
Le programme utilitaire sqldiff.exe pourrait être utilisé pour cela, néanmoins, il nécessite de créer une copie locale de la base de données chaque fois que je le mets à jour.

Question:
Est-il possible, en utilisant Python (par le DB-API 2.0 interface ou en utilisant d'autres moyens en Python), pour générer ce type de correctif en mettant à jour la base de données?


pensées Première:
Ne serait-il possible d'écrire un patch (par exemple une liste d'actions à faire pour mettre à jour la base de données) en fonction du curseur avant/pendant l'exécution de la commettre?

import sqlite3 

# Open database 
conn = sqlite3.connect('mydb.db') 
cur = conn.cursor() 

# Insert/Update data 
new_data = 3.14 
cur.execute('INSERT INTO mytable VALUES (?)', (new_data,)) 

# KEEP TRACK & Save (commit) the changes 
conn.dump_planned_actions() # ????? 
conn.commit() 
conn.close() 
+1

La [extension de session] (http://www.sqlite.org/sessionintro.html) n'est pas activée en Python. –

+0

@CL. Connaissez-vous des solutions de contournement? Merci –

Répondre

1

L'extrait suivant montre la solution de contournement que j'ai trouvée.

Il s'appuie sur la méthode Sqlite3 set_trace_callback pour consigner toutes les instructions SQL envoyées et executescript pour appliquer ces instructions.

import sqlite3 

class DBTraceCallbackHandler(object): 
    """Class handling callbacks in order to log sql statements history.""" 
    def __init__(self): 
     self.sql_statements = [] 
    def instance_handler(self, event): 
     self.sql_statements.append(str(event)) 

def database_modification(cursor): 
    # user-defined 
    pass 

def create_patch(db_path): 
    # Openning connection 
    conn = sqlite3.connect(db_path) 
    c = conn.cursor() 
    # Start tracing sql 
    callback_handler = DBTraceCallbackHandler() 
    conn.set_trace_callback(callback_handler.instance_handler) 
    # Modification of database 
    database_modification(c) 
    # End of modification of database 
    conn.commit() 
    c.close() 
    # Generating the patch - selecting sql statements that modify the db 
    idx_rm = [] 
    for idx, sql_statement in enumerate(callback_handler.sql_statements): 
     if not any([sql_statement.startswith(kw) for kw in ['UPDATE', 'INSERT', 'CREATE']]): 
      idx_rm.append(idx) 
    for idx in sorted(idx_rm, reverse=True): 
     del callback_handler.sql_statements[idx] 

    return ';\n'.join(callback_handler.sql_statements) + ';\n' 


def apply_patch(db_path, sql_script): 
    # Openning connection 
    conn = sqlite3.connect(db_path) 
    c = conn.cursor() 
    # Modification of database - apply sql script 
    c.executescript(sql_script) 
    # End of modification of database 
    conn.commit() 
    c.close()