Mysql
 sql >> Base de données >  >> RDS >> Mysql

Vidage MySQL NodeJS

Le code tel qu'il est écrit n'a même pas été enregistré dans un fichier pour moi. Il semble y avoir quelques problèmes. Je ne sais pas s'il s'agit du code réel ou si certaines choses ont été perdues dans le copier-coller. Cependant, en fonction de ce que vous avez :

Un gros problème est que vous ne vous connectez jamais à la base de données dans votre code avec connection.connect().

Le code que vous souhaitez exécuter une fois connecté doit se trouver dans le rappel connection.connect(). ex.

connection.connect(function (err, empty) {
    if (err)
        throw new Error ('Panic');

    // if no error, we are off to the races...
}

Cependant, même si vous refactorisez rapidement votre code pour envelopper vos dernières lignes à l'intérieur de ce rappel de connexion, vous aurez toujours des problèmes, car vous détruisez la connexion avant que les différents appels SQL ne soient effectués, vous voudrez donc déplacer le code dans une sorte de rappel final.

Même après cela, vous aurez toujours un fichier vide, car vous appelez save_backup à partir de votre rappel 'SHOW TABLES' plutôt qu'après l'avoir réellement rempli via le rappel interne où vous obtenez l'instruction CREATE TABLE et remplissez le propriété de sauvegarde.

C'est la réécriture minimale de votre code qui fera ce que vous avez l'intention. Une chose importante à noter est le "compteur" qui gère quand écrire le fichier et fermer la connexion. J'apporterais d'autres modifications si c'était la mienne, notamment :

  • Utiliser "moi" au lieu de "moi"
  • Utiliser une boucle for numérique plutôt que la syntaxe for (... in ...)
  • Avoir mes propres rappels relève de la convention de nœud de (err, stuff)
  • Un changement plus substantiel est que je réécrirais ceci pour utiliser des promesses, car cela peut vous épargner du chagrin avec la confusion inhérente aux rappels profondément imbriqués. Personnellement, j'aime la bibliothèque Q, mais il y a plusieurs options ici.

J'espère que cela a aidé.

var mysql_backup = function(){
    this.backup = '';
    this.mysql = require('mysql');

    this.init = function(){
        this.connection = this.mysql.createConnection({
            user     : 'root',
            password : 'root',
            database : 'test'
        });

    };

    this.query = function(sql, callback) {
        this.connection.query(sql, function (error, results, fields) {
            if (error) {
                throw error;
            }
            if (results.length  > 0) {
                callback(results);
            }
        });
    };

    this.get_tables = function(callback){
        var counter = 0;
        var me = this;
        this.query('SHOW TABLES',
            function(tables) {
                for (table in tables){
                    counter++;
                    me.query(
                        'SHOW CREATE TABLE ' + tables[table].Tables_in_mvc,
                        function(r){
                            for (t in r) {
                                me.backup += "DROP TABLE " + r[t].Table + "\n\n";
                                me.backup += r[t]["Create Table"] + "\n\n";
                            }
                            counter--;
                            if (counter === 0){
                                me.save_backup();
                                me.connection.destroy();

                            }
                        }
                    )
                }
            });
    };

    this.save_backup = function(){
        var fs = require('fs');
        fs.writeFile("./backup_test.txt", this.backup, function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log("The file was saved!");
            }
        });
    }

};

var db = new mysql_backup;
db.init();
db.connection.connect(function (err){
    if (err) console.log(err);
    db.get_tables(function(x){;});

});

Mise à jour :si vous êtes curieux, voici une implémentation fortement commentée utilisant des promesses. Notez que sans les commentaires expliquant les fonctions de la bibliothèque Q promise, elle est un peu plus courte que la version originale et offre également une gestion des erreurs plus complète.

var MysqlBackup = function(connectionInfo, filename){

    var Q = require('q');
    var self = this;
    this.backup = '';
    // my personal preference is to simply require() inline if I am only
    // going to use something a single time. I am certain some will find
    // this a terrible practice
    this.connection = require('mysql').createConnection(connectionInfo);

    function getTables(){
        //  return a promise from invoking the node-style 'query' method
        //  of self.connection with parameter 'SHOW TABLES'.
        return Q.ninvoke(self.connection,'query', 'SHOW TABLES');
    };

    function doTableEntries(theResults){

        // note that because promises only pass a single parameter around,
        // if the 'denodeify-ed' callback has more than two parameters (the
        // first being the err param), the parameters will be stuffed into
        // an array. In this case, the content of the 'fields' param of the
        // mysql callback is in theResults[1]

        var tables = theResults[0];
        // create an array of promises resulting from another Q.ninvoke()
        // query call, chained to .then(). Note that then() expects a function,
        // so recordEntry() in fact builds and returns a new one-off function
        // for actually recording the entry (see recordEntry() impl. below)

        var tableDefinitionGetters = [];
        for (var i = 0; i < tables.length ; i++){
            //  I noticed in your original code that your Tables_in_[] did not
            //  match your connection details ('mvc' vs 'test'), but the below
            //  should work and is a more generalized solution
            var tableName = tables[i]['Tables_in_'+connectionInfo.database];

            tableDefinitionGetters.push(Q.ninvoke(self.connection, 'query', 'SHOW CREATE TABLE ' + tableName)
                                        .then(recordEntry(tableName)) );
        }

        // now that you have an array of promises, you can use Q.allSettled
        // to return a promise which will be settled (resolved or rejected)
        // when all of the promises in the array are settled. Q.all is similar,
        // but its promise will be rejected (immediately) if any promise in the
        // array is rejected. I tend to use allSettled() in most cases.

        return Q.allSettled(tableDefinitionGetters);
    };

    function recordEntry (tableName){
        return function(createTableQryResult){
            self.backup += "DROP TABLE " + tableName + "\n\n";
            self.backup += createTableQryResult[0][0]["Create Table"] + "\n\n";
        };
    };

    function saveFile(){
        // Q.denodeify return a promise-enabled version of a node-style function
        // the below is probably excessively terse with its immediate invocation
        return (Q.denodeify(require('fs').writeFile))(filename, self.backup);
    }

    // with the above all done, now you can actually make the magic happen,
    // starting with the promise-return Q.ninvoke to connect to the DB
    // note that the successive .then()s will be executed iff (if and only
    // if) the preceding item resolves successfully, .catch() will get
    // executed in the event of any upstream error, and finally() will
    // get executed no matter what.

    Q.ninvoke(this.connection, 'connect')
    .then(getTables)
    .then(doTableEntries)
    .then(saveFile)
    .then( function() {console.log('Success'); } )
    .catch( function(err) {console.log('Something went awry', err); } )
    .finally( function() {self.connection.destroy(); } );
};

var myConnection = {
    host     : '127.0.0.1',
    user     : 'root',
    password : 'root',
    database : 'test'
};

// I have left this as constructor-based calling approach, but the
// constructor just does it all so I just ignore the return value

new MysqlBackup(myConnection,'./backup_test.txt');