0

Im' trying to build my first module in nodejs. I have this code working perfectly :

var express = require('express');
var router = express.Router();
var sqlite3 = require('sqlite3').verbose();
var db;
var io = require('socket.io-client');
const notifier = require('node-notifier');

/* GET home page. */
router.get('/', function(req, res, next) {
    createDb();
    socket = io.connect('http://localhost:4000');
    socket.on('connect', () => {
        console.log("socket connected");
    });
    socket.on('message', (contenu) => {
        console.log('message received');
        console.log(contenu);
        notifier.notify(contenu.contenu);
    });
    socket.emit('message', { contenu : 'test'});
  res.render('index', { title: 'Accueil' });
});

/* SQLite */
function createDb() {
    console.log("createDb chain");
    db = new sqlite3.Database('./database_institut-villebon.db', createTable);
}

function createTable() {
    console.log("createTable etudiants");
    db.run("DROP TABLE IF EXISTS etudiants");
    db.run("CREATE TABLE IF NOT EXISTS etudiants (Nom TEXT, NumeroGroupe INTEGER, NumeroCandidat INTEGER PRIMARY KEY, Filiere TEXT)", insertRows);
}

function insertRows() {
    console.log("insertRows in etudiants");
    var stmt = db.prepare("INSERT INTO etudiants VALUES (?,?,?,?)");

    for (var i = 0; i < 3; i++) {
        stmt.run("John Doe",i,i,"S");
    }

    stmt.finalize(readAllRows);
}

function readAllRows() {
    console.log("readAllRows etudiants");
    db.all("SELECT rowid AS id, Nom, NumeroGroupe, NumeroCandidat, Filiere FROM etudiants", function(err, rows) {
        rows.forEach(function (row) {
            console.log(row.id + ": " + row.NumeroCandidat +","+ row.Filiere);
        });
        closeDb();
    });
}

function closeDb() {
    console.log("closeDb");
    db.close();
}

function runChain() {
    createDb();
}

module.exports = router;

But when i try to put it in a module it say that the table "etudiants" doesn't exist ...

This is my module :

var sqlite3 = require('sqlite3').verbose();

"use strict";

/* SQLite */
var BddUtils = function () {
    console.log("createDb chain");
    this.database = new sqlite3.Database('./database_institut-villebon.db');
}

BddUtils.prototype.closeDb = function () {
    console.log("closeDb");
    this.database.close();
}

BddUtils.prototype.readAllRows = function() {
    console.log("readAllRows etudiants");
    this.database.all("SELECT rowid AS id, Nom, NumeroGroupe, NumeroCandidat, Filiere FROM etudiants", function(err, rows) {
        rows.forEach(function (row) {
            console.log(row.id + ": " + row.NumeroCandidat +","+ row.Filiere);
        });
        this.database.closeDb();
    });
}

BddUtils.prototype.insertRows = function() {
    console.log("insertRows in etudiants");
    var stmt = this.database.prepare("INSERT INTO etudiants VALUES (?,?,?,?)");
    for (var i = 0; i < 3; i++) {
        stmt.run("John Doe",i,i,"S");
    }
    //stmt.finalize(this.readAllRows());
}

BddUtils.prototype.createTable = function () {
    console.log("createTable etudiants");
    this.database.run("DROP TABLE IF EXISTS etudiants");
    this.database.run("CREATE TABLE IF NOT EXISTS etudiants (Nom TEXT, NumeroGroupe INTEGER, NumeroCandidat INTEGER PRIMARY KEY, Filiere TEXT)", this.insertRows());
}

BddUtils.prototype.init = function () {
    this.createTable();
}

exports.BddUtils = exports = new BddUtils();

I have been looking for an issue and i found that if I don't drop the table everything works ! So i suppose that the "insertRows" function is called before the create table... but it's a callback function .... Any help will be appreciate, thanks in advance.

EDIT : I'm maybe on something :

The context of the function (the this object inside the function) is the statement object. Note that it is not possible to run the statement again because it is automatically finalized after running for the first time. Any subsequent attempts to run the statement again will fail.

If execution was successful, the this object will contain two properties named lastID and changes which contain the value of the last inserted row ID and the number of rows affected by this query respectively. Note that lastID only contains valid information when the query was a successfully completed INSERT statement and changes only contains valid information when the query was a successfully completed UPDATE or DELETE statement. In all other cases, the content of these properties is inaccurate and should not be used. The .run() function is the only query method that sets these two values; all other query methods such as .all() or .get() don't retrieve these values.

So it's possible that my this.database is not in the current context anymore... don't know how to proceed..

2 Answers 2

1

It looks like you need to wrap your CREATE TABLE statement into a Database.serialize() function.

Database#serialize([callback])

Puts the execution mode into serialized. This means that at most one statement object can execute a query at a time. Other statements wait in a queue until the previous statements are executed.

This ensures the CREATE TABLE statement gets executed in isolation.

The example that comes from the documentation:

db.serialize(function() {
  // These two queries will run sequentially.
  db.run("CREATE TABLE foo (num)");
  db.run("INSERT INTO foo VALUES (?)", 1, function() {
    // These queries will run in parallel and the second query will probably
    // fail because the table might not exist yet.
    db.run("CREATE TABLE bar (num)");
    db.run("INSERT INTO bar VALUES (?)", 1);
  });
});
Sign up to request clarification or add additional context in comments.

2 Comments

Alternatively, have a look at Promises, which is a more generic (and very handy) concept to gain control of any (asynchronous) flow.
Thanks for your help ! I've tried with a Promies but it said that this.database is undefined... (cannot read property run of undefined). I'm having trouble with scope .. var p1 = new Promise( function(resolve,reject) { console.log("createTable etudiants"); this.database.run("DROP TABLE IF EXISTS etudiants"); this.database.run("CREATE TABLE IF NOT EXISTS etudiants (Nom TEXT, NumeroGroupe INTEGER, NumeroCandidat INTEGER PRIMARY KEY, Filiere TEXT)"); } );
0

Solved by using db.serialized()

BddUtils.prototype.createTable = function () {
    var db = this.database;

    db.serialize(function() {
      console.log("createTable etudiants");
      db.run("DROP TABLE IF EXISTS etudiants");
      db.run("CREATE TABLE IF NOT EXISTS etudiants (Nom TEXT, NumeroGroupe INTEGER, NumeroCandidat INTEGER PRIMARY KEY, Filiere TEXT)");
      var stmt = db.prepare("INSERT INTO etudiants VALUES (?,?,?,?)");
      for (var i = 0; i < 3; i++) {
          stmt.run("John Doe",i,i,"S");
      }
      stmt.finalize(function(){
        console.log("readAllRows etudiants");
        db.all("SELECT rowid AS id, Nom, NumeroGroupe, NumeroCandidat, Filiere FROM etudiants", function(err, rows) {
            rows.forEach(function (row) {
                console.log(row.id + ": " + row.NumeroCandidat +","+ row.Filiere);
            });
            db.close();
        });
      });
    })
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.